Teuchos Package Browser (Single Doxygen Collection) 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 #ifdef HAVE_TEUCHOS_DEBUG
00290   return ValueTypeConversionTraits<TypeTo,TypeFrom>::safeConvert(t);
00291 #else
00292   return ValueTypeConversionTraits<TypeTo,TypeFrom>::convert(t);
00293 #endif // HAVE_TEUCHOS_DEBUG
00294 }
00295 
00296 
00362 template<class TypeTo, class TypeFrom>
00363 inline TypeTo asSafe( const TypeFrom& t )
00364 {
00365   return ValueTypeConversionTraits<TypeTo,TypeFrom>::safeConvert(t);
00366 }
00367 
00368 
00381 template <class TypeTo>
00382 class asFunc {
00383 public:
00384   asFunc() {}
00385 
00386   template <class TypeFrom>
00387   inline TypeTo operator()(const TypeFrom &t) {
00388     return as<TypeTo>(t);
00389   }
00390 };
00391 
00392 
00393 
00394 namespace { // anonymous
00395 
00413   template<class IntType>
00414   IntType
00415   intToString (const std::string& t,
00416                IntType (*rawConvert) (const char*, char**, int),
00417                const char* intTypeName)
00418   {
00419     // We call the "raw" conversion function instead of using
00420     // std::istringstream, because we want more detailed information
00421     // in case of failure to convert.  I have no idea what
00422     // operator>>(std::istream&, unsigned long long&) does if it
00423     // encounters an integer too long to fit in IntType, for example.
00424     //
00425     // mfh 13 Nov 2012: It's fair to assume that if you have "long
00426     // long", then your implementation of the C standard library
00427     // includes strtoul().  Ditto for "unsigned long long" and
00428     // strtoull().  If this is not the case, we could include a
00429     // configure-time test for these functions(), with a fall-back to
00430     // an std::istringstream operator>> implementation.
00431     char* endptr = NULL;
00432     // Keep the pointer, because std::string doesn't necessarily
00433     // guarantee that this is the same across calls to c_str(), does
00434     // it?  Or perhaps it does...
00435     const char* t_ptr = t.c_str ();
00436     // We preset errno to 0, to distinguish success or failure after
00437     // calling strtoull.  Most implementations of the C standard
00438     // library written with threads in mind have errno be a macro that
00439     // expands to thread-local storage.  Thanks to the Linux
00440     // documentation for strtol ("man 3 strtol", Red Hat Enterprise
00441     // Linux 5) for advice with the following checks.
00442     errno = 0;
00443     const IntType val = rawConvert (t_ptr, &endptr, 10);
00444 
00445     const IntType minVal = std::numeric_limits<IntType>::min ();
00446     const IntType maxVal = std::numeric_limits<IntType>::max ();
00447     TEUCHOS_TEST_FOR_EXCEPTION(
00448       errno == ERANGE && (val == minVal || val == maxVal),
00449       std::range_error,
00450       "Teuchos::ValueTypeConversionTraits<" << intTypeName << ", std::string>::convert: "
00451       "The integer value in the given string \"" << t << "\" overflows " << intTypeName << ".");
00452     TEUCHOS_TEST_FOR_EXCEPTION(
00453       errno != 0 && val == 0,
00454       std::invalid_argument,
00455       "Teuchos::ValueTypeConversionTraits<" << intTypeName << ", std::string>::convert: "
00456       "The conversion function was unable to convert the given string \"" << t << "\" to " << intTypeName << ".");
00457     TEUCHOS_TEST_FOR_EXCEPTION(
00458       endptr == t_ptr, // See above discussion of c_str().
00459       std::invalid_argument,
00460       "Teuchos::ValueTypeConversionTraits<" << intTypeName << ", std::string>::convert: "
00461       "The conversion function was unable to read any integer digits from the given string "
00462       "\"" << t << "\".");
00463     return val;
00464   }
00465 
00477   template<class OutputRealType, class InputRealType>
00478   OutputRealType
00479   realToReal (const InputRealType& x, const bool doBoundsChecking)
00480   {
00481     using Teuchos::TypeNameTraits;
00482 
00483     if (doBoundsChecking) {
00484       // For floating-point types T, std::numeric_limits<T>::min()
00485       // returns the smallest positive value.  IEEE 754 types have a
00486       // sign bit, so the largest-magnitude negative value is the
00487       // negative of the largest-magnitude positive value.
00488       const OutputRealType minVal = -std::numeric_limits<OutputRealType>::max ();
00489       const OutputRealType maxVal = std::numeric_limits<OutputRealType>::max ();
00490 
00491       // NaN is neither less than nor greater than anything.  We just
00492       // let it pass through, per the rules for propagation of silent
00493       // NaN.  (Signaling NaN will signal, but that's OK.)
00494       TEUCHOS_TEST_FOR_EXCEPTION(
00495         x < minVal || x > maxVal,
00496         std::range_error,
00497         "realToReal<" << TypeNameTraits<OutputRealType>::name () << ", "
00498         << TypeNameTraits<InputRealType>::name () << ">: "
00499         "Input value x = " << x << " is out of the valid range [" << minVal
00500         << ", " << maxVal << "] for conversion to the output type.");
00501     }
00502 
00503     // Call as() and not static_cast, because there might not
00504     // necessarily be a conversion defined between the two types,
00505     // other than via as().  Definitely don't call asSafe(), because
00506     // that could cause infinite recursion.
00507     return as<OutputRealType> (x);
00508   }
00509 
00510 
00535   template<class RealType>
00536   RealType
00537   stringToReal (const std::string& t,
00538                RealType (*rawConvert) (const char*, char**),
00539                const char* realTypeName)
00540   {
00541     if (rawConvert == NULL) {
00542       std::istringstream in (t);
00543       RealType out;
00544       in >> out;
00545       return out;
00546     }
00547     else {
00548       char* endptr = NULL;
00549       // Keep the pointer, because std::string doesn't necessarily
00550       // guarantee that this is the same across calls to c_str(), does
00551       // it?  Or perhaps it does...
00552       const char* t_ptr = t.c_str ();
00553       // We preset errno to 0, to distinguish success or failure after
00554       // calling strtoull.  Most implementations of the C standard
00555       // library written with threads in mind have errno be a macro that
00556       // expands to thread-local storage.  Thanks to the Linux
00557       // documentation for strtod ("man 3 strtod", Red Hat Enterprise
00558       // Linux 5) for advice with the following checks.
00559       errno = 0;
00560       const RealType val = rawConvert (t_ptr, &endptr);
00561 
00562       TEUCHOS_TEST_FOR_EXCEPTION(
00563         errno == ERANGE && (val != 0),
00564         std::range_error,
00565         "Teuchos::ValueTypeConversionTraits<" << realTypeName
00566         << ", std::string>::convert: "
00567         "The value in the given string \"" << t << "\" overflows "
00568         << realTypeName << ".");
00569       //
00570       // mfh 20 Nov 2012: Should we treat underflow as an error?
00571       //
00572       TEUCHOS_TEST_FOR_EXCEPTION(
00573         errno == ERANGE && val == 0,
00574         std::invalid_argument,
00575         "Teuchos::ValueTypeConversionTraits<" << realTypeName
00576         << ", std::string>::convert: "
00577         "The value in the given string \"" << t << "\" underflows "
00578         << realTypeName << ".");
00579       TEUCHOS_TEST_FOR_EXCEPTION(
00580         endptr == t_ptr, // See above discussion of c_str().
00581         std::invalid_argument,
00582         "Teuchos::ValueTypeConversionTraits<" << realTypeName
00583         << ", std::string>::convert: "
00584         "The conversion function was unable to read any floating-point data "
00585         "from the given string \"" << t << "\".");
00586       return val;
00587     }
00588   }
00589 
00590 } // namespace (anonymous)
00591 
00592 
00593 //
00594 // Standard specializations of ValueTypeConversionTraits
00595 //
00596 
00597 //
00598 // * Partial specialization for conversion from std::string to any type T.
00599 //   There are full specializations for specific types T below.
00600 //
00601 
00614 template<class OutType>
00615 class ValueTypeConversionTraits<OutType, std::string> {
00616 public:
00617   static OutType safeConvert (const std::string& t) {
00618     return convert (t);
00619   }
00620 
00621   static OutType convert (const std::string& t) {
00622     std::istringstream in (t);
00623     OutType out;
00624     t >> out;
00625     return out;
00626   }
00627 };
00628 
00629 //
00630 // * Specializations for conversions from std::string to build-in
00631 //   real-valued floating-point types.
00632 //
00633 
00635 template<>
00636 class ValueTypeConversionTraits<double, std::string> {
00637 public:
00638   static double convert (const std::string& t) {
00639     return stringToReal<double> (t, &strtod, "double");
00640   }
00641 
00642   static double safeConvert (const std::string& t) {
00643     return stringToReal<double> (t, &strtod, "double");
00644   }
00645 };
00646 
00648 template<>
00649 class ValueTypeConversionTraits<float, std::string> {
00650 public:
00651   static float convert (const std::string& t) {
00652 #ifdef _ISOC99_SOURCE
00653     return stringToReal<float> (t, &strtof, "float");
00654 #else
00655     // strtof is new in C99.  If you don't have it, just use strtod
00656     // and convert the resulting double to float.
00657     const double d = stringToReal<double> (t, &strtod, "double");
00658     return realToReal<float, double> (d, false);
00659 #endif // _ISOC99_SOURCE
00660   }
00661 
00662   static float safeConvert (const std::string& t) {
00663 #ifdef _ISOC99_SOURCE
00664     return stringToReal<float> (t, &strtof, "float");
00665 #else
00666     // strtof is new in C99.  If you don't have it, just use strtod
00667     // and convert the resulting double to float.
00668     const double d = stringToReal<double> (t, &strtod, "double");
00669     return realToReal<float, double> (d, true);
00670 #endif // _ISOC99_SOURCE
00671   }
00672 };
00673 
00675 template<>
00676 class ValueTypeConversionTraits<long double, std::string> {
00677 public:
00678   static long double convert (const std::string& t) {
00679 #ifdef _ISOC99_SOURCE
00680     return stringToReal<long double> (t, &strtold, "long double");
00681 #else
00682     // strtof is new in C99.  If you don't have it, just use
00683     // operator>>(std::istream&, long double&).
00684     return stringToReal<long double> (t, NULL, "long double");
00685 #endif // _ISOC99_SOURCE
00686   }
00687 
00688   static long double safeConvert (const std::string& t) {
00689     return convert (t);
00690   }
00691 };
00692 
00693 
00694 //
00695 // * Specializations for conversions from std::string to build-in integer types.
00696 //
00697 
00698 #ifdef HAVE_TEUCHOS_LONG_LONG_INT
00699 
00703 template<>
00704 class ValueTypeConversionTraits<long long, std::string> {
00705 public:
00711   static long long safeConvert (const std::string& t) {
00712 #if defined(_MSC_VER)
00713     // Windows does not implement strtoull, so we resort to a
00714     // fallback.  Thanks to Ross Bartlett for pointing out _strtoi64.
00715     // See the MSDN reference [last accessed 21 Mar 2013]:
00716     //
00717     // http://msdn.microsoft.com/en-us/library/h80404d3%28v=vs.80%29.aspx
00718     return intToString<long long> (t, &_strtoi64, "long long");
00719 #else
00720     return intToString<long long> (t, &strtoll, "long long");
00721 #endif // defined(_MSC_VER)
00722   }
00723 
00725   static long long convert (const std::string& t) {
00726     return safeConvert (t);
00727   }
00728 };
00729 
00730 
00734 template<>
00735 class ValueTypeConversionTraits<unsigned long long, std::string> {
00736 public:
00742   static unsigned long long safeConvert (const std::string& t) {
00743 #if defined(_MSC_VER)
00744     // Windows does not implement strtoull, so we resort to a
00745     // fallback.  The fallback does not know how to check for under-
00746     // or overflow.  Alas, Windows does not seem to have an equivalent
00747     // of _strtoi64 for unsigned long long.
00748     const char intTypeName[] = "unsigned long long";
00749     std::istringstream istr (t);
00750     unsigned long long i = 0;
00751     istr >> i;
00752     TEUCHOS_TEST_FOR_EXCEPTION(
00753       ! istr, std::invalid_argument,
00754       "Teuchos::ValueTypeConversionTraits<" << intTypeName << ", std::string>::"
00755       "convert: Unable to convert the given string \"" << t << "\" to " <<
00756       intTypeName << ".  Windows lacks strtoull(), so we had to resort to a "
00757       "fall-back conversion.  The fall-back method does not know how to test "
00758       "for overflow.");
00759     return i;
00760 #else
00761     return intToString<unsigned long long> (t, &strtoull, "unsigned long long");
00762 #endif // defined(_MSC_VER)
00763   }
00764 
00766   static unsigned long long convert (const std::string& t) {
00767     return safeConvert (t);
00768   }
00769 };
00770 
00771 #endif // HAVE_TEUCHOS_LONG_LONG_INT
00772 
00773 
00777 template<>
00778 class ValueTypeConversionTraits<long, std::string> {
00779 public:
00785   static long safeConvert (const std::string& t) {
00786     return intToString<long> (t, &strtol, "long");
00787   }
00788 
00790   static long convert (const std::string& t) {
00791     return safeConvert (t);
00792   }
00793 };
00794 
00795 
00799 template<>
00800 class ValueTypeConversionTraits<unsigned long, std::string> {
00801 public:
00807   static unsigned long safeConvert (const std::string& t) {
00808     return intToString<unsigned long> (t, &strtoul, "unsigned long");
00809   }
00810 
00812   static unsigned long convert (const std::string& t) {
00813     return safeConvert (t);
00814   }
00815 };
00816 
00817 
00821 template<>
00822 class ValueTypeConversionTraits<int, std::string> {
00823 private:
00825   static long safeConvertToLong (const std::string& t) {
00826     long val = 0;
00827     try {
00828       val = ValueTypeConversionTraits<long, std::string>::safeConvert (t);
00829     } catch (std::range_error&) {
00830       TEUCHOS_TEST_FOR_EXCEPTION(
00831         true,
00832         std::range_error,
00833         "Teuchos::ValueTypeConversionTraits<int, std::string>::convert: "
00834         "The given std::string \"" << t << "\" is too big to fit into long, so there is no way it could fit into int.");
00835     } catch (std::invalid_argument& e) {
00836       TEUCHOS_TEST_FOR_EXCEPTION(
00837         true,
00838         std::invalid_argument,
00839         "Teuchos::ValueTypeConversionTraits<int, std::string>::convert: "
00840         "Intermediate conversion from std::string to long failed, with the following error message: "
00841         << e.what ());
00842     }
00843     return val;
00844   }
00845 
00846 public:
00852   static int safeConvert (const std::string& t) {
00853     return asSafe<int> (safeConvertToLong (t));
00854   }
00855 
00857   static int convert (const std::string& t) {
00858     return as<int> (safeConvertToLong (t));
00859   }
00860 };
00861 
00862 
00866 template<>
00867 class ValueTypeConversionTraits<unsigned int, std::string> {
00868 private:
00870   static unsigned long safeConvertToUnsignedLong (const std::string& t) {
00871     unsigned long val = 0;
00872     try {
00873       val = as<unsigned long> (t);
00874     } catch (std::range_error&) {
00875       TEUCHOS_TEST_FOR_EXCEPTION(
00876         true,
00877         std::range_error,
00878         "Teuchos::ValueTypeConversionTraits<unsigned int, std::string>::convert: "
00879         "The given std::string \"" << t << "\" is too big to fit into unsigned long, so there is no way it could fit into unsigned int.");
00880     } catch (std::invalid_argument& e) {
00881       TEUCHOS_TEST_FOR_EXCEPTION(
00882         true,
00883         std::invalid_argument,
00884         "Teuchos::ValueTypeConversionTraits<unsigned int, std::string>::convert: "
00885         "Intermediate conversion from std::string to unsigned long failed, with the following error message: "
00886         << e.what ());
00887     }
00888     return val;
00889   }
00890 
00891 public:
00897   static unsigned int safeConvert (const std::string& t) {
00898     return asSafe<unsigned int> (safeConvertToUnsignedLong (t));
00899   }
00900 
00902   static unsigned int convert (const std::string& t) {
00903     return as<unsigned int> (safeConvertToUnsignedLong (t));
00904   }
00905 };
00906 
00907 
00911 template<>
00912 class ValueTypeConversionTraits<short, std::string> {
00913 private:
00915   static long safeConvertToLong (const std::string& t) {
00916     long val = 0;
00917     try {
00918       val = ValueTypeConversionTraits<long, std::string>::safeConvert (t);
00919     } catch (std::range_error&) {
00920       TEUCHOS_TEST_FOR_EXCEPTION(
00921         true,
00922         std::range_error,
00923         "Teuchos::ValueTypeConversionTraits<short, std::string>::convert: "
00924         "The given std::string \"" << t << "\" is too big to fit into long, so there is no way it could fit into short.");
00925     } catch (std::invalid_argument& e) {
00926       TEUCHOS_TEST_FOR_EXCEPTION(
00927         true,
00928         std::invalid_argument,
00929         "Teuchos::ValueTypeConversionTraits<short, std::string>::convert: "
00930         "Intermediate conversion from std::string to long failed, with the following error message: "
00931         << e.what ());
00932     }
00933     return val;
00934   }
00935 
00936 public:
00942   static short safeConvert (const std::string& t) {
00943     return asSafe<short> (safeConvertToLong (t));
00944   }
00945 
00947   static short convert (const std::string& t) {
00948     return as<short> (safeConvertToLong (t));
00949   }
00950 };
00951 
00952 
00956 template<>
00957 class ValueTypeConversionTraits<unsigned short, std::string> {
00958 private:
00960   static unsigned long safeConvertToUnsignedLong (const std::string& t) {
00961     unsigned long val = 0;
00962     try {
00963       val = as<unsigned long> (t);
00964     } catch (std::range_error&) {
00965       TEUCHOS_TEST_FOR_EXCEPTION(
00966         true,
00967         std::range_error,
00968         "Teuchos::ValueTypeConversionTraits<unsigned short, std::string>::convert: "
00969         "The given std::string \"" << t << "\" is too big to fit into unsigned long, so there is no way it could fit into unsigned short.");
00970     } catch (std::invalid_argument& e) {
00971       TEUCHOS_TEST_FOR_EXCEPTION(
00972         true,
00973         std::invalid_argument,
00974         "Teuchos::ValueTypeConversionTraits<unsigned short, std::string>::convert: "
00975         "Intermediate conversion from std::string to unsigned long failed, with the following error message: "
00976         << e.what ());
00977     }
00978     return val;
00979   }
00980 
00981 public:
00987   static unsigned short safeConvert (const std::string& t) {
00988     return asSafe<unsigned short> (safeConvertToUnsignedLong (t));
00989   }
00990 
00992   static unsigned short convert (const std::string& t) {
00993     return as<unsigned short> (safeConvertToUnsignedLong (t));
00994   }
00995 };
00996 
00997 //
00998 // * Specializations for conversions between built-in real-valued
00999 //   floating-point types (like float and double).
01000 //
01001 
01003 template<>
01004 class ValueTypeConversionTraits<float, double> {
01005 public:
01006   static float safeConvert (const double t) {
01007     // mfh 25 Nov 2012: Disabling bounds checking, in favor of IEEE
01008     // 754 overflow semantics.  Users who want bounds checking should
01009     // set the appropriate trap.
01010 #if 0
01011     // For floating-point types T, std::numeric_limits<T>::min()
01012     // returns the smallest positive value.  IEEE 754 types have a
01013     // sign bit, so the largest-magnitude negative value is the
01014     // negative of the largest-magnitude positive value.
01015     const float minVal = -std::numeric_limits<float>::max ();
01016     const float maxVal = std::numeric_limits<float>::max ();
01017 
01018     // NaN is neither less than nor greater than anything.  We just
01019     // let it pass through, per the rules for propagation of silent
01020     // NaN.  (Signaling NaN will signal, but that's OK.)
01021     TEUCHOS_TEST_FOR_EXCEPTION(
01022       t < minVal || t > maxVal,
01023       std::range_error,
01024       "Teuchos::ValueTypeConversionTraits<float, double>::safeConvert: "
01025       "Input double t = " << t << " is out of the valid range [" << minVal
01026       << ", " << maxVal << "] for conversion to float.");
01027 #endif // 0
01028 
01029     return static_cast<float> (t);
01030   }
01031 
01032   static float convert (const double t) {
01033     return static_cast<float> (t);
01034   }
01035 };
01036 
01037 
01039 template<>
01040 class ValueTypeConversionTraits<float, long double> {
01041 public:
01042   static float safeConvert (const long double t) {
01043     // mfh 25 Nov 2012: Disabling bounds checking, in favor of IEEE
01044     // 754 overflow semantics.  Users who want bounds checking should
01045     // set the appropriate trap.
01046 #if 0
01047     // For floating-point types T, std::numeric_limits<T>::min()
01048     // returns the smallest positive value.  IEEE 754 types have a
01049     // sign bit, so the largest-magnitude negative value is the
01050     // negative of the largest-magnitude positive value.
01051     const float minVal = -std::numeric_limits<float>::max ();
01052     const float maxVal = std::numeric_limits<float>::max ();
01053 
01054     // NaN is neither less than nor greater than anything.  We just
01055     // let it pass through, per the rules for propagation of silent
01056     // NaN.  (Signaling NaN will signal, but that's OK.)
01057     TEUCHOS_TEST_FOR_EXCEPTION(
01058       t < minVal || t > maxVal,
01059       std::range_error,
01060       "Teuchos::ValueTypeConversionTraits<float, long double>::safeConvert: "
01061       "Input long double t = " << t << " is out of the valid range [" << minVal
01062       << ", " << maxVal << "] for conversion to float.");
01063 #endif // 0
01064 
01065     return static_cast<float> (t);
01066   }
01067 
01068   static float convert (const long double t) {
01069     return static_cast<float> (t);
01070   }
01071 };
01072 
01073 
01075 template<>
01076 class ValueTypeConversionTraits<double, long double> {
01077 public:
01078   static double safeConvert (const long double t) {
01079     // mfh 25 Nov 2012: Disabling bounds checking, in favor of IEEE
01080     // 754 overflow semantics.  Users who want bounds checking should
01081     // set the appropriate trap.
01082 #if 0
01083     // For floating-point types T, std::numeric_limits<T>::min()
01084     // returns the smallest positive value.  IEEE 754 types have a
01085     // sign bit, so the largest-magnitude negative value is the
01086     // negative of the largest-magnitude positive value.
01087     const double minVal = -std::numeric_limits<double>::max ();
01088     const double maxVal = std::numeric_limits<double>::max ();
01089 
01090     // NaN is neither less than nor greater than anything.  We just
01091     // let it pass through, per the rules for propagation of silent
01092     // NaN.  (Signaling NaN will signal, but that's OK.)
01093     TEUCHOS_TEST_FOR_EXCEPTION(
01094       t < minVal || t > maxVal,
01095       std::range_error,
01096       "Teuchos::ValueTypeConversionTraits<double, long double>::safeConvert: "
01097       "Input long double t = " << t << " is out of the valid range [" << minVal
01098       << ", " << maxVal << "] for conversion to double.");
01099 #endif // 0
01100 
01101     return static_cast<double> (t);
01102   }
01103 
01104   static double convert (const long double t) {
01105     return static_cast<double> (t);
01106   }
01107 };
01108 
01109 
01110 //
01111 // * Specializations for conversions from built-in real-valued
01112 //   floating-point types (float and double) to build-in integer
01113 //   types.
01114 //
01115 
01117 template<>
01118 class ValueTypeConversionTraits<short, double> {
01119 public:
01125   static short convert (const double t) {
01126     // Implicit conversion may cause compiler warnings, but
01127     // static_cast does not.
01128     return static_cast<short> (t);
01129   }
01130 
01132   static short safeConvert (const double t) {
01133     const short minVal = std::numeric_limits<short>::min ();
01134     const short maxVal = std::numeric_limits<short>::max ();
01135 
01136     // Cases:
01137     // 1. sizeof(short) < sizeof(double) == 8
01138     // 2. sizeof(short) == sizeof(double) == 8
01139     // 3. sizeof(short) > sizeof(double) == 8
01140     //
01141     // Overflow when converting from double to short is possible only
01142     // for Case 1.  Loss of accuracy (rounding) is possible for Cases
01143     // 2 and 3, but safeConvert() only cares about overflow, not
01144     // rounding.  In Case 3, casting minVal or maxVal to double in
01145     // this case could result in overflow.  Thus, we only do the test
01146     // for Case 1.
01147     //
01148     // All three cases are legal according to both C++03 and C99.
01149     // However, I (mfh 15 Nov 2012) have never encountered Cases 2 and
01150     // 3.
01151     if (sizeof (short) < sizeof (double)) {
01152       TEUCHOS_TEST_FOR_EXCEPTION(
01153         t < minVal || t > maxVal,
01154         std::range_error,
01155         "Teuchos::ValueTypeConversionTraits<short, double>::safeConvert: "
01156         "Input double t = " << t << " is out of the valid range [" << minVal
01157         << ", " << maxVal << "] for conversion to short.");
01158     }
01159     return static_cast<short> (t);
01160   }
01161 };
01162 
01163 
01165 template<>
01166 class ValueTypeConversionTraits<unsigned short, double> {
01167 public:
01169   static unsigned short convert (const double t) {
01170     // Implicit conversion may cause compiler warnings, but
01171     // static_cast does not.
01172     return static_cast<unsigned short> (t);
01173   }
01174 
01176   static unsigned short safeConvert (const double t) {
01177     const unsigned short minVal = 0;
01178     const unsigned short maxVal = std::numeric_limits<unsigned short>::max ();
01179 
01180     TEUCHOS_TEST_FOR_EXCEPTION(
01181       t < minVal || t > maxVal,
01182       std::range_error,
01183       "Teuchos::ValueTypeConversionTraits<unsigned short, double>::safeConvert: "
01184       "Input double t = " << t << " is out of the valid range [" << minVal
01185       << ", " << maxVal << "] for conversion to unsigned short.");
01186 
01187     return static_cast<unsigned short> (t);
01188   }
01189 };
01190 
01191 
01193 template<>
01194 class ValueTypeConversionTraits<int, double> {
01195 public:
01201   static int convert (const double t) {
01202     // Implicit conversion from double to int causes compiler
01203     // warnings, but static_cast does not.
01204     return static_cast<int> (t);
01205   }
01206 
01208   static int safeConvert (const double t) {
01209     const int minVal = std::numeric_limits<int>::min ();
01210     const int maxVal = std::numeric_limits<int>::max ();
01211 
01212     // Cases:
01213     // 1. sizeof(int) < sizeof(double) == 8
01214     // 2. sizeof(int) == sizeof(double) == 8
01215     // 3. sizeof(int) > sizeof(double) == 8
01216     //
01217     // Overflow when converting from double to int is possible only
01218     // for Case 1.  Loss of accuracy (rounding) is possible for Cases
01219     // 2 and 3, but safeConvert() only cares about overflow, not
01220     // rounding.  Case 3 is quite rare, but casting minVal or maxVal
01221     // to double in this case could result in overflow.  Thus, we only
01222     // do the cast for Case 1.
01223     if (sizeof (int) < sizeof (double)) {
01224       TEUCHOS_TEST_FOR_EXCEPTION(
01225         t < minVal || t > maxVal,
01226         std::range_error,
01227         "Teuchos::ValueTypeConversionTraits<int, double>::safeConvert: "
01228         "Input double t = " << t << " is out of the valid range [" << minVal
01229         << ", " << maxVal << "] for conversion to int.");
01230     }
01231     return static_cast<int> (t);
01232   }
01233 };
01234 
01235 
01237 template<>
01238 class ValueTypeConversionTraits<unsigned int, double> {
01239 public:
01241   static unsigned int convert (const double t) {
01242     // Implicit conversion may cause compiler warnings, but
01243     // static_cast does not.
01244     return static_cast<unsigned int> (t);
01245   }
01246 
01248   static unsigned int safeConvert (const double t) {
01249     const unsigned int minVal = 0;
01250     const unsigned int maxVal = std::numeric_limits<unsigned int>::max ();
01251 
01252     TEUCHOS_TEST_FOR_EXCEPTION(
01253       t < minVal || t > maxVal,
01254       std::range_error,
01255       "Teuchos::ValueTypeConversionTraits<unsigned int, double>::safeConvert: "
01256       "Input double t = " << t << " is out of the valid range [" << minVal
01257       << ", " << maxVal << "] for conversion to unsigned int.");
01258 
01259     return static_cast<unsigned int> (t);
01260   }
01261 };
01262 
01263 
01265 template<>
01266 class ValueTypeConversionTraits<long, double> {
01267 public:
01269   static long convert (const double t) {
01270     // Implicit conversion may cause compiler warnings, but
01271     // static_cast does not.
01272     return static_cast<long> (t);
01273   }
01274 
01276   static long safeConvert (const double t) {
01277     const long minVal = std::numeric_limits<long>::min ();
01278     const long maxVal = std::numeric_limits<long>::max ();
01279 
01280     // Cases:
01281     // 1. sizeof(long) < sizeof(double) == 8
01282     // 2. sizeof(long) == sizeof(double) == 8
01283     // 3. sizeof(long) > sizeof(double) == 8
01284     //
01285     // Overflow when converting from double to long is possible only
01286     // for Case 1.  Loss of accuracy (rounding) is possible for Cases
01287     // 2 and 3, but safeConvert() only cares about overflow, not
01288     // rounding.  In Case 3, casting minVal or maxVal to double could
01289     // result in overflow.  Thus, we only test for Case 1.
01290     //
01291     // Case 1 is entirely possible, for example on Win64 (an
01292     // implementation of the LLP64 integer model, on which
01293     // sizeof(long) == 4, and sizeof(long long) == sizeof(void*) ==
01294     // 8).
01295     if (sizeof (long) < sizeof (double)) {
01296       TEUCHOS_TEST_FOR_EXCEPTION(
01297         t < minVal || t > maxVal,
01298         std::range_error,
01299         "Teuchos::ValueTypeConversionTraits<long, double>::safeConvert: "
01300         "Input double t = " << t << " is out of the valid range [" << minVal
01301         << ", " << maxVal << "] for conversion to long.");
01302     }
01303     return static_cast<long> (t);
01304   }
01305 };
01306 
01307 
01309 template<>
01310 class ValueTypeConversionTraits<unsigned long, double> {
01311 public:
01313   static unsigned long convert (const double t) {
01314     // Implicit conversion may cause compiler warnings, but
01315     // static_cast does not.
01316     return static_cast<unsigned long> (t);
01317   }
01318 
01320   static unsigned long safeConvert (const double t) {
01321     const unsigned long minVal = 0;
01322     const unsigned long maxVal = std::numeric_limits<unsigned long>::max ();
01323 
01324     TEUCHOS_TEST_FOR_EXCEPTION(
01325       t < minVal || t > maxVal,
01326       std::range_error,
01327       "Teuchos::ValueTypeConversionTraits<unsigned long, double>::safeConvert: "
01328       "Input double t = " << t << " is out of the valid range [" << minVal
01329       << ", " << maxVal << "] for conversion to unsigned long.");
01330 
01331     return static_cast<unsigned long> (t);
01332   }
01333 };
01334 
01335 #ifdef HAVE_TEUCHOS_LONG_LONG_INT
01336 
01338 template<>
01339 class ValueTypeConversionTraits<long long, double> {
01340 public:
01342   static long long convert (const double t) {
01343     // Implicit conversion may cause compiler warnings, but
01344     // static_cast does not.
01345     return static_cast<long long> (t);
01346   }
01347 
01349   static long safeConvert (const double t) {
01350     // Cases:
01351     // 1. sizeof(long long) < sizeof(double) == 8
01352     // 2. sizeof(long long) == sizeof(double) == 8
01353     // 3. sizeof(long long) > sizeof(double) == 8
01354     //
01355     // C99 (which defines long long) prohibits Case 1.  Case 2 could
01356     // result in loss of accuracy (rounding), but safeConvert() only
01357     // cares about overflow, not rounding.  In Case 3, casting minVal
01358     // or maxVal to double could result in overflow.  Thus, we don't
01359     // need to check anything here.
01360     return static_cast<long long> (t);
01361   }
01362 };
01363 
01364 
01366 template<>
01367 class ValueTypeConversionTraits<unsigned long long, double> {
01368 public:
01370   static unsigned long long convert (const double t) {
01371     // Implicit conversion may cause compiler warnings, but
01372     // static_cast does not.
01373     return static_cast<unsigned long long> (t);
01374   }
01375 
01377   static unsigned long long safeConvert (const double t) {
01378     const unsigned long long minVal = 0; // unsigned, so min value is 0.
01379     const unsigned long long maxVal = std::numeric_limits<unsigned long long>::max ();
01380 
01381     TEUCHOS_TEST_FOR_EXCEPTION(
01382       t < minVal || t > maxVal,
01383       std::range_error,
01384       "Teuchos::ValueTypeConversionTraits<unsigned long long, double>::safeConvert: "
01385       "Input double t = " << t << " is out of the valid range [" << minVal
01386       << ", " << maxVal << "] for conversion to unsigned long long.");
01387 
01388     return static_cast<unsigned long long> (t);
01389   }
01390 };
01391 
01392 #endif // HAVE_TEUCHOS_LONG_LONG_INT
01393 
01394 
01396 template<>
01397 class ValueTypeConversionTraits<short, float> {
01398 public:
01404   static short convert (const float t) {
01405     // Implicit conversion may cause compiler warnings, but
01406     // static_cast does not.
01407     return static_cast<short> (t);
01408   }
01409 
01411   static short safeConvert (const float t) {
01412     const short minVal = std::numeric_limits<short>::min ();
01413     const short maxVal = std::numeric_limits<short>::max ();
01414 
01415     // Cases:
01416     // 1. sizeof(short) < sizeof(float) == 4
01417     // 2. sizeof(short) == sizeof(float) == 4
01418     // 3. sizeof(short) > sizeof(float) == 4
01419     //
01420     // Overflow when converting from float to short is possible only
01421     // for Case 1.  Loss of accuracy (rounding) is possible for Cases
01422     // 2 and 3, but safeConvert() only cares about overflow, not
01423     // rounding.  In Case 3, casting minVal or maxVal to float in this
01424     // case could result in overflow.  Thus, we only do the test for
01425     // Case 1.
01426     //
01427     // All three cases are legal according to both C++03 and C99.  I
01428     // (mfh 15 Nov 2012) think Case 1 is the most common, but Case 2
01429     // is certainly reasonable.  (For example, some hardware prefers
01430     // to work only with 32-bit words, so _every_ built-in type has
01431     // size a multiple of 4 bytes.)
01432     if (sizeof (short) < sizeof (float)) {
01433       TEUCHOS_TEST_FOR_EXCEPTION(
01434         t < minVal || t > maxVal,
01435         std::range_error,
01436         "Teuchos::ValueTypeConversionTraits<short, float>::safeConvert: "
01437         "Input float t = " << t << " is out of the valid range [" << minVal
01438         << ", " << maxVal << "] for conversion to short.");
01439     }
01440 
01441     return static_cast<short> (t);
01442   }
01443 };
01444 
01445 
01447 template<>
01448 class ValueTypeConversionTraits<unsigned short, float> {
01449 public:
01451   static unsigned short convert (const float t) {
01452     // Implicit conversion may cause compiler warnings, but
01453     // static_cast does not.
01454     return static_cast<unsigned short> (t);
01455   }
01456 
01458   static unsigned short safeConvert (const float t) {
01459     const unsigned short minVal = 0;
01460     const unsigned short maxVal = std::numeric_limits<unsigned short>::max ();
01461 
01462     TEUCHOS_TEST_FOR_EXCEPTION(
01463       t < minVal || t > maxVal,
01464       std::range_error,
01465       "Teuchos::ValueTypeConversionTraits<unsigned short, float>::safeConvert: "
01466       "Input float t = " << t << " is out of the valid range [" << minVal
01467       << ", " << maxVal << "] for conversion to unsigned short.");
01468 
01469     return static_cast<unsigned short> (t);
01470   }
01471 };
01472 
01473 
01475 template<>
01476 class ValueTypeConversionTraits<int, float> {
01477 public:
01479   static int convert (const float t) {
01480     // Implicit conversion from float to int may cause compiler
01481     // warnings, but static_cast does not.  Overflow here would mean
01482     // that sizeof(int) < sizeof(float), which is legal, but unlikely
01483     // on platforms of interest.
01484     return static_cast<int> (t);
01485   }
01486 
01488   static int safeConvert (const float t) {
01489     const int minVal = std::numeric_limits<int>::min ();
01490     const int maxVal = std::numeric_limits<int>::max ();
01491 
01492     // Cases:
01493     // 1. sizeof(int) < sizeof(float) == 4
01494     // 2. sizeof(int) == sizeof(float) == 4
01495     // 3. sizeof(int) > sizeof(float) == 4
01496     //
01497     // Overflow when converting from float to int is possible only for
01498     // Case 1.  Loss of accuracy (rounding) is possible for Cases 2
01499     // and 3, but safeConvert() only cares about overflow, not
01500     // rounding.  Case 3 is rare, but casting minVal or maxVal to
01501     // float in this case could result in loss of accuracy
01502     // (sizeof(int) == 8 or 16) or overflow (sizeof(int) > 16).  Thus,
01503     // we only do the test for Case 1.
01504     if (sizeof (int) < sizeof (float)) {
01505       TEUCHOS_TEST_FOR_EXCEPTION(
01506         t < minVal || t > maxVal,
01507         std::range_error,
01508         "Teuchos::ValueTypeConversionTraits<int, float>::safeConvert: "
01509         "Input float t = " << t << " is out of the valid range ["
01510         << minVal << ", " << maxVal << "] for conversion to int.");
01511     }
01512     return static_cast<int> (t);
01513   }
01514 };
01515 
01516 
01518 template<>
01519 class ValueTypeConversionTraits<unsigned int, float> {
01520 public:
01522   static unsigned int convert (const float t) {
01523     // Implicit conversion from float to unsigned int may cause
01524     // compiler warnings, but static_cast does not.
01525     return static_cast<unsigned int> (t);
01526   }
01527 
01529   static unsigned int safeConvert (const float t) {
01530     const unsigned int minVal = 0; // Had better be, since it's unsigned.
01531     const unsigned int maxVal = std::numeric_limits<unsigned int>::max ();
01532 
01533     TEUCHOS_TEST_FOR_EXCEPTION(
01534       t < minVal || t > maxVal,
01535       std::range_error,
01536       "Teuchos::ValueTypeConversionTraits<unsigned int, float>::safeConvert: "
01537       "Input double t = " << t << " is out of the valid range [" << minVal
01538       << ", " << maxVal << "] for conversion to unsigned int.");
01539 
01540     return static_cast<unsigned int> (t);
01541   }
01542 };
01543 
01544 
01546 template<>
01547 class ValueTypeConversionTraits<long, float> {
01548 public:
01550   static long convert (const float t) {
01551     // Implicit conversion from float to long may cause compiler
01552     // warnings, but static_cast does not.  Overflow here would mean
01553     // that sizeof(long) < sizeof(float), which is legal, but unlikely
01554     // on platforms of longerest.
01555     return static_cast<long> (t);
01556   }
01557 
01559   static long safeConvert (const float t) {
01560     const long minVal = std::numeric_limits<long>::min ();
01561     const long maxVal = std::numeric_limits<long>::max ();
01562 
01563     // Cases:
01564     // 1. sizeof(long) < sizeof(float) == 4
01565     // 2. sizeof(long) == sizeof(float) == 4
01566     // 3. sizeof(long) > sizeof(float) == 4
01567     //
01568     // Overflow when converting from float to long is possible only
01569     // for Case 1.  Loss of accuracy (rounding) is possible for Cases
01570     // 2 and 3, but safeConvert() only cares about overflow, not
01571     // rounding.  Casting minVal or maxVal to double in Case 3 could
01572     // result in overflow.  Thus, we only do the cast for Case 1.
01573     //
01574     // I've never encountered a Case 1 platform (mfh 14 Nov 2012).
01575     // C99 actually forbids it, though I don't think a valid C++
01576     // compiler (for version C++03 of the language standard) needs to
01577     // implement C99 (mfh 14 Nov 2012).  Case 2 occurs in Win64
01578     // (64-bit Windows) and other implementations of (I32L32)LLP64.
01579     // Case 3 is common (e.g., in the (I32)LP64 integer model of
01580     // GNU/Linux and other operating systems).
01581     if (sizeof (long) < sizeof (float)) {
01582       TEUCHOS_TEST_FOR_EXCEPTION(
01583         t < minVal || t > maxVal,
01584         std::range_error,
01585         "Teuchos::ValueTypeConversionTraits<long, float>::safeConvert: "
01586         "Input float t = " << t << " is out of the valid range ["
01587         << minVal << ", " << maxVal << "] for conversion to long.");
01588     }
01589     return static_cast<long> (t);
01590   }
01591 };
01592 
01593 
01595 template<>
01596 class ValueTypeConversionTraits<unsigned long, float> {
01597 public:
01599   static unsigned long convert (const float t) {
01600     // Implicit conversion from float to unsigned long may cause
01601     // compiler warnings, but static_cast does not.
01602     return static_cast<unsigned long> (t);
01603   }
01604 
01606   static unsigned long safeConvert (const float t) {
01607     const unsigned long minVal = 0; // Had better be, since it's unsigned.
01608     const unsigned long maxVal = std::numeric_limits<unsigned long>::max ();
01609 
01610     TEUCHOS_TEST_FOR_EXCEPTION(
01611       t < minVal || t > maxVal,
01612       std::range_error,
01613       "Teuchos::ValueTypeConversionTraits<unsigned long, float>::safeConvert: "
01614       << "Input float t = " << t << " is out of the valid range [" << minVal
01615       << ", " << maxVal << "] for conversion to unsigned long.");
01616 
01617     return static_cast<unsigned long> (t);
01618   }
01619 };
01620 
01621 #ifdef HAVE_TEUCHOS_LONG_LONG_INT
01622 
01624 template<>
01625 class ValueTypeConversionTraits<long long, float> {
01626 public:
01628   static long long convert (const float t) {
01629     return static_cast<long long> (t);
01630   }
01631 
01633   static long long safeConvert (const float t) {
01634     // The C99 standard (Section 5.2.4.2.1) actually requires
01635     // sizeof(long long) >= 64, so overflow is impossible.
01636     return static_cast<long long> (t);
01637   }
01638 };
01639 
01640 
01642 template<>
01643 class ValueTypeConversionTraits<unsigned long long, float> {
01644 public:
01646   static unsigned long long convert (const float t) {
01647     return static_cast<unsigned long long> (t);
01648   }
01649 
01651   static unsigned long long safeConvert (const float t) {
01652     const unsigned long long minVal = 0; // unsigned, so min value is 0.
01653     const unsigned long long maxVal = std::numeric_limits<unsigned long long>::max ();
01654 
01655     TEUCHOS_TEST_FOR_EXCEPTION(
01656       t < minVal || t > maxVal,
01657       std::range_error,
01658       "Teuchos::ValueTypeConversionTraits<unsigned long long, float>::safeConvert: "
01659       "Input float t = " << t << " is out of the valid range [" << minVal
01660       << ", " << maxVal << "] for conversion to unsigned long long.");
01661 
01662     return static_cast<unsigned long long> (t);
01663   }
01664 };
01665 
01666 #endif // HAVE_TEUCHOS_LONG_LONG_INT
01667 
01668 //
01669 // * Specializations for conversions between a unsigned built-in
01670 //   integer type and the signed version of the same type (either
01671 //   direction).
01672 //
01673 
01674 namespace {
01675 // Implementation of conversion from an unsigned built-in integer
01676 // type, to an signed built-in integer type with the same number of
01677 // bits.
01678 template<class SignedIntType, class UnsignedIntType>
01679 class UnsignedToSignedValueTypeConversionTraits {
01680 public:
01688   static SignedIntType convert (const UnsignedIntType t) {
01689     // Implicit conversion may cause compiler warnings, but
01690     // static_cast does not.
01691     return static_cast<SignedIntType> (t);
01692   }
01693 
01695   static SignedIntType safeConvert (const UnsignedIntType t) {
01696     using Teuchos::TypeNameTraits;
01697     const SignedIntType maxSigned = std::numeric_limits<SignedIntType>::max ();
01698 
01699     // SignedIntType and UnsignedIntType have the same number of bits,
01700     // so it suffices (via two's complement arithmetic) to check
01701     // whether the cast turned a positive number negative.
01702     const SignedIntType signedVal = static_cast<SignedIntType> (t);
01703     TEUCHOS_TEST_FOR_EXCEPTION(
01704       signedVal < 0,
01705       std::range_error,
01706       "Teuchos::ValueTypeConversionTraits<" << TypeNameTraits<SignedIntType>::name ()
01707       << ", " << TypeNameTraits<UnsignedIntType>::name () << ">::safeConvert: "
01708       "Input " << TypeNameTraits<UnsignedIntType>::name () << " t = " << t
01709       << " is out of the valid range [0, " << ", " << maxSigned
01710       << "] for conversion to " << TypeNameTraits<SignedIntType>::name () << ".");
01711     return signedVal;
01712   }
01713 };
01714 
01715 
01716 // Implementation of conversion from a signed built-in integer type,
01717 // to an unsigned built-in integer type with the same number of bits.
01718 template<class UnsignedIntType, class SignedIntType>
01719 class SignedToUnsignedValueTypeConversionTraits {
01720 public:
01722   static UnsignedIntType convert (const SignedIntType t) {
01723     // Implicit conversion may cause compiler warnings, but
01724     // static_cast does not.
01725     return static_cast<UnsignedIntType> (t);
01726   }
01727 
01729   static UnsignedIntType safeConvert (const SignedIntType t) {
01730     using Teuchos::TypeNameTraits;
01731 
01732     // SignedIntType and UnsignedIntType have the same number of bits,
01733     // so it suffices (via two's complement arithmetic) to check
01734     // whether the input is negative.
01735     TEUCHOS_TEST_FOR_EXCEPTION(
01736       t < static_cast<SignedIntType> (0),
01737       std::range_error,
01738       "Teuchos::ValueTypeConversionTraits<" << TypeNameTraits<UnsignedIntType>::name ()
01739       << ", " << TypeNameTraits<SignedIntType>::name () << ">::safeConvert: "
01740       "Input " << TypeNameTraits<SignedIntType>::name () << " t = " << t
01741       << " is negative, so it cannot be correctly converted to the unsigned type "
01742       << TypeNameTraits<UnsignedIntType>::name () << ".");
01743 
01744     return static_cast<UnsignedIntType> (t);
01745   }
01746 };
01747 
01748 } // namespace (anonymous)
01749 
01750 
01752 template<>
01753 class ValueTypeConversionTraits<short, unsigned short> {
01754 public:
01755   static short convert (const unsigned short t) {
01756     return UnsignedToSignedValueTypeConversionTraits<short, unsigned short>::convert (t);
01757   }
01758 
01759   static short safeConvert (const unsigned short t) {
01760     return UnsignedToSignedValueTypeConversionTraits<short, unsigned short>::safeConvert (t);
01761   }
01762 };
01763 
01764 
01766 template<>
01767 class ValueTypeConversionTraits<unsigned short, short> {
01768 public:
01769   static unsigned short convert (const short t) {
01770     return SignedToUnsignedValueTypeConversionTraits<unsigned short, short>::convert (t);
01771   }
01772 
01773   static unsigned short safeConvert (const short t) {
01774     return SignedToUnsignedValueTypeConversionTraits<unsigned short, short>::safeConvert (t);
01775   }
01776 };
01777 
01778 
01780 template<>
01781 class ValueTypeConversionTraits<int, unsigned int> {
01782 public:
01783   static int convert (const unsigned int t) {
01784     return UnsignedToSignedValueTypeConversionTraits<int, unsigned int>::convert (t);
01785   }
01786 
01787   static int safeConvert (const unsigned int t) {
01788     return UnsignedToSignedValueTypeConversionTraits<int, unsigned int>::safeConvert (t);
01789   }
01790 };
01791 
01792 
01794 template<>
01795 class ValueTypeConversionTraits<unsigned int, int> {
01796 public:
01797   static unsigned int convert (const int t) {
01798     return SignedToUnsignedValueTypeConversionTraits<unsigned int, int>::convert (t);
01799   }
01800 
01801   static unsigned int safeConvert (const int t) {
01802     return SignedToUnsignedValueTypeConversionTraits<unsigned int, int>::safeConvert (t);
01803   }
01804 };
01805 
01806 
01808 template<>
01809 class ValueTypeConversionTraits<long, unsigned long> {
01810 public:
01811   static long convert (const unsigned long t) {
01812     return UnsignedToSignedValueTypeConversionTraits<long, unsigned long>::convert (t);
01813   }
01814 
01815   static long safeConvert (const unsigned long t) {
01816     return UnsignedToSignedValueTypeConversionTraits<long, unsigned long>::safeConvert (t);
01817   }
01818 };
01819 
01820 
01822 template<>
01823 class ValueTypeConversionTraits<unsigned long, long> {
01824 public:
01825   static unsigned long convert (const long t) {
01826     return SignedToUnsignedValueTypeConversionTraits<unsigned long, long>::convert (t);
01827   }
01828 
01829   static unsigned long safeConvert (const long t) {
01830     return SignedToUnsignedValueTypeConversionTraits<unsigned long, long>::safeConvert (t);
01831   }
01832 };
01833 
01834 
01835 #ifdef HAVE_TEUCHOS_LONG_LONG_INT
01836 
01838 template<>
01839 class ValueTypeConversionTraits<long long, unsigned long long> {
01840 public:
01841   static long long convert (const unsigned long long t) {
01842     return UnsignedToSignedValueTypeConversionTraits<long long, unsigned long long>::convert (t);
01843   }
01844 
01845   static long long safeConvert (const unsigned long long t) {
01846     return UnsignedToSignedValueTypeConversionTraits<long long, unsigned long long>::safeConvert (t);
01847   }
01848 };
01849 
01850 
01852 template<>
01853 class ValueTypeConversionTraits<unsigned long long, long long> {
01854 public:
01855   static unsigned long long convert (const long long t) {
01856     return SignedToUnsignedValueTypeConversionTraits<unsigned long long, long long>::convert (t);
01857   }
01858 
01859   static unsigned long long safeConvert (const long long t) {
01860     return SignedToUnsignedValueTypeConversionTraits<unsigned long long, long long>::safeConvert (t);
01861   }
01862 };
01863 
01864 #endif // HAVE_TEUCHOS_LONG_LONG_INT
01865 
01866 //
01867 // * Specializations for conversions between different built-in
01868 //   integer types.
01869 //
01870 
01872 template<>
01873 class ValueTypeConversionTraits<short, int> {
01874 public:
01880   static short convert (const int t) {
01881     // Implicit conversion may cause compiler warnings, but
01882     // static_cast does not.
01883     return static_cast<short> (t);
01884   }
01885 
01887   static short safeConvert (const int t) {
01888     const short minShort = std::numeric_limits<short>::min ();
01889     const short maxShort = std::numeric_limits<short>::max ();
01890 
01891     // Casting from short to int never overflows, since the C++
01892     // standard guarantees that sizeof (short) <= sizeof (int).
01893     TEUCHOS_TEST_FOR_EXCEPTION(
01894       t < static_cast<int> (minShort) ||
01895       t > static_cast<int> (maxShort),
01896       std::range_error,
01897       "Teuchos::ValueTypeConversionTraits<short, int>::safeConvert: "
01898       "Input int t = " << t << " is out of the valid range [" << minShort
01899       << ", " << maxShort << "] for conversion to short.");
01900 
01901     return static_cast<short> (t);
01902   }
01903 };
01904 
01905 
01907 template<>
01908 class ValueTypeConversionTraits<short, long> {
01909 public:
01915   static short convert (const long t) {
01916     // Implicit conversion may cause compiler warnings, but
01917     // static_cast does not.
01918     return static_cast<short> (t);
01919   }
01920 
01922   static short safeConvert (const long t) {
01923     const short minShort = std::numeric_limits<short>::min ();
01924     const short maxShort = std::numeric_limits<short>::max ();
01925 
01926     // Casting from short to long never overflows, since the C++
01927     // standard guarantees that sizeof (short) <= sizeof (long).
01928     TEUCHOS_TEST_FOR_EXCEPTION(
01929       t < static_cast<long> (minShort) ||
01930       t > static_cast<long> (maxShort),
01931       std::range_error,
01932       "Teuchos::ValueTypeConversionTraits<short, long>::safeConvert: "
01933       "Input long t = " << t << " is out of the valid range [" << minShort
01934       << ", " << maxShort << "] for conversion to short.");
01935 
01936     return static_cast<short> (t);
01937   }
01938 };
01939 
01940 
01942 template<>
01943 class ValueTypeConversionTraits<int, long> {
01944 public:
01950   static int convert (const long t) {
01951     // Implicit conversion from long to int may cause compiler
01952     // warnings, but static_cast does not.
01953     return static_cast<int> (t);
01954   }
01955 
01957   static int safeConvert (const long t) {
01958     const int minInt = std::numeric_limits<int>::min ();
01959     const int maxInt = std::numeric_limits<int>::max ();
01960 
01961     // Casting from int to long never overflows, since the C++
01962     // standard guarantees that sizeof (int) <= sizeof (long).
01963     TEUCHOS_TEST_FOR_EXCEPTION(
01964       t < static_cast<long> (minInt) ||
01965       t > static_cast<long> (maxInt),
01966       std::range_error,
01967       "Teuchos::ValueTypeConversionTraits<int, long>::safeConvert: "
01968       "Input long t = " << t << " is out of the valid range [" << minInt
01969       << ", " << maxInt << "] for conversion to int.");
01970 
01971     // Implicit conversion from long to int may cause compiler
01972     // warnings, but static_cast does not.
01973     return static_cast<int> (t);
01974   }
01975 };
01976 
01977 
01979 template<>
01980 class ValueTypeConversionTraits<int, unsigned long> {
01981 public:
01988   static int convert (const unsigned long t) {
01989     // Implicit conversion may cause compiler warnings, but
01990     // static_cast does not.
01991     return static_cast<int> (t);
01992   }
01993 
01995   static int safeConvert (const unsigned long t) {
01996     const int minInt = std::numeric_limits<int>::min ();
01997     const int maxInt = std::numeric_limits<int>::max ();
01998 
01999     // On some platforms, sizeof(int) == sizeof(long).  (This is the
02000     // "LLP64" model of Win64, which aims for backwards compatibility
02001     // with 32-bit code by making sizeof(int) == sizeof(long) == 4.)
02002     // If this is the case, then we can't safely cast unsigned long to
02003     // int, or unsigned int to long, because values with the most
02004     // significant bit set will overflow to negative values.
02005 
02006     // The C++ standard promises that sizeof (int) <= sizeof (unsigned
02007     // long).  We use #if with INT_MAX and LONG_MAX to test for this,
02008     // rather than if statements, in order to avoid a compiler
02009     // warning.  Thanks to Jeremie Gaidamour (13 Nov 2012) for letting
02010     // me know about the warning.
02011 #if INT_MAX == LONG_MAX
02012     // The two types have the same number of bits.  Thus,
02013     // two's-complement arithmetic means that if casting from unsigned
02014     // long to int results in a negative number, it overflowed.
02015     // Otherwise, it didn't overflow (same number of bits).
02016     TEUCHOS_TEST_FOR_EXCEPTION(
02017       static_cast<int> (t) < static_cast<int> (0),
02018       std::range_error,
02019       "Teuchos::ValueTypeConversionTraits<int, unsigned long>::safeConvert: "
02020       "Input unsigned long t = " << t << " is out of the valid range ["
02021       << minInt << ", " << maxInt << "] for conversion to int.");
02022 #else // INT_MAX < LONG_MAX
02023     // t is unsigned, so it is >= 0 by definition.
02024     // Casting from int to unsigned long won't overflow in this case.
02025     TEUCHOS_TEST_FOR_EXCEPTION(
02026       t > static_cast<unsigned long> (maxInt),
02027       std::range_error,
02028       "Teuchos::ValueTypeConversionTraits<int, unsigned long>::safeConvert: "
02029       "Input unsigned long t = " << t << " is out of the valid range ["
02030       << minInt << ", " << maxInt << "] for conversion to int.  An unchecked "
02031       "cast would have resulted in " << static_cast<int> (t) << ".");
02032 #endif // INT_MAX == LONG_MAX
02033 
02034     // Implicit conversion from unsigned long to int may cause
02035     // compiler warnings, but static_cast does not.
02036     return static_cast<int> (t);
02037   }
02038 };
02039 
02040 
02042 template<>
02043 class ValueTypeConversionTraits<long, unsigned int> {
02044 public:
02052   static long convert (const unsigned int t) {
02053     // Implicit conversion may cause compiler warnings, but
02054     // static_cast does not.
02055     return static_cast<long> (t);
02056   }
02057 
02059   static long safeConvert (const unsigned int t) {
02060     // On some platforms, sizeof(int) == sizeof(long).  (This is the
02061     // "LLP64" model of Win64, which aims for backwards compatibility
02062     // with 32-bit code by making sizeof(int) == sizeof(long) == 4.)
02063     // If this is the case, then we can't safely cast unsigned long to
02064     // int, or unsigned int to long, because values with the most
02065     // significant bit set will overflow to negative values.
02066 
02067     // The C++ standard promises that sizeof (unsigned int) <= sizeof
02068     // (long).  If strictly less, then the conversion won't overflow.
02069     // We protect the test with an #ifdef ... #endif to avoid compiler
02070     // warnings like the following: "warning: comparison is always
02071     // false due to limited range of data type".
02072 #if UINT_MAX == LONG_MAX
02073     const long minLong = std::numeric_limits<long>::min ();
02074     const long maxLong = std::numeric_limits<long>::max ();
02075 
02076     // The two types have the same number of bits.  Thus,
02077     // two's-complement arithmetic means that if casting from
02078     // unsigned int to long results in a negative number, it
02079     // overflowed.  Otherwise, it didn't overflow (same number of
02080     // bits).
02081     TEUCHOS_TEST_FOR_EXCEPTION(
02082       static_cast<long> (t) < static_cast<long> (0),
02083       std::range_error,
02084       "Teuchos::ValueTypeConversionTraits<long, unsigned int>::safeConvert: "
02085       "Input unsigned int t = " << t << " is out of the valid range ["
02086       << minLong << ", " << maxLong << "] for conversion to long.");
02087 #endif // UINT_MAX == LONG_MAX
02088 
02089     return static_cast<long> (t);
02090   }
02091 };
02092 
02093 
02095 template<>
02096 class ValueTypeConversionTraits<unsigned int, long> {
02097 public:
02104   static unsigned int convert (const long t) {
02105     // Implicit conversion from long to unsigned int may cause
02106     // compiler warnings, but static_cast does not.
02107     return static_cast<unsigned int> (t);
02108   }
02109 
02111   static unsigned int safeConvert (const long t) {
02112     // On some platforms, sizeof(int) == sizeof(long).  (This is the
02113     // "LLP64" model of Win64, which aims for backwards compatibility
02114     // with 32-bit code by making sizeof(int) == sizeof(long) == 4.)
02115     // In this case, conversion from long to unsigned int can't
02116     // overflow.
02117 
02118     // The C++ standard promises that sizeof (unsigned int) <= sizeof (long).
02119     if (sizeof (unsigned int) < sizeof (long)) {
02120       const unsigned int maxInt = std::numeric_limits<unsigned int>::max ();
02121 
02122       TEUCHOS_TEST_FOR_EXCEPTION(
02123         t < static_cast<long> (0) || t > static_cast<long> (maxInt),
02124         std::range_error,
02125         "Teuchos::ValueTypeConversionTraits<unsigned int, long>::safeConvert: "
02126         "Input long t = " << t << " is out of the valid range [0, "
02127         << maxInt << "] for conversion to unsigned int.");
02128     }
02129     // Implicit conversion from long to unsigned int may cause
02130     // compiler warnings, but static_cast does not.
02131     return static_cast<unsigned int> (t);
02132   }
02133 };
02134 
02135 
02137 template<>
02138 class ValueTypeConversionTraits<unsigned int, unsigned long> {
02139 public:
02146   static unsigned int convert (const unsigned long t) {
02147     // Implicit conversion from unsigned long to unsigned int may cause
02148     // compiler warnings, but static_cast does not.
02149     return static_cast<unsigned int> (t);
02150   }
02151 
02153   static unsigned int safeConvert (const unsigned long t) {
02154     const unsigned int minInt = 0; // Had better be, since it's unsigned.
02155     const unsigned int maxInt = std::numeric_limits<unsigned int>::max ();
02156 
02157     // t >= 0 by definition, because it is unsigned.
02158     TEUCHOS_TEST_FOR_EXCEPTION(
02159       t > static_cast<unsigned long> (maxInt),
02160       std::range_error,
02161       "Teuchos::ValueTypeConversionTraits<unsigned int, unsigned long>::safeConvert: "
02162       "Input unsigned long t = " << t << " is out of the valid range [" << minInt
02163       << ", " << maxInt << "] for conversion to unsigned int.");
02164 
02165     // Implicit conversion from unsigned long to unsigned int may
02166     // cause compiler warnings, but static_cast does not.
02167     return static_cast<unsigned int> (t);
02168   }
02169 };
02170 
02171 #ifdef HAVE_TEUCHOS_LONG_LONG_INT
02172 
02174 template<>
02175 class ValueTypeConversionTraits<int, long long> {
02176 public:
02182   static int convert (const long long t) {
02183     // Implicit conversion from long long to int may cause compiler
02184     // warnings, but static_cast does not.
02185     return static_cast<int> (t);
02186   }
02187 
02189   static int safeConvert (const long long t) {
02190     const int minInt = std::numeric_limits<int>::min ();
02191     const int maxInt = std::numeric_limits<int>::max ();
02192 
02193     TEUCHOS_TEST_FOR_EXCEPTION(
02194       t < static_cast<long long> (minInt) ||
02195       t > static_cast<long long> (maxInt),
02196       std::range_error,
02197       "Teuchos::ValueTypeConversionTraits<int, long long>::safeConvert: "
02198       "Input long long t = " << t << " is out of the valid range [" << minInt
02199       << ", " << maxInt << "] for conversion to int.");
02200 
02201     // Implicit conversion from long long to int may cause compiler
02202     // warnings, but static_cast does not.
02203     return static_cast<int> (t);
02204   }
02205 };
02206 
02207 
02209 template<>
02210 class ValueTypeConversionTraits<unsigned int, long long> {
02211 public:
02218   static unsigned int convert (const long long t) {
02219     // Implicit conversion from long long to unsigned int may cause
02220     // compiler warnings, but static_cast does not.
02221     return static_cast<unsigned int> (t);
02222   }
02223 
02225   static unsigned int safeConvert (const long long t) {
02226     const unsigned int minInt = 0; // Had better be, because it's unsigned.
02227     const unsigned int maxInt = std::numeric_limits<unsigned int>::max ();
02228 
02229     TEUCHOS_TEST_FOR_EXCEPTION(
02230       t < static_cast<long long> (minInt) || t > static_cast<long long> (maxInt),
02231       std::range_error,
02232       "Teuchos::ValueTypeConversionTraits<unsigned int, long long>::safeConvert: "
02233       "Input long long t = " << t << " is out of the valid range [" << minInt
02234       << ", " << maxInt << "] for conversion to unsigned int.");
02235 
02236     // Implicit conversion from long long to unsigned int may cause
02237     // compiler warnings, but static_cast does not.
02238     return static_cast<unsigned int> (t);
02239   }
02240 };
02241 
02242 
02244 template<>
02245 class ValueTypeConversionTraits<int, unsigned long long> {
02246 public:
02252   static int convert (const unsigned long long t) {
02253     // Implicit conversion from unsigned long long to int may cause
02254     // compiler warnings, but static_cast does not.
02255     return static_cast<int> (t);
02256   }
02257 
02259   static int safeConvert (const unsigned long long t) {
02260     const int minInt = std::numeric_limits<int>::min ();
02261     const int maxInt = std::numeric_limits<int>::max ();
02262 
02263     // t >= 0 by definition, because it is unsigned.
02264     TEUCHOS_TEST_FOR_EXCEPTION(
02265       t > static_cast<unsigned long long> (maxInt),
02266       std::invalid_argument,
02267       "Teuchos::ValueTypeConversionTraits<int, unsigned long long>::safeConvert: "
02268       "Input unsigned long long t = " << t << " is out of the valid range [" << minInt
02269       << ", " << maxInt << "] for conversion to int.");
02270 
02271     // Implicit conversion from unsigned long long to int may cause
02272     // compiler warnings, but static_cast does not.
02273     return static_cast<int> (t);
02274   }
02275 };
02276 
02277 
02279 template<>
02280 class ValueTypeConversionTraits<unsigned int, unsigned long long> {
02281 public:
02288   static unsigned int convert (const unsigned long long t) {
02289     // Implicit conversion from unsigned long long to unsigned int may
02290     // cause compiler warnings, but static_cast does not.
02291     return static_cast<unsigned int> (t);
02292   }
02293 
02295   static unsigned int safeConvert (const unsigned long long t) {
02296     const unsigned int minInt = 0; // Had better be, since it's unsigned.
02297     const unsigned int maxInt = std::numeric_limits<unsigned int>::max ();
02298 
02299     // t >= 0 by definition, because it is unsigned.
02300     TEUCHOS_TEST_FOR_EXCEPTION(
02301       t > static_cast<unsigned long long> (maxInt),
02302       std::invalid_argument,
02303       "Teuchos::ValueTypeConversionTraits<unsigned int, unsigned long long>::safeConvert: "
02304       "Input unsigned long long t = " << t << " is out of the valid range [" << minInt
02305       << ", " << maxInt << "] for conversion to unsigned int.");
02306 
02307     // Implicit conversion from unsigned long long to unsigned int may
02308     // cause compiler warnings, but static_cast does not.
02309     return static_cast<unsigned int> (t);
02310   }
02311 };
02312 
02313 #endif // HAVE_TEUCHOS_LONG_LONG_INT
02314 
02315 //
02316 // * Conversions from built-in integer types to built-in real-valued
02317 //   floating-point types.
02318 //
02319 
02320 #ifdef HAVE_TEUCHOS_LONG_LONG_INT
02321 
02323 template<>
02324 class ValueTypeConversionTraits<float, long long> {
02325 public:
02331   static float convert (const long long t) {
02332     // Implicit conversion from long long to float may cause compiler
02333     // warnings, but static_cast does not.
02334     return static_cast<float> (t);
02335   }
02336 
02338   static float safeConvert (const long long t) {
02339     // std::numeric_limits<float>::min() gives the minimum _positive_
02340     // normalized value of type float.  IEEE 754 floating-point values
02341     // can change sign just by flipping the sign bit, so the "most
02342     // negative" finite float is just the negative of the "most
02343     // positive" finite float.
02344     const float minFloat = -std::numeric_limits<float>::max ();
02345     const float maxFloat = std::numeric_limits<float>::max ();
02346 
02347     // mfh 16 Nov 2012: On my platform (gcc 4.7.2, Red Hat Linux 5,
02348     // Intel x86_64), first casting [minFloat,maxFloat] to long long
02349     // (so that the comparison only compares long long values)
02350     // gives different results in the comparison below than just
02351     // comparing t (as a long long) with minFloat and maxFloat.  It
02352     // doesn't matter whether you use static_cast<long long> (...) or
02353     // (long long) (...) to do the cast: the original float interval
02354     // of [-3.40282e+38, 3.40282e+38] becomes [-9223372036854775808,
02355     // -9223372036854775808], which is obviously wrong.
02356     TEUCHOS_TEST_FOR_EXCEPTION(
02357       t < minFloat || t > maxFloat,
02358       std::range_error,
02359       "Teuchos::ValueTypeConversionTraits<float, long long>::safeConvert: "
02360       "Input long long t = " << t << " is out of the valid range [" << minFloat
02361       << ", " << maxFloat << "] for conversion to float.");
02362 
02363     // Implicit conversion from long long to float may cause compiler
02364     // warnings, but static_cast does not.
02365     return static_cast<float> (t);
02366   }
02367 };
02368 
02369 
02371 template<>
02372 class ValueTypeConversionTraits<float, unsigned long long> {
02373 public:
02379   static float convert (const unsigned long long t) {
02380     // Implicit conversion from unsigned long long to float may cause
02381     // compiler warnings, but static_cast does not.
02382     return static_cast<float> (t);
02383   }
02384 
02386   static float safeConvert (const unsigned long long t) {
02387     // std::numeric_limits<float>::min() gives the minimum _positive_
02388     // normalized value of type float.  IEEE 754 floating-point values
02389     // can change sign just by flipping the sign bit, so the "most
02390     // negative" finite float is just the negative of the "most
02391     // positive" finite float.
02392     const float minFloat = -std::numeric_limits<float>::max ();
02393     const float maxFloat = std::numeric_limits<float>::max ();
02394 
02395     // t >= 0 by definition, because it is unsigned.
02396     //
02397     // mfh 16 Nov 2012: See my note above on the <float, long long>
02398     // specialization that explains why I don't cast maxFloat to
02399     // unsigned long long here.
02400     TEUCHOS_TEST_FOR_EXCEPTION(
02401       t > maxFloat,
02402       std::invalid_argument,
02403       "Teuchos::ValueTypeConversionTraits<float, unsigned long long>::safeConvert: "
02404       "Input unsigned long long t = " << t << " is out of the valid range [" << minFloat
02405       << ", " << maxFloat << "] for conversion to float.");
02406 
02407     // Implicit conversion from unsigned long long to float may cause
02408     // compiler warnings, but static_cast does not.
02409     return static_cast<float> (t);
02410   }
02411 };
02412 
02413 #endif // HAVE_TEUCHOS_LONG_LONG_INT
02414 
02415 //
02416 // * Other conversions
02417 //
02418 
02420 template<int N>
02421 class ValueTypeConversionTraits<std::string, char[N]> {
02422 public:
02423   static std::string convert( const char t[] )
02424     { return std::string(t); }
02425   static std::string safeConvert( const char t[] )
02426     { return std::string(t); }
02427 };
02428 
02429 //
02430 // * Conversions from built-in integer types to std::complex<T>.
02431 //
02432 
02433 #ifdef HAVE_TEUCHOS_COMPLEX
02434 
02436 template<class RealType>
02437 class ValueTypeConversionTraits<std::complex<RealType>, short> {
02438 public:
02439   inline static std::complex<RealType> convert (const short t) {
02440     // Let RealType handle the conversion of the zero imaginary part.
02441     return std::complex<RealType> (t, as<RealType> (0));
02442   }
02443   static std::complex<RealType> safeConvert (const short t) {
02444     // Let RealType handle the conversion of the zero imaginary part.
02445     return std::complex<RealType> (t, asSafe<RealType> (0));
02446   }
02447 };
02448 
02450 template<class RealType>
02451 class ValueTypeConversionTraits<std::complex<RealType>, unsigned short> {
02452 public:
02453   inline static std::complex<RealType> convert (const unsigned short t) {
02454     // Let RealType handle the conversion of the zero imaginary part.
02455     return std::complex<RealType> (t, as<RealType> (0));
02456   }
02457   static std::complex<RealType> safeConvert (const unsigned short t) {
02458     // Let RealType handle the conversion of the zero imaginary part.
02459     return std::complex<RealType> (t, asSafe<RealType> (0));
02460   }
02461 };
02462 
02464 template<class RealType>
02465 class ValueTypeConversionTraits<std::complex<RealType>, int> {
02466 public:
02467   inline static std::complex<RealType> convert (const int t) {
02468     // Let RealType handle the conversion of the zero imaginary part.
02469     return std::complex<RealType> (t, as<RealType> (0));
02470   }
02471   static std::complex<RealType> safeConvert (const int t) {
02472     // Let RealType handle the conversion of the zero imaginary part.
02473     return std::complex<RealType> (t, asSafe<RealType> (0));
02474   }
02475 };
02476 
02478 template<class RealType>
02479 class ValueTypeConversionTraits<std::complex<RealType>, unsigned int> {
02480 public:
02481   inline static std::complex<RealType> convert (const unsigned int t) {
02482     // Let RealType handle the conversion of the zero imaginary part.
02483     return std::complex<RealType> (t, as<RealType> (0));
02484   }
02485   static std::complex<RealType> safeConvert (const unsigned int t) {
02486     // Let RealType handle the conversion of the zero imaginary part.
02487     return std::complex<RealType> (t, asSafe<RealType> (0));
02488   }
02489 };
02490 
02492 template<class RealType>
02493 class ValueTypeConversionTraits<std::complex<RealType>, long> {
02494 public:
02495   inline static std::complex<RealType> convert (const long t) {
02496     // Let RealType handle the conversion of the zero imaginary part.
02497     return std::complex<RealType> (t, as<RealType> (0));
02498   }
02499   static std::complex<RealType> safeConvert (const long t) {
02500     // Let RealType handle the conversion of the zero imaginary part.
02501     return std::complex<RealType> (t, asSafe<RealType> (0));
02502   }
02503 };
02504 
02506 template<class RealType>
02507 class ValueTypeConversionTraits<std::complex<RealType>, unsigned long> {
02508 public:
02509   inline static std::complex<RealType> convert (const unsigned long t) {
02510     // Let RealType handle the conversion of the zero imaginary part.
02511     return std::complex<RealType> (t, as<RealType> (0));
02512   }
02513   static std::complex<RealType> safeConvert (const unsigned long t) {
02514     // Let RealType handle the conversion of the zero imaginary part.
02515     return std::complex<RealType> (t, asSafe<RealType> (0));
02516   }
02517 };
02518 
02519 #ifdef HAVE_TEUCHOS_LONG_LONG_INT
02520 
02522 template<class RealType>
02523 class ValueTypeConversionTraits<std::complex<RealType>, long long> {
02524 public:
02525   inline static std::complex<RealType> convert (const long long t) {
02526     // Let RealType handle the conversion of the zero imaginary part.
02527     return std::complex<RealType> (t, as<RealType> (0));
02528   }
02529   static std::complex<RealType> safeConvert (const long long t) {
02530     // Let RealType handle the conversion of the zero imaginary part.
02531     return std::complex<RealType> (t, asSafe<RealType> (0));
02532   }
02533 };
02534 
02536 template<class RealType>
02537 class ValueTypeConversionTraits<std::complex<RealType>, unsigned long long> {
02538 public:
02539   inline static std::complex<RealType> convert (const unsigned long long t) {
02540     // Let RealType handle the conversion of the zero imaginary part.
02541     return std::complex<RealType> (t, as<RealType> (0));
02542   }
02543   static std::complex<RealType> safeConvert (const unsigned long long t) {
02544     // Let RealType handle the conversion of the zero imaginary part.
02545     return std::complex<RealType> (t, asSafe<RealType> (0));
02546   }
02547 };
02548 
02549 #endif // HAVE_TEUCHOS_LONG_LONG_INT
02550 #endif // HAVE_TEUCHOS_COMPLEX
02551 
02552 //
02553 // * Conversions for dd_real and qd_real
02554 //
02555 
02556 #ifdef HAVE_TEUCHOS_QD
02557 
02559 template <>
02560 class ValueTypeConversionTraits<double, qd_real> {
02561 public:
02562   inline static double convert (const qd_real t) {
02563     return to_double (t);
02564   }
02565   static double safeConvert (const qd_real t) {
02566     // std::numeric_limits<double>::min() gives the minimum _positive_
02567     // normalized value of type double.  IEEE 754 floating-point
02568     // values can change sign just by flipping the sign bit, so the
02569     // "most negative" finite double is just the negative of the "most
02570     // positive" finite double.
02571     const qd_real minVal = -std::numeric_limits<double>::max ();
02572     const qd_real maxVal = std::numeric_limits<double>::max ();
02573 
02574     TEUCHOS_TEST_FOR_EXCEPTION(
02575       t < minVal || t > maxVal,
02576       std::range_error,
02577       "Teuchos::ValueTypeConversionTraits<double, qd_real>::safeConvert: "
02578       "Input qd_real t = " << t << " is out of the valid range [" << minVal
02579       << ", " << maxVal << "] for conversion to double.");
02580 
02581     return to_double (t);
02582   }
02583 };
02584 
02586 template <>
02587 class ValueTypeConversionTraits<float, qd_real> {
02588 public:
02589   inline static float convert (const qd_real t) {
02590     // In a debug build, this should also test the double->float
02591     // conversion for overflow.
02592     return as<float> (to_double (t));
02593   }
02594 
02595   static float safeConvert (const qd_real t) {
02596     // std::numeric_limits<float>::min() gives the minimum _positive_
02597     // normalized value of type float.  IEEE 754 floating-point
02598     // values can change sign just by flipping the sign bit, so the
02599     // "most negative" finite float is just the negative of the "most
02600     // positive" finite float.
02601     //
02602     // qd_real has a constructor for double, but not for float,
02603     // so we cast to double first.
02604     const qd_real minVal = static_cast<double> (-std::numeric_limits<float>::max ());
02605     const qd_real maxVal = static_cast<double> (std::numeric_limits<float>::max ());
02606 
02607     TEUCHOS_TEST_FOR_EXCEPTION(
02608       t < minVal || t > maxVal,
02609       std::range_error,
02610       "Teuchos::ValueTypeConversionTraits<float, qd_real>::safeConvert: "
02611       "Input qd_real t = " << t << " is out of the valid range [" << minVal
02612       << ", " << maxVal << "] for conversion to float.");
02613 
02614     // This should also test the double->float conversion for overflow.
02615     return asSafe<float> (to_double (t));
02616   }
02617 };
02618 
02620 template <>
02621 class ValueTypeConversionTraits<int, qd_real> {
02622 public:
02623   inline static int convert (const qd_real t) {
02624     return to_int (t);
02625   }
02626   static int safeConvert (const qd_real t) {
02627     // qd_real has a constructor for int.
02628     const qd_real minVal = std::numeric_limits<int>::min ();
02629     const qd_real maxVal = std::numeric_limits<int>::max ();
02630 
02631     TEUCHOS_TEST_FOR_EXCEPTION(
02632       t < minVal || t > maxVal,
02633       std::range_error,
02634       "Teuchos::ValueTypeConversionTraits<int, qd_real>::safeConvert: "
02635       "Input qd_real t = " << t << " is out of the valid range [" << minVal
02636       << ", " << maxVal << "] for conversion to int.");
02637     return to_int (t);
02638   }
02639 };
02640 
02642 template <>
02643 class ValueTypeConversionTraits<dd_real, qd_real> {
02644 public:
02645   inline static dd_real convert (const qd_real t) {
02646     return to_dd_real(t);
02647   }
02648   static dd_real safeConvert (const qd_real t) {
02649     // std::numeric_limits<dd_real>::min() gives the minimum
02650     // _positive_ (normalized? not sure what this means for dd_real --
02651     // mfh 14 Nov 2012) value of type dd_real.  dd_real values are
02652     // built from two IEEE 754 doubles.  This means they can change
02653     // sign just by flipping the sign bit, so the "most negative"
02654     // finite dd_real is just the negative of the "most positive"
02655     // finite dd_real.
02656     //
02657     // qd_real has a constructor for dd_real.
02658     const qd_real minVal = -std::numeric_limits<dd_real>::max ();
02659     const qd_real maxVal = std::numeric_limits<dd_real>::max ();
02660 
02661     TEUCHOS_TEST_FOR_EXCEPTION(
02662       t < minVal || t > maxVal,
02663       std::range_error,
02664       "Teuchos::ValueTypeConversionTraits<dd_real, qd_real>::safeConvert: "
02665       "Input qd_real t = " << t << " is out of the valid range [" << minVal
02666       << ", " << maxVal << "] for conversion to dd_real.");
02667 
02668     return to_dd_real (t);
02669   }
02670 };
02671 
02673 template <>
02674 class ValueTypeConversionTraits<double, dd_real> {
02675 public:
02676   inline static double convert (const dd_real t) {
02677     return to_double (t);
02678   }
02679   static double safeConvert (const dd_real t) {
02680     // std::numeric_limits<double>::min() gives the minimum _positive_
02681     // normalized value of type double.  IEEE 754 floating-point
02682     // values can change sign just by flipping the sign bit, so the
02683     // "most negative" finite double is just the negative of the "most
02684     // positive" finite double.
02685     //
02686     // qd_real has a constructor for double.
02687     const dd_real minVal = -std::numeric_limits<double>::max ();
02688     const dd_real maxVal = std::numeric_limits<double>::max ();
02689 
02690     TEUCHOS_TEST_FOR_EXCEPTION(
02691       t < minVal || t > maxVal,
02692       std::range_error,
02693       "Teuchos::ValueTypeConversionTraits<double, dd_real>::safeConvert: "
02694       "Input dd_real t = " << t << " is out of the valid range [" << minVal
02695       << ", " << maxVal << "] for conversion to double.");
02696 
02697     return to_double (t);
02698   }
02699 };
02700 
02702 template <>
02703 class ValueTypeConversionTraits<float, dd_real> {
02704 public:
02705   inline static float convert (const dd_real t) {
02706     // This also checks for double->float overflow in a debug build.
02707     return as<float> (to_double (t));
02708   }
02709   static float safeConvert (const dd_real t) {
02710     // std::numeric_limits<float>::min() gives the minimum _positive_
02711     // normalized value of type float.  IEEE 754 floating-point
02712     // values can change sign just by flipping the sign bit, so the
02713     // "most negative" finite float is just the negative of the "most
02714     // positive" finite float.
02715     //
02716     // dd_real has a constructor for double but not for float,
02717     // so we cast to double first.
02718     const dd_real minVal = static_cast<double> (-std::numeric_limits<float>::max ());
02719     const dd_real maxVal = static_cast<double> (std::numeric_limits<float>::max ());
02720 
02721     TEUCHOS_TEST_FOR_EXCEPTION(
02722       t < minVal || t > maxVal,
02723       std::range_error,
02724       "Teuchos::ValueTypeConversionTraits<float, dd_real>::safeConvert: "
02725       "Input dd_real t = " << t << " is out of the valid range [" << minVal
02726       << ", " << maxVal << "] for conversion to float.");
02727 
02728     // This also checks for double->float overflow.
02729     return as<float> (to_double (t));
02730   }
02731 };
02732 
02734 template <>
02735 class ValueTypeConversionTraits<int, dd_real> {
02736 public:
02737   inline static int convert (const dd_real t) {
02738     return to_int (t);
02739   }
02740   static int safeConvert (const dd_real t) {
02741     // dd_real has a constructor for int.
02742     const dd_real minVal = std::numeric_limits<int>::min ();
02743     const dd_real maxVal = std::numeric_limits<int>::max ();
02744 
02745     TEUCHOS_TEST_FOR_EXCEPTION(
02746       t < minVal || t > maxVal,
02747       std::range_error,
02748       "Teuchos::ValueTypeConversionTraits<int, dd_real>::safeConvert: "
02749       "Input dd_real t = " << t << " is out of the valid range [" << minVal
02750       << ", " << maxVal << "] for conversion to int.");
02751     return to_int (t);
02752   }
02753 };
02754 
02756 template <>
02757 class ValueTypeConversionTraits<qd_real, long unsigned int> {
02758 public:
02759   inline static qd_real convert( const long unsigned int t ) {
02760     // FIXME (mfh 14 Nov 2012): qd_real unfortunately lacks a
02761     // constructor or conversion function for conversions from
02762     // built-in integer types other than int.  However, it does allow
02763     // reading in values from a string.  We could use this to convert
02764     // from any type to qd_real, by first writing the value to an
02765     // std::ostringstream, then creating a qd_real from the resulting
02766     // string.
02767     return ValueTypeConversionTraits<qd_real,int>::convert(ValueTypeConversionTraits<int,long unsigned int>::convert(t));
02768   }
02769   inline static qd_real safeConvert( const long unsigned int t )
02770     { return ValueTypeConversionTraits<qd_real,int>::safeConvert(ValueTypeConversionTraits<int,long unsigned int>::safeConvert(t)); }
02771 };
02772 
02774 template <>
02775 class ValueTypeConversionTraits<dd_real, long unsigned int> {
02776 public:
02777   inline static dd_real convert( const long unsigned int t ) {
02778     // FIXME (mfh 14 Nov 2012): dd_real unfortunately lacks a
02779     // constructor or conversion function for conversions from
02780     // built-in integer types other than int.  However, it does allow
02781     // reading in values from a string.  We could use this to convert
02782     // from any type to dd_real, by first writing the value to an
02783     // std::ostringstream, then creating a dd_real from the resulting
02784     // string.
02785     return ValueTypeConversionTraits<dd_real,int>::convert(ValueTypeConversionTraits<int,long unsigned int>::convert(t));
02786   }
02787   inline static dd_real safeConvert( const long unsigned int t )
02788     { return ValueTypeConversionTraits<dd_real,int>::safeConvert(ValueTypeConversionTraits<int,long unsigned int>::safeConvert(t)); }
02789 };
02790 
02791 #endif // HAVE_TEUCHOS_QD
02792 
02793 // ToDo: Add more specializations as needed!
02794 
02795 
02796 } // end namespace Teuchos
02797 
02798 
02799 #endif // TEUCHOS_AS_HPP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines