diff --git a/include/boost/math/special_functions/detail/hypergeometric_1F1_small_a_negative_b_by_ratio.hpp b/include/boost/math/special_functions/detail/hypergeometric_1F1_small_a_negative_b_by_ratio.hpp index 245eb4fd4..f2814f5f8 100644 --- a/include/boost/math/special_functions/detail/hypergeometric_1F1_small_a_negative_b_by_ratio.hpp +++ b/include/boost/math/special_functions/detail/hypergeometric_1F1_small_a_negative_b_by_ratio.hpp @@ -45,13 +45,14 @@ // We grab the ratio for M[a, b, z] / M[a, b+1, z] and use it to seed 2 initial values, // then recurse until b > 0, compute a reference value and normalize (Millers method). // + int iterations = boost::math::itrunc(-b, pol); boost::uintmax_t max_iter = boost::math::policies::get_max_series_iterations(); T ratio = boost::math::tools::function_ratio_from_forwards_recurrence(boost::math::detail::hypergeometric_1F1_recurrence_b_coefficients(a, b, z), boost::math::tools::epsilon(), max_iter); boost::math::policies::check_series_iterations("boost::math::hypergeometric_1F1_small_a_negative_b_by_ratio<%1%>(%1%,%1%,%1%)", max_iter, pol); T first = 1; T second = 1 / ratio; - int iterations = boost::math::itrunc(-b, pol); int scaling1 = 0; + BOOST_ASSERT(b + iterations != a); second = boost::math::tools::apply_recurrence_relation_forward(boost::math::detail::hypergeometric_1F1_recurrence_b_coefficients(a, b + 1, z), iterations, first, second, &scaling1); int scaling2 = 0; first = hypergeometric_1F1_imp(a, b + iterations + 1, z, pol, scaling2); diff --git a/include/boost/math/special_functions/hypergeometric_1F1.hpp b/include/boost/math/special_functions/hypergeometric_1F1.hpp index 69cc13619..14ba74cac 100644 --- a/include/boost/math/special_functions/hypergeometric_1F1.hpp +++ b/include/boost/math/special_functions/hypergeometric_1F1.hpp @@ -256,7 +256,16 @@ namespace boost { namespace math { namespace detail { // // This is a tricky area, potentially we have no good method at all: // - if (max_b_for_1F1_small_a_negative_b_by_ratio(z) < b) + if (b - ceil(b) == a) + { + // Fractional parts of a and b are genuinely equal, we might as well + // apply Kummer's relation and get a truncated series: + int scaling = itrunc(z); + T r = exp(z - scaling) * detail::hypergeometric_1F1_imp(b_minus_a, b, -z, pol, log_scaling); + log_scaling += scaling; + return r; + } + if ((b < -1) && (max_b_for_1F1_small_a_negative_b_by_ratio(z) < b)) return hypergeometric_1F1_small_a_negative_b_by_ratio(a, b, z, pol, log_scaling); if ((b > -1) && (b < -0.5f)) { @@ -408,7 +417,6 @@ namespace boost { namespace math { namespace detail { // 13.3.6 appears to be the most efficient and often the most accurate method. return boost::math::detail::hypergeometric_1F1_AS_13_3_6(a, b, z, b_minus_a, pol, log_scaling); } - if ((a > 0) && (b > 0) && (a * z / b > 2)) { //