]>
Commit | Line | Data |
---|---|---|
92f5a8d4 TL |
1 | // Copyright Paul A. Bristow 2017. |
2 | // Copyright John Maddock 2017. | |
3 | ||
4 | // Use, modification and distribution are subject to the | |
5 | // Boost Software License, Version 1.0. | |
6 | // (See accompanying file LICENSE_1_0.txt | |
7 | // or copy at http://www.boost.org/LICENSE_1_0.txt) | |
8 | ||
9 | // test_value.hpp | |
10 | ||
11 | #ifndef TEST_VALUE_HPP | |
12 | #define TEST_VALUE_HPP | |
13 | ||
14 | // BOOST_MATH_TEST_VALUE is used to create a test value of suitable type from a decimal digit string. | |
15 | // Two parameters, both a floating-point literal double like 1.23 (not long double so no suffix L) | |
16 | // and a decimal digit string const char* like "1.23" must be provided. | |
17 | // The decimal value represented must be the same of course, with at least enough precision for long double. | |
18 | // Note there are two gotchas to this approach: | |
19 | // * You need all values to be real floating-point values | |
20 | // * and *MUST* include a decimal point (to avoid confusion with an integer literal). | |
21 | // * It's slow to compile compared to a simple literal. | |
22 | ||
23 | // Speed is not an issue for a few test values, | |
24 | // but it's not generally usable in large tables | |
25 | // where you really need everything to be statically initialized. | |
26 | ||
27 | // Macro BOOST_MATH_INSTRUMENT_CREATE_TEST_VALUE provides a global diagnostic value for create_type. | |
28 | ||
29 | #include <boost/cstdfloat.hpp> // For float_64_t, float128_t. Must be first include! | |
30 | #include <boost/lexical_cast.hpp> | |
31 | #include <boost/type_traits/is_constructible.hpp> | |
32 | #include <boost/type_traits/is_convertible.hpp> | |
33 | ||
34 | #ifdef BOOST_MATH_INSTRUMENT_CREATE_TEST_VALUE | |
35 | // global int create_type(0); must be defined before including this file. | |
36 | #endif | |
37 | ||
38 | #ifdef BOOST_HAS_FLOAT128 | |
39 | typedef __float128 largest_float; | |
40 | #define BOOST_MATH_TEST_LARGEST_FLOAT_SUFFIX(x) x##Q | |
41 | #define BOOST_MATH_TEST_LARGEST_FLOAT_DIGITS 113 | |
42 | #else | |
43 | typedef long double largest_float; | |
44 | #define BOOST_MATH_TEST_LARGEST_FLOAT_SUFFIX(x) x##L | |
45 | #define BOOST_MATH_TEST_LARGEST_FLOAT_DIGITS std::numeric_limits<long double>::digits | |
46 | #endif | |
47 | ||
48 | template <class T, class T2> | |
f67539c2 | 49 | inline T create_test_value(largest_float val, const char*, const boost::true_type&, const T2&) |
92f5a8d4 TL |
50 | { // Construct from long double or quad parameter val (ignoring string/const char* str). |
51 | // (This is case for MPL parameters = true_ and T2 == false_, | |
52 | // and MPL parameters = true_ and T2 == true_ cpp_bin_float) | |
53 | // All built-in/fundamental floating-point types, | |
54 | // and other User-Defined Types that can be constructed without loss of precision | |
55 | // from long double suffix L (or quad suffix Q), | |
56 | // | |
57 | // Choose this method, even if can be constructed from a string, | |
58 | // because it will be faster, and more likely to be the closest representation. | |
f67539c2 | 59 | // (This is case for MPL parameters = true_type and T2 == true_type). |
92f5a8d4 TL |
60 | #ifdef BOOST_MATH_INSTRUMENT_CREATE_TEST_VALUE |
61 | create_type = 1; | |
62 | #endif | |
63 | return static_cast<T>(val); | |
64 | } | |
65 | ||
66 | template <class T> | |
f67539c2 | 67 | inline T create_test_value(largest_float, const char* str, const boost::false_type&, const boost::true_type&) |
92f5a8d4 TL |
68 | { // Construct from decimal digit string const char* @c str (ignoring long double parameter). |
69 | // For example, extended precision or other User-Defined types which ARE constructible from a string | |
70 | // (but not from double, or long double without loss of precision). | |
f67539c2 | 71 | // (This is case for MPL parameters = false_type and T2 == true_type). |
92f5a8d4 TL |
72 | #ifdef BOOST_MATH_INSTRUMENT_CREATE_TEST_VALUE |
73 | create_type = 2; | |
74 | #endif | |
75 | return T(str); | |
76 | } | |
77 | ||
78 | template <class T> | |
f67539c2 | 79 | inline T create_test_value(largest_float, const char* str, const boost::false_type&, const boost::false_type&) |
92f5a8d4 TL |
80 | { // Create test value using from lexical cast of decimal digit string const char* str. |
81 | // For example, extended precision or other User-Defined types which are NOT constructible from a string | |
82 | // (NOR constructible from a long double). | |
f67539c2 | 83 | // (This is case T1 = false_type and T2 == false_type). |
92f5a8d4 TL |
84 | #ifdef BOOST_MATH_INSTRUMENT_CREATE_TEST_VALUE |
85 | create_type = 3; | |
86 | #endif | |
87 | return boost::lexical_cast<T>(str); | |
88 | } | |
89 | ||
90 | // T real type, x a decimal digits representation of a floating-point, for example: 12.34. | |
91 | // It must include a decimal point (or it would be interpreted as an integer). | |
92 | ||
93 | // x is converted to a long double by appending the letter L (to suit long double fundamental type), 12.34L. | |
94 | // x is also passed as a const char* or string representation "12.34" | |
95 | // (to suit most other types that cannot be constructed from long double without possible loss). | |
96 | ||
97 | // BOOST_MATH_TEST_LARGEST_FLOAT_SUFFIX(x) makes a long double or quad version, with | |
98 | // suffix a letter L (or Q) to suit long double (or quad) fundamental type, 12.34L or 12.34Q. | |
99 | // #x makes a decimal digit string version to suit multiprecision and fixed_point constructors, "12.34". | |
100 | // (Constructing from double or long double (or quad) could lose precision for multiprecision or fixed-point). | |
101 | ||
102 | // The matching create_test_value function above is chosen depending on the T1 and T2 mpl bool truths. | |
103 | // The string version from #x is used if the precision of T is greater than long double. | |
104 | ||
105 | // Example: long double test_value = BOOST_MATH_TEST_VALUE(double, 1.23456789); | |
106 | ||
107 | #define BOOST_MATH_TEST_VALUE(T, x) create_test_value<T>(\ | |
108 | BOOST_MATH_TEST_LARGEST_FLOAT_SUFFIX(x),\ | |
109 | #x,\ | |
f67539c2 | 110 | boost::integral_constant<bool, \ |
92f5a8d4 TL |
111 | std::numeric_limits<T>::is_specialized &&\ |
112 | (std::numeric_limits<T>::radix == 2)\ | |
113 | && (std::numeric_limits<T>::digits <= BOOST_MATH_TEST_LARGEST_FLOAT_DIGITS)\ | |
114 | && boost::is_convertible<largest_float, T>::value>(),\ | |
f67539c2 | 115 | boost::integral_constant<bool, \ |
92f5a8d4 TL |
116 | boost::is_constructible<T, const char*>::value>()\ |
117 | ) | |
118 | #endif // TEST_VALUE_HPP |