diff --git a/include/boost/math/special_functions/detail/ibeta_inverse.hpp b/include/boost/math/special_functions/detail/ibeta_inverse.hpp index 4ec944a9c..7de5da5c5 100644 --- a/include/boost/math/special_functions/detail/ibeta_inverse.hpp +++ b/include/boost/math/special_functions/detail/ibeta_inverse.hpp @@ -673,7 +673,28 @@ T ibeta_inv_imp(T a, T b, T p, T q, const Policy& pol, T* py) invert = !invert; xs = 1 - xs; } - T xg = pow(a * p * boost::math::beta(a, b, pol), 1/a); + if (a < tools::min_value()) + return invert ? 1 : 0; // nothing interesting going on here. + // + // The call to beta may overflow, plus the alternative using lgamma may do the same + // if T is a type where 1/T is infinite for small values (denorms for example). + // + T bet = 0; + T xg; + bool overflow = false; + try { + bet = boost::math::beta(a, b, pol); + } + catch (const std::runtime_error&) + { + overflow = true; + } + if (overflow || !(boost::math::isfinite)(bet)) + { + xg = exp((boost::math::lgamma(a + 1, pol) + boost::math::lgamma(b + 1) - boost::math::lgamma(a + b + 1) + log(p) - log(b) + log(a + b)) / a); + } + else + xg = pow(a * p * bet, 1/a); x = xg / (1 + xg); y = 1 / (1 + xg); // diff --git a/test/test_students_t.cpp b/test/test_students_t.cpp index 9a133835e..47e9c4916 100644 --- a/test/test_students_t.cpp +++ b/test/test_students_t.cpp @@ -381,6 +381,13 @@ void test_spots(RealType) boost::math::quantile( students_t_distribution(static_cast(0x0fffffff)), static_cast(0.25f))), static_cast(0.25f), tolerance); + // + // Bug cases: + // + if (std::numeric_limits::is_specialized && std::numeric_limits::has_denorm) + { + BOOST_CHECK_THROW(boost::math::quantile(students_t_distribution((std::numeric_limits::min)() / 2), static_cast(0.0025f)), std::overflow_error); + } } // Student's t pdf tests.