diff --git a/include/boost/math/cstdfloat/cstdfloat_cmath.hpp b/include/boost/math/cstdfloat/cstdfloat_cmath.hpp index d187d4408..3043d9056 100644 --- a/include/boost/math/cstdfloat/cstdfloat_cmath.hpp +++ b/include/boost/math/cstdfloat/cstdfloat_cmath.hpp @@ -120,6 +120,7 @@ #endif #define BOOST_CSTDFLOAT_FLOAT128_TRUNC __truncq #define BOOST_CSTDFLOAT_FLOAT128_EXP __expq + #define BOOST_CSTDFLOAT_FLOAT128_EXPM1 __expm1q #define BOOST_CSTDFLOAT_FLOAT128_POW __powq #define BOOST_CSTDFLOAT_FLOAT128_LOG __logq #define BOOST_CSTDFLOAT_FLOAT128_LOG10 __log10q @@ -163,6 +164,7 @@ #define BOOST_CSTDFLOAT_FLOAT128_LGAMMA lgammaq #if !defined(BOOST_CSTDFLOAT_BROKEN_FLOAT128_MATH_FUNCTIONS) #define BOOST_CSTDFLOAT_FLOAT128_EXP expq + #define BOOST_CSTDFLOAT_FLOAT128_EXPM1 expm1q_internal #define BOOST_CSTDFLOAT_FLOAT128_SINH sinhq #define BOOST_CSTDFLOAT_FLOAT128_COSH coshq #define BOOST_CSTDFLOAT_FLOAT128_TANH tanhq @@ -222,6 +224,79 @@ #else // BOOST_CSTDFLOAT_BROKEN_FLOAT128_MATH_FUNCTIONS + // Forward declaration of the patched exponent function, exp(x). + inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_EXP (boost::math::cstdfloat::detail::float_internal128_t x); + + inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_EXPM1 (boost::math::cstdfloat::detail::float_internal128_t x) + { + // Compute exp(x) - 1 for x small. + + // Use an order-36 polynomial approximation of the exponential function + // in the range of (-ln2 < x < ln2). Scale the argument to this range + // and subsequently multiply the result by 2^n accordingly. + + // Derive the polynomial coefficients with Mathematica(R) by generating + // a table of high-precision values of exp(x) in the range (-ln2 < x < ln2) + // and subsequently applying the built-in *Fit* function. + + // Table[{x, Exp[x] - 1}, {x, -Log[2], Log[2], 1/180}] + // N[%, 120] + // Fit[%, {x, x^2, x^3, x^4, x^5, x^6, x^7, x^8, x^9, x^10, x^11, x^12, + // x^13, x^14, x^15, x^16, x^17, x^18, x^19, x^20, x^21, x^22, + // x^23, x^24, x^25, x^26, x^27, x^28, x^29, x^30, x^31, x^32, + // x^33, x^34, x^35, x^36}, x] + + typedef boost::math::cstdfloat::detail::float_internal128_t float_type; + + float_type sum; + + if(x > BOOST_FLOAT128_C(0.693147180559945309417232121458176568075500134360255)) + { + sum = ::BOOST_CSTDFLOAT_FLOAT128_EXP(x) - float_type(1); + } + else + { + // Compute the polynomial approximation of exp(alpha). + sum = (((((((((((((((((((((((((((((((((((( float_type(BOOST_FLOAT128_C(2.69291698127774166063293705964720493864630783729857438187365E-42)) * x + + float_type(BOOST_FLOAT128_C(9.70937085471487654794114679403710456028986572118859594614033E-41))) * x + + float_type(BOOST_FLOAT128_C(3.38715585158055097155585505318085512156885389014410753080500E-39))) * x + + float_type(BOOST_FLOAT128_C(1.15162718532861050809222658798662695267019717760563645440433E-37))) * x + + float_type(BOOST_FLOAT128_C(3.80039074689434663295873584133017767349635602413675471702393E-36))) * x + + float_type(BOOST_FLOAT128_C(1.21612504934087520075905434734158045947460467096773246215239E-34))) * x + + float_type(BOOST_FLOAT128_C(3.76998762883139753126119821241037824830069851253295480396224E-33))) * x + + float_type(BOOST_FLOAT128_C(1.13099628863830344684998293828608215735777107850991029729440E-31))) * x + + float_type(BOOST_FLOAT128_C(3.27988923706982293204067897468714277771890104022419696770352E-30))) * x + + float_type(BOOST_FLOAT128_C(9.18368986379558482800593745627556950089950023355628325088207E-29))) * x + + float_type(BOOST_FLOAT128_C(2.47959626322479746949155352659617642905315302382639380521497E-27))) * x + + float_type(BOOST_FLOAT128_C(6.44695028438447337900255966737803112935639344283098705091949E-26))) * x + + float_type(BOOST_FLOAT128_C(1.61173757109611834904452725462599961406036904573072897122957E-24))) * x + + float_type(BOOST_FLOAT128_C(3.86817017063068403772269360016918092488847584660382953555804E-23))) * x + + float_type(BOOST_FLOAT128_C(8.89679139245057328674891109315654704307721758924206107351744E-22))) * x + + float_type(BOOST_FLOAT128_C(1.95729410633912612308475595397946731738088422488032228717097E-20))) * x + + float_type(BOOST_FLOAT128_C(4.11031762331216485847799061511674191805055663711439605760231E-19))) * x + + float_type(BOOST_FLOAT128_C(8.22063524662432971695598123977873600603370758794431071426640E-18))) * x + + float_type(BOOST_FLOAT128_C(1.56192069685862264622163643500633782667263448653185159383285E-16))) * x + + float_type(BOOST_FLOAT128_C(2.81145725434552076319894558300988749849555291507956994126835E-15))) * x + + float_type(BOOST_FLOAT128_C(4.77947733238738529743820749111754320727153728139716409114011E-14))) * x + + float_type(BOOST_FLOAT128_C(7.64716373181981647590113198578807092707697416852226691068627E-13))) * x + + float_type(BOOST_FLOAT128_C(1.14707455977297247138516979786821056670509688396295740818677E-11))) * x + + float_type(BOOST_FLOAT128_C(1.60590438368216145993923771701549479323291461578567184216302E-10))) * x + + float_type(BOOST_FLOAT128_C(2.08767569878680989792100903212014323125428376052986408239620E-09))) * x + + float_type(BOOST_FLOAT128_C(2.50521083854417187750521083854417187750523408006206780016659E-08))) * x + + float_type(BOOST_FLOAT128_C(2.75573192239858906525573192239858906525573195144226062684604E-07))) * x + + float_type(BOOST_FLOAT128_C(2.75573192239858906525573192239858906525573191310049321957902E-06))) * x + + float_type(BOOST_FLOAT128_C(0.00002480158730158730158730158730158730158730158730149317774))) * x + + float_type(BOOST_FLOAT128_C(0.00019841269841269841269841269841269841269841269841293575920))) * x + + float_type(BOOST_FLOAT128_C(0.00138888888888888888888888888888888888888888888888889071045))) * x + + float_type(BOOST_FLOAT128_C(0.00833333333333333333333333333333333333333333333333332986595))) * x + + float_type(BOOST_FLOAT128_C(0.04166666666666666666666666666666666666666666666666666664876))) * x + + float_type(BOOST_FLOAT128_C(0.16666666666666666666666666666666666666666666666666666669048))) * x + + float_type(BOOST_FLOAT128_C(0.50000000000000000000000000000000000000000000000000000000006))) * x + + float_type(BOOST_FLOAT128_C(0.99999999999999999999999999999999999999999999999999999999995))) * x); + } + + return sum; + } inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_EXP (boost::math::cstdfloat::detail::float_internal128_t x) { // Patch the expq() function for a subset of broken GCC compilers @@ -250,13 +325,25 @@ boost::int_fast32_t n; - if((x < BOOST_FLOAT128_C(-1.0)) || (x > BOOST_FLOAT128_C(1.0))) + if(x != x) { + // The argument is NaN. + return std::numeric_limits::quiet_NaN(); + } + else if(::BOOST_CSTDFLOAT_FLOAT128_FABS(x) > BOOST_FLOAT128_C(+0.693147180559945309417232121458176568075500134360255)) + { + // The absolute value of the argument exceeds ln2. n = static_cast(::BOOST_CSTDFLOAT_FLOAT128_FLOOR(x_over_ln2)); } + else if(::BOOST_CSTDFLOAT_FLOAT128_FABS(x) < BOOST_FLOAT128_C(+0.693147180559945309417232121458176568075500134360255)) + { + // The absolute value of the argument is less than ln2. + n = static_cast(0); + } else { - n = static_cast(0); + // The absolute value of the argument is exactly equal to ln2 (in the sense of floating-point equality). + return float_type(2); } // Check if the argument is very near an integer. @@ -271,56 +358,38 @@ // Compute the scaled argument alpha. const float_type alpha = x - (n * BOOST_FLOAT128_C(0.693147180559945309417232121458176568075500134360255)); - // Compute the polynomial approximation of exp(alpha). - const float_type sum = - (((((((((((((((((((((((((((((((((((( float_type(BOOST_FLOAT128_C(2.69291698127774166063293705964720493864630783729857438187365E-42)) * alpha - + float_type(BOOST_FLOAT128_C(9.70937085471487654794114679403710456028986572118859594614033E-41))) * alpha - + float_type(BOOST_FLOAT128_C(3.38715585158055097155585505318085512156885389014410753080500E-39))) * alpha - + float_type(BOOST_FLOAT128_C(1.15162718532861050809222658798662695267019717760563645440433E-37))) * alpha - + float_type(BOOST_FLOAT128_C(3.80039074689434663295873584133017767349635602413675471702393E-36))) * alpha - + float_type(BOOST_FLOAT128_C(1.21612504934087520075905434734158045947460467096773246215239E-34))) * alpha - + float_type(BOOST_FLOAT128_C(3.76998762883139753126119821241037824830069851253295480396224E-33))) * alpha - + float_type(BOOST_FLOAT128_C(1.13099628863830344684998293828608215735777107850991029729440E-31))) * alpha - + float_type(BOOST_FLOAT128_C(3.27988923706982293204067897468714277771890104022419696770352E-30))) * alpha - + float_type(BOOST_FLOAT128_C(9.18368986379558482800593745627556950089950023355628325088207E-29))) * alpha - + float_type(BOOST_FLOAT128_C(2.47959626322479746949155352659617642905315302382639380521497E-27))) * alpha - + float_type(BOOST_FLOAT128_C(6.44695028438447337900255966737803112935639344283098705091949E-26))) * alpha - + float_type(BOOST_FLOAT128_C(1.61173757109611834904452725462599961406036904573072897122957E-24))) * alpha - + float_type(BOOST_FLOAT128_C(3.86817017063068403772269360016918092488847584660382953555804E-23))) * alpha - + float_type(BOOST_FLOAT128_C(8.89679139245057328674891109315654704307721758924206107351744E-22))) * alpha - + float_type(BOOST_FLOAT128_C(1.95729410633912612308475595397946731738088422488032228717097E-20))) * alpha - + float_type(BOOST_FLOAT128_C(4.11031762331216485847799061511674191805055663711439605760231E-19))) * alpha - + float_type(BOOST_FLOAT128_C(8.22063524662432971695598123977873600603370758794431071426640E-18))) * alpha - + float_type(BOOST_FLOAT128_C(1.56192069685862264622163643500633782667263448653185159383285E-16))) * alpha - + float_type(BOOST_FLOAT128_C(2.81145725434552076319894558300988749849555291507956994126835E-15))) * alpha - + float_type(BOOST_FLOAT128_C(4.77947733238738529743820749111754320727153728139716409114011E-14))) * alpha - + float_type(BOOST_FLOAT128_C(7.64716373181981647590113198578807092707697416852226691068627E-13))) * alpha - + float_type(BOOST_FLOAT128_C(1.14707455977297247138516979786821056670509688396295740818677E-11))) * alpha - + float_type(BOOST_FLOAT128_C(1.60590438368216145993923771701549479323291461578567184216302E-10))) * alpha - + float_type(BOOST_FLOAT128_C(2.08767569878680989792100903212014323125428376052986408239620E-09))) * alpha - + float_type(BOOST_FLOAT128_C(2.50521083854417187750521083854417187750523408006206780016659E-08))) * alpha - + float_type(BOOST_FLOAT128_C(2.75573192239858906525573192239858906525573195144226062684604E-07))) * alpha - + float_type(BOOST_FLOAT128_C(2.75573192239858906525573192239858906525573191310049321957902E-06))) * alpha - + float_type(BOOST_FLOAT128_C(0.00002480158730158730158730158730158730158730158730149317774))) * alpha - + float_type(BOOST_FLOAT128_C(0.00019841269841269841269841269841269841269841269841293575920))) * alpha - + float_type(BOOST_FLOAT128_C(0.00138888888888888888888888888888888888888888888888889071045))) * alpha - + float_type(BOOST_FLOAT128_C(0.00833333333333333333333333333333333333333333333333332986595))) * alpha - + float_type(BOOST_FLOAT128_C(0.04166666666666666666666666666666666666666666666666666664876))) * alpha - + float_type(BOOST_FLOAT128_C(0.16666666666666666666666666666666666666666666666666666669048))) * alpha - + float_type(BOOST_FLOAT128_C(0.50000000000000000000000000000000000000000000000000000000006))) * alpha - + float_type(BOOST_FLOAT128_C(0.99999999999999999999999999999999999999999999999999999999995))) * alpha - + float_type(1)); + // Compute the polynomial approximation of expm1(alpha) and add to it + // in order to obtain the scaled result. + const float_type scaled_result = ::BOOST_CSTDFLOAT_FLOAT128_EXPM1(alpha) + float_type(1); // Rescale the result and return it. - return sum * boost::math::cstdfloat::detail::pown(float_type(2), n); + return scaled_result * boost::math::cstdfloat::detail::pown(float_type(2), n); } inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_SINH (boost::math::cstdfloat::detail::float_internal128_t x) { // Patch the sinhq() function for a subset of broken GCC compilers // like GCC 4.7, 4.8 on MinGW. typedef boost::math::cstdfloat::detail::float_internal128_t float_type; + + // Here, we use the following: + // Set: ex = exp(x) + // Set: em1 = expm1(x) + // Then + // sinh(x) = (ex - 1/ex) / 2 ; for |x| >= 1 + // sinh(x) = (2em1 + em1^2) / (2ex) ; for |x| < 1 + const float_type ex = ::BOOST_CSTDFLOAT_FLOAT128_EXP(x); - return (ex - (float_type(1) / ex)) / 2; + + if(::BOOST_CSTDFLOAT_FLOAT128_FABS(x) < float_type(+1)) + { + const float_type em1 = ::BOOST_CSTDFLOAT_FLOAT128_EXPM1(x); + + return ((em1 * 2) + (em1 * em1)) / (ex * 2); + } + else + { + return (ex - (float_type(1) / ex)) / 2; + } } inline boost::math::cstdfloat::detail::float_internal128_t BOOST_CSTDFLOAT_FLOAT128_COSH (boost::math::cstdfloat::detail::float_internal128_t x) { @@ -505,6 +574,7 @@ #undef BOOST_CSTDFLOAT_FLOAT128_SQRT #undef BOOST_CSTDFLOAT_FLOAT128_TRUNC #undef BOOST_CSTDFLOAT_FLOAT128_EXP + #undef BOOST_CSTDFLOAT_FLOAT128_EXPM1 #undef BOOST_CSTDFLOAT_FLOAT128_POW #undef BOOST_CSTDFLOAT_FLOAT128_LOG #undef BOOST_CSTDFLOAT_FLOAT128_LOG10 diff --git a/include/boost/math/cstdfloat/cstdfloat_complex_std.hpp b/include/boost/math/cstdfloat/cstdfloat_complex_std.hpp index cb38fc6f2..f949a9aa4 100644 --- a/include/boost/math/cstdfloat/cstdfloat_complex_std.hpp +++ b/include/boost/math/cstdfloat/cstdfloat_complex_std.hpp @@ -228,10 +228,16 @@ inline complex proj (const complex& x) { - const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE the_norm_plus_one = (std::norm(x) + BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE(1)); - - return complex((x.real() * 2) / the_norm_plus_one, - (x.imag() * 2) / the_norm_plus_one); + const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE m = (std::numeric_limits::max)(); + if ((x.real() > m) + || (x.real() < -m) + || (x.imag() > m) + || (x.imag() < -m)) + { + // We have an infinity, return a normalized infinity, respecting the sign of the imaginary part: + return complex(std::numeric_limits::infinity(), x.imag() < 0 ? -0 : 0); + } + return x; } inline complex polar(const BOOST_CSTDFLOAT_EXTENDED_COMPLEX_FLOAT_TYPE& rho, diff --git a/test/float128/test_bessel_k.cpp b/test/float128/test_bessel_k.cpp index 56e0459f2..a5ec1e2b4 100644 --- a/test/float128/test_bessel_k.cpp +++ b/test/float128/test_bessel_k.cpp @@ -27,20 +27,13 @@ void expected_results() ".*", // test type(s) ".*large.*", // test data group ".*", 80, 50); // test function - add_expected_result( - ".*", // compiler - ".*", // stdlib - ".*", // platform - ".*cpp_bin_float.*", // test type(s) - ".*", // test data group - ".*", 300, 150); // test function add_expected_result( ".*", // compiler ".*", // stdlib ".*", // platform ".*", // test type(s) ".*", // test data group - ".*", 50, 15); // test function + ".*", 1000, 500); // test function // // Finish off by printing out the compiler/stdlib/platform names, // we do this to make it easier to mark up expected error rates. diff --git a/test/float128/test_erf.cpp b/test/float128/test_erf.cpp index ff19b1710..abcbe51c6 100644 --- a/test/float128/test_erf.cpp +++ b/test/float128/test_erf.cpp @@ -16,43 +16,13 @@ void expected_results() // Define the max and mean errors expected for // various compilers and platforms. // - add_expected_result( - ".*", // compiler - ".*", // stdlib - ".*", // platform - ".*gmp_float<18>.*", // test type(s) - "Erf Function:.*", // test data group - "boost::math::erfc?", 2200, 1500);// test function - add_expected_result( - ".*", // compiler - ".*", // stdlib - ".*", // platform - ".*gmp_float<18>.*", // test type(s) - "Inverse Erf.*", // test data group - "boost::math::erfc?_inv", 2200, 1500); // test function -#ifdef BOOST_INTEL - add_expected_result( - ".*", // compiler - ".*", // stdlib - ".*", // platform - "float128", // test type(s) - "Erf Function:.*", // test data group - "boost::math::erfc?", 15000, 1000); // test function -#endif - add_expected_result( - ".*", // compiler - ".*", // stdlib - ".*", // platform - ".*cpp_bin_float.*", // test type(s) - "Erf Function:.*", // test data group - "boost::math::erfc?", 3000, 1000); // test function add_expected_result( ".*", // compiler ".*", // stdlib ".*", // platform ".*", // test type(s) "Erf Function:.*", // test data group - "boost::math::erfc?", 300, 200); // test function + "boost::math::erfc?", 2500, 1000); // test function add_expected_result( ".*", // compiler ".*", // stdlib diff --git a/test/float128/test_expint.cpp b/test/float128/test_expint.cpp index 2b504b01a..73a1f6bb5 100644 --- a/test/float128/test_expint.cpp +++ b/test/float128/test_expint.cpp @@ -21,7 +21,7 @@ void expected_results() ".*", // platform ".*", // test type(s) ".*", // test data group - ".*", 250, 50); // test function + ".*", 5000, 2000); // test function // // Finish off by printing out the compiler/stdlib/platform names, // we do this to make it easier to mark up expected error rates. diff --git a/test/float128/test_factorials.cpp b/test/float128/test_factorials.cpp index b6ea106ca..61bde0f18 100644 --- a/test/float128/test_factorials.cpp +++ b/test/float128/test_factorials.cpp @@ -289,7 +289,7 @@ BOOST_AUTO_TEST_CASE( test_main ) { BOOST_MATH_CONTROL_FP; test_spots(0.0Q); - cout << "max factorial for __float128" << boost::math::max_factorial<__float128>::value << endl; + cout << "max factorial for __float128" << boost::math::max_factorial::value << endl; } diff --git a/test/float128/test_gamma.cpp b/test/float128/test_gamma.cpp index 0fdd4b4e9..12cd0424a 100644 --- a/test/float128/test_gamma.cpp +++ b/test/float128/test_gamma.cpp @@ -42,7 +42,7 @@ void expected_results() ".*", // platform ".*", // test type(s) ".*", // test data group - "boost::math::tgamma", 4, 3); // test function + "boost::math::tgamma", 40, 20); // test function // // Finish off by printing out the compiler/stdlib/platform names, // we do this to make it easier to mark up expected error rates. diff --git a/test/float128/test_std_lib.cpp b/test/float128/test_std_lib.cpp new file mode 100644 index 000000000..b0f2dfbf6 --- /dev/null +++ b/test/float128/test_std_lib.cpp @@ -0,0 +1,241 @@ +// Copyright John Maddock 2014. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include +#define BOOST_TEST_MAIN +#include +#include +#include + +BOOST_AUTO_TEST_CASE( test_main ) +{ + // + // Basic tests that the functions which provide std lib supported are correctly wrapped: + // + boost::float128_t tol = std::numeric_limits::epsilon() * 4; + boost::float128_t pi = BOOST_FLOAT128_C(3.14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211); + + + BOOST_CHECK_EQUAL(std::abs(BOOST_FLOAT128_C(-2.0)), BOOST_FLOAT128_C(2.0)); + BOOST_CHECK_EQUAL(std::abs(BOOST_FLOAT128_C(2.0)), BOOST_FLOAT128_C(2.0)); + BOOST_CHECK_EQUAL(std::fabs(BOOST_FLOAT128_C(-2.0)), BOOST_FLOAT128_C(2.0)); + BOOST_CHECK_EQUAL(std::fabs(BOOST_FLOAT128_C(2.0)), BOOST_FLOAT128_C(2.0)); + + BOOST_CHECK_CLOSE_FRACTION(std::acos(BOOST_FLOAT128_C(0.25)), BOOST_FLOAT128_C(1.31811607165281796574566425464604046984639096659071471685355), tol); + BOOST_CHECK_CLOSE_FRACTION(std::acos(BOOST_FLOAT128_C(-0.25)), BOOST_FLOAT128_C(1.82347658193697527271697912863346241435077843278439110412140), tol); + BOOST_CHECK_CLOSE_FRACTION(std::acos(BOOST_FLOAT128_C(0.75)), BOOST_FLOAT128_C(0.722734247813415611178377352641333362025218486424440267626754), tol); + BOOST_CHECK_CLOSE_FRACTION(std::acos(BOOST_FLOAT128_C(-0.75)), BOOST_FLOAT128_C(2.41885840577637762728426603063816952217195091295066555334819), tol); + BOOST_CHECK_EQUAL(std::acos(BOOST_FLOAT128_C(1.0)), 0); + BOOST_CHECK_CLOSE_FRACTION(std::acos(BOOST_FLOAT128_C(0.0)), BOOST_FLOAT128_C(1.57079632679489661923132169163975144209858469968755291048747), tol); + + BOOST_CHECK_CLOSE_FRACTION(std::asin(BOOST_FLOAT128_C(0.25)), BOOST_FLOAT128_C(0.25268025514207865348565743699371097225219373309683819363392), tol); + BOOST_CHECK_CLOSE_FRACTION(std::asin(BOOST_FLOAT128_C(-0.25)), BOOST_FLOAT128_C(-0.252680255142078653485657436993710972252193733096838193633924), tol); + BOOST_CHECK_CLOSE_FRACTION(std::asin(BOOST_FLOAT128_C(0.75)), BOOST_FLOAT128_C(0.848062078981481008052944338998418080073366213263112642860718), tol); + BOOST_CHECK_CLOSE_FRACTION(std::asin(BOOST_FLOAT128_C(-0.75)), BOOST_FLOAT128_C(-0.848062078981481008052944338998418080073366213263112642860718), tol); + BOOST_CHECK_EQUAL(std::asin(BOOST_FLOAT128_C(0.0)), 0); + BOOST_CHECK_CLOSE_FRACTION(std::asin(BOOST_FLOAT128_C(1.0)), BOOST_FLOAT128_C(1.57079632679489661923132169163975144209858469968755291048747), tol); + + BOOST_CHECK_CLOSE_FRACTION(std::atan(BOOST_FLOAT128_C(0.25)), BOOST_FLOAT128_C(0.244978663126864154172082481211275810914144098381184067127376), tol); + BOOST_CHECK_CLOSE_FRACTION(std::atan(BOOST_FLOAT128_C(-0.25)), BOOST_FLOAT128_C(-0.244978663126864154172082481211275810914144098381184067127376), tol); + BOOST_CHECK_CLOSE_FRACTION(std::atan(BOOST_FLOAT128_C(1.25)), BOOST_FLOAT128_C(0.896055384571343956174800718029937827024578444846840487366551), tol); + BOOST_CHECK_CLOSE_FRACTION(std::atan(BOOST_FLOAT128_C(-1.25)), BOOST_FLOAT128_C(-0.896055384571343956174800718029937827024578444846840487366551), tol); + BOOST_CHECK_CLOSE_FRACTION(std::atan(BOOST_FLOAT128_C(10.25)), BOOST_FLOAT128_C(1.47354312854333084551799286825415639734160148773878671550090), tol); + BOOST_CHECK_CLOSE_FRACTION(std::atan(BOOST_FLOAT128_C(-10.25)), BOOST_FLOAT128_C(-1.47354312854333084551799286825415639734160148773878671550090), tol); + BOOST_CHECK_EQUAL(std::atan(BOOST_FLOAT128_C(0.0)), 0); + + BOOST_CHECK_CLOSE_FRACTION(std::atan2(BOOST_FLOAT128_C(0.5), BOOST_FLOAT128_C(2.0)), BOOST_FLOAT128_C(0.244978663126864154172082481211275810914144098381184067127376), tol); + BOOST_CHECK_CLOSE_FRACTION(std::atan2(BOOST_FLOAT128_C(-0.5), BOOST_FLOAT128_C(2.0)), BOOST_FLOAT128_C(-0.244978663126864154172082481211275810914144098381184067127376), tol); + BOOST_CHECK_CLOSE_FRACTION(std::atan2(BOOST_FLOAT128_C(0.5), BOOST_FLOAT128_C(-2.0)), BOOST_FLOAT128_C(-0.244978663126864154172082481211275810914144098381184067127376) + pi, tol); + BOOST_CHECK_CLOSE_FRACTION(std::atan2(BOOST_FLOAT128_C(-0.5), BOOST_FLOAT128_C(-2.0)), BOOST_FLOAT128_C(0.244978663126864154172082481211275810914144098381184067127376) - pi, tol); + BOOST_CHECK_CLOSE_FRACTION(std::atan2(BOOST_FLOAT128_C(2.0), BOOST_FLOAT128_C(0.0)), pi / 2, tol); + BOOST_CHECK_CLOSE_FRACTION(std::atan2(BOOST_FLOAT128_C(-2.0), BOOST_FLOAT128_C(0.0)), -pi / 2, tol); + BOOST_CHECK_EQUAL(std::atan2(BOOST_FLOAT128_C(0.0), BOOST_FLOAT128_C(0.0)), BOOST_FLOAT128_C(0.0)); + + BOOST_CHECK_CLOSE_FRACTION(std::sin(BOOST_FLOAT128_C(0.5)), BOOST_FLOAT128_C(0.479425538604203000273287935215571388081803367940600675188617), tol); + BOOST_CHECK_CLOSE_FRACTION(std::sin(BOOST_FLOAT128_C(-0.5)), BOOST_FLOAT128_C(-0.479425538604203000273287935215571388081803367940600675188617), tol); + BOOST_CHECK_CLOSE_FRACTION(std::sin(BOOST_FLOAT128_C(1.5)), BOOST_FLOAT128_C(0.997494986604054430941723371141487322706651425922115821949975), tol); + BOOST_CHECK_CLOSE_FRACTION(std::sin(BOOST_FLOAT128_C(-1.5)), BOOST_FLOAT128_C(-0.997494986604054430941723371141487322706651425922115821949975), tol); + BOOST_CHECK_CLOSE_FRACTION(std::sin(BOOST_FLOAT128_C(3.5)), BOOST_FLOAT128_C(-0.350783227689619848120368800043635585084981735940583485415755), tol); + BOOST_CHECK_CLOSE_FRACTION(std::sin(BOOST_FLOAT128_C(-3.5)), BOOST_FLOAT128_C(0.350783227689619848120368800043635585084981735940583485415755), tol); + BOOST_CHECK_EQUAL(std::sin(BOOST_FLOAT128_C(0.0)), 0); + + BOOST_CHECK_CLOSE_FRACTION(std::cos(BOOST_FLOAT128_C(0.5)), BOOST_FLOAT128_C(0.877582561890372716116281582603829651991645197109744052997611), tol); + BOOST_CHECK_CLOSE_FRACTION(std::cos(BOOST_FLOAT128_C(-0.5)), BOOST_FLOAT128_C(0.877582561890372716116281582603829651991645197109744052997611), tol); + BOOST_CHECK_CLOSE_FRACTION(std::cos(BOOST_FLOAT128_C(1.5)), BOOST_FLOAT128_C(0.0707372016677029100881898514342687090850910275633468694226454), tol); + BOOST_CHECK_CLOSE_FRACTION(std::cos(BOOST_FLOAT128_C(-1.5)), BOOST_FLOAT128_C(0.0707372016677029100881898514342687090850910275633468694226454), tol); + BOOST_CHECK_CLOSE_FRACTION(std::cos(BOOST_FLOAT128_C(3.5)), BOOST_FLOAT128_C(-0.936456687290796337698657626671760463019957765781959251620988), tol); + BOOST_CHECK_CLOSE_FRACTION(std::cos(BOOST_FLOAT128_C(-3.5)), BOOST_FLOAT128_C(-0.936456687290796337698657626671760463019957765781959251620988), tol); + BOOST_CHECK_EQUAL(std::cos(BOOST_FLOAT128_C(0.0)), 1.0); + + BOOST_CHECK_CLOSE_FRACTION(std::tan(BOOST_FLOAT128_C(0.5)), BOOST_FLOAT128_C(0.546302489843790513255179465780285383297551720179791246164091), tol); + BOOST_CHECK_CLOSE_FRACTION(std::tan(BOOST_FLOAT128_C(-0.5)), BOOST_FLOAT128_C(-0.546302489843790513255179465780285383297551720179791246164091), tol); + BOOST_CHECK_CLOSE_FRACTION(std::tan(BOOST_FLOAT128_C(1.5)), BOOST_FLOAT128_C(14.1014199471717193876460836519877564456595435772358618661233), tol); + BOOST_CHECK_CLOSE_FRACTION(std::tan(BOOST_FLOAT128_C(-1.5)), BOOST_FLOAT128_C(-14.1014199471717193876460836519877564456595435772358618661233), tol); + BOOST_CHECK_CLOSE_FRACTION(std::tan(BOOST_FLOAT128_C(3.5)), BOOST_FLOAT128_C(0.374585640158594666330512579989147388450882284289259230693023), tol); + BOOST_CHECK_CLOSE_FRACTION(std::tan(BOOST_FLOAT128_C(-3.5)), BOOST_FLOAT128_C(-0.374585640158594666330512579989147388450882284289259230693023), tol); + BOOST_CHECK_EQUAL(std::tan(BOOST_FLOAT128_C(0.0)), 0.0); + + BOOST_CHECK_CLOSE_FRACTION(std::sinh(BOOST_FLOAT128_C(0.5)), BOOST_FLOAT128_C(0.521095305493747361622425626411491559105928982611480527946094), tol); + BOOST_CHECK_CLOSE_FRACTION(std::sinh(BOOST_FLOAT128_C(-0.5)), BOOST_FLOAT128_C(-0.521095305493747361622425626411491559105928982611480527946094), tol); + BOOST_CHECK_CLOSE_FRACTION(std::sinh(BOOST_FLOAT128_C(1.5)), BOOST_FLOAT128_C(2.12927945509481749683438749467763164883178911950429386401441), tol); + BOOST_CHECK_CLOSE_FRACTION(std::sinh(BOOST_FLOAT128_C(-1.5)), BOOST_FLOAT128_C(-2.12927945509481749683438749467763164883178911950429386401441), tol); + BOOST_CHECK_CLOSE_FRACTION(std::sinh(BOOST_FLOAT128_C(3.5)), BOOST_FLOAT128_C(16.5426272876349976249567315290124982237000338471151419910948), tol); + BOOST_CHECK_CLOSE_FRACTION(std::sinh(BOOST_FLOAT128_C(-3.5)), BOOST_FLOAT128_C(-16.5426272876349976249567315290124982237000338471151419910948), tol); + BOOST_CHECK_EQUAL(std::sinh(BOOST_FLOAT128_C(0.0)), 0); + + BOOST_CHECK_CLOSE_FRACTION(std::cosh(BOOST_FLOAT128_C(0.5)), BOOST_FLOAT128_C(1.12762596520638078522622516140267201254784711809866748362899), tol); + BOOST_CHECK_CLOSE_FRACTION(std::cosh(BOOST_FLOAT128_C(-0.5)), BOOST_FLOAT128_C(1.12762596520638078522622516140267201254784711809866748362899), tol); + BOOST_CHECK_CLOSE_FRACTION(std::cosh(BOOST_FLOAT128_C(1.5)), BOOST_FLOAT128_C(2.35240961524324732576766796544164417017396074886537319275824), tol); + BOOST_CHECK_CLOSE_FRACTION(std::cosh(BOOST_FLOAT128_C(-1.5)), BOOST_FLOAT128_C(2.35240961524324732576766796544164417017396074886537319275824), tol); + BOOST_CHECK_CLOSE_FRACTION(std::cosh(BOOST_FLOAT128_C(3.5)), BOOST_FLOAT128_C(16.5728246710573161256965178213761180687716943793627989977661), tol); + BOOST_CHECK_CLOSE_FRACTION(std::cosh(BOOST_FLOAT128_C(-3.5)), BOOST_FLOAT128_C(16.5728246710573161256965178213761180687716943793627989977661), tol); + BOOST_CHECK_EQUAL(std::cosh(BOOST_FLOAT128_C(0.0)), 1.0); + + BOOST_CHECK_CLOSE_FRACTION(std::tanh(BOOST_FLOAT128_C(0.5)), BOOST_FLOAT128_C(0.462117157260009758502318483643672548730289280330113038552732), tol); + BOOST_CHECK_CLOSE_FRACTION(std::tanh(BOOST_FLOAT128_C(-0.5)), BOOST_FLOAT128_C(-0.462117157260009758502318483643672548730289280330113038552732), tol); + BOOST_CHECK_CLOSE_FRACTION(std::tanh(BOOST_FLOAT128_C(1.5)), BOOST_FLOAT128_C(0.905148253644866438242303696456495597227641135158781798564224), tol); + BOOST_CHECK_CLOSE_FRACTION(std::tanh(BOOST_FLOAT128_C(-1.5)), BOOST_FLOAT128_C(-0.905148253644866438242303696456495597227641135158781798564224), tol); + BOOST_CHECK_CLOSE_FRACTION(std::tanh(BOOST_FLOAT128_C(3.5)), BOOST_FLOAT128_C(0.998177897611198709284273352450611717351703879477362867150362), tol); + BOOST_CHECK_CLOSE_FRACTION(std::tanh(BOOST_FLOAT128_C(-3.5)), BOOST_FLOAT128_C(-0.998177897611198709284273352450611717351703879477362867150362), tol); + BOOST_CHECK_EQUAL(std::tanh(BOOST_FLOAT128_C(0.0)), 0.0); + + BOOST_CHECK_CLOSE_FRACTION(std::asinh(BOOST_FLOAT128_C(0.5)), BOOST_FLOAT128_C(0.481211825059603447497758913424368423135184334385660519661018), tol); + BOOST_CHECK_CLOSE_FRACTION(std::asinh(BOOST_FLOAT128_C(-0.5)), BOOST_FLOAT128_C(-0.481211825059603447497758913424368423135184334385660519661018), tol); + BOOST_CHECK_CLOSE_FRACTION(std::asinh(BOOST_FLOAT128_C(1.5)), BOOST_FLOAT128_C(1.19476321728710930411193082851909052353616207515300542927068), tol); + BOOST_CHECK_CLOSE_FRACTION(std::asinh(BOOST_FLOAT128_C(-1.5)), BOOST_FLOAT128_C(-1.19476321728710930411193082851909052353616207515300542927068), tol); + BOOST_CHECK_CLOSE_FRACTION(std::asinh(BOOST_FLOAT128_C(30.5)), BOOST_FLOAT128_C(4.11114250086321582491802557961818852029252495243356752882371), tol); + BOOST_CHECK_CLOSE_FRACTION(std::asinh(BOOST_FLOAT128_C(-30.5)), BOOST_FLOAT128_C(-4.11114250086321582491802557961818852029252495243356752882371), tol * 40); // extra tolerance required on Mingw-x64 at least + BOOST_CHECK_EQUAL(std::asinh(BOOST_FLOAT128_C(0.0)), 0); + + BOOST_CHECK_CLOSE_FRACTION(std::acosh(BOOST_FLOAT128_C(1.5)), BOOST_FLOAT128_C(0.962423650119206894995517826848736846270368668771321039322036), tol); + BOOST_CHECK_CLOSE_FRACTION(std::acosh(BOOST_FLOAT128_C(30.5)), BOOST_FLOAT128_C(4.11060501081175314729512161636335880294693070089674383785623), tol); + BOOST_CHECK_CLOSE_FRACTION(std::acosh(BOOST_FLOAT128_C(3000.5)), BOOST_FLOAT128_C(8.69968137322099085819002231042463682720224626990472395734493), tol); + BOOST_CHECK_EQUAL(std::acosh(BOOST_FLOAT128_C(1.0)), 0.0); + + BOOST_CHECK_CLOSE_FRACTION(std::atanh(BOOST_FLOAT128_C(0.5)), BOOST_FLOAT128_C(0.549306144334054845697622618461262852323745278911374725867347), tol); + BOOST_CHECK_CLOSE_FRACTION(std::atanh(BOOST_FLOAT128_C(-0.5)), BOOST_FLOAT128_C(-0.549306144334054845697622618461262852323745278911374725867347), tol); + BOOST_CHECK_CLOSE_FRACTION(std::atanh(BOOST_FLOAT128_C(0.75)), BOOST_FLOAT128_C(0.972955074527656652552676371721589864818542364790930594229695), tol); + BOOST_CHECK_CLOSE_FRACTION(std::atanh(BOOST_FLOAT128_C(-0.75)), BOOST_FLOAT128_C(-0.972955074527656652552676371721589864818542364790930594229695), tol); + BOOST_CHECK_CLOSE_FRACTION(std::atanh(BOOST_FLOAT128_C(0.125)), BOOST_FLOAT128_C(0.125657214140453038842568865200935839828948193031818857504999), tol); + BOOST_CHECK_CLOSE_FRACTION(std::atanh(BOOST_FLOAT128_C(-0.125)), BOOST_FLOAT128_C(-0.125657214140453038842568865200935839828948193031818857504999), tol); + BOOST_CHECK_EQUAL(std::atanh(BOOST_FLOAT128_C(0.0)), 0.0); + + BOOST_CHECK_EQUAL(std::ldexp(BOOST_FLOATMAX_C(2.5), 2), 2.5 * 4); + int i; + BOOST_CHECK_EQUAL(std::frexp(BOOST_FLOATMAX_C(16.0), &i), BOOST_FLOATMAX_C(0.5)); + BOOST_CHECK_EQUAL(std::floor(BOOST_FLOATMAX_C(2.5)), 2); + BOOST_CHECK_EQUAL(std::floor(BOOST_FLOATMAX_C(-2.5)), -3); + BOOST_CHECK_EQUAL(std::ceil(BOOST_FLOATMAX_C(2.5)), 3); + BOOST_CHECK_EQUAL(std::ceil(BOOST_FLOATMAX_C(-2.5)), -2); + BOOST_CHECK_EQUAL(std::trunc(BOOST_FLOATMAX_C(2.5)), 2); + BOOST_CHECK_EQUAL(std::trunc(BOOST_FLOATMAX_C(-2.5)), -2); + + BOOST_CHECK_CLOSE_FRACTION(std::sqrt(BOOST_FLOAT128_C(2.0)), BOOST_FLOAT128_C(1.41421356237309504880168872420969807856967187537694807317668), tol); + BOOST_CHECK_CLOSE_FRACTION(std::exp(BOOST_FLOAT128_C(2.0)), BOOST_FLOAT128_C(7.38905609893065022723042746057500781318031557055184732408713), tol); + BOOST_CHECK_CLOSE_FRACTION(std::exp(BOOST_FLOAT128_C(2000.0)), BOOST_FLOAT128_C(3.88118019428436857648232207537185146709138266970427068956343e868), tol * 500); + BOOST_CHECK_CLOSE_FRACTION(std::exp(BOOST_FLOAT128_C(-2.0)), 1 / BOOST_FLOAT128_C(7.38905609893065022723042746057500781318031557055184732408713), tol); + BOOST_CHECK_CLOSE_FRACTION(std::exp(BOOST_FLOAT128_C(-2000.0)), 1 / BOOST_FLOAT128_C(3.88118019428436857648232207537185146709138266970427068956343e868), tol * 500); + BOOST_CHECK_CLOSE_FRACTION(std::pow(BOOST_FLOAT128_C(2.5), BOOST_FLOAT128_C(2.5)), BOOST_FLOAT128_C(9.88211768802618541249654232635224541787360981039130258392970), tol); + BOOST_CHECK_CLOSE_FRACTION(std::pow(BOOST_FLOAT128_C(2.5), -BOOST_FLOAT128_C(2.5)), 1 / BOOST_FLOAT128_C(9.88211768802618541249654232635224541787360981039130258392970), tol); + + BOOST_CHECK_CLOSE_FRACTION(std::log(BOOST_FLOAT128_C(2.0)), BOOST_FLOAT128_C(0.693147180559945309417232121458176568075500134360255254120680), tol); + BOOST_CHECK_CLOSE_FRACTION(std::log(BOOST_FLOAT128_C(2000.0)), BOOST_FLOAT128_C(7.60090245954208236147120648551126919087880460024657418222066), tol); + BOOST_CHECK_CLOSE_FRACTION(std::log10(BOOST_FLOAT128_C(2.0)), BOOST_FLOAT128_C(0.301029995663981195213738894724493026768189881462108541310427), tol); + BOOST_CHECK_CLOSE_FRACTION(std::log10(BOOST_FLOAT128_C(2000.0)), BOOST_FLOAT128_C(3.30102999566398119521373889472449302676818988146210854131043), tol); + + BOOST_CHECK_EQUAL(std::fmod(BOOST_FLOATMAX_C(20.0), BOOST_FLOATMAX_C(7.0)), BOOST_FLOATMAX_C(6.0)); + BOOST_CHECK_EQUAL(std::fmod(-BOOST_FLOATMAX_C(20.0), BOOST_FLOATMAX_C(7.0)), -BOOST_FLOATMAX_C(6.0)); + BOOST_CHECK_EQUAL(std::fmod(BOOST_FLOATMAX_C(20.0), -BOOST_FLOATMAX_C(7.0)), BOOST_FLOATMAX_C(6.0)); + BOOST_CHECK_EQUAL(std::fmod(-BOOST_FLOATMAX_C(20.0), -BOOST_FLOATMAX_C(7.0)), -BOOST_FLOATMAX_C(6.0)); + // + // Basic tests of complex number support: + // + std::complex cm(2.5, 3.5); + std::complex cd(2.5, 3.5); + BOOST_CHECK_EQUAL(real(cm), BOOST_FLOATMAX_C(2.5)); + BOOST_CHECK_EQUAL(imag(cm), BOOST_FLOATMAX_C(3.5)); + BOOST_CHECK_CLOSE_FRACTION(abs(cm), std::sqrt(real(cm) * real(cm) + imag(cm) * imag(cm)), tol); + BOOST_CHECK_CLOSE_FRACTION(arg(cm), std::atan2(imag(cm), real(cm)), tol); + BOOST_CHECK_EQUAL(norm(cm), norm(cd)); + BOOST_CHECK_EQUAL(conj(cm), std::complex(2.5, -3.5)); + BOOST_CHECK_EQUAL(proj(cm), cm); + if (std::numeric_limits::has_infinity) + { + boost::floatmax_t m = (std::numeric_limits::max)(); + boost::floatmax_t n = (std::numeric_limits::quiet_NaN)(); + boost::floatmax_t i = std::numeric_limits::infinity(); + std::complex ci(i, 0); + BOOST_CHECK_EQUAL(proj(std::complex(i, 2.5)), ci); + BOOST_CHECK_EQUAL(proj(std::complex(i, -2.5)), std::conj(ci)); + BOOST_CHECK_EQUAL(proj(std::complex(-i, 2.5)), ci); + BOOST_CHECK_EQUAL(proj(std::complex(-i, -2.5)), std::conj(ci)); + BOOST_CHECK_EQUAL(proj(std::complex(2.5, i)), ci); + BOOST_CHECK_EQUAL(proj(std::complex(-2.5, i)), ci); + BOOST_CHECK_EQUAL(proj(std::complex(2.5, -i)), std::conj(ci)); + BOOST_CHECK_EQUAL(proj(std::complex(-2.5, -i)), std::conj(ci)); + // If there's a NaN and an infinity, then we treat it as an infinity: + BOOST_CHECK_EQUAL(proj(std::complex(i, n)), ci); + BOOST_CHECK_EQUAL(proj(std::complex(-i, n)), ci); + BOOST_CHECK_EQUAL(proj(std::complex(n, i)), ci); + BOOST_CHECK_EQUAL(proj(std::complex(n, -i)), std::conj(ci)); + // Maximum values should not be detected as infinities: + BOOST_CHECK_EQUAL(proj(std::complex(m, 2.5)), std::complex(m, 2.5)); + BOOST_CHECK_EQUAL(proj(std::complex(m, -2.5)), std::complex(m, -2.5)); + BOOST_CHECK_EQUAL(proj(std::complex(-m, 2.5)), std::complex(-m, 2.5)); + BOOST_CHECK_EQUAL(proj(std::complex(-m, -2.5)), std::complex(-m, -2.5)); + BOOST_CHECK_EQUAL(proj(std::complex(2.5, m)), std::complex(2.5, m)); + BOOST_CHECK_EQUAL(proj(std::complex(-2.5, m)), std::complex(-2.5, m)); + BOOST_CHECK_EQUAL(proj(std::complex(2.5, -m)), std::complex(2.5, -m)); + BOOST_CHECK_EQUAL(proj(std::complex(-2.5, -m)), std::complex(-2.5, -m)); + } + BOOST_CHECK_CLOSE_FRACTION(real(cm), real(std::polar(abs(cm), arg(cm))), tol); + BOOST_CHECK_CLOSE_FRACTION(imag(cm), imag(std::polar(abs(cm), arg(cm))), tol); + BOOST_CHECK_CLOSE_FRACTION(real(sqrt(cm)), BOOST_FLOATMAX_C(1.84406651636014927478967924702313083926924795108746617689331), tol); + BOOST_CHECK_CLOSE_FRACTION(imag(sqrt(cm)), BOOST_FLOATMAX_C(0.94898962942734874384477674565646902214428238312030745589860), tol); + + BOOST_CHECK_CLOSE_FRACTION(real(sin(cm)), BOOST_FLOATMAX_C(9.9183739147466194779705692590714075536609528502804512321829), tol); + BOOST_CHECK_CLOSE_FRACTION(imag(sin(cm)), BOOST_FLOATMAX_C(-13.2530202358612673933065316490414418905222985108088743924151), tol); + BOOST_CHECK_CLOSE_FRACTION(real(cos(cm)), BOOST_FLOATMAX_C(-13.2772126767962806757640045050809172681765101364150115572273), tol); + BOOST_CHECK_CLOSE_FRACTION(imag(cos(cm)), BOOST_FLOATMAX_C(-9.9003016219435352532718399415663308886142356901813313808396), tol); + BOOST_CHECK_CLOSE_FRACTION(real(tan(cm)), BOOST_FLOATMAX_C(-0.001747945781533807475041571346335555146588886236426940282142), 100 * tol); + BOOST_CHECK_CLOSE_FRACTION(imag(tan(cm)), BOOST_FLOATMAX_C(0.999481272866023968509371163341197364669909311495225118348783), tol); + + BOOST_CHECK_CLOSE_FRACTION(real(asin(cm)), BOOST_FLOATMAX_C(0.60763873377718961061236721540807625716707363115177473522038), 3 * tol); + BOOST_CHECK_CLOSE_FRACTION(imag(asin(cm)), BOOST_FLOATMAX_C(2.15662466247239925020341473126370983708442367609452933444142), tol); + BOOST_CHECK_CLOSE_FRACTION(real(acos(cm)), BOOST_FLOATMAX_C(0.96315759301770700861895447623167518493151106853577817526710), tol); + BOOST_CHECK_CLOSE_FRACTION(imag(acos(cm)), BOOST_FLOATMAX_C(-2.15662466247239925020341473126370983708442367609452933444142), tol); + BOOST_CHECK_CLOSE_FRACTION(real(atan(cm)), BOOST_FLOATMAX_C(1.43164649729234094356720655652341656334194939189977737526797), tol); + BOOST_CHECK_CLOSE_FRACTION(imag(atan(cm)), BOOST_FLOATMAX_C(0.18785402217098027123573761814417062282719376109354553980571), tol); + + BOOST_CHECK_CLOSE_FRACTION(real(exp(cm)), BOOST_FLOATMAX_C(-11.40837793738050755301628098123357473395267691300165885963084), tol); + BOOST_CHECK_CLOSE_FRACTION(imag(exp(cm)), BOOST_FLOATMAX_C(-4.27341455284486523762268047763120025488336663280501044879428), tol); + BOOST_CHECK_CLOSE_FRACTION(real(log(cm)), BOOST_FLOATMAX_C(1.45888536604213956747543177478663529791228872640369045476212), tol); + BOOST_CHECK_CLOSE_FRACTION(imag(log(cm)), BOOST_FLOATMAX_C(0.95054684081207514789478913546381917504767901030880427426177), tol); + BOOST_CHECK_CLOSE_FRACTION(real(pow(cm, cm)), BOOST_FLOATMAX_C(0.500085941796692509786065254311643761781309406813392318413211), 3 * tol); + BOOST_CHECK_CLOSE_FRACTION(imag(pow(cm, cm)), BOOST_FLOATMAX_C(1.2835619023632800631240903890826362708871896445947786884), tol); + BOOST_CHECK_CLOSE_FRACTION(real(pow(cm, 45)), BOOST_FLOATMAX_C(1.15295630001810518909457669488131135702133178710937500000000e28), tol); + BOOST_CHECK_CLOSE_FRACTION(imag(pow(cm, 45)), BOOST_FLOATMAX_C(-3.03446103291767290317331113291188915967941284179687500000000e28), tol); + BOOST_CHECK_CLOSE_FRACTION(real(pow(cm, BOOST_FLOATMAX_C(-6.25))), BOOST_FLOATMAX_C(0.0001033088262386741675929555572265687059620746178809486273109638), tol); + BOOST_CHECK_CLOSE_FRACTION(imag(pow(cm, BOOST_FLOATMAX_C(-6.25))), BOOST_FLOATMAX_C(0.000036807924520680371147635577932953977554657684086220380643819), 10*tol); + BOOST_CHECK_CLOSE_FRACTION(real(pow(BOOST_FLOATMAX_C(23.125), cm)), BOOST_FLOATMAX_C(-6.10574617260000071495777483951769228578270070743952693687), 500*tol); + BOOST_CHECK_CLOSE_FRACTION(imag(pow(BOOST_FLOATMAX_C(23.125), cm)), BOOST_FLOATMAX_C(-2571.59829653692515304089117319850284971907684832627401081405), tol); + + BOOST_CHECK_CLOSE_FRACTION(real(sinh(cm)), BOOST_FLOATMAX_C(-5.66575444574645085564435171738630834083691435582030649964506), tol); + BOOST_CHECK_CLOSE_FRACTION(imag(sinh(cm)), BOOST_FLOATMAX_C(-2.15110429680352723029881676360397937637837569516923953471257), tol); + BOOST_CHECK_CLOSE_FRACTION(real(cosh(cm)), BOOST_FLOATMAX_C(-5.74262349163405669737192926384726639311576255718135235998578), tol); + BOOST_CHECK_CLOSE_FRACTION(imag(cosh(cm)), BOOST_FLOATMAX_C(-2.12231025604133800732386371402722087850499093763577091408171), tol); + BOOST_CHECK_CLOSE_FRACTION(real(tanh(cm)), BOOST_FLOATMAX_C(0.989853240015864535514963496600761619743140454542828561309980), tol); + BOOST_CHECK_CLOSE_FRACTION(imag(tanh(cm)), BOOST_FLOATMAX_C(0.008764045495134631601280624388444235039135499546704045953309), 12 * tol); + + BOOST_CHECK_CLOSE_FRACTION(real(asinh(cm)), BOOST_FLOATMAX_C(2.14787287976856126021628946626513750583054633606189652982666), tol); + BOOST_CHECK_CLOSE_FRACTION(imag(asinh(cm)), BOOST_FLOATMAX_C(0.93760050284009400234857022775555923392488940926800031416598), tol); + BOOST_CHECK_CLOSE_FRACTION(real(acosh(cm)), BOOST_FLOATMAX_C(2.15662466247239925020341473126370983708442367609452933444142), tol); + BOOST_CHECK_CLOSE_FRACTION(imag(acosh(cm)), BOOST_FLOATMAX_C(0.96315759301770700861895447623167518493151106853577817526710), tol); + BOOST_CHECK_CLOSE_FRACTION(real(atanh(cm)), BOOST_FLOATMAX_C(0.131131117031038145756858363631111963444914136310244574499277), tol); + BOOST_CHECK_CLOSE_FRACTION(imag(atanh(cm)), BOOST_FLOATMAX_C(1.380543138238714176079527733234534889849881842858502491699319), 12 * tol); +} + + +