1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright 2014 Anton Bikineev
3 // Copyright 2014 Christopher Kormanyos
4 // Copyright 2014 John Maddock
5 // Copyright 2014 Paul Bristow
6 // Distributed under the Boost
7 // Software License, Version 1.0. (See accompanying file
8 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
10 #ifndef BOOST_MATH_HYPERGEOMETRIC_ASYM_HPP
11 #define BOOST_MATH_HYPERGEOMETRIC_ASYM_HPP
13 #include <boost/math/special_functions/gamma.hpp>
14 #include <boost/math/special_functions/hypergeometric_2F0.hpp>
18 #pragma warning(disable:4127)
21 namespace boost { namespace math {
26 // Asymptotic series based on https://dlmf.nist.gov/13.7#E1
28 // Note that a and b must not be negative integers, in addition
29 // we require z > 0 and so apply Kummer's relation for z < 0.
31 template <class T, class Policy>
32 inline T hypergeometric_1F1_asym_large_z_series(T a, const T& b, T z, const Policy& pol, int& log_scaling)
35 static const char* function = "boost::math::hypergeometric_1F1_asym_large_z_series<%1%>(%1%, %1%, %1%)";
46 e = z > INT_MAX ? INT_MAX : itrunc(z, pol);
50 if ((fabs(a) < 10) && (fabs(b) < 10))
52 prefix *= pow(z, a) * pow(z, -b) * boost::math::tgamma(b, pol) / boost::math::tgamma(a, pol);
56 T t = log(z) * (a - b);
61 t = boost::math::lgamma(b, &s, pol);
64 prefix *= s * exp(t - e);
66 t = boost::math::lgamma(a, &s, pol);
69 prefix /= s * exp(t - e);
87 term *= a1_poch * a2_poch * z_mult;
91 if (fabs(sum) * boost::math::policies::get_epsilon<T, Policy>() > fabs(term))
93 if(fabs(sum) / abs_sum < boost::math::policies::get_epsilon<T, Policy>())
94 return boost::math::policies::raise_evaluation_error<T>(function, "Large-z asymptotic approximation to 1F1 has destroyed all the digits in the result due to cancellation. Current best guess is %1%",
95 prefix * sum, Policy());
96 if(k > boost::math::policies::get_max_series_iterations<Policy>())
97 return boost::math::policies::raise_evaluation_error<T>(function, "1F1: Unable to locate solution in a reasonable time:"
98 " large-z asymptotic approximation. Current best guess is %1%", prefix * sum, Policy());
99 if((k > 10) && (fabs(term) > fabs(last_term)))
100 return boost::math::policies::raise_evaluation_error<T>(function, "Large-z asymptotic approximation to 1F1 is divergent. Current best guess is %1%", prefix * sum, Policy());
107 // experimental range
108 template <class T, class Policy>
109 inline bool hypergeometric_1F1_asym_region(const T& a, const T& b, const T& z, const Policy&)
112 int half_digits = policies::digits<T, Policy>() / 2;
113 bool in_region = false;
115 if (fabs(a) < 0.001f)
116 return false; // Haven't been able to make this work, why not? TODO!
119 // We use the following heuristic, if after we have had half_digits terms
120 // of the 2F0 series, we require terms to be decreasing in size by a factor
121 // of at least 0.7. Assuming the earlier terms were converging much faster
122 // than this, then this should be enough to achieve convergence before the
123 // series shoots off to infinity.
127 T one_minus_a = 1 - a;
129 if (fabs((one_minus_a + half_digits) * (b_minus_a + half_digits) / (half_digits * z)) < 0.7)
133 // double check that we are not divergent at the start if a,b < 0:
135 if ((one_minus_a < 0) || (b_minus_a < 0))
137 if (fabs(one_minus_a * b_minus_a / z) > 0.5)
142 else if (fabs((1 - (b - a) + half_digits) * (a + half_digits) / (half_digits * z)) < 0.7)
144 if ((floor(b - a) == (b - a)) && (b - a < 0))
145 return false; // Can't have a negative integer b-a.
148 // double check that we are not divergent at the start if a,b < 0:
151 if ((a1 < 0) || (a < 0))
153 if (fabs(a1 * a / z) > 0.5)
158 // Check for a and b negative integers as these aren't supported by the approximation:
162 if ((a < 0) && (floor(a) == a))
164 if ((b < 0) && (floor(b) == b))
178 #endif // BOOST_MATH_HYPERGEOMETRIC_ASYM_HPP