Teuchos - Trilinos Tools Package Version of the Day
Teuchos_as.hpp
Go to the documentation of this file.
00001 // @HEADER
00002 // ***********************************************************************
00003 //
00004 //                    Teuchos: Common Tools Package
00005 //                 Copyright (2004) Sandia Corporation
00006 //
00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00008 // license for use of this work by or on behalf of the U.S. Government.
00009 //
00010 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are
00012 // met:
00013 //
00014 // 1. Redistributions of source code must retain the above copyright
00015 // notice, this list of conditions and the following disclaimer.
00016 //
00017 // 2. Redistributions in binary form must reproduce the above copyright
00018 // notice, this list of conditions and the following disclaimer in the
00019 // documentation and/or other materials provided with the distribution.
00020 //
00021 // 3. Neither the name of the Corporation nor the names of the
00022 // contributors may be used to endorse or promote products derived from
00023 // this software without specific prior written permission.
00024 //
00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036 //
00037 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
00038 //
00039 // ***********************************************************************
00040 // @HEADER
00041 
00042 #ifndef TEUCHOS_AS_HPP
00043 #define TEUCHOS_AS_HPP
00044 
00070 
00071 #include "Teuchos_ConfigDefs.hpp"
00072 #include "Teuchos_Assert.hpp"
00073 #include <limits>
00074 #include <cstdlib>
00075 #include <cerrno>
00076 #include <climits>
00077 
00078 #ifdef HAVE_TEUCHOS_COMPLEX
00079 #include <complex>
00080 #endif // HAVE_TEUCHOS_COMPLEX
00081 
00082 #ifdef HAVE_TEUCHOS_QD
00083 #include <qd/qd_real.h>
00084 #include <qd/dd_real.h>
00085 #endif // HAVE_TEUCHOS_QD
00086 
00087 namespace Teuchos {
00088 
00089 
00178 template<class TypeTo, class TypeFrom>
00179 class ValueTypeConversionTraits {
00180 public:
00182   static TypeTo convert (const TypeFrom t) {
00183     // This default implementation is just an implicit conversion and
00184     // may generate compiler warnings on dangerous conversions.
00185     return t;
00186   }
00187 
00189   static TypeTo safeConvert (const TypeFrom t) {
00190     // This default implementation is just an implicit conversion and
00191     // may generate compiler warnings on dangerous conversions.  No
00192     // runtime checking (e.g., for overflow) can be done by default;
00193     // only specializations can define meaningful and portable
00194     // run-time checks of conversions.
00195     return t;
00196   }
00197 };
00198 
00286 template<class TypeTo, class TypeFrom>
00287 inline TypeTo as( const TypeFrom& t );
00288 
00289 
00355 template<class TypeTo, class TypeFrom>
00356 inline TypeTo asSafe( const TypeFrom& t );
00357 
00358 
00371 template <class TypeTo>
00372 class asFunc {
00373 public:
00374   asFunc() {}
00375 
00376   template <class TypeFrom>
00377   inline TypeTo operator()(const TypeFrom &t) {
00378     return as<TypeTo>(t);
00379   }
00380 };
00381 
00382 
00383 
00384 namespace { // anonymous
00385 
00403   template<class IntType>
00404   IntType
00405   intToString (const std::string& t,
00406                IntType (*rawConvert) (const char*, char**, int),
00407                const char* intTypeName)
00408   {
00409     // We call the "raw" conversion function instead of using
00410     // std::istringstream, because we want more detailed information
00411     // in case of failure to convert.  I have no idea what
00412     // operator>>(std::istream&, unsigned long long&) does if it
00413     // encounters an integer too long to fit in IntType, for example.
00414     //
00415     // mfh 13 Nov 2012: It's fair to assume that if you have "long
00416     // long", then your implementation of the C standard library
00417     // includes strtoul().  Ditto for "unsigned long long" and
00418     // strtoull().  If this is not the case, we could include a
00419     // configure-time test for these functions(), with a fall-back to
00420     // an std::istringstream operator>> implementation.
00421     char* endptr = NULL;
00422     // Keep the pointer, because std::string doesn't necessarily
00423     // guarantee that this is the same across calls to c_str(), does
00424     // it?  Or perhaps it does...
00425     const char* t_ptr = t.c_str ();
00426     // We preset errno to 0, to distinguish success or failure after
00427     // calling strtoull.  Most implementations of the C standard
00428     // library written with threads in mind have errno be a macro that
00429     // expands to thread-local storage.  Thanks to the Linux
00430     // documentation for strtol ("man 3 strtol", Red Hat Enterprise
00431     // Linux 5) for advice with the following checks.
00432     errno = 0;
00433     const IntType val = rawConvert (t_ptr, &endptr, 10);
00434 
00435     const IntType minVal = std::numeric_limits<IntType>::min ();
00436     const IntType maxVal = std::numeric_limits<IntType>::max ();
00437     TEUCHOS_TEST_FOR_EXCEPTION(
00438       errno == ERANGE && (val == minVal || val == maxVal),
00439       std::range_error,
00440       "Teuchos::ValueTypeConversionTraits<" << intTypeName << ", std::string>::convert: "
00441       "The integer value in the given string \"" << t << "\" overflows " << intTypeName << ".");
00442     TEUCHOS_TEST_FOR_EXCEPTION(
00443       errno != 0 && val == 0,
00444       std::invalid_argument,
00445       "Teuchos::ValueTypeConversionTraits<" << intTypeName << ", std::string>::convert: "
00446       "The conversion function was unable to convert the given string \"" << t << "\" to " << intTypeName << ".");
00447     TEUCHOS_TEST_FOR_EXCEPTION(
00448       endptr == t_ptr, // See above discussion of c_str().
00449       std::invalid_argument,
00450       "Teuchos::ValueTypeConversionTraits<" << intTypeName << ", std::string>::convert: "
00451       "The conversion function was unable to read any integer digits from the given string "
00452       "\"" << t << "\".");
00453     return val;
00454   }
00455 
00467   template<class OutputRealType, class InputRealType>
00468   OutputRealType
00469   realToReal (const InputRealType& x, const bool doBoundsChecking)
00470   {
00471     using Teuchos::TypeNameTraits;
00472 
00473     if (doBoundsChecking) {
00474       // For floating-point types T, std::numeric_limits<T>::min()
00475       // returns the smallest positive value.  IEEE 754 types have a
00476       // sign bit, so the largest-magnitude negative value is the
00477       // negative of the largest-magnitude positive value.
00478       const OutputRealType minVal = -std::numeric_limits<OutputRealType>::max ();
00479       const OutputRealType maxVal = std::numeric_limits<OutputRealType>::max ();
00480 
00481       // NaN is neither less than nor greater than anything.  We just
00482       // let it pass through, per the rules for propagation of silent
00483       // NaN.  (Signaling NaN will signal, but that's OK.)
00484       TEUCHOS_TEST_FOR_EXCEPTION(
00485         x < minVal || x > maxVal,
00486         std::range_error,
00487         "realToReal<" << TypeNameTraits<OutputRealType>::name () << ", "
00488         << TypeNameTraits<InputRealType>::name () << ">: "
00489         "Input value x = " << x << " is out of the valid range [" << minVal
00490         << ", " << maxVal << "] for conversion to the output type.");
00491     }
00492 
00493     // Call as() and not static_cast, because there might not
00494     // necessarily be a conversion defined between the two types,
00495     // other than via as().  Definitely don't call asSafe(), because
00496     // that could cause infinite recursion.
00497     return as<OutputRealType> (x);
00498   }
00499 
00500 
00525   template<class RealType>
00526   RealType
00527   stringToReal (const std::string& t,
00528                RealType (*rawConvert) (const char*, char**),
00529                const char* realTypeName)
00530   {
00531     if (rawConvert == NULL) {
00532       std::istringstream in (t);
00533       RealType out;
00534       in >> out;
00535       return out;
00536     }
00537     else {
00538       char* endptr = NULL;
00539       // Keep the pointer, because std::string doesn't necessarily
00540       // guarantee that this is the same across calls to c_str(), does
00541       // it?  Or perhaps it does...
00542       const char* t_ptr = t.c_str ();
00543       // We preset errno to 0, to distinguish success or failure after
00544       // calling strtoull.  Most implementations of the C standard
00545       // library written with threads in mind have errno be a macro that
00546       // expands to thread-local storage.  Thanks to the Linux
00547       // documentation for strtod ("man 3 strtod", Red Hat Enterprise
00548       // Linux 5) for advice with the following checks.
00549       errno = 0;
00550       const RealType val = rawConvert (t_ptr, &endptr);
00551 
00552       TEUCHOS_TEST_FOR_EXCEPTION(
00553         errno == ERANGE && (val != 0),
00554         std::range_error,
00555         "Teuchos::ValueTypeConversionTraits<" << realTypeName
00556         << ", std::string>::convert: "
00557         "The value in the given string \"" << t << "\" overflows "
00558         << realTypeName << ".");
00559       //
00560       // mfh 20 Nov 2012: Should we treat underflow as an error?
00561       //
00562       TEUCHOS_TEST_FOR_EXCEPTION(
00563         errno == ERANGE && val == 0,
00564         std::invalid_argument,
00565         "Teuchos::ValueTypeConversionTraits<" << realTypeName
00566         << ", std::string>::convert: "
00567         "The value in the given string \"" << t << "\" underflows "
00568         << realTypeName << ".");
00569       TEUCHOS_TEST_FOR_EXCEPTION(
00570         endptr == t_ptr, // See above discussion of c_str().
00571         std::invalid_argument,
00572         "Teuchos::ValueTypeConversionTraits<" << realTypeName
00573         << ", std::string>::convert: "
00574         "The conversion function was unable to read any floating-point data "
00575         "from the given string \"" << t << "\".");
00576       return val;
00577     }
00578   }
00579 
00580 } // namespace (anonymous)
00581 
00582 
00583 //
00584 // Standard specializations of ValueTypeConversionTraits
00585 //
00586 
00587 //
00588 // * Partial specialization for conversion from std::string to any type T.
00589 //   There are full specializations for specific types T below.
00590 //
00591 
00604 template<class OutType>
00605 class ValueTypeConversionTraits<OutType, std::string> {
00606 public:
00607   static OutType safeConvert (const std::string& t) {
00608     return convert (t);
00609   }
00610 
00611   static OutType convert (const std::string& t) {
00612     std::istringstream in (t);
00613     OutType out;
00614     t >> out;
00615     return out;
00616   }
00617 };
00618 
00619 //
00620 // * Specializations for conversions from std::string to build-in
00621 //   real-valued floating-point types.
00622 //
00623 
00625 template<>
00626 class ValueTypeConversionTraits<double, std::string> {
00627 public:
00628   static double convert (const std::string& t) {
00629     return stringToReal<double> (t, &strtod, "double");
00630   }
00631 
00632   static double safeConvert (const std::string& t) {
00633     return stringToReal<double> (t, &strtod, "double");
00634   }
00635 };
00636 
00638 template<>
00639 class ValueTypeConversionTraits<float, std::string> {
00640 public:
00641   static float convert (const std::string& t) {
00642 #ifdef _ISOC99_SOURCE
00643     return stringToReal<float> (t, &strtof, "float");
00644 #else
00645     // strtof is new in C99.  If you don't have it, just use strtod
00646     // and convert the resulting double to float.
00647     const double d = stringToReal<double> (t, &strtod, "double");
00648     return realToReal<float, double> (d, false);
00649 #endif // _ISOC99_SOURCE
00650   }
00651 
00652   static float safeConvert (const std::string& t) {
00653 #ifdef _ISOC99_SOURCE
00654     return stringToReal<float> (t, &strtof, "float");
00655 #else
00656     // strtof is new in C99.  If you don't have it, just use strtod
00657     // and convert the resulting double to float.
00658     const double d = stringToReal<double> (t, &strtod, "double");
00659     return realToReal<float, double> (d, true);
00660 #endif // _ISOC99_SOURCE
00661   }
00662 };
00663 
00665 template<>
00666 class ValueTypeConversionTraits<long double, std::string> {
00667 public:
00668   static long double convert (const std::string& t) {
00669 #ifdef _ISOC99_SOURCE
00670     return stringToReal<long double> (t, &strtold, "long double");
00671 #else
00672     // strtof is new in C99.  If you don't have it, just use
00673     // operator>>(std::istream&, long double&).
00674     return stringToReal<long double> (t, NULL, "long double");
00675 #endif // _ISOC99_SOURCE
00676   }
00677 
00678   static long double safeConvert (const std::string& t) {
00679     return convert (t);
00680   }
00681 };
00682 
00683 
00684 //
00685 // * Specializations for conversions from std::string to build-in integer types.
00686 //
00687 
00688 #ifdef HAVE_TEUCHOS_LONG_LONG_INT
00689 
00693 template<>
00694 class ValueTypeConversionTraits<long long, std::string> {
00695 public:
00701   static long long safeConvert (const std::string& t) {
00702 #if defined(_MSC_VER)
00703     // Windows does not implement strtoull, so we resort to a
00704     // fallback.  Thanks to Ross Bartlett for pointing out _strtoi64.
00705     // See the MSDN reference [last accessed 21 Mar 2013]:
00706     //
00707     // http://msdn.microsoft.com/en-us/library/h80404d3%28v=vs.80%29.aspx
00708     return intToString<long long> (t, &_strtoi64, "long long");
00709 #else
00710     return intToString<long long> (t, &strtoll, "long long");
00711 #endif // defined(_MSC_VER)
00712   }
00713 
00715   static long long convert (const std::string& t) {
00716     return safeConvert (t);
00717   }
00718 };
00719 
00720 
00724 template<>
00725 class ValueTypeConversionTraits<unsigned long long, std::string> {
00726 public:
00732   static unsigned long long safeConvert (const std::string& t) {
00733 #if defined(_MSC_VER)
00734     // Windows does not implement strtoull, so we resort to a
00735     // fallback.  The fallback does not know how to check for under-
00736     // or overflow.  Alas, Windows does not seem to have an equivalent
00737     // of _strtoi64 for unsigned long long.
00738     const char intTypeName[] = "unsigned long long";
00739     std::istringstream istr (t);
00740     unsigned long long i = 0;
00741     istr >> i;
00742     TEUCHOS_TEST_FOR_EXCEPTION(
00743       ! istr, std::invalid_argument,
00744       "Teuchos::ValueTypeConversionTraits<" << intTypeName << ", std::string>::"
00745       "convert: Unable to convert the given string \"" << t << "\" to " <<
00746       intTypeName << ".  Windows lacks strtoull(), so we had to resort to a "
00747       "fall-back conversion.  The fall-back method does not know how to test "
00748       "for overflow.");
00749     return i;
00750 #else
00751     return intToString<unsigned long long> (t, &strtoull, "unsigned long long");
00752 #endif // defined(_MSC_VER)
00753   }
00754 
00756   static unsigned long long convert (const std::string& t) {
00757     return safeConvert (t);
00758   }
00759 };
00760 
00761 #endif // HAVE_TEUCHOS_LONG_LONG_INT
00762 
00763 
00767 template<>
00768 class ValueTypeConversionTraits<long, std::string> {
00769 public:
00775   static long safeConvert (const std::string& t) {
00776     return intToString<long> (t, &strtol, "long");
00777   }
00778 
00780   static long convert (const std::string& t) {
00781     return safeConvert (t);
00782   }
00783 };
00784 
00785 
00789 template<>
00790 class ValueTypeConversionTraits<unsigned long, std::string> {
00791 public:
00797   static unsigned long safeConvert (const std::string& t) {
00798     return intToString<unsigned long> (t, &strtoul, "unsigned long");
00799   }
00800 
00802   static unsigned long convert (const std::string& t) {
00803     return safeConvert (t);
00804   }
00805 };
00806 
00807 
00811 template<>
00812 class ValueTypeConversionTraits<int, std::string> {
00813 private:
00815   static long safeConvertToLong (const std::string& t) {
00816     long val = 0;
00817     try {
00818       val = ValueTypeConversionTraits<long, std::string>::safeConvert (t);
00819     } catch (std::range_error&) {
00820       TEUCHOS_TEST_FOR_EXCEPTION(
00821         true,
00822         std::range_error,
00823         "Teuchos::ValueTypeConversionTraits<int, std::string>::convert: "
00824         "The given std::string \"" << t << "\" is too big to fit into long, so there is no way it could fit into int.");
00825     } catch (std::invalid_argument& e) {
00826       TEUCHOS_TEST_FOR_EXCEPTION(
00827         true,
00828         std::invalid_argument,
00829         "Teuchos::ValueTypeConversionTraits<int, std::string>::convert: "
00830         "Intermediate conversion from std::string to long failed, with the following error message: "
00831         << e.what ());
00832     }
00833     return val;
00834   }
00835 
00836 public:
00842   static int safeConvert (const std::string& t) {
00843     return asSafe<int> (safeConvertToLong (t));
00844   }
00845 
00847   static int convert (const std::string& t) {
00848     return as<int> (safeConvertToLong (t));
00849   }
00850 };
00851 
00852 
00856 template<>
00857 class ValueTypeConversionTraits<unsigned int, std::string> {
00858 private:
00860   static unsigned long safeConvertToUnsignedLong (const std::string& t) {
00861     unsigned long val = 0;
00862     try {
00863       val = as<unsigned long> (t);
00864     } catch (std::range_error&) {
00865       TEUCHOS_TEST_FOR_EXCEPTION(
00866         true,
00867         std::range_error,
00868         "Teuchos::ValueTypeConversionTraits<unsigned int, std::string>::convert: "
00869         "The given std::string \"" << t << "\" is too big to fit into unsigned long, so there is no way it could fit into unsigned int.");
00870     } catch (std::invalid_argument& e) {
00871       TEUCHOS_TEST_FOR_EXCEPTION(
00872         true,
00873         std::invalid_argument,
00874         "Teuchos::ValueTypeConversionTraits<unsigned int, std::string>::convert: "
00875         "Intermediate conversion from std::string to unsigned long failed, with the following error message: "
00876         << e.what ());
00877     }
00878     return val;
00879   }
00880 
00881 public:
00887   static unsigned int safeConvert (const std::string& t) {
00888     return asSafe<unsigned int> (safeConvertToUnsignedLong (t));
00889   }
00890 
00892   static unsigned int convert (const std::string& t) {
00893     return as<unsigned int> (safeConvertToUnsignedLong (t));
00894   }
00895 };
00896 
00897 
00901 template<>
00902 class ValueTypeConversionTraits<short, std::string> {
00903 private:
00905   static long safeConvertToLong (const std::string& t) {
00906     long val = 0;
00907     try {
00908       val = ValueTypeConversionTraits<long, std::string>::safeConvert (t);
00909     } catch (std::range_error&) {
00910       TEUCHOS_TEST_FOR_EXCEPTION(
00911         true,
00912         std::range_error,
00913         "Teuchos::ValueTypeConversionTraits<short, std::string>::convert: "
00914         "The given std::string \"" << t << "\" is too big to fit into long, so there is no way it could fit into short.");
00915     } catch (std::invalid_argument& e) {
00916       TEUCHOS_TEST_FOR_EXCEPTION(
00917         true,
00918         std::invalid_argument,
00919         "Teuchos::ValueTypeConversionTraits<short, std::string>::convert: "
00920         "Intermediate conversion from std::string to long failed, with the following error message: "
00921         << e.what ());
00922     }
00923     return val;
00924   }
00925 
00926 public:
00932   static short safeConvert (const std::string& t) {
00933     return asSafe<short> (safeConvertToLong (t));
00934   }
00935 
00937   static short convert (const std::string& t) {
00938     return as<short> (safeConvertToLong (t));
00939   }
00940 };
00941 
00942 
00946 template<>
00947 class ValueTypeConversionTraits<unsigned short, std::string> {
00948 private:
00950   static unsigned long safeConvertToUnsignedLong (const std::string& t) {
00951     unsigned long val = 0;
00952     try {
00953       val = as<unsigned long> (t);
00954     } catch (std::range_error&) {
00955       TEUCHOS_TEST_FOR_EXCEPTION(
00956         true,
00957         std::range_error,
00958         "Teuchos::ValueTypeConversionTraits<unsigned short, std::string>::convert: "
00959         "The given std::string \"" << t << "\" is too big to fit into unsigned long, so there is no way it could fit into unsigned short.");
00960     } catch (std::invalid_argument& e) {
00961       TEUCHOS_TEST_FOR_EXCEPTION(
00962         true,
00963         std::invalid_argument,
00964         "Teuchos::ValueTypeConversionTraits<unsigned short, std::string>::convert: "
00965         "Intermediate conversion from std::string to unsigned long failed, with the following error message: "
00966         << e.what ());
00967     }
00968     return val;
00969   }
00970 
00971 public:
00977   static unsigned short safeConvert (const std::string& t) {
00978     return asSafe<unsigned short> (safeConvertToUnsignedLong (t));
00979   }
00980 
00982   static unsigned short convert (const std::string& t) {
00983     return as<unsigned short> (safeConvertToUnsignedLong (t));
00984   }
00985 };
00986 
00987 //
00988 // * Specializations for conversions between built-in real-valued
00989 //   floating-point types (like float and double).
00990 //
00991 
00993 template<>
00994 class ValueTypeConversionTraits<float, double> {
00995 public:
00996   static float safeConvert (const double t) {
00997     // mfh 25 Nov 2012: Disabling bounds checking, in favor of IEEE
00998     // 754 overflow semantics.  Users who want bounds checking should
00999     // set the appropriate trap.
01000 #if 0
01001     // For floating-point types T, std::numeric_limits<T>::min()
01002     // returns the smallest positive value.  IEEE 754 types have a
01003     // sign bit, so the largest-magnitude negative value is the
01004     // negative of the largest-magnitude positive value.
01005     const float minVal = -std::numeric_limits<float>::max ();
01006     const float maxVal = std::numeric_limits<float>::max ();
01007 
01008     // NaN is neither less than nor greater than anything.  We just
01009     // let it pass through, per the rules for propagation of silent
01010     // NaN.  (Signaling NaN will signal, but that's OK.)
01011     TEUCHOS_TEST_FOR_EXCEPTION(
01012       t < minVal || t > maxVal,
01013       std::range_error,
01014       "Teuchos::ValueTypeConversionTraits<float, double>::safeConvert: "
01015       "Input double t = " << t << " is out of the valid range [" << minVal
01016       << ", " << maxVal << "] for conversion to float.");
01017 #endif // 0
01018 
01019     return static_cast<float> (t);
01020   }
01021 
01022   static float convert (const double t) {
01023     return static_cast<float> (t);
01024   }
01025 };
01026 
01027 
01029 template<>
01030 class ValueTypeConversionTraits<float, long double> {
01031 public:
01032   static float safeConvert (const long double t) {
01033     // mfh 25 Nov 2012: Disabling bounds checking, in favor of IEEE
01034     // 754 overflow semantics.  Users who want bounds checking should
01035     // set the appropriate trap.
01036 #if 0
01037     // For floating-point types T, std::numeric_limits<T>::min()
01038     // returns the smallest positive value.  IEEE 754 types have a
01039     // sign bit, so the largest-magnitude negative value is the
01040     // negative of the largest-magnitude positive value.
01041     const float minVal = -std::numeric_limits<float>::max ();
01042     const float maxVal = std::numeric_limits<float>::max ();
01043 
01044     // NaN is neither less than nor greater than anything.  We just
01045     // let it pass through, per the rules for propagation of silent
01046     // NaN.  (Signaling NaN will signal, but that's OK.)
01047     TEUCHOS_TEST_FOR_EXCEPTION(
01048       t < minVal || t > maxVal,
01049       std::range_error,
01050       "Teuchos::ValueTypeConversionTraits<float, long double>::safeConvert: "
01051       "Input long double t = " << t << " is out of the valid range [" << minVal
01052       << ", " << maxVal << "] for conversion to float.");
01053 #endif // 0
01054 
01055     return static_cast<float> (t);
01056   }
01057 
01058   static float convert (const long double t) {
01059     return static_cast<float> (t);
01060   }
01061 };
01062 
01063 
01065 template<>
01066 class ValueTypeConversionTraits<double, long double> {
01067 public:
01068   static double safeConvert (const long double t) {
01069     // mfh 25 Nov 2012: Disabling bounds checking, in favor of IEEE
01070     // 754 overflow semantics.  Users who want bounds checking should
01071     // set the appropriate trap.
01072 #if 0
01073     // For floating-point types T, std::numeric_limits<T>::min()
01074     // returns the smallest positive value.  IEEE 754 types have a
01075     // sign bit, so the largest-magnitude negative value is the
01076     // negative of the largest-magnitude positive value.
01077     const double minVal = -std::numeric_limits<double>::max ();
01078     const double maxVal = std::numeric_limits<double>::max ();
01079 
01080     // NaN is neither less than nor greater than anything.  We just
01081     // let it pass through, per the rules for propagation of silent
01082     // NaN.  (Signaling NaN will signal, but that's OK.)
01083     TEUCHOS_TEST_FOR_EXCEPTION(
01084       t < minVal || t > maxVal,
01085       std::range_error,
01086       "Teuchos::ValueTypeConversionTraits<double, long double>::safeConvert: "
01087       "Input long double t = " << t << " is out of the valid range [" << minVal
01088       << ", " << maxVal << "] for conversion to double.");
01089 #endif // 0
01090 
01091     return static_cast<double> (t);
01092   }
01093 
01094   static double convert (const long double t) {
01095     return static_cast<double> (t);
01096   }
01097 };
01098 
01099 
01100 //
01101 // * Specializations for conversions from built-in real-valued
01102 //   floating-point types (float and double) to build-in integer
01103 //   types.
01104 //
01105 
01107 template<>
01108 class ValueTypeConversionTraits<short, double> {
01109 public:
01115   static short convert (const double t) {
01116     // Implicit conversion may cause compiler warnings, but
01117     // static_cast does not.
01118     return static_cast<short> (t);
01119   }
01120 
01122   static short safeConvert (const double t) {
01123     const short minVal = std::numeric_limits<short>::min ();
01124     const short maxVal = std::numeric_limits<short>::max ();
01125 
01126     // Cases:
01127     // 1. sizeof(short) < sizeof(double) == 8
01128     // 2. sizeof(short) == sizeof(double) == 8
01129     // 3. sizeof(short) > sizeof(double) == 8
01130     //
01131     // Overflow when converting from double to short is possible only
01132     // for Case 1.  Loss of accuracy (rounding) is possible for Cases
01133     // 2 and 3, but safeConvert() only cares about overflow, not
01134     // rounding.  In Case 3, casting minVal or maxVal to double in
01135     // this case could result in overflow.  Thus, we only do the test
01136     // for Case 1.
01137     //
01138     // All three cases are legal according to both C++03 and C99.
01139     // However, I (mfh 15 Nov 2012) have never encountered Cases 2 and
01140     // 3.
01141     if (sizeof (short) < sizeof (double)) {
01142       TEUCHOS_TEST_FOR_EXCEPTION(
01143         t < minVal || t > maxVal,
01144         std::range_error,
01145         "Teuchos::ValueTypeConversionTraits<short, double>::safeConvert: "
01146         "Input double t = " << t << " is out of the valid range [" << minVal
01147         << ", " << maxVal << "] for conversion to short.");
01148     }
01149     return static_cast<short> (t);
01150   }
01151 };
01152 
01153 
01155 template<>
01156 class ValueTypeConversionTraits<unsigned short, double> {
01157 public:
01159   static unsigned short convert (const double t) {
01160     // Implicit conversion may cause compiler warnings, but
01161     // static_cast does not.
01162     return static_cast<unsigned short> (t);
01163   }
01164 
01166   static unsigned short safeConvert (const double t) {
01167     const unsigned short minVal = 0;
01168     const unsigned short maxVal = std::numeric_limits<unsigned short>::max ();
01169 
01170     TEUCHOS_TEST_FOR_EXCEPTION(
01171       t < minVal || t > maxVal,
01172       std::range_error,
01173       "Teuchos::ValueTypeConversionTraits<unsigned short, double>::safeConvert: "
01174       "Input double t = " << t << " is out of the valid range [" << minVal
01175       << ", " << maxVal << "] for conversion to unsigned short.");
01176 
01177     return static_cast<unsigned short> (t);
01178   }
01179 };
01180 
01181 
01183 template<>
01184 class ValueTypeConversionTraits<int, double> {
01185 public:
01191   static int convert (const double t) {
01192     // Implicit conversion from double to int causes compiler
01193     // warnings, but static_cast does not.
01194     return static_cast<int> (t);
01195   }
01196 
01198   static int safeConvert (const double t) {
01199     const int minVal = std::numeric_limits<int>::min ();
01200     const int maxVal = std::numeric_limits<int>::max ();
01201 
01202     // Cases:
01203     // 1. sizeof(int) < sizeof(double) == 8
01204     // 2. sizeof(int) == sizeof(double) == 8
01205     // 3. sizeof(int) > sizeof(double) == 8
01206     //
01207     // Overflow when converting from double to int is possible only
01208     // for Case 1.  Loss of accuracy (rounding) is possible for Cases
01209     // 2 and 3, but safeConvert() only cares about overflow, not
01210     // rounding.  Case 3 is quite rare, but casting minVal or maxVal
01211     // to double in this case could result in overflow.  Thus, we only
01212     // do the cast for Case 1.
01213     if (sizeof (int) < sizeof (double)) {
01214       TEUCHOS_TEST_FOR_EXCEPTION(
01215         t < minVal || t > maxVal,
01216         std::range_error,
01217         "Teuchos::ValueTypeConversionTraits<int, double>::safeConvert: "
01218         "Input double t = " << t << " is out of the valid range [" << minVal
01219         << ", " << maxVal << "] for conversion to int.");
01220     }
01221     return static_cast<int> (t);
01222   }
01223 };
01224 
01225 
01227 template<>
01228 class ValueTypeConversionTraits<unsigned int, double> {
01229 public:
01231   static unsigned int convert (const double t) {
01232     // Implicit conversion may cause compiler warnings, but
01233     // static_cast does not.
01234     return static_cast<unsigned int> (t);
01235   }
01236 
01238   static unsigned int safeConvert (const double t) {
01239     const unsigned int minVal = 0;
01240     const unsigned int maxVal = std::numeric_limits<unsigned int>::max ();
01241 
01242     TEUCHOS_TEST_FOR_EXCEPTION(
01243       t < minVal || t > maxVal,
01244       std::range_error,
01245       "Teuchos::ValueTypeConversionTraits<unsigned int, double>::safeConvert: "
01246       "Input double t = " << t << " is out of the valid range [" << minVal
01247       << ", " << maxVal << "] for conversion to unsigned int.");
01248 
01249     return static_cast<unsigned int> (t);
01250   }
01251 };
01252 
01253 
01255 template<>
01256 class ValueTypeConversionTraits<long, double> {
01257 public:
01259   static long convert (const double t) {
01260     // Implicit conversion may cause compiler warnings, but
01261     // static_cast does not.
01262     return static_cast<long> (t);
01263   }
01264 
01266   static long safeConvert (const double t) {
01267     const long minVal = std::numeric_limits<long>::min ();
01268     const long maxVal = std::numeric_limits<long>::max ();
01269 
01270     // Cases:
01271     // 1. sizeof(long) < sizeof(double) == 8
01272     // 2. sizeof(long) == sizeof(double) == 8
01273     // 3. sizeof(long) > sizeof(double) == 8
01274     //
01275     // Overflow when converting from double to long is possible only
01276     // for Case 1.  Loss of accuracy (rounding) is possible for Cases
01277     // 2 and 3, but safeConvert() only cares about overflow, not
01278     // rounding.  In Case 3, casting minVal or maxVal to double could
01279     // result in overflow.  Thus, we only test for Case 1.
01280     //
01281     // Case 1 is entirely possible, for example on Win64 (an
01282     // implementation of the LLP64 integer model, on which
01283     // sizeof(long) == 4, and sizeof(long long) == sizeof(void*) ==
01284     // 8).
01285     if (sizeof (long) < sizeof (double)) {
01286       TEUCHOS_TEST_FOR_EXCEPTION(
01287         t < minVal || t > maxVal,
01288         std::range_error,
01289         "Teuchos::ValueTypeConversionTraits<long, double>::safeConvert: "
01290         "Input double t = " << t << " is out of the valid range [" << minVal
01291         << ", " << maxVal << "] for conversion to long.");
01292     }
01293     return static_cast<long> (t);
01294   }
01295 };
01296 
01297 
01299 template<>
01300 class ValueTypeConversionTraits<unsigned long, double> {
01301 public:
01303   static unsigned long convert (const double t) {
01304     // Implicit conversion may cause compiler warnings, but
01305     // static_cast does not.
01306     return static_cast<unsigned long> (t);
01307   }
01308 
01310   static unsigned long safeConvert (const double t) {
01311     const unsigned long minVal = 0;
01312     const unsigned long maxVal = std::numeric_limits<unsigned long>::max ();
01313 
01314     TEUCHOS_TEST_FOR_EXCEPTION(
01315       t < minVal || t > maxVal,
01316       std::range_error,
01317       "Teuchos::ValueTypeConversionTraits<unsigned long, double>::safeConvert: "
01318       "Input double t = " << t << " is out of the valid range [" << minVal
01319       << ", " << maxVal << "] for conversion to unsigned long.");
01320 
01321     return static_cast<unsigned long> (t);
01322   }
01323 };
01324 
01325 #ifdef HAVE_TEUCHOS_LONG_LONG_INT
01326 
01328 template<>
01329 class ValueTypeConversionTraits<long long, double> {
01330 public:
01332   static long long convert (const double t) {
01333     // Implicit conversion may cause compiler warnings, but
01334     // static_cast does not.
01335     return static_cast<long long> (t);
01336   }
01337 
01339   static long long safeConvert (const double t) {
01340     // Cases:
01341     // 1. sizeof(long long) < sizeof(double) == 8
01342     // 2. sizeof(long long) == sizeof(double) == 8
01343     // 3. sizeof(long long) > sizeof(double) == 8
01344     //
01345     // C99 (which defines long long) prohibits Case 1.  Case 2 could
01346     // result in loss of accuracy (rounding), but safeConvert() only
01347     // cares about overflow, not rounding.  In Case 3, casting minVal
01348     // or maxVal to double could result in overflow.  Thus, we don't
01349     // need to check anything here.
01350     return static_cast<long long> (t);
01351   }
01352 };
01353 
01354 
01356 template<>
01357 class ValueTypeConversionTraits<unsigned long long, double> {
01358 public:
01360   static unsigned long long convert (const double t) {
01361     // Implicit conversion may cause compiler warnings, but
01362     // static_cast does not.
01363     return static_cast<unsigned long long> (t);
01364   }
01365 
01367   static unsigned long long safeConvert (const double t) {
01368     const unsigned long long minVal = 0; // unsigned, so min value is 0.
01369     const unsigned long long maxVal = std::numeric_limits<unsigned long long>::max ();
01370 
01371     TEUCHOS_TEST_FOR_EXCEPTION(
01372       t < minVal || t > maxVal,
01373       std::range_error,
01374       "Teuchos::ValueTypeConversionTraits<unsigned long long, double>::safeConvert: "
01375       "Input double t = " << t << " is out of the valid range [" << minVal
01376       << ", " << maxVal << "] for conversion to unsigned long long.");
01377 
01378     return static_cast<unsigned long long> (t);
01379   }
01380 };
01381 
01382 #endif // HAVE_TEUCHOS_LONG_LONG_INT
01383 
01384 
01386 template<>
01387 class ValueTypeConversionTraits<short, float> {
01388 public:
01394   static short convert (const float t) {
01395     // Implicit conversion may cause compiler warnings, but
01396     // static_cast does not.
01397     return static_cast<short> (t);
01398   }
01399 
01401   static short safeConvert (const float t) {
01402     const short minVal = std::numeric_limits<short>::min ();
01403     const short maxVal = std::numeric_limits<short>::max ();
01404 
01405     // Cases:
01406     // 1. sizeof(short) < sizeof(float) == 4
01407     // 2. sizeof(short) == sizeof(float) == 4
01408     // 3. sizeof(short) > sizeof(float) == 4
01409     //
01410     // Overflow when converting from float to short is possible only
01411     // for Case 1.  Loss of accuracy (rounding) is possible for Cases
01412     // 2 and 3, but safeConvert() only cares about overflow, not
01413     // rounding.  In Case 3, casting minVal or maxVal to float in this
01414     // case could result in overflow.  Thus, we only do the test for
01415     // Case 1.
01416     //
01417     // All three cases are legal according to both C++03 and C99.  I
01418     // (mfh 15 Nov 2012) think Case 1 is the most common, but Case 2
01419     // is certainly reasonable.  (For example, some hardware prefers
01420     // to work only with 32-bit words, so _every_ built-in type has
01421     // size a multiple of 4 bytes.)
01422     if (sizeof (short) < sizeof (float)) {
01423       TEUCHOS_TEST_FOR_EXCEPTION(
01424         t < minVal || t > maxVal,
01425         std::range_error,
01426         "Teuchos::ValueTypeConversionTraits<short, float>::safeConvert: "
01427         "Input float t = " << t << " is out of the valid range [" << minVal
01428         << ", " << maxVal << "] for conversion to short.");
01429     }
01430 
01431     return static_cast<short> (t);
01432   }
01433 };
01434 
01435 
01437 template<>
01438 class ValueTypeConversionTraits<unsigned short, float> {
01439 public:
01441   static unsigned short convert (const float t) {
01442     // Implicit conversion may cause compiler warnings, but
01443     // static_cast does not.
01444     return static_cast<unsigned short> (t);
01445   }
01446 
01448   static unsigned short safeConvert (const float t) {
01449     const unsigned short minVal = 0;
01450     const unsigned short maxVal = std::numeric_limits<unsigned short>::max ();
01451 
01452     TEUCHOS_TEST_FOR_EXCEPTION(
01453       t < minVal || t > maxVal,
01454       std::range_error,
01455       "Teuchos::ValueTypeConversionTraits<unsigned short, float>::safeConvert: "
01456       "Input float t = " << t << " is out of the valid range [" << minVal
01457       << ", " << maxVal << "] for conversion to unsigned short.");
01458 
01459     return static_cast<unsigned short> (t);
01460   }
01461 };
01462 
01463 
01465 template<>
01466 class ValueTypeConversionTraits<int, float> {
01467 public:
01469   static int convert (const float t) {
01470     // Implicit conversion from float to int may cause compiler
01471     // warnings, but static_cast does not.  Overflow here would mean
01472     // that sizeof(int) < sizeof(float), which is legal, but unlikely
01473     // on platforms of interest.
01474     return static_cast<int> (t);
01475   }
01476 
01478   static int safeConvert (const float t) {
01479     const int minVal = std::numeric_limits<int>::min ();
01480     const int maxVal = std::numeric_limits<int>::max ();
01481 
01482     // Cases:
01483     // 1. sizeof(int) < sizeof(float) == 4
01484     // 2. sizeof(int) == sizeof(float) == 4
01485     // 3. sizeof(int) > sizeof(float) == 4
01486     //
01487     // Overflow when converting from float to int is possible only for
01488     // Case 1.  Loss of accuracy (rounding) is possible for Cases 2
01489     // and 3, but safeConvert() only cares about overflow, not
01490     // rounding.  Case 3 is rare, but casting minVal or maxVal to
01491     // float in this case could result in loss of accuracy
01492     // (sizeof(int) == 8 or 16) or overflow (sizeof(int) > 16).  Thus,
01493     // we only do the test for Case 1.
01494     if (sizeof (int) < sizeof (float)) {
01495       TEUCHOS_TEST_FOR_EXCEPTION(
01496         t < minVal || t > maxVal,
01497         std::range_error,
01498         "Teuchos::ValueTypeConversionTraits<int, float>::safeConvert: "
01499         "Input float t = " << t << " is out of the valid range ["
01500         << minVal << ", " << maxVal << "] for conversion to int.");
01501     }
01502     return static_cast<int> (t);
01503   }
01504 };
01505 
01506 
01508 template<>
01509 class ValueTypeConversionTraits<unsigned int, float> {
01510 public:
01512   static unsigned int convert (const float t) {
01513     // Implicit conversion from float to unsigned int may cause
01514     // compiler warnings, but static_cast does not.
01515     return static_cast<unsigned int> (t);
01516   }
01517 
01519   static unsigned int safeConvert (const float t) {
01520     const unsigned int minVal = 0; // Had better be, since it's unsigned.
01521     const unsigned int maxVal = std::numeric_limits<unsigned int>::max ();
01522 
01523     TEUCHOS_TEST_FOR_EXCEPTION(
01524       t < minVal || t > maxVal,
01525       std::range_error,
01526       "Teuchos::ValueTypeConversionTraits<unsigned int, float>::safeConvert: "
01527       "Input double t = " << t << " is out of the valid range [" << minVal
01528       << ", " << maxVal << "] for conversion to unsigned int.");
01529 
01530     return static_cast<unsigned int> (t);
01531   }
01532 };
01533 
01534 
01536 template<>
01537 class ValueTypeConversionTraits<long, float> {
01538 public:
01540   static long convert (const float t) {
01541     // Implicit conversion from float to long may cause compiler
01542     // warnings, but static_cast does not.  Overflow here would mean
01543     // that sizeof(long) < sizeof(float), which is legal, but unlikely
01544     // on platforms of longerest.
01545     return static_cast<long> (t);
01546   }
01547 
01549   static long safeConvert (const float t) {
01550     const long minVal = std::numeric_limits<long>::min ();
01551     const long maxVal = std::numeric_limits<long>::max ();
01552 
01553     // Cases:
01554     // 1. sizeof(long) < sizeof(float) == 4
01555     // 2. sizeof(long) == sizeof(float) == 4
01556     // 3. sizeof(long) > sizeof(float) == 4
01557     //
01558     // Overflow when converting from float to long is possible only
01559     // for Case 1.  Loss of accuracy (rounding) is possible for Cases
01560     // 2 and 3, but safeConvert() only cares about overflow, not
01561     // rounding.  Casting minVal or maxVal to double in Case 3 could
01562     // result in overflow.  Thus, we only do the cast for Case 1.
01563     //
01564     // I've never encountered a Case 1 platform (mfh 14 Nov 2012).
01565     // C99 actually forbids it, though I don't think a valid C++
01566     // compiler (for version C++03 of the language standard) needs to
01567     // implement C99 (mfh 14 Nov 2012).  Case 2 occurs in Win64
01568     // (64-bit Windows) and other implementations of (I32L32)LLP64.
01569     // Case 3 is common (e.g., in the (I32)LP64 integer model of
01570     // GNU/Linux and other operating systems).
01571     if (sizeof (long) < sizeof (float)) {
01572       TEUCHOS_TEST_FOR_EXCEPTION(
01573         t < minVal || t > maxVal,
01574         std::range_error,
01575         "Teuchos::ValueTypeConversionTraits<long, float>::safeConvert: "
01576         "Input float t = " << t << " is out of the valid range ["
01577         << minVal << ", " << maxVal << "] for conversion to long.");
01578     }
01579     return static_cast<long> (t);
01580   }
01581 };
01582 
01583 
01585 template<>
01586 class ValueTypeConversionTraits<unsigned long, float> {
01587 public:
01589   static unsigned long convert (const float t) {
01590     // Implicit conversion from float to unsigned long may cause
01591     // compiler warnings, but static_cast does not.
01592     return static_cast<unsigned long> (t);
01593   }
01594 
01596   static unsigned long safeConvert (const float t) {
01597     const unsigned long minVal = 0; // Had better be, since it's unsigned.
01598     const unsigned long maxVal = std::numeric_limits<unsigned long>::max ();
01599 
01600     TEUCHOS_TEST_FOR_EXCEPTION(
01601       t < minVal || t > maxVal,
01602       std::range_error,
01603       "Teuchos::ValueTypeConversionTraits<unsigned long, float>::safeConvert: "
01604       << "Input float t = " << t << " is out of the valid range [" << minVal
01605       << ", " << maxVal << "] for conversion to unsigned long.");
01606 
01607     return static_cast<unsigned long> (t);
01608   }
01609 };
01610 
01611 #ifdef HAVE_TEUCHOS_LONG_LONG_INT
01612 
01614 template<>
01615 class ValueTypeConversionTraits<long long, float> {
01616 public:
01618   static long long convert (const float t) {
01619     return static_cast<long long> (t);
01620   }
01621 
01623   static long long safeConvert (const float t) {
01624     // The C99 standard (Section 5.2.4.2.1) actually requires
01625     // sizeof(long long) >= 64, so overflow is impossible.
01626     return static_cast<long long> (t);
01627   }
01628 };
01629 
01630 
01632 template<>
01633 class ValueTypeConversionTraits<unsigned long long, float> {
01634 public:
01636   static unsigned long long convert (const float t) {
01637     return static_cast<unsigned long long> (t);
01638   }
01639 
01641   static unsigned long long safeConvert (const float t) {
01642     const unsigned long long minVal = 0; // unsigned, so min value is 0.
01643     const unsigned long long maxVal = std::numeric_limits<unsigned long long>::max ();
01644 
01645     TEUCHOS_TEST_FOR_EXCEPTION(
01646       t < minVal || t > maxVal,
01647       std::range_error,
01648       "Teuchos::ValueTypeConversionTraits<unsigned long long, float>::safeConvert: "
01649       "Input float t = " << t << " is out of the valid range [" << minVal
01650       << ", " << maxVal << "] for conversion to unsigned long long.");
01651 
01652     return static_cast<unsigned long long> (t);
01653   }
01654 };
01655 
01656 #endif // HAVE_TEUCHOS_LONG_LONG_INT
01657 
01658 //
01659 // * Specializations for conversions between a unsigned built-in
01660 //   integer type and the signed version of the same type (either
01661 //   direction).
01662 //
01663 
01664 namespace {
01665 // Implementation of conversion from an unsigned built-in integer
01666 // type, to an signed built-in integer type with the same number of
01667 // bits.
01668 template<class SignedIntType, class UnsignedIntType>
01669 class UnsignedToSignedValueTypeConversionTraits {
01670 public:
01678   static SignedIntType convert (const UnsignedIntType t) {
01679     // Implicit conversion may cause compiler warnings, but
01680     // static_cast does not.
01681     return static_cast<SignedIntType> (t);
01682   }
01683 
01685   static SignedIntType safeConvert (const UnsignedIntType t) {
01686     using Teuchos::TypeNameTraits;
01687     const SignedIntType maxSigned = std::numeric_limits<SignedIntType>::max ();
01688 
01689     // SignedIntType and UnsignedIntType have the same number of bits,
01690     // so it suffices (via two's complement arithmetic) to check
01691     // whether the cast turned a positive number negative.
01692     const SignedIntType signedVal = static_cast<SignedIntType> (t);
01693     TEUCHOS_TEST_FOR_EXCEPTION(
01694       signedVal < 0,
01695       std::range_error,
01696       "Teuchos::ValueTypeConversionTraits<" << TypeNameTraits<SignedIntType>::name ()
01697       << ", " << TypeNameTraits<UnsignedIntType>::name () << ">::safeConvert: "
01698       "Input " << TypeNameTraits<UnsignedIntType>::name () << " t = " << t
01699       << " is out of the valid range [0, " << ", " << maxSigned
01700       << "] for conversion to " << TypeNameTraits<SignedIntType>::name () << ".");
01701     return signedVal;
01702   }
01703 };
01704 
01705 
01706 // Implementation of conversion from a signed built-in integer type,
01707 // to an unsigned built-in integer type with the same number of bits.
01708 template<class UnsignedIntType, class SignedIntType>
01709 class SignedToUnsignedValueTypeConversionTraits {
01710 public:
01712   static UnsignedIntType convert (const SignedIntType t) {
01713     // Implicit conversion may cause compiler warnings, but
01714     // static_cast does not.
01715     return static_cast<UnsignedIntType> (t);
01716   }
01717 
01719   static UnsignedIntType safeConvert (const SignedIntType t) {
01720     using Teuchos::TypeNameTraits;
01721 
01722     // SignedIntType and UnsignedIntType have the same number of bits,
01723     // so it suffices (via two's complement arithmetic) to check
01724     // whether the input is negative.
01725     TEUCHOS_TEST_FOR_EXCEPTION(
01726       t < static_cast<SignedIntType> (0),
01727       std::range_error,
01728       "Teuchos::ValueTypeConversionTraits<" << TypeNameTraits<UnsignedIntType>::name ()
01729       << ", " << TypeNameTraits<SignedIntType>::name () << ">::safeConvert: "
01730       "Input " << TypeNameTraits<SignedIntType>::name () << " t = " << t
01731       << " is negative, so it cannot be correctly converted to the unsigned type "
01732       << TypeNameTraits<UnsignedIntType>::name () << ".");
01733 
01734     return static_cast<UnsignedIntType> (t);
01735   }
01736 };
01737 
01738 } // namespace (anonymous)
01739 
01740 
01742 template<>
01743 class ValueTypeConversionTraits<short, unsigned short> {
01744 public:
01745   static short convert (const unsigned short t) {
01746     return UnsignedToSignedValueTypeConversionTraits<short, unsigned short>::convert (t);
01747   }
01748 
01749   static short safeConvert (const unsigned short t) {
01750     return UnsignedToSignedValueTypeConversionTraits<short, unsigned short>::safeConvert (t);
01751   }
01752 };
01753 
01754 
01756 template<>
01757 class ValueTypeConversionTraits<unsigned short, short> {
01758 public:
01759   static unsigned short convert (const short t) {
01760     return SignedToUnsignedValueTypeConversionTraits<unsigned short, short>::convert (t);
01761   }
01762 
01763   static unsigned short safeConvert (const short t) {
01764     return SignedToUnsignedValueTypeConversionTraits<unsigned short, short>::safeConvert (t);
01765   }
01766 };
01767 
01768 
01770 template<>
01771 class ValueTypeConversionTraits<int, unsigned int> {
01772 public:
01773   static int convert (const unsigned int t) {
01774     return UnsignedToSignedValueTypeConversionTraits<int, unsigned int>::convert (t);
01775   }
01776 
01777   static int safeConvert (const unsigned int t) {
01778     return UnsignedToSignedValueTypeConversionTraits<int, unsigned int>::safeConvert (t);
01779   }
01780 };
01781 
01782 
01784 template<>
01785 class ValueTypeConversionTraits<unsigned int, int> {
01786 public:
01787   static unsigned int convert (const int t) {
01788     return SignedToUnsignedValueTypeConversionTraits<unsigned int, int>::convert (t);
01789   }
01790 
01791   static unsigned int safeConvert (const int t) {
01792     return SignedToUnsignedValueTypeConversionTraits<unsigned int, int>::safeConvert (t);
01793   }
01794 };
01795 
01796 
01798 template<>
01799 class ValueTypeConversionTraits<long, unsigned long> {
01800 public:
01801   static long convert (const unsigned long t) {
01802     return UnsignedToSignedValueTypeConversionTraits<long, unsigned long>::convert (t);
01803   }
01804 
01805   static long safeConvert (const unsigned long t) {
01806     return UnsignedToSignedValueTypeConversionTraits<long, unsigned long>::safeConvert (t);
01807   }
01808 };
01809 
01810 
01812 template<>
01813 class ValueTypeConversionTraits<unsigned long, long> {
01814 public:
01815   static unsigned long convert (const long t) {
01816     return SignedToUnsignedValueTypeConversionTraits<unsigned long, long>::convert (t);
01817   }
01818 
01819   static unsigned long safeConvert (const long t) {
01820     return SignedToUnsignedValueTypeConversionTraits<unsigned long, long>::safeConvert (t);
01821   }
01822 };
01823 
01824 
01825 #ifdef HAVE_TEUCHOS_LONG_LONG_INT
01826 
01828 template<>
01829 class ValueTypeConversionTraits<long long, unsigned long long> {
01830 public:
01831   static long long convert (const unsigned long long t) {
01832     return UnsignedToSignedValueTypeConversionTraits<long long, unsigned long long>::convert (t);
01833   }
01834 
01835   static long long safeConvert (const unsigned long long t) {
01836     return UnsignedToSignedValueTypeConversionTraits<long long, unsigned long long>::safeConvert (t);
01837   }
01838 };
01839 
01840 
01842 template<>
01843 class ValueTypeConversionTraits<unsigned long long, long long> {
01844 public:
01845   static unsigned long long convert (const long long t) {
01846     return SignedToUnsignedValueTypeConversionTraits<unsigned long long, long long>::convert (t);
01847   }
01848 
01849   static unsigned long long safeConvert (const long long t) {
01850     return SignedToUnsignedValueTypeConversionTraits<unsigned long long, long long>::safeConvert (t);
01851   }
01852 };
01853 
01854 #endif // HAVE_TEUCHOS_LONG_LONG_INT
01855 
01856 //
01857 // * Specializations for conversions between different built-in
01858 //   integer types.
01859 //
01860 
01862 template<>
01863 class ValueTypeConversionTraits<short, int> {
01864 public:
01870   static short convert (const int t) {
01871     // Implicit conversion may cause compiler warnings, but
01872     // static_cast does not.
01873     return static_cast<short> (t);
01874   }
01875 
01877   static short safeConvert (const int t) {
01878     const short minShort = std::numeric_limits<short>::min ();
01879     const short maxShort = std::numeric_limits<short>::max ();
01880 
01881     // Casting from short to int never overflows, since the C++
01882     // standard guarantees that sizeof (short) <= sizeof (int).
01883     TEUCHOS_TEST_FOR_EXCEPTION(
01884       t < static_cast<int> (minShort) ||
01885       t > static_cast<int> (maxShort),
01886       std::range_error,
01887       "Teuchos::ValueTypeConversionTraits<short, int>::safeConvert: "
01888       "Input int t = " << t << " is out of the valid range [" << minShort
01889       << ", " << maxShort << "] for conversion to short.");
01890 
01891     return static_cast<short> (t);
01892   }
01893 };
01894 
01895 
01897 template<>
01898 class ValueTypeConversionTraits<short, long> {
01899 public:
01905   static short convert (const long t) {
01906     // Implicit conversion may cause compiler warnings, but
01907     // static_cast does not.
01908     return static_cast<short> (t);
01909   }
01910 
01912   static short safeConvert (const long t) {
01913     const short minShort = std::numeric_limits<short>::min ();
01914     const short maxShort = std::numeric_limits<short>::max ();
01915 
01916     // Casting from short to long never overflows, since the C++
01917     // standard guarantees that sizeof (short) <= sizeof (long).
01918     TEUCHOS_TEST_FOR_EXCEPTION(
01919       t < static_cast<long> (minShort) ||
01920       t > static_cast<long> (maxShort),
01921       std::range_error,
01922       "Teuchos::ValueTypeConversionTraits<short, long>::safeConvert: "
01923       "Input long t = " << t << " is out of the valid range [" << minShort
01924       << ", " << maxShort << "] for conversion to short.");
01925 
01926     return static_cast<short> (t);
01927   }
01928 };
01929 
01930 
01932 template<>
01933 class ValueTypeConversionTraits<int, long> {
01934 public:
01940   static int convert (const long t) {
01941     // Implicit conversion from long to int may cause compiler
01942     // warnings, but static_cast does not.
01943     return static_cast<int> (t);
01944   }
01945 
01947   static int safeConvert (const long t) {
01948     const int minInt = std::numeric_limits<int>::min ();
01949     const int maxInt = std::numeric_limits<int>::max ();
01950 
01951     // Casting from int to long never overflows, since the C++
01952     // standard guarantees that sizeof (int) <= sizeof (long).
01953     TEUCHOS_TEST_FOR_EXCEPTION(
01954       t < static_cast<long> (minInt) ||
01955       t > static_cast<long> (maxInt),
01956       std::range_error,
01957       "Teuchos::ValueTypeConversionTraits<int, long>::safeConvert: "
01958       "Input long t = " << t << " is out of the valid range [" << minInt
01959       << ", " << maxInt << "] for conversion to int.");
01960 
01961     // Implicit conversion from long to int may cause compiler
01962     // warnings, but static_cast does not.
01963     return static_cast<int> (t);
01964   }
01965 };
01966 
01967 
01969 template<>
01970 class ValueTypeConversionTraits<int, unsigned long> {
01971 public:
01978   static int convert (const unsigned long t) {
01979     // Implicit conversion may cause compiler warnings, but
01980     // static_cast does not.
01981     return static_cast<int> (t);
01982   }
01983 
01985   static int safeConvert (const unsigned long t) {
01986     const int minInt = std::numeric_limits<int>::min ();
01987     const int maxInt = std::numeric_limits<int>::max ();
01988 
01989     // On some platforms, sizeof(int) == sizeof(long).  (This is the
01990     // "LLP64" model of Win64, which aims for backwards compatibility
01991     // with 32-bit code by making sizeof(int) == sizeof(long) == 4.)
01992     // If this is the case, then we can't safely cast unsigned long to
01993     // int, or unsigned int to long, because values with the most
01994     // significant bit set will overflow to negative values.
01995 
01996     // The C++ standard promises that sizeof (int) <= sizeof (unsigned
01997     // long).  We use #if with INT_MAX and LONG_MAX to test for this,
01998     // rather than if statements, in order to avoid a compiler
01999     // warning.  Thanks to Jeremie Gaidamour (13 Nov 2012) for letting
02000     // me know about the warning.
02001 #if INT_MAX == LONG_MAX
02002     // The two types have the same number of bits.  Thus,
02003     // two's-complement arithmetic means that if casting from unsigned
02004     // long to int results in a negative number, it overflowed.
02005     // Otherwise, it didn't overflow (same number of bits).
02006     TEUCHOS_TEST_FOR_EXCEPTION(
02007       static_cast<int> (t) < static_cast<int> (0),
02008       std::range_error,
02009       "Teuchos::ValueTypeConversionTraits<int, unsigned long>::safeConvert: "
02010       "Input unsigned long t = " << t << " is out of the valid range ["
02011       << minInt << ", " << maxInt << "] for conversion to int.");
02012 #else // INT_MAX < LONG_MAX
02013     // t is unsigned, so it is >= 0 by definition.
02014     // Casting from int to unsigned long won't overflow in this case.
02015     TEUCHOS_TEST_FOR_EXCEPTION(
02016       t > static_cast<unsigned long> (maxInt),
02017       std::range_error,
02018       "Teuchos::ValueTypeConversionTraits<int, unsigned long>::safeConvert: "
02019       "Input unsigned long t = " << t << " is out of the valid range ["
02020       << minInt << ", " << maxInt << "] for conversion to int.  An unchecked "
02021       "cast would have resulted in " << static_cast<int> (t) << ".");
02022 #endif // INT_MAX == LONG_MAX
02023 
02024     // Implicit conversion from unsigned long to int may cause
02025     // compiler warnings, but static_cast does not.
02026     return static_cast<int> (t);
02027   }
02028 };
02029 
02030 
02032 template<>
02033 class ValueTypeConversionTraits<long, unsigned int> {
02034 public:
02042   static long convert (const unsigned int t) {
02043     // Implicit conversion may cause compiler warnings, but
02044     // static_cast does not.
02045     return static_cast<long> (t);
02046   }
02047 
02049   static long safeConvert (const unsigned int t) {
02050     // On some platforms, sizeof(int) == sizeof(long).  (This is the
02051     // "LLP64" model of Win64, which aims for backwards compatibility
02052     // with 32-bit code by making sizeof(int) == sizeof(long) == 4.)
02053     // If this is the case, then we can't safely cast unsigned long to
02054     // int, or unsigned int to long, because values with the most
02055     // significant bit set will overflow to negative values.
02056 
02057     // The C++ standard promises that sizeof (unsigned int) <= sizeof
02058     // (long).  If strictly less, then the conversion won't overflow.
02059     // We protect the test with an #ifdef ... #endif to avoid compiler
02060     // warnings like the following: "warning: comparison is always
02061     // false due to limited range of data type".
02062 #if UINT_MAX == LONG_MAX
02063     const long minLong = std::numeric_limits<long>::min ();
02064     const long maxLong = std::numeric_limits<long>::max ();
02065 
02066     // The two types have the same number of bits.  Thus,
02067     // two's-complement arithmetic means that if casting from
02068     // unsigned int to long results in a negative number, it
02069     // overflowed.  Otherwise, it didn't overflow (same number of
02070     // bits).
02071     TEUCHOS_TEST_FOR_EXCEPTION(
02072       static_cast<long> (t) < static_cast<long> (0),
02073       std::range_error,
02074       "Teuchos::ValueTypeConversionTraits<long, unsigned int>::safeConvert: "
02075       "Input unsigned int t = " << t << " is out of the valid range ["
02076       << minLong << ", " << maxLong << "] for conversion to long.");
02077 #endif // UINT_MAX == LONG_MAX
02078 
02079     return static_cast<long> (t);
02080   }
02081 };
02082 
02083 
02085 template<>
02086 class ValueTypeConversionTraits<unsigned int, long> {
02087 public:
02094   static unsigned int convert (const long t) {
02095     // Implicit conversion from long to unsigned int may cause
02096     // compiler warnings, but static_cast does not.
02097     return static_cast<unsigned int> (t);
02098   }
02099 
02101   static unsigned int safeConvert (const long t) {
02102     // On some platforms, sizeof(int) == sizeof(long).  (This is the
02103     // "LLP64" model of Win64, which aims for backwards compatibility
02104     // with 32-bit code by making sizeof(int) == sizeof(long) == 4.)
02105     // In this case, conversion from long to unsigned int can't
02106     // overflow.
02107 
02108     // The C++ standard promises that sizeof (unsigned int) <= sizeof (long).
02109     if (sizeof (unsigned int) < sizeof (long)) {
02110       const unsigned int maxInt = std::numeric_limits<unsigned int>::max ();
02111 
02112       TEUCHOS_TEST_FOR_EXCEPTION(
02113         t < static_cast<long> (0) || t > static_cast<long> (maxInt),
02114         std::range_error,
02115         "Teuchos::ValueTypeConversionTraits<unsigned int, long>::safeConvert: "
02116         "Input long t = " << t << " is out of the valid range [0, "
02117         << maxInt << "] for conversion to unsigned int.");
02118     }
02119     // Implicit conversion from long to unsigned int may cause
02120     // compiler warnings, but static_cast does not.
02121     return static_cast<unsigned int> (t);
02122   }
02123 };
02124 
02125 
02127 template<>
02128 class ValueTypeConversionTraits<unsigned int, unsigned long> {
02129 public:
02136   static unsigned int convert (const unsigned long t) {
02137     // Implicit conversion from unsigned long to unsigned int may cause
02138     // compiler warnings, but static_cast does not.
02139     return static_cast<unsigned int> (t);
02140   }
02141 
02143   static unsigned int safeConvert (const unsigned long t) {
02144     const unsigned int minInt = 0; // Had better be, since it's unsigned.
02145     const unsigned int maxInt = std::numeric_limits<unsigned int>::max ();
02146 
02147     // t >= 0 by definition, because it is unsigned.
02148     TEUCHOS_TEST_FOR_EXCEPTION(
02149       t > static_cast<unsigned long> (maxInt),
02150       std::range_error,
02151       "Teuchos::ValueTypeConversionTraits<unsigned int, unsigned long>::safeConvert: "
02152       "Input unsigned long t = " << t << " is out of the valid range [" << minInt
02153       << ", " << maxInt << "] for conversion to unsigned int.");
02154 
02155     // Implicit conversion from unsigned long to unsigned int may
02156     // cause compiler warnings, but static_cast does not.
02157     return static_cast<unsigned int> (t);
02158   }
02159 };
02160 
02162 template<>
02163 class ValueTypeConversionTraits<unsigned short, unsigned long> {
02164 public:
02171   static unsigned short convert (const unsigned long t) {
02172     // Implicit conversion from unsigned long to unsigned short may cause
02173     // compiler warnings, but static_cast does not.
02174     return static_cast<unsigned short> (t);
02175   }
02176 
02178   static unsigned short safeConvert (const unsigned long t) {
02179     const unsigned short minShort = 0; // Had better be, since it's unsigned.
02180     const unsigned short maxShort = std::numeric_limits<unsigned short>::max ();
02181 
02182     // t >= 0 by definition, because it is unsigned.
02183     TEUCHOS_TEST_FOR_EXCEPTION(
02184       t > static_cast<unsigned long> (maxShort),
02185       std::range_error,
02186       "Teuchos::ValueTypeConversionTraits<unsigned short, unsigned long>::safeConvert: "
02187       "Input unsigned long t = " << t << " is out of the valid range [" << minShort
02188       << ", " << maxShort << "] for conversion to unsigned short.");
02189 
02190     // Implicit conversion from unsigned long to unsigned short may
02191     // cause compiler warnings, but static_cast does not.
02192     return static_cast<unsigned short> (t);
02193   }
02194 };
02195 
02196 #ifdef HAVE_TEUCHOS_LONG_LONG_INT
02197 
02199 template<>
02200 class ValueTypeConversionTraits<int, long long> {
02201 public:
02207   static int convert (const long long t) {
02208     // Implicit conversion from long long to int may cause compiler
02209     // warnings, but static_cast does not.
02210     return static_cast<int> (t);
02211   }
02212 
02214   static int safeConvert (const long long t) {
02215     const int minInt = std::numeric_limits<int>::min ();
02216     const int maxInt = std::numeric_limits<int>::max ();
02217 
02218     TEUCHOS_TEST_FOR_EXCEPTION(
02219       t < static_cast<long long> (minInt) ||
02220       t > static_cast<long long> (maxInt),
02221       std::range_error,
02222       "Teuchos::ValueTypeConversionTraits<int, long long>::safeConvert: "
02223       "Input long long t = " << t << " is out of the valid range [" << minInt
02224       << ", " << maxInt << "] for conversion to int.");
02225 
02226     // Implicit conversion from long long to int may cause compiler
02227     // warnings, but static_cast does not.
02228     return static_cast<int> (t);
02229   }
02230 };
02231 
02232 
02234 template<>
02235 class ValueTypeConversionTraits<unsigned int, long long> {
02236 public:
02243   static unsigned int convert (const long long t) {
02244     // Implicit conversion from long long to unsigned int may cause
02245     // compiler warnings, but static_cast does not.
02246     return static_cast<unsigned int> (t);
02247   }
02248 
02250   static unsigned int safeConvert (const long long t) {
02251     const unsigned int minInt = 0; // Had better be, because it's unsigned.
02252     const unsigned int maxInt = std::numeric_limits<unsigned int>::max ();
02253 
02254     TEUCHOS_TEST_FOR_EXCEPTION(
02255       t < static_cast<long long> (minInt) || t > static_cast<long long> (maxInt),
02256       std::range_error,
02257       "Teuchos::ValueTypeConversionTraits<unsigned int, long long>::safeConvert: "
02258       "Input long long t = " << t << " is out of the valid range [" << minInt
02259       << ", " << maxInt << "] for conversion to unsigned int.");
02260 
02261     // Implicit conversion from long long to unsigned int may cause
02262     // compiler warnings, but static_cast does not.
02263     return static_cast<unsigned int> (t);
02264   }
02265 };
02266 
02267 
02269 template<>
02270 class ValueTypeConversionTraits<int, unsigned long long> {
02271 public:
02277   static int convert (const unsigned long long t) {
02278     // Implicit conversion from unsigned long long to int may cause
02279     // compiler warnings, but static_cast does not.
02280     return static_cast<int> (t);
02281   }
02282 
02284   static int safeConvert (const unsigned long long t) {
02285     const int minInt = std::numeric_limits<int>::min ();
02286     const int maxInt = std::numeric_limits<int>::max ();
02287 
02288     // t >= 0 by definition, because it is unsigned.
02289     TEUCHOS_TEST_FOR_EXCEPTION(
02290       t > static_cast<unsigned long long> (maxInt),
02291       std::invalid_argument,
02292       "Teuchos::ValueTypeConversionTraits<int, unsigned long long>::safeConvert: "
02293       "Input unsigned long long t = " << t << " is out of the valid range [" << minInt
02294       << ", " << maxInt << "] for conversion to int.");
02295 
02296     // Implicit conversion from unsigned long long to int may cause
02297     // compiler warnings, but static_cast does not.
02298     return static_cast<int> (t);
02299   }
02300 };
02301 
02302 
02304 template<>
02305 class ValueTypeConversionTraits<unsigned int, unsigned long long> {
02306 public:
02313   static unsigned int convert (const unsigned long long t) {
02314     // Implicit conversion from unsigned long long to unsigned int may
02315     // cause compiler warnings, but static_cast does not.
02316     return static_cast<unsigned int> (t);
02317   }
02318 
02320   static unsigned int safeConvert (const unsigned long long t) {
02321     const unsigned int minInt = 0; // Had better be, since it's unsigned.
02322     const unsigned int maxInt = std::numeric_limits<unsigned int>::max ();
02323 
02324     // t >= 0 by definition, because it is unsigned.
02325     TEUCHOS_TEST_FOR_EXCEPTION(
02326       t > static_cast<unsigned long long> (maxInt),
02327       std::invalid_argument,
02328       "Teuchos::ValueTypeConversionTraits<unsigned int, unsigned long long>::safeConvert: "
02329       "Input unsigned long long t = " << t << " is out of the valid range [" << minInt
02330       << ", " << maxInt << "] for conversion to unsigned int.");
02331 
02332     // Implicit conversion from unsigned long long to unsigned int may
02333     // cause compiler warnings, but static_cast does not.
02334     return static_cast<unsigned int> (t);
02335   }
02336 };
02337 
02338 #endif // HAVE_TEUCHOS_LONG_LONG_INT
02339 
02340 //
02341 // * Conversions from built-in integer types to built-in real-valued
02342 //   floating-point types.
02343 //
02344 
02345 #ifdef HAVE_TEUCHOS_LONG_LONG_INT
02346 
02348 template<>
02349 class ValueTypeConversionTraits<float, long long> {
02350 public:
02356   static float convert (const long long t) {
02357     // Implicit conversion from long long to float may cause compiler
02358     // warnings, but static_cast does not.
02359     return static_cast<float> (t);
02360   }
02361 
02363   static float safeConvert (const long long t) {
02364     // std::numeric_limits<float>::min() gives the minimum _positive_
02365     // normalized value of type float.  IEEE 754 floating-point values
02366     // can change sign just by flipping the sign bit, so the "most
02367     // negative" finite float is just the negative of the "most
02368     // positive" finite float.
02369     const float minFloat = -std::numeric_limits<float>::max ();
02370     const float maxFloat = std::numeric_limits<float>::max ();
02371 
02372     // mfh 16 Nov 2012: On my platform (gcc 4.7.2, Red Hat Linux 5,
02373     // Intel x86_64), first casting [minFloat,maxFloat] to long long
02374     // (so that the comparison only compares long long values)
02375     // gives different results in the comparison below than just
02376     // comparing t (as a long long) with minFloat and maxFloat.  It
02377     // doesn't matter whether you use static_cast<long long> (...) or
02378     // (long long) (...) to do the cast: the original float interval
02379     // of [-3.40282e+38, 3.40282e+38] becomes [-9223372036854775808,
02380     // -9223372036854775808], which is obviously wrong.
02381     TEUCHOS_TEST_FOR_EXCEPTION(
02382       t < minFloat || t > maxFloat,
02383       std::range_error,
02384       "Teuchos::ValueTypeConversionTraits<float, long long>::safeConvert: "
02385       "Input long long t = " << t << " is out of the valid range [" << minFloat
02386       << ", " << maxFloat << "] for conversion to float.");
02387 
02388     // Implicit conversion from long long to float may cause compiler
02389     // warnings, but static_cast does not.
02390     return static_cast<float> (t);
02391   }
02392 };
02393 
02394 
02396 template<>
02397 class ValueTypeConversionTraits<float, unsigned long long> {
02398 public:
02404   static float convert (const unsigned long long t) {
02405     // Implicit conversion from unsigned long long to float may cause
02406     // compiler warnings, but static_cast does not.
02407     return static_cast<float> (t);
02408   }
02409 
02411   static float safeConvert (const unsigned long long t) {
02412     // std::numeric_limits<float>::min() gives the minimum _positive_
02413     // normalized value of type float.  IEEE 754 floating-point values
02414     // can change sign just by flipping the sign bit, so the "most
02415     // negative" finite float is just the negative of the "most
02416     // positive" finite float.
02417     const float minFloat = -std::numeric_limits<float>::max ();
02418     const float maxFloat = std::numeric_limits<float>::max ();
02419 
02420     // t >= 0 by definition, because it is unsigned.
02421     //
02422     // mfh 16 Nov 2012: See my note above on the <float, long long>
02423     // specialization that explains why I don't cast maxFloat to
02424     // unsigned long long here.
02425     TEUCHOS_TEST_FOR_EXCEPTION(
02426       t > maxFloat,
02427       std::invalid_argument,
02428       "Teuchos::ValueTypeConversionTraits<float, unsigned long long>::safeConvert: "
02429       "Input unsigned long long t = " << t << " is out of the valid range [" << minFloat
02430       << ", " << maxFloat << "] for conversion to float.");
02431 
02432     // Implicit conversion from unsigned long long to float may cause
02433     // compiler warnings, but static_cast does not.
02434     return static_cast<float> (t);
02435   }
02436 };
02437 
02438 #endif // HAVE_TEUCHOS_LONG_LONG_INT
02439 
02440 //
02441 // * Other conversions
02442 //
02443 
02445 template<int N>
02446 class ValueTypeConversionTraits<std::string, char[N]> {
02447 public:
02448   static std::string convert( const char t[] )
02449     { return std::string(t); }
02450   static std::string safeConvert( const char t[] )
02451     { return std::string(t); }
02452 };
02453 
02454 //
02455 // * Conversions from built-in integer types to std::complex<T>.
02456 //
02457 
02458 #ifdef HAVE_TEUCHOS_COMPLEX
02459 
02461 template<class RealType>
02462 class ValueTypeConversionTraits<std::complex<RealType>, short> {
02463 public:
02464   inline static std::complex<RealType> convert (const short t) {
02465     // Let RealType handle the conversion of the zero imaginary part.
02466     return std::complex<RealType> (t, as<RealType> (0));
02467   }
02468   static std::complex<RealType> safeConvert (const short t) {
02469     // Let RealType handle the conversion of the zero imaginary part.
02470     return std::complex<RealType> (t, asSafe<RealType> (0));
02471   }
02472 };
02473 
02475 template<class RealType>
02476 class ValueTypeConversionTraits<std::complex<RealType>, unsigned short> {
02477 public:
02478   inline static std::complex<RealType> convert (const unsigned short t) {
02479     // Let RealType handle the conversion of the zero imaginary part.
02480     return std::complex<RealType> (t, as<RealType> (0));
02481   }
02482   static std::complex<RealType> safeConvert (const unsigned short t) {
02483     // Let RealType handle the conversion of the zero imaginary part.
02484     return std::complex<RealType> (t, asSafe<RealType> (0));
02485   }
02486 };
02487 
02489 template<class RealType>
02490 class ValueTypeConversionTraits<std::complex<RealType>, int> {
02491 public:
02492   inline static std::complex<RealType> convert (const int t) {
02493     // Let RealType handle the conversion of the zero imaginary part.
02494     return std::complex<RealType> (t, as<RealType> (0));
02495   }
02496   static std::complex<RealType> safeConvert (const int t) {
02497     // Let RealType handle the conversion of the zero imaginary part.
02498     return std::complex<RealType> (t, asSafe<RealType> (0));
02499   }
02500 };
02501 
02503 template<class RealType>
02504 class ValueTypeConversionTraits<std::complex<RealType>, unsigned int> {
02505 public:
02506   inline static std::complex<RealType> convert (const unsigned int t) {
02507     // Let RealType handle the conversion of the zero imaginary part.
02508     return std::complex<RealType> (t, as<RealType> (0));
02509   }
02510   static std::complex<RealType> safeConvert (const unsigned int t) {
02511     // Let RealType handle the conversion of the zero imaginary part.
02512     return std::complex<RealType> (t, asSafe<RealType> (0));
02513   }
02514 };
02515 
02517 template<class RealType>
02518 class ValueTypeConversionTraits<std::complex<RealType>, long> {
02519 public:
02520   inline static std::complex<RealType> convert (const long t) {
02521     // Let RealType handle the conversion of the zero imaginary part.
02522     return std::complex<RealType> (t, as<RealType> (0));
02523   }
02524   static std::complex<RealType> safeConvert (const long t) {
02525     // Let RealType handle the conversion of the zero imaginary part.
02526     return std::complex<RealType> (t, asSafe<RealType> (0));
02527   }
02528 };
02529 
02531 template<class RealType>
02532 class ValueTypeConversionTraits<std::complex<RealType>, unsigned long> {
02533 public:
02534   inline static std::complex<RealType> convert (const unsigned long t) {
02535     // Let RealType handle the conversion of the zero imaginary part.
02536     return std::complex<RealType> (t, as<RealType> (0));
02537   }
02538   static std::complex<RealType> safeConvert (const unsigned long t) {
02539     // Let RealType handle the conversion of the zero imaginary part.
02540     return std::complex<RealType> (t, asSafe<RealType> (0));
02541   }
02542 };
02543 
02544 #ifdef HAVE_TEUCHOS_LONG_LONG_INT
02545 
02547 template<class RealType>
02548 class ValueTypeConversionTraits<std::complex<RealType>, long long> {
02549 public:
02550   inline static std::complex<RealType> convert (const long long t) {
02551     // Let RealType handle the conversion of the zero imaginary part.
02552     return std::complex<RealType> (t, as<RealType> (0));
02553   }
02554   static std::complex<RealType> safeConvert (const long long t) {
02555     // Let RealType handle the conversion of the zero imaginary part.
02556     return std::complex<RealType> (t, asSafe<RealType> (0));
02557   }
02558 };
02559 
02561 template<class RealType>
02562 class ValueTypeConversionTraits<std::complex<RealType>, unsigned long long> {
02563 public:
02564   inline static std::complex<RealType> convert (const unsigned long long t) {
02565     // Let RealType handle the conversion of the zero imaginary part.
02566     return std::complex<RealType> (t, as<RealType> (0));
02567   }
02568   static std::complex<RealType> safeConvert (const unsigned long long t) {
02569     // Let RealType handle the conversion of the zero imaginary part.
02570     return std::complex<RealType> (t, asSafe<RealType> (0));
02571   }
02572 };
02573 
02574 #endif // HAVE_TEUCHOS_LONG_LONG_INT
02575 #endif // HAVE_TEUCHOS_COMPLEX
02576 
02577 //
02578 // * Conversions for dd_real and qd_real
02579 //
02580 
02581 #ifdef HAVE_TEUCHOS_QD
02582 
02584 template <>
02585 class ValueTypeConversionTraits<double, qd_real> {
02586 public:
02587   inline static double convert (const qd_real t) {
02588     return to_double (t);
02589   }
02590   static double safeConvert (const qd_real t) {
02591     // std::numeric_limits<double>::min() gives the minimum _positive_
02592     // normalized value of type double.  IEEE 754 floating-point
02593     // values can change sign just by flipping the sign bit, so the
02594     // "most negative" finite double is just the negative of the "most
02595     // positive" finite double.
02596     const qd_real minVal = -std::numeric_limits<double>::max ();
02597     const qd_real maxVal = std::numeric_limits<double>::max ();
02598 
02599     TEUCHOS_TEST_FOR_EXCEPTION(
02600       t < minVal || t > maxVal,
02601       std::range_error,
02602       "Teuchos::ValueTypeConversionTraits<double, qd_real>::safeConvert: "
02603       "Input qd_real t = " << t << " is out of the valid range [" << minVal
02604       << ", " << maxVal << "] for conversion to double.");
02605 
02606     return to_double (t);
02607   }
02608 };
02609 
02611 template <>
02612 class ValueTypeConversionTraits<float, qd_real> {
02613 public:
02614   inline static float convert (const qd_real t) {
02615     // In a debug build, this should also test the double->float
02616     // conversion for overflow.
02617     return as<float> (to_double (t));
02618   }
02619 
02620   static float safeConvert (const qd_real t) {
02621     // std::numeric_limits<float>::min() gives the minimum _positive_
02622     // normalized value of type float.  IEEE 754 floating-point
02623     // values can change sign just by flipping the sign bit, so the
02624     // "most negative" finite float is just the negative of the "most
02625     // positive" finite float.
02626     //
02627     // qd_real has a constructor for double, but not for float,
02628     // so we cast to double first.
02629     const qd_real minVal = static_cast<double> (-std::numeric_limits<float>::max ());
02630     const qd_real maxVal = static_cast<double> (std::numeric_limits<float>::max ());
02631 
02632     TEUCHOS_TEST_FOR_EXCEPTION(
02633       t < minVal || t > maxVal,
02634       std::range_error,
02635       "Teuchos::ValueTypeConversionTraits<float, qd_real>::safeConvert: "
02636       "Input qd_real t = " << t << " is out of the valid range [" << minVal
02637       << ", " << maxVal << "] for conversion to float.");
02638 
02639     // This should also test the double->float conversion for overflow.
02640     return asSafe<float> (to_double (t));
02641   }
02642 };
02643 
02645 template <>
02646 class ValueTypeConversionTraits<int, qd_real> {
02647 public:
02648   inline static int convert (const qd_real t) {
02649     return to_int (t);
02650   }
02651   static int safeConvert (const qd_real t) {
02652     // qd_real has a constructor for int.
02653     const qd_real minVal = std::numeric_limits<int>::min ();
02654     const qd_real maxVal = std::numeric_limits<int>::max ();
02655 
02656     TEUCHOS_TEST_FOR_EXCEPTION(
02657       t < minVal || t > maxVal,
02658       std::range_error,
02659       "Teuchos::ValueTypeConversionTraits<int, qd_real>::safeConvert: "
02660       "Input qd_real t = " << t << " is out of the valid range [" << minVal
02661       << ", " << maxVal << "] for conversion to int.");
02662     return to_int (t);
02663   }
02664 };
02665 
02667 template <>
02668 class ValueTypeConversionTraits<dd_real, qd_real> {
02669 public:
02670   inline static dd_real convert (const qd_real t) {
02671     return to_dd_real(t);
02672   }
02673   static dd_real safeConvert (const qd_real t) {
02674     // std::numeric_limits<dd_real>::min() gives the minimum
02675     // _positive_ (normalized? not sure what this means for dd_real --
02676     // mfh 14 Nov 2012) value of type dd_real.  dd_real values are
02677     // built from two IEEE 754 doubles.  This means they can change
02678     // sign just by flipping the sign bit, so the "most negative"
02679     // finite dd_real is just the negative of the "most positive"
02680     // finite dd_real.
02681     //
02682     // qd_real has a constructor for dd_real.
02683     const qd_real minVal = -std::numeric_limits<dd_real>::max ();
02684     const qd_real maxVal = std::numeric_limits<dd_real>::max ();
02685 
02686     TEUCHOS_TEST_FOR_EXCEPTION(
02687       t < minVal || t > maxVal,
02688       std::range_error,
02689       "Teuchos::ValueTypeConversionTraits<dd_real, qd_real>::safeConvert: "
02690       "Input qd_real t = " << t << " is out of the valid range [" << minVal
02691       << ", " << maxVal << "] for conversion to dd_real.");
02692 
02693     return to_dd_real (t);
02694   }
02695 };
02696 
02698 template <>
02699 class ValueTypeConversionTraits<double, dd_real> {
02700 public:
02701   inline static double convert (const dd_real t) {
02702     return to_double (t);
02703   }
02704   static double safeConvert (const dd_real t) {
02705     // std::numeric_limits<double>::min() gives the minimum _positive_
02706     // normalized value of type double.  IEEE 754 floating-point
02707     // values can change sign just by flipping the sign bit, so the
02708     // "most negative" finite double is just the negative of the "most
02709     // positive" finite double.
02710     //
02711     // qd_real has a constructor for double.
02712     const dd_real minVal = -std::numeric_limits<double>::max ();
02713     const dd_real maxVal = std::numeric_limits<double>::max ();
02714 
02715     TEUCHOS_TEST_FOR_EXCEPTION(
02716       t < minVal || t > maxVal,
02717       std::range_error,
02718       "Teuchos::ValueTypeConversionTraits<double, dd_real>::safeConvert: "
02719       "Input dd_real t = " << t << " is out of the valid range [" << minVal
02720       << ", " << maxVal << "] for conversion to double.");
02721 
02722     return to_double (t);
02723   }
02724 };
02725 
02727 template <>
02728 class ValueTypeConversionTraits<float, dd_real> {
02729 public:
02730   inline static float convert (const dd_real t) {
02731     // This also checks for double->float overflow in a debug build.
02732     return as<float> (to_double (t));
02733   }
02734   static float safeConvert (const dd_real t) {
02735     // std::numeric_limits<float>::min() gives the minimum _positive_
02736     // normalized value of type float.  IEEE 754 floating-point
02737     // values can change sign just by flipping the sign bit, so the
02738     // "most negative" finite float is just the negative of the "most
02739     // positive" finite float.
02740     //
02741     // dd_real has a constructor for double but not for float,
02742     // so we cast to double first.
02743     const dd_real minVal = static_cast<double> (-std::numeric_limits<float>::max ());
02744     const dd_real maxVal = static_cast<double> (std::numeric_limits<float>::max ());
02745 
02746     TEUCHOS_TEST_FOR_EXCEPTION(
02747       t < minVal || t > maxVal,
02748       std::range_error,
02749       "Teuchos::ValueTypeConversionTraits<float, dd_real>::safeConvert: "
02750       "Input dd_real t = " << t << " is out of the valid range [" << minVal
02751       << ", " << maxVal << "] for conversion to float.");
02752 
02753     // This also checks for double->float overflow.
02754     return as<float> (to_double (t));
02755   }
02756 };
02757 
02759 template <>
02760 class ValueTypeConversionTraits<int, dd_real> {
02761 public:
02762   inline static int convert (const dd_real t) {
02763     return to_int (t);
02764   }
02765   static int safeConvert (const dd_real t) {
02766     // dd_real has a constructor for int.
02767     const dd_real minVal = std::numeric_limits<int>::min ();
02768     const dd_real maxVal = std::numeric_limits<int>::max ();
02769 
02770     TEUCHOS_TEST_FOR_EXCEPTION(
02771       t < minVal || t > maxVal,
02772       std::range_error,
02773       "Teuchos::ValueTypeConversionTraits<int, dd_real>::safeConvert: "
02774       "Input dd_real t = " << t << " is out of the valid range [" << minVal
02775       << ", " << maxVal << "] for conversion to int.");
02776     return to_int (t);
02777   }
02778 };
02779 
02781 template <>
02782 class ValueTypeConversionTraits<qd_real, long unsigned int> {
02783 public:
02784   inline static qd_real convert( const long unsigned int t ) {
02785     // FIXME (mfh 14 Nov 2012): qd_real unfortunately lacks a
02786     // constructor or conversion function for conversions from
02787     // built-in integer types other than int.  However, it does allow
02788     // reading in values from a string.  We could use this to convert
02789     // from any type to qd_real, by first writing the value to an
02790     // std::ostringstream, then creating a qd_real from the resulting
02791     // string.
02792     return ValueTypeConversionTraits<qd_real,int>::convert(ValueTypeConversionTraits<int,long unsigned int>::convert(t));
02793   }
02794   inline static qd_real safeConvert( const long unsigned int t )
02795     { return ValueTypeConversionTraits<qd_real,int>::safeConvert(ValueTypeConversionTraits<int,long unsigned int>::safeConvert(t)); }
02796 };
02797 
02799 template <>
02800 class ValueTypeConversionTraits<dd_real, long unsigned int> {
02801 public:
02802   inline static dd_real convert( const long unsigned int t ) {
02803     // FIXME (mfh 14 Nov 2012): dd_real unfortunately lacks a
02804     // constructor or conversion function for conversions from
02805     // built-in integer types other than int.  However, it does allow
02806     // reading in values from a string.  We could use this to convert
02807     // from any type to dd_real, by first writing the value to an
02808     // std::ostringstream, then creating a dd_real from the resulting
02809     // string.
02810     return ValueTypeConversionTraits<dd_real,int>::convert(ValueTypeConversionTraits<int,long unsigned int>::convert(t));
02811   }
02812   inline static dd_real safeConvert( const long unsigned int t )
02813     { return ValueTypeConversionTraits<dd_real,int>::safeConvert(ValueTypeConversionTraits<int,long unsigned int>::safeConvert(t)); }
02814 };
02815 
02816 #endif // HAVE_TEUCHOS_QD
02817 
02818 // ToDo: Add more specializations as needed!
02819 
02820 template<class TypeTo, class TypeFrom>
02821 inline TypeTo as( const TypeFrom& t )
02822 {
02823 #ifdef HAVE_TEUCHOS_DEBUG
02824   return ValueTypeConversionTraits<TypeTo,TypeFrom>::safeConvert(t);
02825 #else
02826   return ValueTypeConversionTraits<TypeTo,TypeFrom>::convert(t);
02827 #endif // HAVE_TEUCHOS_DEBUG
02828 }
02829 
02830 template<class TypeTo, class TypeFrom>
02831 inline TypeTo asSafe( const TypeFrom& t )
02832 {
02833   return ValueTypeConversionTraits<TypeTo,TypeFrom>::safeConvert(t);
02834 }
02835 
02836 } // end namespace Teuchos
02837 
02838 
02839 #endif // TEUCHOS_AS_HPP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines