mirror of
https://github.com/boostorg/math.git
synced 2026-02-14 12:52:15 +00:00
Failed attempts to get create_test_value to work.
This commit is contained in:
@@ -36,29 +36,43 @@ using boost::multiprecision::cpp_dec_float_50;
|
||||
#include <type_traits>
|
||||
|
||||
// BOOST_MATH_TEST_VALUE is used to create a test value of suitable type from a decimal digit string.
|
||||
// Two parameters, both a literal like 1.23 and a decimal digit string const char* like "1.23" must be provided.
|
||||
// The decimal value represented must be the same of course, with at least enough precision for long double.
|
||||
// Note there are two gotchas to this approach:
|
||||
// * You need all values to be real floating-point values
|
||||
// * and *MUST* include a decimal point.
|
||||
// * It's slow to compile compared to a simple literal - not an issue for a
|
||||
// few test values, but it's not generally usable in large tables
|
||||
// * It's slow to compile compared to a simple literal.
|
||||
// This is not an issue for a few test values,
|
||||
// but it's not generally usable in large tables
|
||||
// where you really need everything to be statically initialized.
|
||||
|
||||
int create_type(0);
|
||||
|
||||
template <class T, class T1, class T2>
|
||||
inline T create_test_value(long double val, const char*, const T1&, const T2&)
|
||||
{ // Construct from long double parameter val (ignoring string/const char*)
|
||||
{ // Construct from long double parameter val (ignoring string/const char* str)
|
||||
create_type = 1;
|
||||
return static_cast<T>(val);
|
||||
}
|
||||
|
||||
template <class T, class T1, class T2>
|
||||
inline T create_test_value(long double val, const char*, const boost::mpl::true_&, const boost::mpl::false_&)
|
||||
{ // Construct from long double parameter val (ignoring string/const char* str)
|
||||
create_type = 1;
|
||||
return static_cast<T>(val);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T create_test_value(long double, const char* str, const boost::mpl::false_&, const boost::mpl::true_&)
|
||||
{ // Construct from string (ignoring long double parameter).
|
||||
{ // Construct from decimal digit string const char* @c str (ignoring long double parameter).
|
||||
create_type = 2;
|
||||
return T(str);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T create_test_value(long double, const char* str, const boost::mpl::false_&, const boost::mpl::false_&)
|
||||
{ // Create test value using from lexical cast of string.
|
||||
{ // Create test value using from lexical cast of decimal digit string const char* str.
|
||||
create_type = 3;
|
||||
return boost::lexical_cast<T>(str);
|
||||
}
|
||||
|
||||
@@ -66,18 +80,25 @@ inline T create_test_value(long double, const char* str, const boost::mpl::false
|
||||
|
||||
// x is converted to a long double by appending the letter L (to suit long double fundamental type)
|
||||
// x is also passed as a const char* or string representation
|
||||
// (to suit most other types that cannot be constructed from long double without loss)
|
||||
// (to suit most other types that cannot be constructed from long double without possible loss).
|
||||
|
||||
// x##L makes a long double version, suffix a letter L to suit long double fundamental type.
|
||||
// #x makes a decimal digit string version to suit multiprecision and fixed_point constructors.
|
||||
// (Constructing from double or long double could lose precision for multiprecision or fixed-point).
|
||||
|
||||
// The matching create_test_value function above is chosen depending on the T1 and T2 mpl bool truths.
|
||||
// The string version from #x is used if the precision of T is greater than long double.
|
||||
|
||||
// Example: long double test_value = BOOST_MATH_TEST_VALUE(long double, 9.);
|
||||
|
||||
// x##L is a long double version, suffix a letter L to suit long double fundamental type.
|
||||
// #x is a string version to suit multiprecision constructors
|
||||
// (constructing from double or long double would loose precision).
|
||||
#define BOOST_MATH_TEST_VALUE(T, x) create_test_value<T>(\
|
||||
x##L,\
|
||||
#x,\
|
||||
boost::mpl::bool_<\
|
||||
std::numeric_limits<T>::is_specialized &&\
|
||||
(std::numeric_limits<T>::radix == 2) && (std::numeric_limits<T>::digits\
|
||||
<= std::numeric_limits<long double>::digits) && boost::is_convertible<long double, T>::value>(),\
|
||||
(std::numeric_limits<T>::radix == 2)\
|
||||
&& (std::numeric_limits<T>::digits <= std::numeric_limits<long double>::digits)\
|
||||
&& boost::is_convertible<long double, T>::value>(),\
|
||||
boost::mpl::bool_<\
|
||||
boost::is_constructible<T, const char*>::value>()\
|
||||
)
|
||||
@@ -85,17 +106,27 @@ inline T create_test_value(long double, const char* str, const boost::mpl::false
|
||||
template <class T>
|
||||
void show()
|
||||
{
|
||||
std::cout << std::boolalpha << typeid(T).name() << std::endl
|
||||
std::cout << std::boolalpha << "Test with type:\n"
|
||||
<< typeid(T).name() << std::endl
|
||||
<< " is specialized " << std::numeric_limits<T>::is_specialized
|
||||
<< " digits " << std::numeric_limits<T>::digits // binary digits 24
|
||||
<< ", is_convertible " << boost::is_convertible<T, const char*>::value << std::endl // convertible to string
|
||||
<< " is_constructible " << boost::is_constructible<T, const char*>::value // constructible from string
|
||||
<< std::endl;
|
||||
<< ", radix = " << std::numeric_limits<T>::radix
|
||||
<< ", digits = " << std::numeric_limits<T>::digits // binary digits, 24 for float, 53 for double ...
|
||||
<< ", is_convertible " << boost::is_convertible<long double, T>::value // is convertible long double *to* T.
|
||||
<< ", is_constructible " << boost::is_constructible<T, const char*>::value // is constructible *from* string.
|
||||
<< std::endl;
|
||||
|
||||
std::cout << " T1 = "
|
||||
<< (
|
||||
(std::numeric_limits<T>::is_specialized)
|
||||
&& (std::numeric_limits<T>::radix == 2)
|
||||
&& (std::numeric_limits<T>::digits <= std::numeric_limits<long double>::digits)
|
||||
&& (boost::is_convertible<long double, T>::value)
|
||||
)
|
||||
<< ", T2 = " << (boost::is_constructible<T, const char*>::value)
|
||||
<< std::endl;
|
||||
} // show
|
||||
|
||||
|
||||
long double test_value = BOOST_MATH_TEST_VALUE(long double, 1.);
|
||||
|
||||
static const unsigned int noof_tests = 2;
|
||||
|
||||
static const boost::array<const char*, noof_tests> test_data =
|
||||
@@ -106,16 +137,12 @@ static const boost::array<const char*, noof_tests> test_data =
|
||||
|
||||
//static const boost::array<const char*, noof_tests> test_expected =
|
||||
//{ {
|
||||
// BOOST_MATH_TEST_VALUE("0.56714329040978387299996866221035554975381578718651"), // Output from https://www.wolframalpha.com/input/?i=productlog(1)
|
||||
// BOOST_MATH_TEST_VALUE("1.432404775898300311234078007212058694786434608804302025655") // Output from https://www.wolframalpha.com/input/?i=productlog(6)
|
||||
// BOOST_MATH_TEST_VALUE(T, 0.56714329040978387299996866221035554975381578718651), // Output from https://www.wolframalpha.com/input/?i=productlog(1)
|
||||
// BOOST_MATH_TEST_VALUE(T, 1.432404775898300311234078007212058694786434608804302025655) // Output from https://www.wolframalpha.com/input/?i=productlog(6)
|
||||
|
||||
// } }; // array test_data
|
||||
|
||||
|
||||
|
||||
//BOOST_MATH_TEST_VALUE("-0.36787944117144232159552377016146086744581113103176783450783680169746149574489980335714727434591964374662732527")
|
||||
// w(-0.367879441171442321595523770161460867445811131031767834)
|
||||
|
||||
//
|
||||
// ProductLog[-0.367879441171442321595523770161460867445811131031767834]
|
||||
|
||||
@@ -134,6 +161,8 @@ void test_spots(RealType)
|
||||
// BOOST_MATH_CHECK_THROW(boost::math::normal_distribution<RealType>(0, -1), std::domain_error); // negative sd
|
||||
//#endif
|
||||
|
||||
using boost::math::productlog;
|
||||
|
||||
using boost::math::constants::expminusone;
|
||||
RealType tolerance = boost::math::tools::epsilon<RealType>() * 5; // 5 eps as a fraction.
|
||||
std::cout << "Testing type " << typeid(RealType).name() << std::endl;
|
||||
@@ -145,27 +174,30 @@ void test_spots(RealType)
|
||||
|
||||
show<RealType>();
|
||||
|
||||
using boost::math::productlog;
|
||||
std::cout << " Create type: "
|
||||
<< ((create_type ==1) ? "create from static_cast<T>(val) " :
|
||||
(create_type == 2) ? "construct from T(str)" :
|
||||
(create_type == 3) ? "boost::lexical_cast<T>(str)" :
|
||||
"???") // ??? create_type == 0 should never happen?
|
||||
<< std::endl;
|
||||
|
||||
RealType test_value = BOOST_MATH_TEST_VALUE(RealType, 1.);
|
||||
RealType expected_value = BOOST_MATH_TEST_VALUE(RealType, 0.56714329040978387299996866221035554975381578718651);
|
||||
|
||||
test_value = BOOST_MATH_TEST_VALUE(RealType, -0.36787944117144232159552377016146086744581113103176);
|
||||
expected_value = BOOST_MATH_TEST_VALUE(RealType, -1.);
|
||||
std::cout.precision(std::numeric_limits <RealType>::max_digits10);
|
||||
test_value = -boost::math::constants::expminusone<RealType>();
|
||||
std::cout << "test " << test_value << ", expected " << expected_value << std::endl;
|
||||
|
||||
BOOST_CHECK_CLOSE_FRACTION(
|
||||
RealType test_value = BOOST_MATH_TEST_VALUE(RealType, -0.36787944117144232159552377016146086744581113103176);
|
||||
RealType expected_value = BOOST_MATH_TEST_VALUE(RealType, -1.);
|
||||
|
||||
test_value = -boost::math::constants::expminusone<RealType>(); // -exp(-1) = -0.367879450
|
||||
std::cout << "test " << test_value << ", expected productlog = " << expected_value << std::endl;
|
||||
|
||||
BOOST_CHECK_CLOSE_FRACTION( // Check -exp(-1) = -0.367879450 = -1
|
||||
productlog(test_value),
|
||||
expected_value,
|
||||
tolerance); // OK
|
||||
|
||||
// This fails for reasons unclear (apparently identical test above passes)???
|
||||
//BOOST_CHECK_CLOSE_FRACTION( // Check -exp(-1) = -0.367879450 = -1
|
||||
// productlog(BOOST_MATH_TEST_VALUE(RealType, -0.36787944117144232159552377016146086744581113103176)),
|
||||
// BOOST_MATH_TEST_VALUE(RealType, -1.),
|
||||
// tolerance);
|
||||
BOOST_CHECK_CLOSE_FRACTION( // Check -exp(-1) = -0.367879450 = -1
|
||||
productlog(BOOST_MATH_TEST_VALUE(RealType, -0.36787944117144232159552377016146086744581113103176)),
|
||||
BOOST_MATH_TEST_VALUE(RealType, -1.),
|
||||
tolerance);
|
||||
|
||||
BOOST_CHECK_CLOSE_FRACTION(
|
||||
productlog(BOOST_MATH_TEST_VALUE(RealType, 1.)),
|
||||
@@ -210,7 +242,7 @@ void test_spots(RealType)
|
||||
// Output from https://www.wolframalpha.com/input/?i=productlog(100)
|
||||
tolerance);
|
||||
|
||||
// Fails here with really big x.
|
||||
// TODO Fails here with really big x.
|
||||
/* BOOST_CHECK_CLOSE_FRACTION(productlog(BOOST_MATH_TEST_VALUE(RealType, 1.0e6)),
|
||||
BOOST_MATH_TEST_VALUE(RealType, 11.383358086140052622000156781585004289033774706019),
|
||||
// Output from https://www.wolframalpha.com/input/?i=productlog(1e6)
|
||||
|
||||
Reference in New Issue
Block a user