diff --git a/include/boost/math/special_functions/detail/hypergeometric_1F1_large_abz.hpp b/include/boost/math/special_functions/detail/hypergeometric_1F1_large_abz.hpp index f34754f95..d072ec2b6 100644 --- a/include/boost/math/special_functions/detail/hypergeometric_1F1_large_abz.hpp +++ b/include/boost/math/special_functions/detail/hypergeometric_1F1_large_abz.hpp @@ -393,9 +393,15 @@ // So shift b to match a (b shifting seems to be more stable via method of ratios). // int b_shift = itrunc(b - a); - if (b_shift < 0) - b_shift -= 2; // Make sure b - a - 0.5 > 0 + if ((b_shift < 0) && (b - b_shift != a)) + b_shift -= 1; T b_local = b - b_shift; + if ((b_local - a - 0.5 <= 0) && (b_local != a)) + { + // Make sure b_local - a - 0.5 > 0 + b_shift -= 1; + b_local += 1; + } T h = boost::math::detail::hypergeometric_1F1_AS_13_3_6(a, b_local, z, T(b_local - a), pol, log_scaling); return hypergeometric_1F1_shift_on_b(h, a, b_local, z, b_shift, pol, log_scaling); } diff --git a/include/boost/math/special_functions/hypergeometric_1F1.hpp b/include/boost/math/special_functions/hypergeometric_1F1.hpp index f40699629..48740a311 100644 --- a/include/boost/math/special_functions/hypergeometric_1F1.hpp +++ b/include/boost/math/special_functions/hypergeometric_1F1.hpp @@ -355,7 +355,9 @@ namespace boost { namespace math { namespace detail { if ((a < 0) && (a == ceil(a)) && (a > -50)) return detail::hypergeometric_1F1_generic_series(a, b, z, pol, log_scaling, function); - return (b + z) * exp(z) / b; + log_scaling = lltrunc(floor(z)); + T local_z = z - log_scaling; + return (b + z) * exp(local_z) / b; } if ((a == 1) && (b == 2)) diff --git a/test/test_1F1_log.cpp b/test/test_1F1_log.cpp index 621a5d943..b0ea07332 100644 --- a/test/test_1F1_log.cpp +++ b/test/test_1F1_log.cpp @@ -160,11 +160,6 @@ BOOST_AUTO_TEST_CASE( test_main ) expected_results(); BOOST_MATH_CONTROL_FP; -#if !defined(TEST) || (TEST == 1) - test_hypergeometric_mellin_transform(); - test_hypergeometric_laplace_transform(); -#endif - #ifndef BOOST_MATH_BUGGY_LARGE_FLOAT_CONSTANTS #if !defined(TEST) || (TEST == 2) test_spots(0.0F, "float"); diff --git a/test/test_1F1_log.hpp b/test/test_1F1_log.hpp index 28ec4c0d5..d3b20fe24 100644 --- a/test/test_1F1_log.hpp +++ b/test/test_1F1_log.hpp @@ -77,10 +77,28 @@ void test_spots2(T, const char* type_name) do_test_1F1(hypergeometric_1f1_log_large_unsolved, type_name, "Large random values - log - unsolved"); } +template +void test_spots_bugs(T, const char* type_name) +{ + static const std::array, 7> hypergeometric_1F1_bugs = { { + // Found while investigating https://github.com/boostorg/math/issues/1034 + {{ 21156.0f, 21156.0f, 11322, SC_(11322.0)}}, + {{ 21156.0f, 21155.0f, 11322, SC_(11322.428655862323560632951631114666466652986288119296800531328684)}}, + {{ 21156.0f, 21154.0f, 11322, SC_(11322.857338938931770780542471014439235046236959098048505808665509)}}, + {{ 21156.0f, 21154.5f, 11322, SC_(11322.642993998700652342915766513423502332460377941025163971463001)}}, + {{ 21156.0f, 21155.0f - 1.0f / 128, 11322, SC_(11322.43200484338133063401686149227756707)}}, + {{ 21156.0f, 21154.5f - 1.0f / 128, 11322, SC_(11322.646343086066466097278446364687150256282052775170519455915995)}}, + {{ 21156.0f, 21154.0f + 1.0f / 128, 11322, SC_(11322.85398974691465958225700429672975704)}}, + } }; + + do_test_1F1(hypergeometric_1F1_bugs, type_name, "Large random values - log - bug cases"); +} + template void test_spots(T z, const char* type_name) { test_spots1(z, type_name); + test_spots_bugs(z, type_name); #ifdef TEST_UNSOLVED test_spots2(z, type_name); #endif