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 #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     return intToString<long long> (t, &strtoll, "long long");
00713   }
00714 
00716   static long long convert (const std::string& t) {
00717     return safeConvert (t);
00718   }
00719 };
00720 
00721 
00725 template<>
00726 class ValueTypeConversionTraits<unsigned long long, std::string> {
00727 public:
00733   static unsigned long long safeConvert (const std::string& t) {
00734     return intToString<unsigned long long> (t, &strtoull, "unsigned long long");
00735   }
00736 
00738   static unsigned long long convert (const std::string& t) {
00739     return safeConvert (t);
00740   }
00741 };
00742 
00743 #endif // HAVE_TEUCHOS_LONG_LONG_INT
00744 
00745 
00749 template<>
00750 class ValueTypeConversionTraits<long, std::string> {
00751 public:
00757   static long safeConvert (const std::string& t) {
00758     return intToString<long> (t, &strtol, "long");
00759   }
00760 
00762   static long convert (const std::string& t) {
00763     return safeConvert (t);
00764   }
00765 };
00766 
00767 
00771 template<>
00772 class ValueTypeConversionTraits<unsigned long, std::string> {
00773 public:
00779   static unsigned long safeConvert (const std::string& t) {
00780     return intToString<unsigned long> (t, &strtoul, "unsigned long");
00781   }
00782 
00784   static unsigned long convert (const std::string& t) {
00785     return safeConvert (t);
00786   }
00787 };
00788 
00789 
00793 template<>
00794 class ValueTypeConversionTraits<int, std::string> {
00795 private:
00797   static long safeConvertToLong (const std::string& t) {
00798     long val = 0;
00799     try {
00800       val = ValueTypeConversionTraits<long, std::string>::safeConvert (t);
00801     } catch (std::range_error&) {
00802       TEUCHOS_TEST_FOR_EXCEPTION(
00803         true,
00804         std::range_error,
00805         "Teuchos::ValueTypeConversionTraits<int, std::string>::convert: "
00806         "The given std::string \"" << t << "\" is too big to fit into long, so there is no way it could fit into int.");
00807     } catch (std::invalid_argument& e) {
00808       TEUCHOS_TEST_FOR_EXCEPTION(
00809         true,
00810         std::invalid_argument,
00811         "Teuchos::ValueTypeConversionTraits<int, std::string>::convert: "
00812         "Intermediate conversion from std::string to long failed, with the following error message: "
00813         << e.what ());
00814     }
00815     return val;
00816   }
00817 
00818 public:
00824   static int safeConvert (const std::string& t) {
00825     return asSafe<int> (safeConvertToLong (t));
00826   }
00827 
00829   static int convert (const std::string& t) {
00830     return as<int> (safeConvertToLong (t));
00831   }
00832 };
00833 
00834 
00838 template<>
00839 class ValueTypeConversionTraits<unsigned int, std::string> {
00840 private:
00842   static unsigned long safeConvertToUnsignedLong (const std::string& t) {
00843     unsigned long val = 0;
00844     try {
00845       val = as<unsigned long> (t);
00846     } catch (std::range_error&) {
00847       TEUCHOS_TEST_FOR_EXCEPTION(
00848         true,
00849         std::range_error,
00850         "Teuchos::ValueTypeConversionTraits<unsigned int, std::string>::convert: "
00851         "The given std::string \"" << t << "\" is too big to fit into unsigned long, so there is no way it could fit into unsigned int.");
00852     } catch (std::invalid_argument& e) {
00853       TEUCHOS_TEST_FOR_EXCEPTION(
00854         true,
00855         std::invalid_argument,
00856         "Teuchos::ValueTypeConversionTraits<unsigned int, std::string>::convert: "
00857         "Intermediate conversion from std::string to unsigned long failed, with the following error message: "
00858         << e.what ());
00859     }
00860     return val;
00861   }
00862 
00863 public:
00869   static unsigned int safeConvert (const std::string& t) {
00870     return asSafe<unsigned int> (safeConvertToUnsignedLong (t));
00871   }
00872 
00874   static unsigned int convert (const std::string& t) {
00875     return as<unsigned int> (safeConvertToUnsignedLong (t));
00876   }
00877 };
00878 
00879 
00883 template<>
00884 class ValueTypeConversionTraits<short, std::string> {
00885 private:
00887   static long safeConvertToLong (const std::string& t) {
00888     long val = 0;
00889     try {
00890       val = ValueTypeConversionTraits<long, std::string>::safeConvert (t);
00891     } catch (std::range_error&) {
00892       TEUCHOS_TEST_FOR_EXCEPTION(
00893         true,
00894         std::range_error,
00895         "Teuchos::ValueTypeConversionTraits<short, std::string>::convert: "
00896         "The given std::string \"" << t << "\" is too big to fit into long, so there is no way it could fit into short.");
00897     } catch (std::invalid_argument& e) {
00898       TEUCHOS_TEST_FOR_EXCEPTION(
00899         true,
00900         std::invalid_argument,
00901         "Teuchos::ValueTypeConversionTraits<short, std::string>::convert: "
00902         "Intermediate conversion from std::string to long failed, with the following error message: "
00903         << e.what ());
00904     }
00905     return val;
00906   }
00907 
00908 public:
00914   static short safeConvert (const std::string& t) {
00915     return asSafe<short> (safeConvertToLong (t));
00916   }
00917 
00919   static short convert (const std::string& t) {
00920     return as<int> (safeConvertToLong (t));
00921   }
00922 };
00923 
00924 
00928 template<>
00929 class ValueTypeConversionTraits<unsigned short, std::string> {
00930 private:
00932   static unsigned long safeConvertToUnsignedLong (const std::string& t) {
00933     unsigned long val = 0;
00934     try {
00935       val = as<unsigned long> (t);
00936     } catch (std::range_error&) {
00937       TEUCHOS_TEST_FOR_EXCEPTION(
00938         true,
00939         std::range_error,
00940         "Teuchos::ValueTypeConversionTraits<unsigned short, std::string>::convert: "
00941         "The given std::string \"" << t << "\" is too big to fit into unsigned long, so there is no way it could fit into unsigned short.");
00942     } catch (std::invalid_argument& e) {
00943       TEUCHOS_TEST_FOR_EXCEPTION(
00944         true,
00945         std::invalid_argument,
00946         "Teuchos::ValueTypeConversionTraits<unsigned short, std::string>::convert: "
00947         "Intermediate conversion from std::string to unsigned long failed, with the following error message: "
00948         << e.what ());
00949     }
00950     return val;
00951   }
00952 
00953 public:
00959   static unsigned short safeConvert (const std::string& t) {
00960     return asSafe<unsigned short> (safeConvertToUnsignedLong (t));
00961   }
00962 
00964   static unsigned short convert (const std::string& t) {
00965     return as<unsigned short> (safeConvertToUnsignedLong (t));
00966   }
00967 };
00968 
00969 //
00970 // * Specializations for conversions between built-in real-valued
00971 //   floating-point types (like float and double).
00972 //
00973 
00975 template<>
00976 class ValueTypeConversionTraits<float, double> {
00977 public:
00978   static float safeConvert (const double t) {
00979     // mfh 25 Nov 2012: Disabling bounds checking, in favor of IEEE
00980     // 754 overflow semantics.  Users who want bounds checking should
00981     // set the appropriate trap.
00982 #if 0
00983     // For floating-point types T, std::numeric_limits<T>::min()
00984     // returns the smallest positive value.  IEEE 754 types have a
00985     // sign bit, so the largest-magnitude negative value is the
00986     // negative of the largest-magnitude positive value.
00987     const float minVal = -std::numeric_limits<float>::max ();
00988     const float maxVal = std::numeric_limits<float>::max ();
00989 
00990     // NaN is neither less than nor greater than anything.  We just
00991     // let it pass through, per the rules for propagation of silent
00992     // NaN.  (Signaling NaN will signal, but that's OK.)
00993     TEUCHOS_TEST_FOR_EXCEPTION(
00994       t < minVal || t > maxVal,
00995       std::range_error,
00996       "Teuchos::ValueTypeConversionTraits<float, double>::safeConvert: "
00997       "Input double t = " << t << " is out of the valid range [" << minVal
00998       << ", " << maxVal << "] for conversion to float.");
00999 #endif // 0
01000 
01001     return static_cast<float> (t);
01002   }
01003 
01004   static float convert (const double t) {
01005     return static_cast<float> (t);
01006   }
01007 };
01008 
01009 
01011 template<>
01012 class ValueTypeConversionTraits<float, long double> {
01013 public:
01014   static float safeConvert (const long double t) {
01015     // mfh 25 Nov 2012: Disabling bounds checking, in favor of IEEE
01016     // 754 overflow semantics.  Users who want bounds checking should
01017     // set the appropriate trap.
01018 #if 0
01019     // For floating-point types T, std::numeric_limits<T>::min()
01020     // returns the smallest positive value.  IEEE 754 types have a
01021     // sign bit, so the largest-magnitude negative value is the
01022     // negative of the largest-magnitude positive value.
01023     const float minVal = -std::numeric_limits<float>::max ();
01024     const float maxVal = std::numeric_limits<float>::max ();
01025 
01026     // NaN is neither less than nor greater than anything.  We just
01027     // let it pass through, per the rules for propagation of silent
01028     // NaN.  (Signaling NaN will signal, but that's OK.)
01029     TEUCHOS_TEST_FOR_EXCEPTION(
01030       t < minVal || t > maxVal,
01031       std::range_error,
01032       "Teuchos::ValueTypeConversionTraits<float, long double>::safeConvert: "
01033       "Input long double t = " << t << " is out of the valid range [" << minVal
01034       << ", " << maxVal << "] for conversion to float.");
01035 #endif // 0
01036 
01037     return static_cast<float> (t);
01038   }
01039 
01040   static float convert (const long double t) {
01041     return static_cast<float> (t);
01042   }
01043 };
01044 
01045 
01047 template<>
01048 class ValueTypeConversionTraits<double, long double> {
01049 public:
01050   static double safeConvert (const long double t) {
01051     // mfh 25 Nov 2012: Disabling bounds checking, in favor of IEEE
01052     // 754 overflow semantics.  Users who want bounds checking should
01053     // set the appropriate trap.
01054 #if 0
01055     // For floating-point types T, std::numeric_limits<T>::min()
01056     // returns the smallest positive value.  IEEE 754 types have a
01057     // sign bit, so the largest-magnitude negative value is the
01058     // negative of the largest-magnitude positive value.
01059     const double minVal = -std::numeric_limits<double>::max ();
01060     const double maxVal = std::numeric_limits<double>::max ();
01061 
01062     // NaN is neither less than nor greater than anything.  We just
01063     // let it pass through, per the rules for propagation of silent
01064     // NaN.  (Signaling NaN will signal, but that's OK.)
01065     TEUCHOS_TEST_FOR_EXCEPTION(
01066       t < minVal || t > maxVal,
01067       std::range_error,
01068       "Teuchos::ValueTypeConversionTraits<double, long double>::safeConvert: "
01069       "Input long double t = " << t << " is out of the valid range [" << minVal
01070       << ", " << maxVal << "] for conversion to double.");
01071 #endif // 0
01072 
01073     return static_cast<double> (t);
01074   }
01075 
01076   static double convert (const long double t) {
01077     return static_cast<double> (t);
01078   }
01079 };
01080 
01081 
01082 //
01083 // * Specializations for conversions from built-in real-valued
01084 //   floating-point types (float and double) to build-in integer
01085 //   types.
01086 //
01087 
01089 template<>
01090 class ValueTypeConversionTraits<short, double> {
01091 public:
01097   static short convert (const double t) {
01098     // Implicit conversion may cause compiler warnings, but
01099     // static_cast does not.
01100     return static_cast<short> (t);
01101   }
01102 
01104   static short safeConvert (const double t) {
01105     const short minVal = std::numeric_limits<short>::min ();
01106     const short maxVal = std::numeric_limits<short>::max ();
01107 
01108     // Cases:
01109     // 1. sizeof(short) < sizeof(double) == 8
01110     // 2. sizeof(short) == sizeof(double) == 8
01111     // 3. sizeof(short) > sizeof(double) == 8
01112     //
01113     // Overflow when converting from double to short is possible only
01114     // for Case 1.  Loss of accuracy (rounding) is possible for Cases
01115     // 2 and 3, but safeConvert() only cares about overflow, not
01116     // rounding.  In Case 3, casting minVal or maxVal to double in
01117     // this case could result in overflow.  Thus, we only do the test
01118     // for Case 1.
01119     //
01120     // All three cases are legal according to both C++03 and C99.
01121     // However, I (mfh 15 Nov 2012) have never encountered Cases 2 and
01122     // 3.
01123     if (sizeof (short) < sizeof (double)) {
01124       TEUCHOS_TEST_FOR_EXCEPTION(
01125         t < minVal || t > maxVal,
01126         std::range_error,
01127         "Teuchos::ValueTypeConversionTraits<short, double>::safeConvert: "
01128         "Input double t = " << t << " is out of the valid range [" << minVal
01129         << ", " << maxVal << "] for conversion to short.");
01130     }
01131     return static_cast<short> (t);
01132   }
01133 };
01134 
01135 
01137 template<>
01138 class ValueTypeConversionTraits<unsigned short, double> {
01139 public:
01141   static unsigned short convert (const double t) {
01142     // Implicit conversion may cause compiler warnings, but
01143     // static_cast does not.
01144     return static_cast<unsigned short> (t);
01145   }
01146 
01148   static unsigned short safeConvert (const double t) {
01149     const unsigned short minVal = 0;
01150     const unsigned short maxVal = std::numeric_limits<unsigned short>::max ();
01151 
01152     TEUCHOS_TEST_FOR_EXCEPTION(
01153       t < minVal || t > maxVal,
01154       std::range_error,
01155       "Teuchos::ValueTypeConversionTraits<unsigned short, double>::safeConvert: "
01156       "Input double t = " << t << " is out of the valid range [" << minVal
01157       << ", " << maxVal << "] for conversion to unsigned short.");
01158 
01159     return static_cast<unsigned short> (t);
01160   }
01161 };
01162 
01163 
01165 template<>
01166 class ValueTypeConversionTraits<int, double> {
01167 public:
01173   static int convert (const double t) {
01174     // Implicit conversion from double to int causes compiler
01175     // warnings, but static_cast does not.
01176     return static_cast<int> (t);
01177   }
01178 
01180   static int safeConvert (const double t) {
01181     const int minVal = std::numeric_limits<int>::min ();
01182     const int maxVal = std::numeric_limits<int>::max ();
01183 
01184     // Cases:
01185     // 1. sizeof(int) < sizeof(double) == 8
01186     // 2. sizeof(int) == sizeof(double) == 8
01187     // 3. sizeof(int) > sizeof(double) == 8
01188     //
01189     // Overflow when converting from double to int is possible only
01190     // for Case 1.  Loss of accuracy (rounding) is possible for Cases
01191     // 2 and 3, but safeConvert() only cares about overflow, not
01192     // rounding.  Case 3 is quite rare, but casting minVal or maxVal
01193     // to double in this case could result in overflow.  Thus, we only
01194     // do the cast for Case 1.
01195     if (sizeof (int) < sizeof (double)) {
01196       TEUCHOS_TEST_FOR_EXCEPTION(
01197         t < minVal || t > maxVal,
01198         std::range_error,
01199         "Teuchos::ValueTypeConversionTraits<int, double>::safeConvert: "
01200         "Input double t = " << t << " is out of the valid range [" << minVal
01201         << ", " << maxVal << "] for conversion to int.");
01202     }
01203     return static_cast<int> (t);
01204   }
01205 };
01206 
01207 
01209 template<>
01210 class ValueTypeConversionTraits<unsigned int, double> {
01211 public:
01213   static unsigned int convert (const double t) {
01214     // Implicit conversion may cause compiler warnings, but
01215     // static_cast does not.
01216     return static_cast<unsigned int> (t);
01217   }
01218 
01220   static unsigned int safeConvert (const double t) {
01221     const unsigned int minVal = 0;
01222     const unsigned int maxVal = std::numeric_limits<unsigned int>::max ();
01223 
01224     TEUCHOS_TEST_FOR_EXCEPTION(
01225       t < minVal || t > maxVal,
01226       std::range_error,
01227       "Teuchos::ValueTypeConversionTraits<unsigned int, double>::safeConvert: "
01228       "Input double t = " << t << " is out of the valid range [" << minVal
01229       << ", " << maxVal << "] for conversion to unsigned int.");
01230 
01231     return static_cast<unsigned int> (t);
01232   }
01233 };
01234 
01235 
01237 template<>
01238 class ValueTypeConversionTraits<long, double> {
01239 public:
01241   static long convert (const double t) {
01242     // Implicit conversion may cause compiler warnings, but
01243     // static_cast does not.
01244     return static_cast<long> (t);
01245   }
01246 
01248   static long safeConvert (const double t) {
01249     const long minVal = std::numeric_limits<long>::min ();
01250     const long maxVal = std::numeric_limits<long>::max ();
01251 
01252     // Cases:
01253     // 1. sizeof(long) < sizeof(double) == 8
01254     // 2. sizeof(long) == sizeof(double) == 8
01255     // 3. sizeof(long) > sizeof(double) == 8
01256     //
01257     // Overflow when converting from double to long is possible only
01258     // for Case 1.  Loss of accuracy (rounding) is possible for Cases
01259     // 2 and 3, but safeConvert() only cares about overflow, not
01260     // rounding.  In Case 3, casting minVal or maxVal to double could
01261     // result in overflow.  Thus, we only test for Case 1.
01262     //
01263     // Case 1 is entirely possible, for example on Win64 (an
01264     // implementation of the LLP64 integer model, on which
01265     // sizeof(long) == 4, and sizeof(long long) == sizeof(void*) ==
01266     // 8).
01267     if (sizeof (long) < sizeof (double)) {
01268       TEUCHOS_TEST_FOR_EXCEPTION(
01269         t < minVal || t > maxVal,
01270         std::range_error,
01271         "Teuchos::ValueTypeConversionTraits<long, double>::safeConvert: "
01272         "Input double t = " << t << " is out of the valid range [" << minVal
01273         << ", " << maxVal << "] for conversion to long.");
01274     }
01275     return static_cast<long> (t);
01276   }
01277 };
01278 
01279 
01281 template<>
01282 class ValueTypeConversionTraits<unsigned long, double> {
01283 public:
01285   static unsigned long convert (const double t) {
01286     // Implicit conversion may cause compiler warnings, but
01287     // static_cast does not.
01288     return static_cast<unsigned long> (t);
01289   }
01290 
01292   static unsigned long safeConvert (const double t) {
01293     const unsigned long minVal = 0;
01294     const unsigned long maxVal = std::numeric_limits<unsigned long>::max ();
01295 
01296     TEUCHOS_TEST_FOR_EXCEPTION(
01297       t < minVal || t > maxVal,
01298       std::range_error,
01299       "Teuchos::ValueTypeConversionTraits<unsigned long, double>::safeConvert: "
01300       "Input double t = " << t << " is out of the valid range [" << minVal
01301       << ", " << maxVal << "] for conversion to unsigned long.");
01302 
01303     return static_cast<unsigned long> (t);
01304   }
01305 };
01306 
01307 #ifdef HAVE_TEUCHOS_LONG_LONG_INT
01308 
01310 template<>
01311 class ValueTypeConversionTraits<long long, double> {
01312 public:
01314   static long long convert (const double t) {
01315     // Implicit conversion may cause compiler warnings, but
01316     // static_cast does not.
01317     return static_cast<long long> (t);
01318   }
01319 
01321   static long safeConvert (const double t) {
01322     // Cases:
01323     // 1. sizeof(long long) < sizeof(double) == 8
01324     // 2. sizeof(long long) == sizeof(double) == 8
01325     // 3. sizeof(long long) > sizeof(double) == 8
01326     //
01327     // C99 (which defines long long) prohibits Case 1.  Case 2 could
01328     // result in loss of accuracy (rounding), but safeConvert() only
01329     // cares about overflow, not rounding.  In Case 3, casting minVal
01330     // or maxVal to double could result in overflow.  Thus, we don't
01331     // need to check anything here.
01332     return static_cast<long long> (t);
01333   }
01334 };
01335 
01336 
01338 template<>
01339 class ValueTypeConversionTraits<unsigned long long, double> {
01340 public:
01342   static unsigned long long convert (const double t) {
01343     // Implicit conversion may cause compiler warnings, but
01344     // static_cast does not.
01345     return static_cast<unsigned long long> (t);
01346   }
01347 
01349   static unsigned long long safeConvert (const double t) {
01350     const unsigned long long minVal = 0; // unsigned, so min value is 0.
01351     const unsigned long long maxVal = std::numeric_limits<unsigned long long>::max ();
01352 
01353     TEUCHOS_TEST_FOR_EXCEPTION(
01354       t < minVal || t > maxVal,
01355       std::range_error,
01356       "Teuchos::ValueTypeConversionTraits<unsigned long long, double>::safeConvert: "
01357       "Input double t = " << t << " is out of the valid range [" << minVal
01358       << ", " << maxVal << "] for conversion to unsigned long long.");
01359 
01360     return static_cast<unsigned long long> (t);
01361   }
01362 };
01363 
01364 #endif // HAVE_TEUCHOS_LONG_LONG_INT
01365 
01366 
01368 template<>
01369 class ValueTypeConversionTraits<short, float> {
01370 public:
01376   static short convert (const float t) {
01377     // Implicit conversion may cause compiler warnings, but
01378     // static_cast does not.
01379     return static_cast<short> (t);
01380   }
01381 
01383   static short safeConvert (const float t) {
01384     const short minVal = std::numeric_limits<short>::min ();
01385     const short maxVal = std::numeric_limits<short>::max ();
01386 
01387     // Cases:
01388     // 1. sizeof(short) < sizeof(float) == 4
01389     // 2. sizeof(short) == sizeof(float) == 4
01390     // 3. sizeof(short) > sizeof(float) == 4
01391     //
01392     // Overflow when converting from float to short is possible only
01393     // for Case 1.  Loss of accuracy (rounding) is possible for Cases
01394     // 2 and 3, but safeConvert() only cares about overflow, not
01395     // rounding.  In Case 3, casting minVal or maxVal to float in this
01396     // case could result in overflow.  Thus, we only do the test for
01397     // Case 1.
01398     //
01399     // All three cases are legal according to both C++03 and C99.  I
01400     // (mfh 15 Nov 2012) think Case 1 is the most common, but Case 2
01401     // is certainly reasonable.  (For example, some hardware prefers
01402     // to work only with 32-bit words, so _every_ built-in type has
01403     // size a multiple of 4 bytes.)
01404     if (sizeof (short) < sizeof (float)) {
01405       TEUCHOS_TEST_FOR_EXCEPTION(
01406         t < minVal || t > maxVal,
01407         std::range_error,
01408         "Teuchos::ValueTypeConversionTraits<short, float>::safeConvert: "
01409         "Input float t = " << t << " is out of the valid range [" << minVal
01410         << ", " << maxVal << "] for conversion to short.");
01411     }
01412 
01413     return static_cast<short> (t);
01414   }
01415 };
01416 
01417 
01419 template<>
01420 class ValueTypeConversionTraits<unsigned short, float> {
01421 public:
01423   static unsigned short convert (const float t) {
01424     // Implicit conversion may cause compiler warnings, but
01425     // static_cast does not.
01426     return static_cast<unsigned short> (t);
01427   }
01428 
01430   static unsigned short safeConvert (const float t) {
01431     const unsigned short minVal = 0;
01432     const unsigned short maxVal = std::numeric_limits<unsigned short>::max ();
01433 
01434     TEUCHOS_TEST_FOR_EXCEPTION(
01435       t < minVal || t > maxVal,
01436       std::range_error,
01437       "Teuchos::ValueTypeConversionTraits<unsigned short, float>::safeConvert: "
01438       "Input float t = " << t << " is out of the valid range [" << minVal
01439       << ", " << maxVal << "] for conversion to unsigned short.");
01440 
01441     return static_cast<unsigned short> (t);
01442   }
01443 };
01444 
01445 
01447 template<>
01448 class ValueTypeConversionTraits<int, float> {
01449 public:
01451   static int convert (const float t) {
01452     // Implicit conversion from float to int may cause compiler
01453     // warnings, but static_cast does not.  Overflow here would mean
01454     // that sizeof(int) < sizeof(float), which is legal, but unlikely
01455     // on platforms of interest.
01456     return static_cast<int> (t);
01457   }
01458 
01460   static int safeConvert (const float t) {
01461     const int minVal = std::numeric_limits<int>::min ();
01462     const int maxVal = std::numeric_limits<int>::max ();
01463 
01464     // Cases:
01465     // 1. sizeof(int) < sizeof(float) == 4
01466     // 2. sizeof(int) == sizeof(float) == 4
01467     // 3. sizeof(int) > sizeof(float) == 4
01468     //
01469     // Overflow when converting from float to int is possible only for
01470     // Case 1.  Loss of accuracy (rounding) is possible for Cases 2
01471     // and 3, but safeConvert() only cares about overflow, not
01472     // rounding.  Case 3 is rare, but casting minVal or maxVal to
01473     // float in this case could result in loss of accuracy
01474     // (sizeof(int) == 8 or 16) or overflow (sizeof(int) > 16).  Thus,
01475     // we only do the test for Case 1.
01476     if (sizeof (int) < sizeof (float)) {
01477       TEUCHOS_TEST_FOR_EXCEPTION(
01478         t < minVal || t > maxVal,
01479         std::range_error,
01480         "Teuchos::ValueTypeConversionTraits<int, float>::safeConvert: "
01481         "Input float t = " << t << " is out of the valid range ["
01482         << minVal << ", " << maxVal << "] for conversion to int.");
01483     }
01484     return static_cast<int> (t);
01485   }
01486 };
01487 
01488 
01490 template<>
01491 class ValueTypeConversionTraits<unsigned int, float> {
01492 public:
01494   static unsigned int convert (const float t) {
01495     // Implicit conversion from float to unsigned int may cause
01496     // compiler warnings, but static_cast does not.
01497     return static_cast<unsigned int> (t);
01498   }
01499 
01501   static unsigned int safeConvert (const float t) {
01502     const unsigned int minVal = 0; // Had better be, since it's unsigned.
01503     const unsigned int maxVal = std::numeric_limits<unsigned int>::max ();
01504 
01505     TEUCHOS_TEST_FOR_EXCEPTION(
01506       t < minVal || t > maxVal,
01507       std::range_error,
01508       "Teuchos::ValueTypeConversionTraits<unsigned int, float>::safeConvert: "
01509       "Input double t = " << t << " is out of the valid range [" << minVal
01510       << ", " << maxVal << "] for conversion to unsigned int.");
01511 
01512     return static_cast<unsigned int> (t);
01513   }
01514 };
01515 
01516 
01518 template<>
01519 class ValueTypeConversionTraits<long, float> {
01520 public:
01522   static long convert (const float t) {
01523     // Implicit conversion from float to long may cause compiler
01524     // warnings, but static_cast does not.  Overflow here would mean
01525     // that sizeof(long) < sizeof(float), which is legal, but unlikely
01526     // on platforms of longerest.
01527     return static_cast<long> (t);
01528   }
01529 
01531   static long safeConvert (const float t) {
01532     const long minVal = std::numeric_limits<long>::min ();
01533     const long maxVal = std::numeric_limits<long>::max ();
01534 
01535     // Cases:
01536     // 1. sizeof(long) < sizeof(float) == 4
01537     // 2. sizeof(long) == sizeof(float) == 4
01538     // 3. sizeof(long) > sizeof(float) == 4
01539     //
01540     // Overflow when converting from float to long is possible only
01541     // for Case 1.  Loss of accuracy (rounding) is possible for Cases
01542     // 2 and 3, but safeConvert() only cares about overflow, not
01543     // rounding.  Casting minVal or maxVal to double in Case 3 could
01544     // result in overflow.  Thus, we only do the cast for Case 1.
01545     //
01546     // I've never encountered a Case 1 platform (mfh 14 Nov 2012).
01547     // C99 actually forbids it, though I don't think a valid C++
01548     // compiler (for version C++03 of the language standard) needs to
01549     // implement C99 (mfh 14 Nov 2012).  Case 2 occurs in Win64
01550     // (64-bit Windows) and other implementations of (I32L32)LLP64.
01551     // Case 3 is common (e.g., in the (I32)LP64 integer model of
01552     // GNU/Linux and other operating systems).
01553     if (sizeof (long) < sizeof (float)) {
01554       TEUCHOS_TEST_FOR_EXCEPTION(
01555         t < minVal || t > maxVal,
01556         std::range_error,
01557         "Teuchos::ValueTypeConversionTraits<long, float>::safeConvert: "
01558         "Input float t = " << t << " is out of the valid range ["
01559         << minVal << ", " << maxVal << "] for conversion to long.");
01560     }
01561     return static_cast<long> (t);
01562   }
01563 };
01564 
01565 
01567 template<>
01568 class ValueTypeConversionTraits<unsigned long, float> {
01569 public:
01571   static unsigned long convert (const float t) {
01572     // Implicit conversion from float to unsigned long may cause
01573     // compiler warnings, but static_cast does not.
01574     return static_cast<unsigned long> (t);
01575   }
01576 
01578   static unsigned long safeConvert (const float t) {
01579     const unsigned long minVal = 0; // Had better be, since it's unsigned.
01580     const unsigned long maxVal = std::numeric_limits<unsigned long>::max ();
01581 
01582     TEUCHOS_TEST_FOR_EXCEPTION(
01583       t < minVal || t > maxVal,
01584       std::range_error,
01585       "Teuchos::ValueTypeConversionTraits<unsigned long, float>::safeConvert: "
01586       << "Input float t = " << t << " is out of the valid range [" << minVal
01587       << ", " << maxVal << "] for conversion to unsigned long.");
01588 
01589     return static_cast<unsigned long> (t);
01590   }
01591 };
01592 
01593 #ifdef HAVE_TEUCHOS_LONG_LONG_INT
01594 
01596 template<>
01597 class ValueTypeConversionTraits<long long, float> {
01598 public:
01600   static long long convert (const float t) {
01601     return static_cast<long long> (t);
01602   }
01603 
01605   static long long safeConvert (const float t) {
01606     // The C99 standard (Section 5.2.4.2.1) actually requires
01607     // sizeof(long long) >= 64, so overflow is impossible.
01608     return static_cast<long long> (t);
01609   }
01610 };
01611 
01612 
01614 template<>
01615 class ValueTypeConversionTraits<unsigned long long, float> {
01616 public:
01618   static unsigned long long convert (const float t) {
01619     return static_cast<unsigned long long> (t);
01620   }
01621 
01623   static unsigned long long safeConvert (const float t) {
01624     const unsigned long long minVal = 0; // unsigned, so min value is 0.
01625     const unsigned long long maxVal = std::numeric_limits<unsigned long long>::max ();
01626 
01627     TEUCHOS_TEST_FOR_EXCEPTION(
01628       t < minVal || t > maxVal,
01629       std::range_error,
01630       "Teuchos::ValueTypeConversionTraits<unsigned long long, float>::safeConvert: "
01631       "Input float t = " << t << " is out of the valid range [" << minVal
01632       << ", " << maxVal << "] for conversion to unsigned long long.");
01633 
01634     return static_cast<unsigned long long> (t);
01635   }
01636 };
01637 
01638 #endif // HAVE_TEUCHOS_LONG_LONG_INT
01639 
01640 //
01641 // * Specializations for conversions between a unsigned built-in
01642 //   integer type and the signed version of the same type (either
01643 //   direction).
01644 //
01645 
01646 namespace {
01647 // Implementation of conversion from an unsigned built-in integer
01648 // type, to an signed built-in integer type with the same number of
01649 // bits.
01650 template<class SignedIntType, class UnsignedIntType>
01651 class UnsignedToSignedValueTypeConversionTraits {
01652 public:
01660   static SignedIntType convert (const UnsignedIntType t) {
01661     // Implicit conversion may cause compiler warnings, but
01662     // static_cast does not.
01663     return static_cast<SignedIntType> (t);
01664   }
01665 
01667   static SignedIntType safeConvert (const UnsignedIntType t) {
01668     using Teuchos::TypeNameTraits;
01669     const SignedIntType maxSigned = std::numeric_limits<SignedIntType>::max ();
01670 
01671     // SignedIntType and UnsignedIntType have the same number of bits,
01672     // so it suffices (via two's complement arithmetic) to check
01673     // whether the cast turned a positive number negative.
01674     const SignedIntType signedVal = static_cast<SignedIntType> (t);
01675     TEUCHOS_TEST_FOR_EXCEPTION(
01676       signedVal < 0,
01677       std::range_error,
01678       "Teuchos::ValueTypeConversionTraits<" << TypeNameTraits<SignedIntType>::name ()
01679       << ", " << TypeNameTraits<UnsignedIntType>::name () << ">::safeConvert: "
01680       "Input " << TypeNameTraits<UnsignedIntType>::name () << " t = " << t
01681       << " is out of the valid range [0, " << ", " << maxSigned
01682       << "] for conversion to " << TypeNameTraits<SignedIntType>::name () << ".");
01683     return signedVal;
01684   }
01685 };
01686 
01687 
01688 // Implementation of conversion from a signed built-in integer type,
01689 // to an unsigned built-in integer type with the same number of bits.
01690 template<class UnsignedIntType, class SignedIntType>
01691 class SignedToUnsignedValueTypeConversionTraits {
01692 public:
01694   static UnsignedIntType convert (const SignedIntType t) {
01695     // Implicit conversion may cause compiler warnings, but
01696     // static_cast does not.
01697     return static_cast<UnsignedIntType> (t);
01698   }
01699 
01701   static UnsignedIntType safeConvert (const SignedIntType t) {
01702     using Teuchos::TypeNameTraits;
01703 
01704     // SignedIntType and UnsignedIntType have the same number of bits,
01705     // so it suffices (via two's complement arithmetic) to check
01706     // whether the input is negative.
01707     TEUCHOS_TEST_FOR_EXCEPTION(
01708       t < static_cast<SignedIntType> (0),
01709       std::range_error,
01710       "Teuchos::ValueTypeConversionTraits<" << TypeNameTraits<UnsignedIntType>::name ()
01711       << ", " << TypeNameTraits<SignedIntType>::name () << ">::safeConvert: "
01712       "Input " << TypeNameTraits<SignedIntType>::name () << " t = " << t
01713       << " is negative, so it cannot be correctly converted to the unsigned type "
01714       << TypeNameTraits<UnsignedIntType>::name () << ".");
01715 
01716     return static_cast<UnsignedIntType> (t);
01717   }
01718 };
01719 
01720 } // namespace (anonymous)
01721 
01722 
01724 template<>
01725 class ValueTypeConversionTraits<short, unsigned short> {
01726 public:
01727   static short convert (const unsigned short t) {
01728     return UnsignedToSignedValueTypeConversionTraits<short, unsigned short>::convert (t);
01729   }
01730 
01731   static short safeConvert (const unsigned short t) {
01732     return UnsignedToSignedValueTypeConversionTraits<short, unsigned short>::safeConvert (t);
01733   }
01734 };
01735 
01736 
01738 template<>
01739 class ValueTypeConversionTraits<unsigned short, short> {
01740 public:
01741   static unsigned short convert (const short t) {
01742     return SignedToUnsignedValueTypeConversionTraits<unsigned short, short>::convert (t);
01743   }
01744 
01745   static unsigned short safeConvert (const short t) {
01746     return SignedToUnsignedValueTypeConversionTraits<unsigned short, short>::safeConvert (t);
01747   }
01748 };
01749 
01750 
01752 template<>
01753 class ValueTypeConversionTraits<int, unsigned int> {
01754 public:
01755   static int convert (const unsigned int t) {
01756     return UnsignedToSignedValueTypeConversionTraits<int, unsigned int>::convert (t);
01757   }
01758 
01759   static int safeConvert (const unsigned int t) {
01760     return UnsignedToSignedValueTypeConversionTraits<int, unsigned int>::safeConvert (t);
01761   }
01762 };
01763 
01764 
01766 template<>
01767 class ValueTypeConversionTraits<unsigned int, int> {
01768 public:
01769   static unsigned int convert (const int t) {
01770     return SignedToUnsignedValueTypeConversionTraits<unsigned int, int>::convert (t);
01771   }
01772 
01773   static unsigned int safeConvert (const int t) {
01774     return SignedToUnsignedValueTypeConversionTraits<unsigned int, int>::safeConvert (t);
01775   }
01776 };
01777 
01778 
01780 template<>
01781 class ValueTypeConversionTraits<long, unsigned long> {
01782 public:
01783   static long convert (const unsigned long t) {
01784     return UnsignedToSignedValueTypeConversionTraits<long, unsigned long>::convert (t);
01785   }
01786 
01787   static long safeConvert (const unsigned long t) {
01788     return UnsignedToSignedValueTypeConversionTraits<long, unsigned long>::safeConvert (t);
01789   }
01790 };
01791 
01792 
01794 template<>
01795 class ValueTypeConversionTraits<unsigned long, long> {
01796 public:
01797   static unsigned long convert (const long t) {
01798     return SignedToUnsignedValueTypeConversionTraits<unsigned long, long>::convert (t);
01799   }
01800 
01801   static unsigned long safeConvert (const long t) {
01802     return SignedToUnsignedValueTypeConversionTraits<unsigned long, long>::safeConvert (t);
01803   }
01804 };
01805 
01806 
01807 #ifdef HAVE_TEUCHOS_LONG_LONG_INT
01808 
01810 template<>
01811 class ValueTypeConversionTraits<long long, unsigned long long> {
01812 public:
01813   static long long convert (const unsigned long long t) {
01814     return UnsignedToSignedValueTypeConversionTraits<long long, unsigned long long>::convert (t);
01815   }
01816 
01817   static long long safeConvert (const unsigned long long t) {
01818     return UnsignedToSignedValueTypeConversionTraits<long long, unsigned long long>::safeConvert (t);
01819   }
01820 };
01821 
01822 
01824 template<>
01825 class ValueTypeConversionTraits<unsigned long long, long long> {
01826 public:
01827   static unsigned long long convert (const long long t) {
01828     return SignedToUnsignedValueTypeConversionTraits<unsigned long long, long long>::convert (t);
01829   }
01830 
01831   static unsigned long long safeConvert (const long long t) {
01832     return SignedToUnsignedValueTypeConversionTraits<unsigned long long, long long>::safeConvert (t);
01833   }
01834 };
01835 
01836 #endif // HAVE_TEUCHOS_LONG_LONG_INT
01837 
01838 //
01839 // * Specializations for conversions between different built-in
01840 //   integer types.
01841 //
01842 
01844 template<>
01845 class ValueTypeConversionTraits<short, int> {
01846 public:
01852   static short convert (const int t) {
01853     // Implicit conversion may cause compiler warnings, but
01854     // static_cast does not.
01855     return static_cast<short> (t);
01856   }
01857 
01859   static short safeConvert (const int t) {
01860     const short minShort = std::numeric_limits<short>::min ();
01861     const short maxShort = std::numeric_limits<short>::max ();
01862 
01863     // Casting from short to int never overflows, since the C++
01864     // standard guarantees that sizeof (short) <= sizeof (int).
01865     TEUCHOS_TEST_FOR_EXCEPTION(
01866       t < static_cast<int> (minShort) ||
01867       t > static_cast<int> (maxShort),
01868       std::range_error,
01869       "Teuchos::ValueTypeConversionTraits<short, int>::safeConvert: "
01870       "Input int t = " << t << " is out of the valid range [" << minShort
01871       << ", " << maxShort << "] for conversion to short.");
01872 
01873     return static_cast<short> (t);
01874   }
01875 };
01876 
01877 
01879 template<>
01880 class ValueTypeConversionTraits<short, long> {
01881 public:
01887   static short convert (const long t) {
01888     // Implicit conversion may cause compiler warnings, but
01889     // static_cast does not.
01890     return static_cast<short> (t);
01891   }
01892 
01894   static short safeConvert (const long t) {
01895     const short minShort = std::numeric_limits<short>::min ();
01896     const short maxShort = std::numeric_limits<short>::max ();
01897 
01898     // Casting from short to long never overflows, since the C++
01899     // standard guarantees that sizeof (short) <= sizeof (long).
01900     TEUCHOS_TEST_FOR_EXCEPTION(
01901       t < static_cast<long> (minShort) ||
01902       t > static_cast<long> (maxShort),
01903       std::range_error,
01904       "Teuchos::ValueTypeConversionTraits<short, long>::safeConvert: "
01905       "Input long t = " << t << " is out of the valid range [" << minShort
01906       << ", " << maxShort << "] for conversion to short.");
01907 
01908     return static_cast<short> (t);
01909   }
01910 };
01911 
01912 
01914 template<>
01915 class ValueTypeConversionTraits<int, long> {
01916 public:
01922   static int convert (const long t) {
01923     // Implicit conversion from long to int may cause compiler
01924     // warnings, but static_cast does not.
01925     return static_cast<int> (t);
01926   }
01927 
01929   static int safeConvert (const long t) {
01930     const int minInt = std::numeric_limits<int>::min ();
01931     const int maxInt = std::numeric_limits<int>::max ();
01932 
01933     // Casting from int to long never overflows, since the C++
01934     // standard guarantees that sizeof (int) <= sizeof (long).
01935     TEUCHOS_TEST_FOR_EXCEPTION(
01936       t < static_cast<long> (minInt) ||
01937       t > static_cast<long> (maxInt),
01938       std::range_error,
01939       "Teuchos::ValueTypeConversionTraits<int, long>::safeConvert: "
01940       "Input long t = " << t << " is out of the valid range [" << minInt
01941       << ", " << maxInt << "] for conversion to int.");
01942 
01943     // Implicit conversion from long to int may cause compiler
01944     // warnings, but static_cast does not.
01945     return static_cast<int> (t);
01946   }
01947 };
01948 
01949 
01951 template<>
01952 class ValueTypeConversionTraits<int, unsigned long> {
01953 public:
01960   static int convert (const unsigned long t) {
01961     // Implicit conversion may cause compiler warnings, but
01962     // static_cast does not.
01963     return static_cast<int> (t);
01964   }
01965 
01967   static int safeConvert (const unsigned long t) {
01968     const int minInt = std::numeric_limits<int>::min ();
01969     const int maxInt = std::numeric_limits<int>::max ();
01970 
01971     // On some platforms, sizeof(int) == sizeof(long).  (This is the
01972     // "LLP64" model of Win64, which aims for backwards compatibility
01973     // with 32-bit code by making sizeof(int) == sizeof(long) == 4.)
01974     // If this is the case, then we can't safely cast unsigned long to
01975     // int, or unsigned int to long, because values with the most
01976     // significant bit set will overflow to negative values.
01977 
01978     // The C++ standard promises that sizeof (int) <= sizeof (unsigned
01979     // long).  We use #if with INT_MAX and LONG_MAX to test for this,
01980     // rather than if statements, in order to avoid a compiler
01981     // warning.  Thanks to Jeremie Gaidamour (13 Nov 2012) for letting
01982     // me know about the warning.
01983 #if INT_MAX == LONG_MAX
01984     // The two types have the same number of bits.  Thus,
01985     // two's-complement arithmetic means that if casting from unsigned
01986     // long to int results in a negative number, it overflowed.
01987     // Otherwise, it didn't overflow (same number of bits).
01988     TEUCHOS_TEST_FOR_EXCEPTION(
01989       static_cast<int> (t) < static_cast<int> (0),
01990       std::range_error,
01991       "Teuchos::ValueTypeConversionTraits<int, unsigned long>::safeConvert: "
01992       "Input unsigned long t = " << t << " is out of the valid range ["
01993       << minInt << ", " << maxInt << "] for conversion to int.");
01994 #else // INT_MAX < LONG_MAX
01995     // t is unsigned, so it is >= 0 by definition.
01996     // Casting from int to unsigned long won't overflow in this case.
01997     TEUCHOS_TEST_FOR_EXCEPTION(
01998       t > static_cast<unsigned long> (maxInt),
01999       std::range_error,
02000       "Teuchos::ValueTypeConversionTraits<int, unsigned long>::safeConvert: "
02001       "Input unsigned long t = " << t << " is out of the valid range ["
02002       << minInt << ", " << maxInt << "] for conversion to int.  An unchecked "
02003       "cast would have resulted in " << static_cast<int> (t) << ".");
02004 #endif // INT_MAX == LONG_MAX
02005 
02006     // Implicit conversion from unsigned long to int may cause
02007     // compiler warnings, but static_cast does not.
02008     return static_cast<int> (t);
02009   }
02010 };
02011 
02012 
02014 template<>
02015 class ValueTypeConversionTraits<long, unsigned int> {
02016 public:
02024   static long convert (const unsigned int t) {
02025     // Implicit conversion may cause compiler warnings, but
02026     // static_cast does not.
02027     return static_cast<long> (t);
02028   }
02029 
02031   static long safeConvert (const unsigned int t) {
02032     // On some platforms, sizeof(int) == sizeof(long).  (This is the
02033     // "LLP64" model of Win64, which aims for backwards compatibility
02034     // with 32-bit code by making sizeof(int) == sizeof(long) == 4.)
02035     // If this is the case, then we can't safely cast unsigned long to
02036     // int, or unsigned int to long, because values with the most
02037     // significant bit set will overflow to negative values.
02038 
02039     // The C++ standard promises that sizeof (unsigned int) <= sizeof
02040     // (long).  If strictly less, then the conversion won't overflow.
02041     // We protect the test with an #ifdef ... #endif to avoid compiler
02042     // warnings like the following: "warning: comparison is always
02043     // false due to limited range of data type".
02044 #if UINT_MIN == LONG_MIN && UINT_MAX == LONG_MAX
02045     const long minLong = std::numeric_limits<long>::min ();
02046     const long maxLong = std::numeric_limits<long>::max ();
02047 
02048     // The two types have the same number of bits.  Thus,
02049     // two's-complement arithmetic means that if casting from
02050     // unsigned int to long results in a negative number, it
02051     // overflowed.  Otherwise, it didn't overflow (same number of
02052     // bits).
02053     TEUCHOS_TEST_FOR_EXCEPTION(
02054       static_cast<long> (t) < static_cast<long> (0),
02055       std::range_error,
02056       "Teuchos::ValueTypeConversionTraits<long, unsigned int>::safeConvert: "
02057       "Input unsigned int t = " << t << " is out of the valid range ["
02058       << minLong << ", " << maxLong << "] for conversion to long.");
02059 #endif // UINT_MAX == LONG_MAX
02060 
02061     return static_cast<long> (t);
02062   }
02063 };
02064 
02065 
02067 template<>
02068 class ValueTypeConversionTraits<unsigned int, long> {
02069 public:
02076   static unsigned int convert (const long t) {
02077     // Implicit conversion from long to unsigned int may cause
02078     // compiler warnings, but static_cast does not.
02079     return static_cast<unsigned int> (t);
02080   }
02081 
02083   static unsigned int safeConvert (const long t) {
02084     // On some platforms, sizeof(int) == sizeof(long).  (This is the
02085     // "LLP64" model of Win64, which aims for backwards compatibility
02086     // with 32-bit code by making sizeof(int) == sizeof(long) == 4.)
02087     // In this case, conversion from long to unsigned int can't
02088     // overflow.
02089 
02090     // The C++ standard promises that sizeof (unsigned int) <= sizeof (long).
02091     if (sizeof (unsigned int) < sizeof (long)) {
02092       const unsigned int maxInt = std::numeric_limits<unsigned int>::max ();
02093 
02094       TEUCHOS_TEST_FOR_EXCEPTION(
02095         t < static_cast<long> (0) || t > static_cast<long> (maxInt),
02096         std::range_error,
02097         "Teuchos::ValueTypeConversionTraits<unsigned int, long>::safeConvert: "
02098         "Input long t = " << t << " is out of the valid range [0, "
02099         << maxInt << "] for conversion to unsigned int.");
02100     }
02101     // Implicit conversion from long to unsigned int may cause
02102     // compiler warnings, but static_cast does not.
02103     return static_cast<unsigned int> (t);
02104   }
02105 };
02106 
02107 
02109 template<>
02110 class ValueTypeConversionTraits<unsigned int, unsigned long> {
02111 public:
02118   static unsigned int convert (const unsigned long t) {
02119     // Implicit conversion from unsigned long to unsigned int may cause
02120     // compiler warnings, but static_cast does not.
02121     return static_cast<unsigned int> (t);
02122   }
02123 
02125   static unsigned int safeConvert (const unsigned long t) {
02126     const unsigned int minInt = 0; // Had better be, since it's unsigned.
02127     const unsigned int maxInt = std::numeric_limits<unsigned int>::max ();
02128 
02129     // t >= 0 by definition, because it is unsigned.
02130     TEUCHOS_TEST_FOR_EXCEPTION(
02131       t > static_cast<unsigned long> (maxInt),
02132       std::range_error,
02133       "Teuchos::ValueTypeConversionTraits<unsigned int, unsigned long>::safeConvert: "
02134       "Input unsigned long t = " << t << " is out of the valid range [" << minInt
02135       << ", " << maxInt << "] for conversion to unsigned int.");
02136 
02137     // Implicit conversion from unsigned long to unsigned int may
02138     // cause compiler warnings, but static_cast does not.
02139     return static_cast<unsigned int> (t);
02140   }
02141 };
02142 
02143 #ifdef HAVE_TEUCHOS_LONG_LONG_INT
02144 
02146 template<>
02147 class ValueTypeConversionTraits<int, long long> {
02148 public:
02154   static int convert (const long long t) {
02155     // Implicit conversion from long long to int may cause compiler
02156     // warnings, but static_cast does not.
02157     return static_cast<int> (t);
02158   }
02159 
02161   static int safeConvert (const long long t) {
02162     const int minInt = std::numeric_limits<int>::min ();
02163     const int maxInt = std::numeric_limits<int>::max ();
02164 
02165     TEUCHOS_TEST_FOR_EXCEPTION(
02166       t < static_cast<long long> (minInt) ||
02167       t > static_cast<long long> (maxInt),
02168       std::range_error,
02169       "Teuchos::ValueTypeConversionTraits<int, long long>::safeConvert: "
02170       "Input long long t = " << t << " is out of the valid range [" << minInt
02171       << ", " << maxInt << "] for conversion to int.");
02172 
02173     // Implicit conversion from long long to int may cause compiler
02174     // warnings, but static_cast does not.
02175     return static_cast<int> (t);
02176   }
02177 };
02178 
02179 
02181 template<>
02182 class ValueTypeConversionTraits<unsigned int, long long> {
02183 public:
02190   static unsigned int convert (const long long t) {
02191     // Implicit conversion from long long to unsigned int may cause
02192     // compiler warnings, but static_cast does not.
02193     return static_cast<unsigned int> (t);
02194   }
02195 
02197   static unsigned int safeConvert (const long long t) {
02198     const unsigned int minInt = 0; // Had better be, because it's unsigned.
02199     const unsigned int maxInt = std::numeric_limits<unsigned int>::max ();
02200 
02201     TEUCHOS_TEST_FOR_EXCEPTION(
02202       t < static_cast<long long> (minInt) || t > static_cast<long long> (maxInt),
02203       std::range_error,
02204       "Teuchos::ValueTypeConversionTraits<unsigned int, long long>::safeConvert: "
02205       "Input long long t = " << t << " is out of the valid range [" << minInt
02206       << ", " << maxInt << "] for conversion to unsigned int.");
02207 
02208     // Implicit conversion from long long to unsigned int may cause
02209     // compiler warnings, but static_cast does not.
02210     return static_cast<unsigned int> (t);
02211   }
02212 };
02213 
02214 
02216 template<>
02217 class ValueTypeConversionTraits<int, unsigned long long> {
02218 public:
02224   static int convert (const unsigned long long t) {
02225     // Implicit conversion from unsigned long long to int may cause
02226     // compiler warnings, but static_cast does not.
02227     return static_cast<int> (t);
02228   }
02229 
02231   static int safeConvert (const unsigned long long t) {
02232     const int minInt = std::numeric_limits<int>::min ();
02233     const int maxInt = std::numeric_limits<int>::max ();
02234 
02235     // t >= 0 by definition, because it is unsigned.
02236     TEUCHOS_TEST_FOR_EXCEPTION(
02237       t > static_cast<unsigned long long> (maxInt),
02238       std::invalid_argument,
02239       "Teuchos::ValueTypeConversionTraits<int, unsigned long long>::safeConvert: "
02240       "Input unsigned long long t = " << t << " is out of the valid range [" << minInt
02241       << ", " << maxInt << "] for conversion to int.");
02242 
02243     // Implicit conversion from unsigned long long to int may cause
02244     // compiler warnings, but static_cast does not.
02245     return static_cast<int> (t);
02246   }
02247 };
02248 
02249 
02251 template<>
02252 class ValueTypeConversionTraits<unsigned int, unsigned long long> {
02253 public:
02260   static unsigned int convert (const unsigned long long t) {
02261     // Implicit conversion from unsigned long long to unsigned int may
02262     // cause compiler warnings, but static_cast does not.
02263     return static_cast<unsigned int> (t);
02264   }
02265 
02267   static unsigned int safeConvert (const unsigned long long t) {
02268     const unsigned int minInt = 0; // Had better be, since it's unsigned.
02269     const unsigned int maxInt = std::numeric_limits<unsigned int>::max ();
02270 
02271     // t >= 0 by definition, because it is unsigned.
02272     TEUCHOS_TEST_FOR_EXCEPTION(
02273       t > static_cast<unsigned long long> (maxInt),
02274       std::invalid_argument,
02275       "Teuchos::ValueTypeConversionTraits<unsigned int, unsigned long long>::safeConvert: "
02276       "Input unsigned long long t = " << t << " is out of the valid range [" << minInt
02277       << ", " << maxInt << "] for conversion to unsigned int.");
02278 
02279     // Implicit conversion from unsigned long long to unsigned int may
02280     // cause compiler warnings, but static_cast does not.
02281     return static_cast<unsigned int> (t);
02282   }
02283 };
02284 
02285 #endif // HAVE_TEUCHOS_LONG_LONG_INT
02286 
02287 //
02288 // * Conversions from built-in integer types to built-in real-valued
02289 //   floating-point types.
02290 //
02291 
02292 #ifdef HAVE_TEUCHOS_LONG_LONG_INT
02293 
02295 template<>
02296 class ValueTypeConversionTraits<float, long long> {
02297 public:
02303   static float convert (const long long t) {
02304     // Implicit conversion from long long to float may cause compiler
02305     // warnings, but static_cast does not.
02306     return static_cast<float> (t);
02307   }
02308 
02310   static float safeConvert (const long long t) {
02311     // std::numeric_limits<float>::min() gives the minimum _positive_
02312     // normalized value of type float.  IEEE 754 floating-point values
02313     // can change sign just by flipping the sign bit, so the "most
02314     // negative" finite float is just the negative of the "most
02315     // positive" finite float.
02316     const float minFloat = -std::numeric_limits<float>::max ();
02317     const float maxFloat = std::numeric_limits<float>::max ();
02318 
02319     // mfh 16 Nov 2012: On my platform (gcc 4.7.2, Red Hat Linux 5,
02320     // Intel x86_64), first casting [minFloat,maxFloat] to long long
02321     // (so that the comparison only compares long long values)
02322     // gives different results in the comparison below than just
02323     // comparing t (as a long long) with minFloat and maxFloat.  It
02324     // doesn't matter whether you use static_cast<long long> (...) or
02325     // (long long) (...) to do the cast: the original float interval
02326     // of [-3.40282e+38, 3.40282e+38] becomes [-9223372036854775808,
02327     // -9223372036854775808], which is obviously wrong.
02328     TEUCHOS_TEST_FOR_EXCEPTION(
02329       t < minFloat || t > maxFloat,
02330       std::range_error,
02331       "Teuchos::ValueTypeConversionTraits<float, long long>::safeConvert: "
02332       "Input long long t = " << t << " is out of the valid range [" << minFloat
02333       << ", " << maxFloat << "] for conversion to float.");
02334 
02335     // Implicit conversion from long long to float may cause compiler
02336     // warnings, but static_cast does not.
02337     return static_cast<float> (t);
02338   }
02339 };
02340 
02341 
02343 template<>
02344 class ValueTypeConversionTraits<float, unsigned long long> {
02345 public:
02351   static float convert (const unsigned long long t) {
02352     // Implicit conversion from unsigned long long to float may cause
02353     // compiler warnings, but static_cast does not.
02354     return static_cast<float> (t);
02355   }
02356 
02358   static float safeConvert (const unsigned long long t) {
02359     // std::numeric_limits<float>::min() gives the minimum _positive_
02360     // normalized value of type float.  IEEE 754 floating-point values
02361     // can change sign just by flipping the sign bit, so the "most
02362     // negative" finite float is just the negative of the "most
02363     // positive" finite float.
02364     const float minFloat = -std::numeric_limits<float>::max ();
02365     const float maxFloat = std::numeric_limits<float>::max ();
02366 
02367     // t >= 0 by definition, because it is unsigned.
02368     //
02369     // mfh 16 Nov 2012: See my note above on the <float, long long>
02370     // specialization that explains why I don't cast maxFloat to
02371     // unsigned long long here.
02372     TEUCHOS_TEST_FOR_EXCEPTION(
02373       t > maxFloat,
02374       std::invalid_argument,
02375       "Teuchos::ValueTypeConversionTraits<float, unsigned long long>::safeConvert: "
02376       "Input unsigned long long t = " << t << " is out of the valid range [" << minFloat
02377       << ", " << maxFloat << "] for conversion to float.");
02378 
02379     // Implicit conversion from unsigned long long to float may cause
02380     // compiler warnings, but static_cast does not.
02381     return static_cast<float> (t);
02382   }
02383 };
02384 
02385 #endif // HAVE_TEUCHOS_LONG_LONG_INT
02386 
02387 //
02388 // * Other conversions
02389 //
02390 
02392 template<int N>
02393 class ValueTypeConversionTraits<std::string, char[N]> {
02394 public:
02395   static std::string convert( const char t[] )
02396     { return std::string(t); }
02397   static std::string safeConvert( const char t[] )
02398     { return std::string(t); }
02399 };
02400 
02401 //
02402 // * Conversions from built-in integer types to std::complex<T>.
02403 //
02404 
02405 #ifdef HAVE_TEUCHOS_COMPLEX
02406 
02408 template<class RealType>
02409 class ValueTypeConversionTraits<std::complex<RealType>, short> {
02410 public:
02411   inline static std::complex<RealType> convert (const short t) {
02412     // Let RealType handle the conversion of the zero imaginary part.
02413     return std::complex<RealType> (t, as<RealType> (0));
02414   }
02415   static std::complex<RealType> safeConvert (const short t) {
02416     // Let RealType handle the conversion of the zero imaginary part.
02417     return std::complex<RealType> (t, asSafe<RealType> (0));
02418   }
02419 };
02420 
02422 template<class RealType>
02423 class ValueTypeConversionTraits<std::complex<RealType>, unsigned short> {
02424 public:
02425   inline static std::complex<RealType> convert (const unsigned short t) {
02426     // Let RealType handle the conversion of the zero imaginary part.
02427     return std::complex<RealType> (t, as<RealType> (0));
02428   }
02429   static std::complex<RealType> safeConvert (const unsigned short t) {
02430     // Let RealType handle the conversion of the zero imaginary part.
02431     return std::complex<RealType> (t, asSafe<RealType> (0));
02432   }
02433 };
02434 
02436 template<class RealType>
02437 class ValueTypeConversionTraits<std::complex<RealType>, int> {
02438 public:
02439   inline static std::complex<RealType> convert (const int 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 int 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 int> {
02452 public:
02453   inline static std::complex<RealType> convert (const unsigned int 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 int 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>, long> {
02466 public:
02467   inline static std::complex<RealType> convert (const long 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 long 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 long> {
02480 public:
02481   inline static std::complex<RealType> convert (const unsigned long 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 long t) {
02486     // Let RealType handle the conversion of the zero imaginary part.
02487     return std::complex<RealType> (t, asSafe<RealType> (0));
02488   }
02489 };
02490 
02491 #ifdef HAVE_TEUCHOS_LONG_LONG_INT
02492 
02494 template<class RealType>
02495 class ValueTypeConversionTraits<std::complex<RealType>, long long> {
02496 public:
02497   inline static std::complex<RealType> convert (const long long t) {
02498     // Let RealType handle the conversion of the zero imaginary part.
02499     return std::complex<RealType> (t, as<RealType> (0));
02500   }
02501   static std::complex<RealType> safeConvert (const long long t) {
02502     // Let RealType handle the conversion of the zero imaginary part.
02503     return std::complex<RealType> (t, asSafe<RealType> (0));
02504   }
02505 };
02506 
02508 template<class RealType>
02509 class ValueTypeConversionTraits<std::complex<RealType>, unsigned long long> {
02510 public:
02511   inline static std::complex<RealType> convert (const unsigned long long t) {
02512     // Let RealType handle the conversion of the zero imaginary part.
02513     return std::complex<RealType> (t, as<RealType> (0));
02514   }
02515   static std::complex<RealType> safeConvert (const unsigned long long t) {
02516     // Let RealType handle the conversion of the zero imaginary part.
02517     return std::complex<RealType> (t, asSafe<RealType> (0));
02518   }
02519 };
02520 
02521 #endif // HAVE_TEUCHOS_LONG_LONG_INT
02522 #endif // HAVE_TEUCHOS_COMPLEX
02523 
02524 //
02525 // * Conversions for dd_real and qd_real
02526 //
02527 
02528 #ifdef HAVE_TEUCHOS_QD
02529 
02531 template <>
02532 class ValueTypeConversionTraits<double, qd_real> {
02533 public:
02534   inline static double convert (const qd_real t) {
02535     return to_double (t);
02536   }
02537   static double safeConvert (const qd_real t) {
02538     // std::numeric_limits<double>::min() gives the minimum _positive_
02539     // normalized value of type double.  IEEE 754 floating-point
02540     // values can change sign just by flipping the sign bit, so the
02541     // "most negative" finite double is just the negative of the "most
02542     // positive" finite double.
02543     const qd_real minVal = -std::numeric_limits<double>::max ();
02544     const qd_real maxVal = std::numeric_limits<double>::max ();
02545 
02546     TEUCHOS_TEST_FOR_EXCEPTION(
02547       t < minVal || t > maxVal,
02548       std::range_error,
02549       "Teuchos::ValueTypeConversionTraits<double, qd_real>::safeConvert: "
02550       "Input qd_real t = " << t << " is out of the valid range [" << minVal
02551       << ", " << maxVal << "] for conversion to double.");
02552 
02553     return to_double (t);
02554   }
02555 };
02556 
02558 template <>
02559 class ValueTypeConversionTraits<float, qd_real> {
02560 public:
02561   inline static float convert (const qd_real t) {
02562     // In a debug build, this should also test the double->float
02563     // conversion for overflow.
02564     return as<float> (to_double (t));
02565   }
02566 
02567   static float safeConvert (const qd_real t) {
02568     // std::numeric_limits<float>::min() gives the minimum _positive_
02569     // normalized value of type float.  IEEE 754 floating-point
02570     // values can change sign just by flipping the sign bit, so the
02571     // "most negative" finite float is just the negative of the "most
02572     // positive" finite float.
02573     //
02574     // qd_real has a constructor for double, but not for float,
02575     // so we cast to double first.
02576     const qd_real minVal = static_cast<double> (-std::numeric_limits<float>::max ());
02577     const qd_real maxVal = static_cast<double> (std::numeric_limits<float>::max ());
02578 
02579     TEUCHOS_TEST_FOR_EXCEPTION(
02580       t < minVal || t > maxVal,
02581       std::range_error,
02582       "Teuchos::ValueTypeConversionTraits<float, qd_real>::safeConvert: "
02583       "Input qd_real t = " << t << " is out of the valid range [" << minVal
02584       << ", " << maxVal << "] for conversion to float.");
02585 
02586     // This should also test the double->float conversion for overflow.
02587     return asSafe<float> (to_double (t));
02588   }
02589 };
02590 
02592 template <>
02593 class ValueTypeConversionTraits<int, qd_real> {
02594 public:
02595   inline static int convert (const qd_real t) {
02596     return to_int (t);
02597   }
02598   static int safeConvert (const qd_real t) {
02599     // qd_real has a constructor for int.
02600     const qd_real minVal = std::numeric_limits<int>::min ();
02601     const qd_real maxVal = std::numeric_limits<int>::max ();
02602 
02603     TEUCHOS_TEST_FOR_EXCEPTION(
02604       t < minVal || t > maxVal,
02605       std::range_error,
02606       "Teuchos::ValueTypeConversionTraits<int, qd_real>::safeConvert: "
02607       "Input qd_real t = " << t << " is out of the valid range [" << minVal
02608       << ", " << maxVal << "] for conversion to int.");
02609     return to_int (t);
02610   }
02611 };
02612 
02614 template <>
02615 class ValueTypeConversionTraits<dd_real, qd_real> {
02616 public:
02617   inline static dd_real convert (const qd_real t) {
02618     return to_dd_real(t);
02619   }
02620   static dd_real safeConvert (const qd_real t) {
02621     // std::numeric_limits<dd_real>::min() gives the minimum
02622     // _positive_ (normalized? not sure what this means for dd_real --
02623     // mfh 14 Nov 2012) value of type dd_real.  dd_real values are
02624     // built from two IEEE 754 doubles.  This means they can change
02625     // sign just by flipping the sign bit, so the "most negative"
02626     // finite dd_real is just the negative of the "most positive"
02627     // finite dd_real.
02628     //
02629     // qd_real has a constructor for dd_real.
02630     const qd_real minVal = -std::numeric_limits<dd_real>::max ();
02631     const qd_real maxVal = std::numeric_limits<dd_real>::max ();
02632 
02633     TEUCHOS_TEST_FOR_EXCEPTION(
02634       t < minVal || t > maxVal,
02635       std::range_error,
02636       "Teuchos::ValueTypeConversionTraits<dd_real, qd_real>::safeConvert: "
02637       "Input qd_real t = " << t << " is out of the valid range [" << minVal
02638       << ", " << maxVal << "] for conversion to dd_real.");
02639 
02640     return to_dd_real (t);
02641   }
02642 };
02643 
02645 template <>
02646 class ValueTypeConversionTraits<double, dd_real> {
02647 public:
02648   inline static double convert (const dd_real t) {
02649     return to_double (t);
02650   }
02651   static double safeConvert (const dd_real t) {
02652     // std::numeric_limits<double>::min() gives the minimum _positive_
02653     // normalized value of type double.  IEEE 754 floating-point
02654     // values can change sign just by flipping the sign bit, so the
02655     // "most negative" finite double is just the negative of the "most
02656     // positive" finite double.
02657     //
02658     // qd_real has a constructor for double.
02659     const dd_real minVal = -std::numeric_limits<double>::max ();
02660     const dd_real maxVal = std::numeric_limits<double>::max ();
02661 
02662     TEUCHOS_TEST_FOR_EXCEPTION(
02663       t < minVal || t > maxVal,
02664       std::range_error,
02665       "Teuchos::ValueTypeConversionTraits<double, dd_real>::safeConvert: "
02666       "Input dd_real t = " << t << " is out of the valid range [" << minVal
02667       << ", " << maxVal << "] for conversion to double.");
02668 
02669     return to_double (t);
02670   }
02671 };
02672 
02674 template <>
02675 class ValueTypeConversionTraits<float, dd_real> {
02676 public:
02677   inline static float convert (const dd_real t) {
02678     // This also checks for double->float overflow in a debug build.
02679     return as<float> (to_double (t));
02680   }
02681   static float safeConvert (const dd_real t) {
02682     // std::numeric_limits<float>::min() gives the minimum _positive_
02683     // normalized value of type float.  IEEE 754 floating-point
02684     // values can change sign just by flipping the sign bit, so the
02685     // "most negative" finite float is just the negative of the "most
02686     // positive" finite float.
02687     //
02688     // dd_real has a constructor for double but not for float,
02689     // so we cast to double first.
02690     const dd_real minVal = static_cast<double> (-std::numeric_limits<float>::max ());
02691     const dd_real maxVal = static_cast<double> (std::numeric_limits<float>::max ());
02692 
02693     TEUCHOS_TEST_FOR_EXCEPTION(
02694       t < minVal || t > maxVal,
02695       std::range_error,
02696       "Teuchos::ValueTypeConversionTraits<float, dd_real>::safeConvert: "
02697       "Input dd_real t = " << t << " is out of the valid range [" << minVal
02698       << ", " << maxVal << "] for conversion to float.");
02699 
02700     // This also checks for double->float overflow.
02701     return as<float> (to_double (t));
02702   }
02703 };
02704 
02706 template <>
02707 class ValueTypeConversionTraits<int, dd_real> {
02708 public:
02709   inline static int convert (const dd_real t) {
02710     return to_int (t);
02711   }
02712   static int safeConvert (const dd_real t) {
02713     // dd_real has a constructor for int.
02714     const dd_real minVal = std::numeric_limits<int>::min ();
02715     const dd_real maxVal = std::numeric_limits<int>::max ();
02716 
02717     TEUCHOS_TEST_FOR_EXCEPTION(
02718       t < minVal || t > maxVal,
02719       std::range_error,
02720       "Teuchos::ValueTypeConversionTraits<int, dd_real>::safeConvert: "
02721       "Input dd_real t = " << t << " is out of the valid range [" << minVal
02722       << ", " << maxVal << "] for conversion to int.");
02723     return to_int (t);
02724   }
02725 };
02726 
02728 template <>
02729 class ValueTypeConversionTraits<qd_real, long unsigned int> {
02730 public:
02731   inline static qd_real convert( const long unsigned int t ) {
02732     // FIXME (mfh 14 Nov 2012): qd_real unfortunately lacks a
02733     // constructor or conversion function for conversions from
02734     // built-in integer types other than int.  However, it does allow
02735     // reading in values from a string.  We could use this to convert
02736     // from any type to qd_real, by first writing the value to an
02737     // std::ostringstream, then creating a qd_real from the resulting
02738     // string.
02739     return ValueTypeConversionTraits<qd_real,int>::convert(ValueTypeConversionTraits<int,long unsigned int>::convert(t));
02740   }
02741   inline static qd_real safeConvert( const long unsigned int t )
02742     { return ValueTypeConversionTraits<qd_real,int>::safeConvert(ValueTypeConversionTraits<int,long unsigned int>::safeConvert(t)); }
02743 };
02744 
02746 template <>
02747 class ValueTypeConversionTraits<dd_real, long unsigned int> {
02748 public:
02749   inline static dd_real convert( const long unsigned int t ) {
02750     // FIXME (mfh 14 Nov 2012): dd_real unfortunately lacks a
02751     // constructor or conversion function for conversions from
02752     // built-in integer types other than int.  However, it does allow
02753     // reading in values from a string.  We could use this to convert
02754     // from any type to dd_real, by first writing the value to an
02755     // std::ostringstream, then creating a dd_real from the resulting
02756     // string.
02757     return ValueTypeConversionTraits<dd_real,int>::convert(ValueTypeConversionTraits<int,long unsigned int>::convert(t));
02758   }
02759   inline static dd_real safeConvert( const long unsigned int t )
02760     { return ValueTypeConversionTraits<dd_real,int>::safeConvert(ValueTypeConversionTraits<int,long unsigned int>::safeConvert(t)); }
02761 };
02762 
02763 #endif // HAVE_TEUCHOS_QD
02764 
02765 // ToDo: Add more specializations as needed!
02766 
02767 
02768 } // end namespace Teuchos
02769 
02770 
02771 #endif // TEUCHOS_AS_HPP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines