From 9ef3540f1a9d8edcd8fe57e2168414e0f263e543 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Stankowski?= Date: Thu, 3 Jul 2025 15:26:48 +0200 Subject: [PATCH] Replaced ldexp with frexp to eliminate errno being set on some compliers (e.g. clang) on underflow or overflow --- .../detail/t_distribution_inv.hpp | 6 ++++-- test/test_students_t.cpp | 15 +++++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/include/boost/math/special_functions/detail/t_distribution_inv.hpp b/include/boost/math/special_functions/detail/t_distribution_inv.hpp index 79a29a027..4b55b4fe2 100644 --- a/include/boost/math/special_functions/detail/t_distribution_inv.hpp +++ b/include/boost/math/special_functions/detail/t_distribution_inv.hpp @@ -404,8 +404,10 @@ calculate_real: // where we use Shaw's tail series. // The crossover point is roughly exponential in -df: // - T crossover = ldexp(1.0f, iround(T(df / -0.654f), typename policies::normalise >::type())); - if(u > crossover) + int u_exp; + T m_exp = frexp(u, &u_exp); + // The following is equivalent to: u > 2^df/-0.654 + if(m_exp > 0 && u_exp < df / 0.654f) { result = boost::math::detail::inverse_students_t_hill(df, u, pol); } diff --git a/test/test_students_t.cpp b/test/test_students_t.cpp index 47454fd96..918d3433b 100644 --- a/test/test_students_t.cpp +++ b/test/test_students_t.cpp @@ -258,6 +258,21 @@ void test_spots(RealType) static_cast(0.1)), // probability. static_cast(-1.475884049), // t tolerance); + errno = 0; + BOOST_CHECK_CLOSE( // Tests of df high and p low. + ::boost::math::cdf( + students_t_distribution(1000.), // degrees_of_freedom + static_cast(-3.30028272)), // t + static_cast(0.0005), // probability. + tolerance); + BOOST_CHECK_EQUAL(errno, 0); + BOOST_CHECK_CLOSE( + ::boost::math::quantile( + students_t_distribution(1000.), // degrees_of_freedom. + static_cast(0.0005)), // probability. + static_cast(-3.30028272), // t. + tolerance); + BOOST_CHECK_EQUAL(errno, 0); BOOST_CHECK_CLOSE( ::boost::math::cdf(