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