Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:40:42

0001 // Copyright Paul A. Bristow 2017.
0002 // Copyright John Maddock 2017.
0003 
0004 // Use, modification and distribution are subject to the
0005 // Boost Software License, Version 1.0.
0006 // (See accompanying file LICENSE_1_0.txt
0007 // or copy at http://www.boost.org/LICENSE_1_0.txt)
0008 
0009 // test_value.hpp
0010 
0011 #ifndef TEST_VALUE_HPP
0012 #define TEST_VALUE_HPP
0013 
0014 // BOOST_MATH_TEST_VALUE is used to create a test value of suitable type from a decimal digit string.
0015 // Two parameters, both a floating-point literal double like 1.23 (not long double so no suffix L)
0016 // and a decimal digit string const char* like "1.23" must be provided.
0017 // The decimal value represented must be the same of course, with at least enough precision for long double.
0018 //   Note there are two gotchas to this approach:
0019 // * You need all values to be real floating-point values
0020 // * and *MUST* include a decimal point (to avoid confusion with an integer literal).
0021 // * It's slow to compile compared to a simple literal.
0022 
0023 // Speed is not an issue for a few test values,
0024 // but it's not generally usable in large tables
0025 // where you really need everything to be statically initialized.
0026 
0027 // Macro BOOST_MATH_INSTRUMENT_CREATE_TEST_VALUE provides a global diagnostic value for create_type.
0028 
0029 #include <boost/cstdfloat.hpp> // For float_64_t, float128_t. Must be first include!
0030 #ifndef BOOST_MATH_STANDALONE
0031 #include <boost/lexical_cast.hpp>
0032 #endif
0033 #include <limits>
0034 #include <type_traits>
0035 
0036 #ifdef BOOST_MATH_INSTRUMENT_CREATE_TEST_VALUE
0037 // global int create_type(0); must be defined before including this file.
0038 #endif
0039 
0040 #ifdef BOOST_HAS_FLOAT128
0041 typedef __float128 largest_float;
0042 #define BOOST_MATH_TEST_LARGEST_FLOAT_SUFFIX(x) x##Q
0043 #define BOOST_MATH_TEST_LARGEST_FLOAT_DIGITS 113
0044 #else
0045 typedef long double largest_float;
0046 #define BOOST_MATH_TEST_LARGEST_FLOAT_SUFFIX(x) x##L
0047 #define BOOST_MATH_TEST_LARGEST_FLOAT_DIGITS std::numeric_limits<long double>::digits
0048 #endif
0049 
0050 template <class T, class T2>
0051 inline T create_test_value(largest_float val, const char*, const std::true_type&, const T2&)
0052 { // Construct from long double or quad parameter val (ignoring string/const char* str).
0053   // (This is case for MPL parameters = true_ and T2 == false_,
0054   // and  MPL parameters = true_ and T2 == true_  cpp_bin_float)
0055   // All built-in/fundamental floating-point types,
0056   // and other User-Defined Types that can be constructed without loss of precision
0057   // from long double suffix L (or quad suffix Q),
0058   //
0059   // Choose this method, even if can be constructed from a string,
0060   // because it will be faster, and more likely to be the closest representation.
0061   // (This is case for MPL parameters = true_type and T2 == true_type).
0062   #ifdef BOOST_MATH_INSTRUMENT_CREATE_TEST_VALUE
0063   create_type = 1;
0064   #endif
0065   return static_cast<T>(val);
0066 }
0067 
0068 template <class T>
0069 inline T create_test_value(largest_float, const char* str, const std::false_type&, const std::true_type&)
0070 { // Construct from decimal digit string const char* @c str (ignoring long double parameter).
0071   // For example, extended precision or other User-Defined types which ARE constructible from a string
0072   // (but not from double, or long double without loss of precision).
0073   // (This is case for MPL parameters = false_type and T2 == true_type).
0074   #ifdef BOOST_MATH_INSTRUMENT_CREATE_TEST_VALUE
0075   create_type = 2;
0076   #endif
0077   return T(str);
0078 }
0079 
0080 template <class T>
0081 inline T create_test_value(largest_float, const char* str, const std::false_type&, const std::false_type&)
0082 { // Create test value using from lexical cast of decimal digit string const char* str.
0083   // For example, extended precision or other User-Defined types which are NOT constructible from a string
0084   // (NOR constructible from a long double).
0085   // (This is case T1 = false_type and T2 == false_type).
0086 #ifdef BOOST_MATH_INSTRUMENT_CREATE_TEST_VALUE
0087   create_type = 3;
0088 #endif
0089 #if defined(BOOST_MATH_STANDALONE)
0090   static_assert(sizeof(T) == 0, "Can not create a test value using lexical cast of string in standalone mode");
0091   return T();
0092 #else
0093   return boost::lexical_cast<T>(str);
0094 #endif
0095 }
0096 
0097 // T real type, x a decimal digits representation of a floating-point, for example: 12.34.
0098 // It must include a decimal point (or it would be interpreted as an integer).
0099 
0100 //  x is converted to a long double by appending the letter L (to suit long double fundamental type), 12.34L.
0101 //  x is also passed as a const char* or string representation "12.34"
0102 //  (to suit most other types that cannot be constructed from long double without possible loss).
0103 
0104 // BOOST_MATH_TEST_LARGEST_FLOAT_SUFFIX(x) makes a long double or quad version, with
0105 // suffix a letter L (or Q) to suit long double (or quad) fundamental type, 12.34L or 12.34Q.
0106 // #x makes a decimal digit string version to suit multiprecision and fixed_point constructors, "12.34".
0107 // (Constructing from double or long double (or quad) could lose precision for multiprecision or fixed-point).
0108 
0109 // The matching create_test_value function above is chosen depending on the T1 and T2 mpl bool truths.
0110 // The string version from #x is used if the precision of T is greater than long double.
0111 
0112 // Example: long double test_value = BOOST_MATH_TEST_VALUE(double, 1.23456789);
0113 
0114 #define BOOST_MATH_TEST_VALUE(T, x) create_test_value<T>(\
0115   BOOST_MATH_TEST_LARGEST_FLOAT_SUFFIX(x),\
0116   #x,\
0117   std::integral_constant<bool, \
0118     std::numeric_limits<T>::is_specialized &&\
0119       (std::numeric_limits<T>::radix == 2)\
0120         && (std::numeric_limits<T>::digits <= BOOST_MATH_TEST_LARGEST_FLOAT_DIGITS)\
0121         && std::is_convertible<largest_float, T>::value>(),\
0122   std::integral_constant<bool, \
0123     std::is_constructible<T, const char*>::value>()\
0124 )
0125 
0126 #if LDBL_MAX_10_EXP > DBL_MAX_10_EXP
0127 #define BOOST_MATH_TEST_HUGE_FLOAT_SUFFIX(x) BOOST_MATH_TEST_LARGEST_FLOAT_SUFFIX(x)
0128 #else
0129 #define BOOST_MATH_TEST_HUGE_FLOAT_SUFFIX(x) 0.0
0130 #endif
0131 
0132 #define BOOST_MATH_HUGE_TEST_VALUE(T, x) create_test_value<T>(\
0133   BOOST_MATH_TEST_HUGE_FLOAT_SUFFIX(x),\
0134   #x,\
0135   std::integral_constant<bool, \
0136     std::numeric_limits<T>::is_specialized &&\
0137       (std::numeric_limits<T>::radix == 2)\
0138         && (std::numeric_limits<T>::digits <= BOOST_MATH_TEST_LARGEST_FLOAT_DIGITS)\
0139         && std::is_convertible<largest_float, T>::value>(),\
0140   std::integral_constant<bool, \
0141     std::is_constructible<T, const char*>::value>()\
0142 )
0143 #endif // TEST_VALUE_HPP