From 13cb3bdacda8c56b7610e5a2dad34e82dfe1b260 Mon Sep 17 00:00:00 2001 From: jzmaddock Date: Sat, 4 Sep 2021 10:46:26 +0100 Subject: [PATCH] Fix low hanging fruit test failures on s390x. This adds some extra instrumentation to bessel_j0.hpp, everything else are fixes for the test programs. The advantage of testing on this platform is that it has a true 128-bit long double which is a good test of our assumptions in code. --- .../special_functions/detail/bessel_j0.hpp | 16 +++++++++++++ test/test_1F1.cpp | 8 +++++++ test/test_airy.cpp | 4 +++- test/test_bessel_j.cpp | 24 +++++++++++++++++++ test/test_bessel_y.cpp | 10 ++++++++ test/test_beta.hpp | 6 ++++- test/test_digamma.cpp | 12 +++++++++- test/test_ellint_2.cpp | 10 ++++++++ test/test_factorials.cpp | 1 + test/test_hankel.cpp | 2 +- test/test_ibeta.hpp | 2 ++ test/test_igamma.hpp | 4 ++-- test/test_tgamma_ratio.hpp | 6 ++--- test/test_zeta.hpp | 2 +- 14 files changed, 97 insertions(+), 10 deletions(-) diff --git a/include/boost/math/special_functions/detail/bessel_j0.hpp b/include/boost/math/special_functions/detail/bessel_j0.hpp index f7a86537f..564f86d7a 100644 --- a/include/boost/math/special_functions/detail/bessel_j0.hpp +++ b/include/boost/math/special_functions/detail/bessel_j0.hpp @@ -64,6 +64,17 @@ T bessel_j0(T x) { bessel_j0_initializer::force_instantiate(); +#ifdef BOOST_MATH_INSTRUMENT + static bool b = false; + if (!b) + { + std::cout << "bessel_j0 called with " << typeid(x).name() << std::endl; + std::cout << "double = " << typeid(double).name() << std::endl; + std::cout << "long double = " << typeid(long double).name() << std::endl; + b = true; + } +#endif + static const T P1[] = { static_cast(BOOST_MATH_BIG_CONSTANT(T, 64, -4.1298668500990866786e+11)), static_cast(BOOST_MATH_BIG_CONSTANT(T, 64, 2.7282507878605942706e+10)), @@ -191,6 +202,11 @@ T bessel_j0(T x) // T sx = sin(x); T cx = cos(x); + BOOST_MATH_INSTRUMENT_VARIABLE(rc); + BOOST_MATH_INSTRUMENT_VARIABLE(rs); + BOOST_MATH_INSTRUMENT_VARIABLE(factor); + BOOST_MATH_INSTRUMENT_VARIABLE(sx); + BOOST_MATH_INSTRUMENT_VARIABLE(cx); value = factor * (rc * (cx + sx) - y * rs * (sx - cx)); } diff --git a/test/test_1F1.cpp b/test/test_1F1.cpp index d3be4aaea..2da92665c 100644 --- a/test/test_1F1.cpp +++ b/test/test_1F1.cpp @@ -106,6 +106,14 @@ void expected_results() "double", // test type(s) "Bug.*", // test data group ".*", 300, 50); // test function +#elif(LDBL_MANT_DIG != DBL_MANT_DIG) + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + "double", // test type(s) + ".*double limited precision.*", // test data group + ".*", 10, 5); // test function #endif diff --git a/test/test_airy.cpp b/test/test_airy.cpp index aba34665f..c1a9f6aad 100644 --- a/test/test_airy.cpp +++ b/test/test_airy.cpp @@ -44,10 +44,12 @@ void test_airy(T, const char* name) {{ -2, static_cast(0.227407428201685575991924436037873799460772225417096716495790L), static_cast(-0.412302587956398488083234054611461042034534834472404728823877L), static_cast(0.618259020741691041406264291332475282915777945124146942159898L), static_cast(0.278795166921169522685097569410983241403000593451631000239732L) }}, {{ -3.5, static_cast(-0.375533823140431911934396951580170239543268576378264063902563L), static_cast(0.168939837481058611843442769540943269911562243926304070915824L), static_cast(-0.343443433454048146287937374098698857094194220958713294264017L), static_cast(-0.693116284907288801752443612670580462699702668014978495343697L) }}, {{ -30.25, static_cast(-0.236900428491559731119806902381433570300271552218956227857722L), static_cast(0.0418614989839147441219283537268101850442118139150748075124111L), static_cast(-0.232197332372689274917364138870840123428255785603863926579897L), static_cast(-1.30261375952554697768880873095691151213006925411329957440342L) }}, - {{ -300.5, static_cast(-0.117584304761702008955433457721670950077867326839023449546057L), static_cast(0.0673518035440918806545676478730240310819758211028871823560384), static_cast(-1.16763702262473888724431076711846459336993902544926162874376L), static_cast(-2.03826035550300900666977975504950803669545593208969273694133L) }}, + {{ -300.5, static_cast(-0.117584304761702008955433457721670950077867326839023449546057L), static_cast(0.0673518035440918806545676478730240310819758211028871823560384L), static_cast(-1.16763702262473888724431076711846459336993902544926162874376L), static_cast(-2.03826035550300900666977975504950803669545593208969273694133L) }}, }}; T tol = boost::math::tools::epsilon() * 800; + if (std::numeric_limits::digits > 100) + tol *= 2; for(unsigned i = 0; i < data.size(); ++i) { BOOST_CHECK_CLOSE_FRACTION(data[i][1], boost::math::airy_ai(data[i][0]), tol); diff --git a/test/test_bessel_j.cpp b/test/test_bessel_j.cpp index 8e9f9f01b..827a34789 100644 --- a/test/test_bessel_j.cpp +++ b/test/test_bessel_j.cpp @@ -234,6 +234,30 @@ void expected_results() ".*(JN|j).*|.*Tricky.*", // test data group ".*", 33000, 20000); // test function } + else if (std::numeric_limits::digits >= 90) + { + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + "double", // test type(s) + ".*J0.*Tricky.*", // test data group + ".*", 100000, 100000); // test function + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + "double", // test type(s) + ".*J1.*Tricky.*", // test data group + ".*", 70, 50); // test function + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + "double", // test type(s) + ".*Mathworld.*", // test data group + ".*", 20, 10); // test function + } #endif add_expected_result( ".*", // compiler diff --git a/test/test_bessel_y.cpp b/test/test_bessel_y.cpp index b37f190fc..1dc7308e2 100644 --- a/test/test_bessel_y.cpp +++ b/test/test_bessel_y.cpp @@ -183,6 +183,16 @@ void expected_results() ".*Yv.*", // test data group ".*", 80, 70); // test function } + else if (std::numeric_limits::digits >= 90) + { + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + "double", // test type(s) + ".*Yv.*Mathworld.*", // test data group + ".*", 20, 5); // test function + } #endif // // defaults are based on MSVC-8 on Win32: diff --git a/test/test_beta.hpp b/test/test_beta.hpp index f9c237d59..217b80108 100644 --- a/test/test_beta.hpp +++ b/test/test_beta.hpp @@ -98,6 +98,10 @@ void test_spots(T) BOOST_CHECK_CLOSE(::boost::math::beta(small, static_cast(4)), 1/small, tolerance); BOOST_CHECK_CLOSE(::boost::math::beta(static_cast(4), small), 1/small, tolerance); BOOST_CHECK_CLOSE(::boost::math::beta(static_cast(4), static_cast(20)), static_cast(0.00002823263692828910220214568040654997176736L), tolerance); - BOOST_CHECK_CLOSE(::boost::math::beta(static_cast(0.0125L), static_cast(0.000023L)), static_cast(43558.24045647538375006349016083320744662L), tolerance * 2); + if (std::numeric_limits::digits < 100) + { + // Inexact input, so disable for ultra precise long doubles: + BOOST_CHECK_CLOSE(::boost::math::beta(static_cast(0.0125L), static_cast(0.000023L)), static_cast(43558.24045647538375006349016083320744662L), tolerance * 2); + } } diff --git a/test/test_digamma.cpp b/test/test_digamma.cpp index 67fee8195..d90203565 100644 --- a/test/test_digamma.cpp +++ b/test/test_digamma.cpp @@ -56,6 +56,16 @@ void expected_results() "real_concept", // test type(s) ".*Half.*", // test data group ".*", 15, 10); // test function + if (std::numeric_limits::digits > 100) + { + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + "real_concept", // test type(s) + ".*Near Zero.*", // test data group + ".*", 15, 10); // test function + } add_expected_result( ".*", // compiler ".*", // stdlib @@ -87,7 +97,7 @@ void test_spots(T, const char* t) BOOST_CHECK_CLOSE(::boost::math::digamma(static_cast(0.5)), static_cast(-1.9635100260214234794409763329987555671931596046604L), tolerance); BOOST_CHECK_CLOSE(::boost::math::digamma(static_cast(1)), static_cast(-0.57721566490153286060651209008240243104215933593992L), tolerance); BOOST_CHECK_CLOSE(::boost::math::digamma(static_cast(1.5)), static_cast(0.036489973978576520559023667001244432806840395339566L), tolerance * 40); - BOOST_CHECK_CLOSE(::boost::math::digamma(static_cast(1.5) - static_cast(1)/32), static_cast(0.00686541147073577672813890866512415766586241385896200579891429L), tolerance * 100); + BOOST_CHECK_CLOSE(::boost::math::digamma(static_cast(1.5) - static_cast(1)/32), static_cast(0.00686541147073577672813890866512415766586241385896200579891429L), tolerance * 200); BOOST_CHECK_CLOSE(::boost::math::digamma(static_cast(2)), static_cast(0.42278433509846713939348790991759756895784066406008L), tolerance); BOOST_CHECK_CLOSE(::boost::math::digamma(static_cast(8)), static_cast(2.0156414779556099965363450527747404261006978069172L), tolerance); BOOST_CHECK_CLOSE(::boost::math::digamma(static_cast(12)), static_cast(2.4426616799758120167383652547949424463027180089374L), tolerance); diff --git a/test/test_ellint_2.cpp b/test/test_ellint_2.cpp index d618569de..ca3e994d4 100644 --- a/test/test_ellint_2.cpp +++ b/test/test_ellint_2.cpp @@ -53,6 +53,16 @@ void expected_results() largest_type = "(long\\s+)?double"; #endif + if (std::numeric_limits::digits > 100) + { + add_expected_result( + ".*", // compiler + ".*", // stdlib + ".*", // platform + "long double|real_concept", // test type(s) + ".*Mathworld.*", // test data group + ".*", 40, 10); // test function + } // // Catch all cases come last: // diff --git a/test/test_factorials.cpp b/test/test_factorials.cpp index 851f6462d..6b413242c 100644 --- a/test/test_factorials.cpp +++ b/test/test_factorials.cpp @@ -44,6 +44,7 @@ T naive_falling_factorial(T x, unsigned n) template void test_spots(T) { + using std::ldexp; // // Basic sanity checks. // diff --git a/test/test_hankel.cpp b/test/test_hankel.cpp index f961234d3..ba5135355 100644 --- a/test/test_hankel.cpp +++ b/test/test_hankel.cpp @@ -57,7 +57,7 @@ void test_hankel(T, const char* name) {{ 4, 4, static_cast(0.281129064961360106322277160229942806897088617059328870629222L), static_cast(-0.488936768533842510615657398339913206218740182079627974737267L) }}, {{ 4, -4, static_cast(0.281129064961360106322277160229942806897088617059328870629222L), std::complex(static_cast(-0.488936768533842510615657398339913206218740182079627974737267L), static_cast(0.562258129922720212644554320459885613794177234118657741258443L)) }}, {{ -4, 4, static_cast(0.281129064961360106322277160229942806897088617059328870629222L), static_cast(-0.488936768533842510615657398339913206218740182079627974737267L) }}, - {{ -4, -4, static_cast(0.281129064961360106322277160229942806897088617059328870629222), std::complex(static_cast(-0.488936768533842510615657398339913206218740182079627974737267), static_cast(0.562258129922720212644554320459885613794177234118657741258443L)) }}, + {{ -4, -4, static_cast(0.281129064961360106322277160229942806897088617059328870629222), std::complex(static_cast(-0.488936768533842510615657398339913206218740182079627974737267L), static_cast(0.562258129922720212644554320459885613794177234118657741258443L)) }}, {{ 3, 3, static_cast(0.309062722255251643618260194946833149429135935993056794354475L), static_cast(-0.538541616105031618004703905338594463807957863604859251481262L) }}, {{ 3, -3, static_cast(-0.309062722255251643618260194946833149429135935993056794354475L), std::complex(static_cast(0.538541616105031618004703905338594463807957863604859251481262L), static_cast(-0.618125444510503287236520389893666298858271871986113588708949L)) }}, {{ -3, 3, static_cast(-0.309062722255251643618260194946833149429135935993056794354475L), static_cast(0.538541616105031618004703905338594463807957863604859251481262L) }}, diff --git a/test/test_ibeta.hpp b/test/test_ibeta.hpp index b581ce988..9d63ff054 100644 --- a/test/test_ibeta.hpp +++ b/test/test_ibeta.hpp @@ -140,6 +140,8 @@ void test_spots(T) // Spot values are from http://functions.wolfram.com/webMathematica/FunctionEvaluation.jsp?name=BetaRegularized // using precision of 50 decimal digits. T tolerance = boost::math::tools::epsilon() * 3000; + if (boost::math::tools::digits() > 100) + tolerance *= 2; BOOST_CHECK_CLOSE( ::boost::math::ibeta( static_cast(159) / 10000, //(0.015964560210704803L), diff --git a/test/test_igamma.hpp b/test/test_igamma.hpp index 1bd2a395d..6cfd86671 100644 --- a/test/test_igamma.hpp +++ b/test/test_igamma.hpp @@ -214,8 +214,8 @@ void test_spots(T) } if(std::numeric_limits::max_exponent >= 1024) { - BOOST_CHECK_CLOSE(::boost::math::tgamma(static_cast(170), static_cast(165)), static_cast(2.737338337642022829223832094019477918166996032112404370e304L), tolerance); - BOOST_CHECK_CLOSE(::boost::math::tgamma_lower(static_cast(170), static_cast(165)), static_cast(1.531729671362682445715419794880088619901822603944331733e304L), tolerance); + BOOST_CHECK_CLOSE(::boost::math::tgamma(static_cast(170), static_cast(165)), static_cast(2.737338337642022829223832094019477918166996032112404370e304L), 3 * tolerance); + BOOST_CHECK_CLOSE(::boost::math::tgamma_lower(static_cast(170), static_cast(165)), static_cast(1.531729671362682445715419794880088619901822603944331733e304L), 3 * tolerance); BOOST_CHECK_CLOSE(::boost::math::tgamma(static_cast(170), static_cast(170)), static_cast(2.090991698081449410761040647015858316167077909285580375e304L), 10 * tolerance); BOOST_CHECK_CLOSE(::boost::math::tgamma_lower(static_cast(170), static_cast(170)), static_cast(2.178076310923255864178211241883708221901740726771155728e304L), 10 * tolerance); BOOST_CHECK_CLOSE(::boost::math::tgamma(static_cast(170), static_cast(190)), static_cast(2.8359275512790301602903689596273175148895758522893941392e303L), 10 * tolerance); diff --git a/test/test_tgamma_ratio.hpp b/test/test_tgamma_ratio.hpp index 23f1946fc..bbcf9ea67 100644 --- a/test/test_tgamma_ratio.hpp +++ b/test/test_tgamma_ratio.hpp @@ -174,9 +174,9 @@ void test_spots(T, const char*) if(0 != ldexp(T(1), -1074)) { // This is denorm_min at double precision: - BOOST_CHECK_CLOSE_FRACTION(boost::math::tgamma_ratio(T(ldexp(T(1), -1074)), T(200)), T(5.13282785052571536804189023927976812551830809667482691717029e-50), tol * 50); - BOOST_CHECK_CLOSE_FRACTION(boost::math::tgamma_ratio(T(200), T(ldexp(T(1), -1074))), T(1.94824379293682687942882944294875087145333536754699303593931e49), tol * 10); - BOOST_CHECK_CLOSE_FRACTION(boost::math::tgamma_delta_ratio(T(ldexp(T(1), -1074)), T(200)), T(5.13282785052571536804189023927976812551830809667482691717029e-50), tol * 10); + BOOST_CHECK_CLOSE_FRACTION(boost::math::tgamma_ratio(T(ldexp(T(1), -1074)), T(200)), T(5.13282785052571536804189023927976812551830809667482691717029e-50L), tol * 50); + BOOST_CHECK_CLOSE_FRACTION(boost::math::tgamma_ratio(T(200), T(ldexp(T(1), -1074))), T(1.94824379293682687942882944294875087145333536754699303593931e49L), tol * 10); + BOOST_CHECK_CLOSE_FRACTION(boost::math::tgamma_delta_ratio(T(ldexp(T(1), -1074)), T(200)), T(5.13282785052571536804189023927976812551830809667482691717029e-50L), tol * 10); BOOST_CHECK_CLOSE_FRACTION(boost::math::tgamma_delta_ratio(T(200), T(ldexp(T(1), -1074))), T(1), tol); } } diff --git a/test/test_zeta.hpp b/test/test_zeta.hpp index 09d24313d..4b1743605 100644 --- a/test/test_zeta.hpp +++ b/test/test_zeta.hpp @@ -129,7 +129,7 @@ void test_spots(T, const char* t) BOOST_CHECK_CLOSE(::boost::math::zeta(ldexp(static_cast(1), -27)), static_cast(-0.500000006846625660947956426350389518286874288247134329498289L), tolerance); BOOST_CHECK_CLOSE(::boost::math::zeta(ldexp(static_cast(1), -28)), static_cast(-0.500000003423312816552083476988056486473169377162409806781384L), tolerance); BOOST_CHECK_CLOSE(::boost::math::zeta(ldexp(static_cast(1), -29)), static_cast(-0.500000001711656404795568073849512135664960180586820144333542L), tolerance); - BOOST_CHECK_CLOSE(::boost::math::zeta(ldexp(static_cast(1), -30)), static_cast(-0.500000000855828201527665623188910582717329375986726355164261L), tolerance); + BOOST_CHECK_CLOSE(::boost::math::zeta(ldexp(static_cast(1), -30)), static_cast(-0.500000000855828201527665623188910582717329375986726355164261L), tolerance * 2); BOOST_CHECK_CLOSE(::boost::math::zeta(ldexp(static_cast(1), -31)), static_cast(-0.500000000427914100546303208463654361814800355929815322493143L), tolerance); BOOST_CHECK_CLOSE(::boost::math::zeta(ldexp(static_cast(1), -32)), static_cast(-0.500000000213957050218769203487022003676593508474107873788445L), tolerance); BOOST_CHECK_CLOSE(::boost::math::zeta(ldexp(static_cast(1), -33)), static_cast(-0.500000000106978525095789001562046589421133388262409441738089L), tolerance);