brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.2 KiB · c44fe05 Raw
144 lines · plain
1// Copyright Paul A. Bristow 2017.2// Copyright John Maddock 2017.3 4// Use, modification and distribution are subject to the5// Boost Software License, Version 1.0.6// (See accompanying file LICENSE_1_0.txt7// or copy at http://www.boost.org/LICENSE_1_0.txt)8 9// test_value.hpp10 11#ifndef TEST_VALUE_HPP12#define TEST_VALUE_HPP13 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 values20// * 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 tables25// 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#ifndef BOOST_MATH_STANDALONE31#include <boost/lexical_cast.hpp>32#endif33#include <limits>34#include <type_traits>35 36#ifdef BOOST_MATH_INSTRUMENT_CREATE_TEST_VALUE37// global int create_type(0); must be defined before including this file.38#endif39 40#ifdef BOOST_HAS_FLOAT12841typedef __float128 largest_float;42#define BOOST_MATH_TEST_LARGEST_FLOAT_SUFFIX(x) x##Q43#define BOOST_MATH_TEST_LARGEST_FLOAT_DIGITS 11344#else45typedef long double largest_float;46#define BOOST_MATH_TEST_LARGEST_FLOAT_SUFFIX(x) x##L47#define BOOST_MATH_TEST_LARGEST_FLOAT_DIGITS std::numeric_limits<long double>::digits48#endif49 50template <class T, class T2>51inline T create_test_value(largest_float val, const char*, const std::true_type&, const T2&)52{ // Construct from long double or quad parameter val (ignoring string/const char* str).53  // (This is case for MPL parameters = true_ and T2 == false_,54  // and  MPL parameters = true_ and T2 == true_  cpp_bin_float)55  // All built-in/fundamental floating-point types,56  // and other User-Defined Types that can be constructed without loss of precision57  // from long double suffix L (or quad suffix Q),58  //59  // Choose this method, even if can be constructed from a string,60  // because it will be faster, and more likely to be the closest representation.61  // (This is case for MPL parameters = true_type and T2 == true_type).62  #ifdef BOOST_MATH_INSTRUMENT_CREATE_TEST_VALUE63  create_type = 1;64  #endif65  return static_cast<T>(val);66}67 68template <class T>69inline T create_test_value(largest_float, const char* str, const std::false_type&, const std::true_type&)70{ // Construct from decimal digit string const char* @c str (ignoring long double parameter).71  // For example, extended precision or other User-Defined types which ARE constructible from a string72  // (but not from double, or long double without loss of precision).73  // (This is case for MPL parameters = false_type and T2 == true_type).74  #ifdef BOOST_MATH_INSTRUMENT_CREATE_TEST_VALUE75  create_type = 2;76  #endif77  return T(str);78}79 80template <class T>81inline T create_test_value(largest_float, const char* str, const std::false_type&, const std::false_type&)82{ // Create test value using from lexical cast of decimal digit string const char* str.83  // For example, extended precision or other User-Defined types which are NOT constructible from a string84  // (NOR constructible from a long double).85  // (This is case T1 = false_type and T2 == false_type).86#ifdef BOOST_MATH_INSTRUMENT_CREATE_TEST_VALUE87  create_type = 3;88#endif89#if defined(BOOST_MATH_STANDALONE)90  static_assert(sizeof(T) == 0, "Can not create a test value using lexical cast of string in standalone mode");91  return T();92#else93  return boost::lexical_cast<T>(str);94#endif95}96 97// T real type, x a decimal digits representation of a floating-point, for example: 12.34.98// It must include a decimal point (or it would be interpreted as an integer).99 100//  x is converted to a long double by appending the letter L (to suit long double fundamental type), 12.34L.101//  x is also passed as a const char* or string representation "12.34"102//  (to suit most other types that cannot be constructed from long double without possible loss).103 104// BOOST_MATH_TEST_LARGEST_FLOAT_SUFFIX(x) makes a long double or quad version, with105// suffix a letter L (or Q) to suit long double (or quad) fundamental type, 12.34L or 12.34Q.106// #x makes a decimal digit string version to suit multiprecision and fixed_point constructors, "12.34".107// (Constructing from double or long double (or quad) could lose precision for multiprecision or fixed-point).108 109// The matching create_test_value function above is chosen depending on the T1 and T2 mpl bool truths.110// The string version from #x is used if the precision of T is greater than long double.111 112// Example: long double test_value = BOOST_MATH_TEST_VALUE(double, 1.23456789);113 114#define BOOST_MATH_TEST_VALUE(T, x) create_test_value<T>(\115  BOOST_MATH_TEST_LARGEST_FLOAT_SUFFIX(x),\116  #x,\117  std::integral_constant<bool, \118    std::numeric_limits<T>::is_specialized &&\119      (std::numeric_limits<T>::radix == 2)\120        && (std::numeric_limits<T>::digits <= BOOST_MATH_TEST_LARGEST_FLOAT_DIGITS)\121        && (std::is_convertible<largest_float, T>::value || std::is_floating_point<T>::value)>(),\122  std::integral_constant<bool, \123    std::is_constructible<T, const char*>::value>()\124)125 126#if LDBL_MAX_10_EXP > DBL_MAX_10_EXP127#define BOOST_MATH_TEST_HUGE_FLOAT_SUFFIX(x) BOOST_MATH_TEST_LARGEST_FLOAT_SUFFIX(x)128#else129#define BOOST_MATH_TEST_HUGE_FLOAT_SUFFIX(x) 0.0130#endif131 132#define BOOST_MATH_HUGE_TEST_VALUE(T, x) create_test_value<T>(\133  BOOST_MATH_TEST_HUGE_FLOAT_SUFFIX(x),\134  #x,\135  std::integral_constant<bool, \136    std::numeric_limits<T>::is_specialized &&\137      (std::numeric_limits<T>::radix == 2)\138        && (std::numeric_limits<T>::digits <= BOOST_MATH_TEST_LARGEST_FLOAT_DIGITS)\139        && std::is_convertible<largest_float, T>::value>(),\140  std::integral_constant<bool, \141    std::is_constructible<T, const char*>::value>()\142)143#endif // TEST_VALUE_HPP144