hypergeometric_1F1_by_ratios.hpp 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // Copyright 2018 John Maddock
  3. // Distributed under the Boost
  4. // Software License, Version 1.0. (See accompanying file
  5. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. #ifndef BOOST_HYPERGEOMETRIC_1F1_BY_RATIOS_HPP_
  7. #define BOOST_HYPERGEOMETRIC_1F1_BY_RATIOS_HPP_
  8. #include <boost/math/tools/recurrence.hpp>
  9. #include <boost/math/policies/error_handling.hpp>
  10. namespace boost { namespace math { namespace detail {
  11. template <class T, class Policy>
  12. T hypergeometric_1F1_imp(const T& a, const T& b, const T& z, const Policy& pol, int& log_scaling);
  13. /*
  14. Evaluation by method of ratios for domain b < 0 < a,z
  15. We first convert the recurrence relation into a ratio
  16. of M(a+1, b+1, z) / M(a, b, z) using Shintan's equivalence
  17. between solving a recurrence relation using Miller's method
  18. and continued fractions. The continued fraction is VERY rapid
  19. to converge (typically < 10 terms), but may converge to entirely
  20. the wrong value if we're in a bad part of the domain. Strangely
  21. it seems to matter not whether we use recurrence on a, b or a and b
  22. they all work or not work about the same, so we might as well make
  23. life easy for ourselves and use the a and b recurrence to avoid
  24. having to apply one extra recurrence to convert from an a or b
  25. recurrence to an a+b one.
  26. See: H. Shintan, Note on Miller's recurrence algorithm, J. Sci. Hiroshima Univ. Ser. A-I Math., 29 (1965), pp. 121-133.
  27. Also: Computational Aspects of Three Term Recurrence Relations, SIAM Review, January 1967.
  28. The following table lists by experiment, how large z can be in order to
  29. ensure the continued fraction converges to the correct value:
  30. a b max z
  31. 13, -130, 22
  32. 13, -1300, 335
  33. 13, -13000, 3585
  34. 130, -130, 8
  35. 130, -1300, 263
  36. 130, - 13000, 3420
  37. 1300, -130, 1
  38. 1300, -1300, 90
  39. 1300, -13000, 2650
  40. 13000, -13, -
  41. 13000, -130, -
  42. 13000, -1300, 13
  43. 13000, -13000, 750
  44. So try z_limit = -b / (4 - 5 * sqrt(log(a)) * a / b);
  45. or z_limit = -b / (4 - 5 * (log(a)) * a / b) for a < 100
  46. This still isn't quite right for both a and b small, but we'll be using a Bessel approximation
  47. in that region anyway.
  48. Normalization using wronksian {1,2} from A&S 13.1.20 (also 13.1.12, 13.1.13):
  49. W{ M(a,b,z), z^(1-b)M(1+a-b, 2-b, z) } = (1-b)z^-b e^z
  50. = M(a,b,z) M2'(a,b,z) - M'(a,b,z) M2(a,b,z)
  51. = M(a,b,z) [(a-b+1)z^(1-b)/(2-b) M2(a+1,b+1,z) + (1-b)z^-b M2(a,b,z)] - a/b M(a+1,b+1,z) z^(1-b)M2(a,b,z)
  52. = M(a,b,z) [(a-b+1)z^(1-b)/(2-b) M2(a+1,b+1,z) + (1-b)z^-b M2(a,b,z)] - a/b R(a,b,z) M(a,b,z) z^(1-b)M2(a,b,z)
  53. = M(a,b,z) [(a-b+1)z^(1-b)/(2-b) M2(a+1,b+1,z) + (1-b)z^-b M2(a,b,z) - a/b R(a,b,z) z^(1-b)M2(a,b,z) ]
  54. so:
  55. (1-b)e^z = M(a,b,z) [(a-b+1)z/(2-b) M2(a+1,b+1,z) + (1-b) M2(a,b,z) - a/b z R(a,b,z) M2(a,b,z) ]
  56. */
  57. template <class T>
  58. inline bool is_in_hypergeometric_1F1_from_function_ratio_negative_b_region(const T& a, const T& b, const T& z)
  59. {
  60. BOOST_MATH_STD_USING
  61. if (a < 100)
  62. return z < -b / (4 - 5 * (log(a)) * a / b);
  63. else
  64. return z < -b / (4 - 5 * sqrt(log(a)) * a / b);
  65. }
  66. template <class T, class Policy>
  67. T hypergeometric_1F1_from_function_ratio_negative_b(const T& a, const T& b, const T& z, const Policy& pol, int& log_scaling, const T& ratio)
  68. {
  69. BOOST_MATH_STD_USING
  70. //
  71. // Let M2 = M(1+a-b, 2-b, z)
  72. // This is going to be a mighty big number:
  73. //
  74. int local_scaling = 0;
  75. T M2 = boost::math::detail::hypergeometric_1F1_imp(T(1 + a - b), T(2 - b), z, pol, local_scaling);
  76. log_scaling -= local_scaling; // all the M2 terms are in the denominator
  77. //
  78. // Since a, b and z are all likely to be large we need the Wronksian
  79. // calculation below to not overflow, so scale everything right down:
  80. //
  81. if (fabs(M2) > 1)
  82. {
  83. int s = itrunc(log(fabs(M2)));
  84. log_scaling -= s; // M2 will be in the denominator, so subtract the scaling!
  85. local_scaling += s;
  86. M2 *= exp(T(-s));
  87. }
  88. //
  89. // Let M3 = M(1+a-b + 1, 2-b + 1, z)
  90. // we can get to this from the ratio which is cheaper to calculate:
  91. //
  92. boost::uintmax_t max_iter = boost::math::policies::get_max_series_iterations<Policy>();
  93. boost::math::detail::hypergeometric_1F1_recurrence_a_and_b_coefficients<T> coef2(1 + a - b + 1, 2 - b + 1, z);
  94. T M3 = boost::math::tools::function_ratio_from_backwards_recurrence(coef2, boost::math::policies::get_epsilon<T, Policy>(), max_iter) * M2;
  95. boost::math::policies::check_series_iterations<T>("boost::math::hypergeometric_1F1_from_function_ratio_negative_b_positive_a<%1%>(%1%,%1%,%1%)", max_iter, pol);
  96. //
  97. // Get the RHS of the Wronksian:
  98. //
  99. int fz = itrunc(z);
  100. log_scaling += fz;
  101. T rhs = (1 - b) * exp(z - fz);
  102. //
  103. // We need to divide that by:
  104. // [(a-b+1)z/(2-b) M2(a+1,b+1,z) + (1-b) M2(a,b,z) - a/b z^b R(a,b,z) M2(a,b,z) ]
  105. // Note that at this stage, both M3 and M2 are scaled by exp(local_scaling).
  106. //
  107. T lhs = (a - b + 1) * z * M3 / (2 - b) + (1 - b) * M2 - a * z * ratio * M2 / b;
  108. return rhs / lhs;
  109. }
  110. template <class T, class Policy>
  111. T hypergeometric_1F1_from_function_ratio_negative_b(const T& a, const T& b, const T& z, const Policy& pol, int& log_scaling)
  112. {
  113. BOOST_MATH_STD_USING
  114. //
  115. // Get the function ratio, M(a+1, b+1, z)/M(a,b,z):
  116. //
  117. boost::uintmax_t max_iter = boost::math::policies::get_max_series_iterations<Policy>();
  118. boost::math::detail::hypergeometric_1F1_recurrence_a_and_b_coefficients<T> coef(a + 1, b + 1, z);
  119. T ratio = boost::math::tools::function_ratio_from_backwards_recurrence(coef, boost::math::policies::get_epsilon<T, Policy>(), max_iter);
  120. boost::math::policies::check_series_iterations<T>("boost::math::hypergeometric_1F1_from_function_ratio_negative_b_positive_a<%1%>(%1%,%1%,%1%)", max_iter, pol);
  121. return hypergeometric_1F1_from_function_ratio_negative_b(a, b, z, pol, log_scaling, ratio);
  122. }
  123. //
  124. // And over again, this time via forwards recurrence when z is large enough:
  125. //
  126. template <class T>
  127. bool hypergeometric_1F1_is_in_forwards_recurence_for_negative_b_region(const T& a, const T& b, const T& z)
  128. {
  129. //
  130. // There's no easy relation between a, b and z that tells us whether we're in the region
  131. // where forwards recursion is stable, so use a lookup table, note that the minumum
  132. // permissible z-value is decreasing with a, and increasing with |b|:
  133. //
  134. static const float data[][3] = {
  135. {7.500e+00f, -7.500e+00f, 8.409e+00f },
  136. {7.500e+00f, -1.125e+01f, 8.409e+00f },
  137. {7.500e+00f, -1.688e+01f, 9.250e+00f },
  138. {7.500e+00f, -2.531e+01f, 1.119e+01f },
  139. {7.500e+00f, -3.797e+01f, 1.354e+01f },
  140. {7.500e+00f, -5.695e+01f, 1.983e+01f },
  141. {7.500e+00f, -8.543e+01f, 2.639e+01f },
  142. {7.500e+00f, -1.281e+02f, 3.864e+01f },
  143. {7.500e+00f, -1.922e+02f, 5.657e+01f },
  144. {7.500e+00f, -2.883e+02f, 8.283e+01f },
  145. {7.500e+00f, -4.325e+02f, 1.213e+02f },
  146. {7.500e+00f, -6.487e+02f, 1.953e+02f },
  147. {7.500e+00f, -9.731e+02f, 2.860e+02f },
  148. {7.500e+00f, -1.460e+03f, 4.187e+02f },
  149. {7.500e+00f, -2.189e+03f, 6.130e+02f },
  150. {7.500e+00f, -3.284e+03f, 9.872e+02f },
  151. {7.500e+00f, -4.926e+03f, 1.445e+03f },
  152. {7.500e+00f, -7.389e+03f, 2.116e+03f },
  153. {7.500e+00f, -1.108e+04f, 3.098e+03f },
  154. {7.500e+00f, -1.663e+04f, 4.990e+03f },
  155. {1.125e+01f, -7.500e+00f, 6.318e+00f },
  156. {1.125e+01f, -1.125e+01f, 6.950e+00f },
  157. {1.125e+01f, -1.688e+01f, 7.645e+00f },
  158. {1.125e+01f, -2.531e+01f, 9.250e+00f },
  159. {1.125e+01f, -3.797e+01f, 1.231e+01f },
  160. {1.125e+01f, -5.695e+01f, 1.639e+01f },
  161. {1.125e+01f, -8.543e+01f, 2.399e+01f },
  162. {1.125e+01f, -1.281e+02f, 3.513e+01f },
  163. {1.125e+01f, -1.922e+02f, 5.657e+01f },
  164. {1.125e+01f, -2.883e+02f, 8.283e+01f },
  165. {1.125e+01f, -4.325e+02f, 1.213e+02f },
  166. {1.125e+01f, -6.487e+02f, 1.776e+02f },
  167. {1.125e+01f, -9.731e+02f, 2.860e+02f },
  168. {1.125e+01f, -1.460e+03f, 4.187e+02f },
  169. {1.125e+01f, -2.189e+03f, 6.130e+02f },
  170. {1.125e+01f, -3.284e+03f, 9.872e+02f },
  171. {1.125e+01f, -4.926e+03f, 1.445e+03f },
  172. {1.125e+01f, -7.389e+03f, 2.116e+03f },
  173. {1.125e+01f, -1.108e+04f, 3.098e+03f },
  174. {1.125e+01f, -1.663e+04f, 4.990e+03f },
  175. {1.688e+01f, -7.500e+00f, 4.747e+00f },
  176. {1.688e+01f, -1.125e+01f, 5.222e+00f },
  177. {1.688e+01f, -1.688e+01f, 5.744e+00f },
  178. {1.688e+01f, -2.531e+01f, 7.645e+00f },
  179. {1.688e+01f, -3.797e+01f, 1.018e+01f },
  180. {1.688e+01f, -5.695e+01f, 1.490e+01f },
  181. {1.688e+01f, -8.543e+01f, 2.181e+01f },
  182. {1.688e+01f, -1.281e+02f, 3.193e+01f },
  183. {1.688e+01f, -1.922e+02f, 5.143e+01f },
  184. {1.688e+01f, -2.883e+02f, 7.530e+01f },
  185. {1.688e+01f, -4.325e+02f, 1.213e+02f },
  186. {1.688e+01f, -6.487e+02f, 1.776e+02f },
  187. {1.688e+01f, -9.731e+02f, 2.600e+02f },
  188. {1.688e+01f, -1.460e+03f, 4.187e+02f },
  189. {1.688e+01f, -2.189e+03f, 6.130e+02f },
  190. {1.688e+01f, -3.284e+03f, 9.872e+02f },
  191. {1.688e+01f, -4.926e+03f, 1.445e+03f },
  192. {1.688e+01f, -7.389e+03f, 2.116e+03f },
  193. {1.688e+01f, -1.108e+04f, 3.098e+03f },
  194. {1.688e+01f, -1.663e+04f, 4.990e+03f },
  195. {2.531e+01f, -7.500e+00f, 3.242e+00f },
  196. {2.531e+01f, -1.125e+01f, 3.566e+00f },
  197. {2.531e+01f, -1.688e+01f, 4.315e+00f },
  198. {2.531e+01f, -2.531e+01f, 5.744e+00f },
  199. {2.531e+01f, -3.797e+01f, 7.645e+00f },
  200. {2.531e+01f, -5.695e+01f, 1.231e+01f },
  201. {2.531e+01f, -8.543e+01f, 1.803e+01f },
  202. {2.531e+01f, -1.281e+02f, 2.903e+01f },
  203. {2.531e+01f, -1.922e+02f, 4.676e+01f },
  204. {2.531e+01f, -2.883e+02f, 6.845e+01f },
  205. {2.531e+01f, -4.325e+02f, 1.102e+02f },
  206. {2.531e+01f, -6.487e+02f, 1.776e+02f },
  207. {2.531e+01f, -9.731e+02f, 2.600e+02f },
  208. {2.531e+01f, -1.460e+03f, 4.187e+02f },
  209. {2.531e+01f, -2.189e+03f, 6.130e+02f },
  210. {2.531e+01f, -3.284e+03f, 8.974e+02f },
  211. {2.531e+01f, -4.926e+03f, 1.445e+03f },
  212. {2.531e+01f, -7.389e+03f, 2.116e+03f },
  213. {2.531e+01f, -1.108e+04f, 3.098e+03f },
  214. {2.531e+01f, -1.663e+04f, 4.990e+03f },
  215. {3.797e+01f, -7.500e+00f, 2.214e+00f },
  216. {3.797e+01f, -1.125e+01f, 2.679e+00f },
  217. {3.797e+01f, -1.688e+01f, 3.242e+00f },
  218. {3.797e+01f, -2.531e+01f, 4.315e+00f },
  219. {3.797e+01f, -3.797e+01f, 6.318e+00f },
  220. {3.797e+01f, -5.695e+01f, 9.250e+00f },
  221. {3.797e+01f, -8.543e+01f, 1.490e+01f },
  222. {3.797e+01f, -1.281e+02f, 2.399e+01f },
  223. {3.797e+01f, -1.922e+02f, 3.864e+01f },
  224. {3.797e+01f, -2.883e+02f, 6.223e+01f },
  225. {3.797e+01f, -4.325e+02f, 1.002e+02f },
  226. {3.797e+01f, -6.487e+02f, 1.614e+02f },
  227. {3.797e+01f, -9.731e+02f, 2.600e+02f },
  228. {3.797e+01f, -1.460e+03f, 3.806e+02f },
  229. {3.797e+01f, -2.189e+03f, 6.130e+02f },
  230. {3.797e+01f, -3.284e+03f, 8.974e+02f },
  231. {3.797e+01f, -4.926e+03f, 1.445e+03f },
  232. {3.797e+01f, -7.389e+03f, 2.116e+03f },
  233. {3.797e+01f, -1.108e+04f, 3.098e+03f },
  234. {3.797e+01f, -1.663e+04f, 4.990e+03f },
  235. {5.695e+01f, -7.500e+00f, 1.513e+00f },
  236. {5.695e+01f, -1.125e+01f, 1.830e+00f },
  237. {5.695e+01f, -1.688e+01f, 2.214e+00f },
  238. {5.695e+01f, -2.531e+01f, 3.242e+00f },
  239. {5.695e+01f, -3.797e+01f, 4.315e+00f },
  240. {5.695e+01f, -5.695e+01f, 7.645e+00f },
  241. {5.695e+01f, -8.543e+01f, 1.231e+01f },
  242. {5.695e+01f, -1.281e+02f, 1.983e+01f },
  243. {5.695e+01f, -1.922e+02f, 3.513e+01f },
  244. {5.695e+01f, -2.883e+02f, 5.657e+01f },
  245. {5.695e+01f, -4.325e+02f, 9.111e+01f },
  246. {5.695e+01f, -6.487e+02f, 1.467e+02f },
  247. {5.695e+01f, -9.731e+02f, 2.363e+02f },
  248. {5.695e+01f, -1.460e+03f, 3.806e+02f },
  249. {5.695e+01f, -2.189e+03f, 5.572e+02f },
  250. {5.695e+01f, -3.284e+03f, 8.974e+02f },
  251. {5.695e+01f, -4.926e+03f, 1.314e+03f },
  252. {5.695e+01f, -7.389e+03f, 2.116e+03f },
  253. {5.695e+01f, -1.108e+04f, 3.098e+03f },
  254. {5.695e+01f, -1.663e+04f, 4.990e+03f },
  255. {8.543e+01f, -7.500e+00f, 1.250e+00f },
  256. {8.543e+01f, -1.125e+01f, 1.250e+00f },
  257. {8.543e+01f, -1.688e+01f, 1.513e+00f },
  258. {8.543e+01f, -2.531e+01f, 2.214e+00f },
  259. {8.543e+01f, -3.797e+01f, 3.242e+00f },
  260. {8.543e+01f, -5.695e+01f, 5.222e+00f },
  261. {8.543e+01f, -8.543e+01f, 9.250e+00f },
  262. {8.543e+01f, -1.281e+02f, 1.639e+01f },
  263. {8.543e+01f, -1.922e+02f, 2.903e+01f },
  264. {8.543e+01f, -2.883e+02f, 5.143e+01f },
  265. {8.543e+01f, -4.325e+02f, 8.283e+01f },
  266. {8.543e+01f, -6.487e+02f, 1.334e+02f },
  267. {8.543e+01f, -9.731e+02f, 2.148e+02f },
  268. {8.543e+01f, -1.460e+03f, 3.460e+02f },
  269. {8.543e+01f, -2.189e+03f, 5.572e+02f },
  270. {8.543e+01f, -3.284e+03f, 8.974e+02f },
  271. {8.543e+01f, -4.926e+03f, 1.314e+03f },
  272. {8.543e+01f, -7.389e+03f, 2.116e+03f },
  273. {8.543e+01f, -1.108e+04f, 3.098e+03f },
  274. {8.543e+01f, -1.663e+04f, 4.536e+03f },
  275. {1.281e+02f, -7.500e+00f, 1.250e+00f },
  276. {1.281e+02f, -1.125e+01f, 1.250e+00f },
  277. {1.281e+02f, -1.688e+01f, 1.250e+00f },
  278. {1.281e+02f, -2.531e+01f, 1.513e+00f },
  279. {1.281e+02f, -3.797e+01f, 2.214e+00f },
  280. {1.281e+02f, -5.695e+01f, 3.923e+00f },
  281. {1.281e+02f, -8.543e+01f, 6.950e+00f },
  282. {1.281e+02f, -1.281e+02f, 1.231e+01f },
  283. {1.281e+02f, -1.922e+02f, 2.181e+01f },
  284. {1.281e+02f, -2.883e+02f, 4.250e+01f },
  285. {1.281e+02f, -4.325e+02f, 6.845e+01f },
  286. {1.281e+02f, -6.487e+02f, 1.213e+02f },
  287. {1.281e+02f, -9.731e+02f, 1.953e+02f },
  288. {1.281e+02f, -1.460e+03f, 3.460e+02f },
  289. {1.281e+02f, -2.189e+03f, 5.572e+02f },
  290. {1.281e+02f, -3.284e+03f, 8.159e+02f },
  291. {1.281e+02f, -4.926e+03f, 1.314e+03f },
  292. {1.281e+02f, -7.389e+03f, 1.924e+03f },
  293. {1.281e+02f, -1.108e+04f, 3.098e+03f },
  294. {1.281e+02f, -1.663e+04f, 4.536e+03f },
  295. {1.922e+02f, -7.500e+00f, 1.250e+00f },
  296. {1.922e+02f, -1.125e+01f, 1.250e+00f },
  297. {1.922e+02f, -1.688e+01f, 1.250e+00f },
  298. {1.922e+02f, -2.531e+01f, 1.250e+00f },
  299. {1.922e+02f, -3.797e+01f, 1.664e+00f },
  300. {1.922e+02f, -5.695e+01f, 2.679e+00f },
  301. {1.922e+02f, -8.543e+01f, 5.222e+00f },
  302. {1.922e+02f, -1.281e+02f, 9.250e+00f },
  303. {1.922e+02f, -1.922e+02f, 1.803e+01f },
  304. {1.922e+02f, -2.883e+02f, 3.193e+01f },
  305. {1.922e+02f, -4.325e+02f, 5.657e+01f },
  306. {1.922e+02f, -6.487e+02f, 1.002e+02f },
  307. {1.922e+02f, -9.731e+02f, 1.776e+02f },
  308. {1.922e+02f, -1.460e+03f, 3.145e+02f },
  309. {1.922e+02f, -2.189e+03f, 5.066e+02f },
  310. {1.922e+02f, -3.284e+03f, 8.159e+02f },
  311. {1.922e+02f, -4.926e+03f, 1.194e+03f },
  312. {1.922e+02f, -7.389e+03f, 1.924e+03f },
  313. {1.922e+02f, -1.108e+04f, 3.098e+03f },
  314. {1.922e+02f, -1.663e+04f, 4.536e+03f },
  315. {2.883e+02f, -7.500e+00f, 1.250e+00f },
  316. {2.883e+02f, -1.125e+01f, 1.250e+00f },
  317. {2.883e+02f, -1.688e+01f, 1.250e+00f },
  318. {2.883e+02f, -2.531e+01f, 1.250e+00f },
  319. {2.883e+02f, -3.797e+01f, 1.250e+00f },
  320. {2.883e+02f, -5.695e+01f, 2.013e+00f },
  321. {2.883e+02f, -8.543e+01f, 3.566e+00f },
  322. {2.883e+02f, -1.281e+02f, 6.950e+00f },
  323. {2.883e+02f, -1.922e+02f, 1.354e+01f },
  324. {2.883e+02f, -2.883e+02f, 2.399e+01f },
  325. {2.883e+02f, -4.325e+02f, 4.676e+01f },
  326. {2.883e+02f, -6.487e+02f, 8.283e+01f },
  327. {2.883e+02f, -9.731e+02f, 1.614e+02f },
  328. {2.883e+02f, -1.460e+03f, 2.600e+02f },
  329. {2.883e+02f, -2.189e+03f, 4.605e+02f },
  330. {2.883e+02f, -3.284e+03f, 7.417e+02f },
  331. {2.883e+02f, -4.926e+03f, 1.194e+03f },
  332. {2.883e+02f, -7.389e+03f, 1.924e+03f },
  333. {2.883e+02f, -1.108e+04f, 2.817e+03f },
  334. {2.883e+02f, -1.663e+04f, 4.536e+03f },
  335. {4.325e+02f, -7.500e+00f, 1.250e+00f },
  336. {4.325e+02f, -1.125e+01f, 1.250e+00f },
  337. {4.325e+02f, -1.688e+01f, 1.250e+00f },
  338. {4.325e+02f, -2.531e+01f, 1.250e+00f },
  339. {4.325e+02f, -3.797e+01f, 1.250e+00f },
  340. {4.325e+02f, -5.695e+01f, 1.375e+00f },
  341. {4.325e+02f, -8.543e+01f, 2.436e+00f },
  342. {4.325e+02f, -1.281e+02f, 4.747e+00f },
  343. {4.325e+02f, -1.922e+02f, 9.250e+00f },
  344. {4.325e+02f, -2.883e+02f, 1.803e+01f },
  345. {4.325e+02f, -4.325e+02f, 3.513e+01f },
  346. {4.325e+02f, -6.487e+02f, 6.845e+01f },
  347. {4.325e+02f, -9.731e+02f, 1.334e+02f },
  348. {4.325e+02f, -1.460e+03f, 2.363e+02f },
  349. {4.325e+02f, -2.189e+03f, 3.806e+02f },
  350. {4.325e+02f, -3.284e+03f, 6.743e+02f },
  351. {4.325e+02f, -4.926e+03f, 1.086e+03f },
  352. {4.325e+02f, -7.389e+03f, 1.749e+03f },
  353. {4.325e+02f, -1.108e+04f, 2.817e+03f },
  354. {4.325e+02f, -1.663e+04f, 4.536e+03f },
  355. {6.487e+02f, -7.500e+00f, 1.250e+00f },
  356. {6.487e+02f, -1.125e+01f, 1.250e+00f },
  357. {6.487e+02f, -1.688e+01f, 1.250e+00f },
  358. {6.487e+02f, -2.531e+01f, 1.250e+00f },
  359. {6.487e+02f, -3.797e+01f, 1.250e+00f },
  360. {6.487e+02f, -5.695e+01f, 1.250e+00f },
  361. {6.487e+02f, -8.543e+01f, 1.664e+00f },
  362. {6.487e+02f, -1.281e+02f, 3.242e+00f },
  363. {6.487e+02f, -1.922e+02f, 6.950e+00f },
  364. {6.487e+02f, -2.883e+02f, 1.354e+01f },
  365. {6.487e+02f, -4.325e+02f, 2.639e+01f },
  366. {6.487e+02f, -6.487e+02f, 5.143e+01f },
  367. {6.487e+02f, -9.731e+02f, 1.002e+02f },
  368. {6.487e+02f, -1.460e+03f, 1.953e+02f },
  369. {6.487e+02f, -2.189e+03f, 3.460e+02f },
  370. {6.487e+02f, -3.284e+03f, 6.130e+02f },
  371. {6.487e+02f, -4.926e+03f, 9.872e+02f },
  372. {6.487e+02f, -7.389e+03f, 1.590e+03f },
  373. {6.487e+02f, -1.108e+04f, 2.561e+03f },
  374. {6.487e+02f, -1.663e+04f, 4.124e+03f },
  375. {9.731e+02f, -7.500e+00f, 1.250e+00f },
  376. {9.731e+02f, -1.125e+01f, 1.250e+00f },
  377. {9.731e+02f, -1.688e+01f, 1.250e+00f },
  378. {9.731e+02f, -2.531e+01f, 1.250e+00f },
  379. {9.731e+02f, -3.797e+01f, 1.250e+00f },
  380. {9.731e+02f, -5.695e+01f, 1.250e+00f },
  381. {9.731e+02f, -8.543e+01f, 1.250e+00f },
  382. {9.731e+02f, -1.281e+02f, 2.214e+00f },
  383. {9.731e+02f, -1.922e+02f, 4.747e+00f },
  384. {9.731e+02f, -2.883e+02f, 9.250e+00f },
  385. {9.731e+02f, -4.325e+02f, 1.983e+01f },
  386. {9.731e+02f, -6.487e+02f, 3.864e+01f },
  387. {9.731e+02f, -9.731e+02f, 7.530e+01f },
  388. {9.731e+02f, -1.460e+03f, 1.467e+02f },
  389. {9.731e+02f, -2.189e+03f, 2.860e+02f },
  390. {9.731e+02f, -3.284e+03f, 5.066e+02f },
  391. {9.731e+02f, -4.926e+03f, 8.974e+02f },
  392. {9.731e+02f, -7.389e+03f, 1.445e+03f },
  393. {9.731e+02f, -1.108e+04f, 2.561e+03f },
  394. {9.731e+02f, -1.663e+04f, 4.124e+03f },
  395. {1.460e+03f, -7.500e+00f, 1.250e+00f },
  396. {1.460e+03f, -1.125e+01f, 1.250e+00f },
  397. {1.460e+03f, -1.688e+01f, 1.250e+00f },
  398. {1.460e+03f, -2.531e+01f, 1.250e+00f },
  399. {1.460e+03f, -3.797e+01f, 1.250e+00f },
  400. {1.460e+03f, -5.695e+01f, 1.250e+00f },
  401. {1.460e+03f, -8.543e+01f, 1.250e+00f },
  402. {1.460e+03f, -1.281e+02f, 1.513e+00f },
  403. {1.460e+03f, -1.922e+02f, 3.242e+00f },
  404. {1.460e+03f, -2.883e+02f, 6.950e+00f },
  405. {1.460e+03f, -4.325e+02f, 1.354e+01f },
  406. {1.460e+03f, -6.487e+02f, 2.903e+01f },
  407. {1.460e+03f, -9.731e+02f, 5.657e+01f },
  408. {1.460e+03f, -1.460e+03f, 1.213e+02f },
  409. {1.460e+03f, -2.189e+03f, 2.148e+02f },
  410. {1.460e+03f, -3.284e+03f, 4.187e+02f },
  411. {1.460e+03f, -4.926e+03f, 7.417e+02f },
  412. {1.460e+03f, -7.389e+03f, 1.314e+03f },
  413. {1.460e+03f, -1.108e+04f, 2.328e+03f },
  414. {1.460e+03f, -1.663e+04f, 3.749e+03f },
  415. {2.189e+03f, -7.500e+00f, 1.250e+00f },
  416. {2.189e+03f, -1.125e+01f, 1.250e+00f },
  417. {2.189e+03f, -1.688e+01f, 1.250e+00f },
  418. {2.189e+03f, -2.531e+01f, 1.250e+00f },
  419. {2.189e+03f, -3.797e+01f, 1.250e+00f },
  420. {2.189e+03f, -5.695e+01f, 1.250e+00f },
  421. {2.189e+03f, -8.543e+01f, 1.250e+00f },
  422. {2.189e+03f, -1.281e+02f, 1.250e+00f },
  423. {2.189e+03f, -1.922e+02f, 2.214e+00f },
  424. {2.189e+03f, -2.883e+02f, 4.747e+00f },
  425. {2.189e+03f, -4.325e+02f, 9.250e+00f },
  426. {2.189e+03f, -6.487e+02f, 1.983e+01f },
  427. {2.189e+03f, -9.731e+02f, 4.250e+01f },
  428. {2.189e+03f, -1.460e+03f, 8.283e+01f },
  429. {2.189e+03f, -2.189e+03f, 1.776e+02f },
  430. {2.189e+03f, -3.284e+03f, 3.460e+02f },
  431. {2.189e+03f, -4.926e+03f, 6.130e+02f },
  432. {2.189e+03f, -7.389e+03f, 1.086e+03f },
  433. {2.189e+03f, -1.108e+04f, 1.924e+03f },
  434. {2.189e+03f, -1.663e+04f, 3.408e+03f },
  435. {3.284e+03f, -7.500e+00f, 1.250e+00f },
  436. {3.284e+03f, -1.125e+01f, 1.250e+00f },
  437. {3.284e+03f, -1.688e+01f, 1.250e+00f },
  438. {3.284e+03f, -2.531e+01f, 1.250e+00f },
  439. {3.284e+03f, -3.797e+01f, 1.250e+00f },
  440. {3.284e+03f, -5.695e+01f, 1.250e+00f },
  441. {3.284e+03f, -8.543e+01f, 1.250e+00f },
  442. {3.284e+03f, -1.281e+02f, 1.250e+00f },
  443. {3.284e+03f, -1.922e+02f, 1.513e+00f },
  444. {3.284e+03f, -2.883e+02f, 3.242e+00f },
  445. {3.284e+03f, -4.325e+02f, 6.318e+00f },
  446. {3.284e+03f, -6.487e+02f, 1.354e+01f },
  447. {3.284e+03f, -9.731e+02f, 2.903e+01f },
  448. {3.284e+03f, -1.460e+03f, 6.223e+01f },
  449. {3.284e+03f, -2.189e+03f, 1.334e+02f },
  450. {3.284e+03f, -3.284e+03f, 2.600e+02f },
  451. {3.284e+03f, -4.926e+03f, 5.066e+02f },
  452. {3.284e+03f, -7.389e+03f, 9.872e+02f },
  453. {3.284e+03f, -1.108e+04f, 1.749e+03f },
  454. {3.284e+03f, -1.663e+04f, 3.098e+03f },
  455. {4.926e+03f, -7.500e+00f, 1.250e+00f },
  456. {4.926e+03f, -1.125e+01f, 1.250e+00f },
  457. {4.926e+03f, -1.688e+01f, 1.250e+00f },
  458. {4.926e+03f, -2.531e+01f, 1.250e+00f },
  459. {4.926e+03f, -3.797e+01f, 1.250e+00f },
  460. {4.926e+03f, -5.695e+01f, 1.250e+00f },
  461. {4.926e+03f, -8.543e+01f, 1.250e+00f },
  462. {4.926e+03f, -1.281e+02f, 1.250e+00f },
  463. {4.926e+03f, -1.922e+02f, 1.250e+00f },
  464. {4.926e+03f, -2.883e+02f, 2.013e+00f },
  465. {4.926e+03f, -4.325e+02f, 4.315e+00f },
  466. {4.926e+03f, -6.487e+02f, 9.250e+00f },
  467. {4.926e+03f, -9.731e+02f, 2.181e+01f },
  468. {4.926e+03f, -1.460e+03f, 4.250e+01f },
  469. {4.926e+03f, -2.189e+03f, 9.111e+01f },
  470. {4.926e+03f, -3.284e+03f, 1.953e+02f },
  471. {4.926e+03f, -4.926e+03f, 3.806e+02f },
  472. {4.926e+03f, -7.389e+03f, 7.417e+02f },
  473. {4.926e+03f, -1.108e+04f, 1.445e+03f },
  474. {4.926e+03f, -1.663e+04f, 2.561e+03f },
  475. {7.389e+03f, -7.500e+00f, 1.250e+00f },
  476. {7.389e+03f, -1.125e+01f, 1.250e+00f },
  477. {7.389e+03f, -1.688e+01f, 1.250e+00f },
  478. {7.389e+03f, -2.531e+01f, 1.250e+00f },
  479. {7.389e+03f, -3.797e+01f, 1.250e+00f },
  480. {7.389e+03f, -5.695e+01f, 1.250e+00f },
  481. {7.389e+03f, -8.543e+01f, 1.250e+00f },
  482. {7.389e+03f, -1.281e+02f, 1.250e+00f },
  483. {7.389e+03f, -1.922e+02f, 1.250e+00f },
  484. {7.389e+03f, -2.883e+02f, 1.375e+00f },
  485. {7.389e+03f, -4.325e+02f, 2.947e+00f },
  486. {7.389e+03f, -6.487e+02f, 6.318e+00f },
  487. {7.389e+03f, -9.731e+02f, 1.490e+01f },
  488. {7.389e+03f, -1.460e+03f, 3.193e+01f },
  489. {7.389e+03f, -2.189e+03f, 6.845e+01f },
  490. {7.389e+03f, -3.284e+03f, 1.334e+02f },
  491. {7.389e+03f, -4.926e+03f, 2.860e+02f },
  492. {7.389e+03f, -7.389e+03f, 5.572e+02f },
  493. {7.389e+03f, -1.108e+04f, 1.086e+03f },
  494. {7.389e+03f, -1.663e+04f, 2.116e+03f },
  495. {1.108e+04f, -7.500e+00f, 1.250e+00f },
  496. {1.108e+04f, -1.125e+01f, 1.250e+00f },
  497. {1.108e+04f, -1.688e+01f, 1.250e+00f },
  498. {1.108e+04f, -2.531e+01f, 1.250e+00f },
  499. {1.108e+04f, -3.797e+01f, 1.250e+00f },
  500. {1.108e+04f, -5.695e+01f, 1.250e+00f },
  501. {1.108e+04f, -8.543e+01f, 1.250e+00f },
  502. {1.108e+04f, -1.281e+02f, 1.250e+00f },
  503. {1.108e+04f, -1.922e+02f, 1.250e+00f },
  504. {1.108e+04f, -2.883e+02f, 1.250e+00f },
  505. {1.108e+04f, -4.325e+02f, 2.013e+00f },
  506. {1.108e+04f, -6.487e+02f, 4.315e+00f },
  507. {1.108e+04f, -9.731e+02f, 1.018e+01f },
  508. {1.108e+04f, -1.460e+03f, 2.181e+01f },
  509. {1.108e+04f, -2.189e+03f, 4.676e+01f },
  510. {1.108e+04f, -3.284e+03f, 1.002e+02f },
  511. {1.108e+04f, -4.926e+03f, 2.148e+02f },
  512. {1.108e+04f, -7.389e+03f, 4.187e+02f },
  513. {1.108e+04f, -1.108e+04f, 8.974e+02f },
  514. {1.108e+04f, -1.663e+04f, 1.749e+03f },
  515. {1.663e+04f, -7.500e+00f, 1.250e+00f },
  516. {1.663e+04f, -1.125e+01f, 1.250e+00f },
  517. {1.663e+04f, -1.688e+01f, 1.250e+00f },
  518. {1.663e+04f, -2.531e+01f, 1.250e+00f },
  519. {1.663e+04f, -3.797e+01f, 1.250e+00f },
  520. {1.663e+04f, -5.695e+01f, 1.250e+00f },
  521. {1.663e+04f, -8.543e+01f, 1.250e+00f },
  522. {1.663e+04f, -1.281e+02f, 1.250e+00f },
  523. {1.663e+04f, -1.922e+02f, 1.250e+00f },
  524. {1.663e+04f, -2.883e+02f, 1.250e+00f },
  525. {1.663e+04f, -4.325e+02f, 1.375e+00f },
  526. {1.663e+04f, -6.487e+02f, 2.947e+00f },
  527. {1.663e+04f, -9.731e+02f, 6.318e+00f },
  528. {1.663e+04f, -1.460e+03f, 1.490e+01f },
  529. {1.663e+04f, -2.189e+03f, 3.193e+01f },
  530. {1.663e+04f, -3.284e+03f, 6.845e+01f },
  531. {1.663e+04f, -4.926e+03f, 1.467e+02f },
  532. {1.663e+04f, -7.389e+03f, 3.145e+02f },
  533. {1.663e+04f, -1.108e+04f, 6.743e+02f },
  534. {1.663e+04f, -1.663e+04f, 1.314e+03f },
  535. };
  536. if ((a > 1.663e+04) || (-b > 1.663e+04))
  537. return z > -b; // Way overly conservative?
  538. if (a < data[0][0])
  539. return false;
  540. int index = 0;
  541. while (data[index][0] < a)
  542. ++index;
  543. if(a != data[index][0])
  544. --index;
  545. while ((data[index][1] < b) && (data[index][2] > 1.25))
  546. --index;
  547. ++index;
  548. BOOST_ASSERT(a > data[index][0]);
  549. BOOST_ASSERT(-b < -data[index][1]);
  550. return z > data[index][2];
  551. }
  552. template <class T, class Policy>
  553. T hypergeometric_1F1_from_function_ratio_negative_b_forwards(const T& a, const T& b, const T& z, const Policy& pol, int& log_scaling)
  554. {
  555. BOOST_MATH_STD_USING
  556. //
  557. // Get the function ratio, M(a+1, b+1, z)/M(a,b,z):
  558. //
  559. boost::uintmax_t max_iter = boost::math::policies::get_max_series_iterations<Policy>();
  560. boost::math::detail::hypergeometric_1F1_recurrence_a_and_b_coefficients<T> coef(a, b, z);
  561. T ratio = 1 / boost::math::tools::function_ratio_from_forwards_recurrence(coef, boost::math::policies::get_epsilon<T, Policy>(), max_iter);
  562. boost::math::policies::check_series_iterations<T>("boost::math::hypergeometric_1F1_from_function_ratio_negative_b_positive_a<%1%>(%1%,%1%,%1%)", max_iter, pol);
  563. //
  564. // We can't normalise via the Wronksian as the subtraction in the Wronksian will suffer an exquisite amount of cancellation -
  565. // potentially many hundreds of digits in this region. However, if forwards iteration is stable at this point
  566. // it will also be stable for M(a, b+1, z) etc all the way up to the origin, and hopefully one step beyond. So
  567. // use a reference value just over the origin to normalise:
  568. //
  569. int scale = 0;
  570. int steps = itrunc(ceil(-b));
  571. T reference_value = hypergeometric_1F1_imp(T(a + steps), T(b + steps), z, pol, log_scaling);
  572. T found = boost::math::tools::apply_recurrence_relation_forward(boost::math::detail::hypergeometric_1F1_recurrence_a_and_b_coefficients<T>(a + 1, b + 1, z), steps - 1, T(1), ratio, &scale);
  573. log_scaling -= scale;
  574. if ((fabs(reference_value) < 1) && (fabs(reference_value) < tools::min_value<T>() * fabs(found)))
  575. {
  576. // Possible underflow, rescale
  577. int s = itrunc(tools::log_max_value<T>());
  578. log_scaling -= s;
  579. reference_value *= exp(T(s));
  580. }
  581. else if ((fabs(found) < 1) && (fabs(reference_value) > tools::max_value<T>() * fabs(found)))
  582. {
  583. // Overflow, rescale:
  584. int s = itrunc(tools::log_max_value<T>());
  585. log_scaling += s;
  586. reference_value /= exp(T(s));
  587. }
  588. return reference_value / found;
  589. }
  590. //
  591. // This next version is largely the same as above, but calculates the ratio for the b recurrence relation
  592. // which has a larger area of stability than the ab recurrence when a,b < 0. We can then use a single
  593. // recurrence step to convert this to the ratio for the ab recursion and proceed largly as before.
  594. // The routine is quite insensitive to the size of z, but requires |a| < |5b| for accuracy.
  595. // Fortunately the accuracy outside this domain falls off steadily rather than suddenly switching
  596. // to a different behaviour.
  597. //
  598. template <class T, class Policy>
  599. T hypergeometric_1F1_from_function_ratio_negative_ab(const T& a, const T& b, const T& z, const Policy& pol, int& log_scaling)
  600. {
  601. BOOST_MATH_STD_USING
  602. //
  603. // Get the function ratio, M(a+1, b+1, z)/M(a,b,z):
  604. //
  605. boost::uintmax_t max_iter = boost::math::policies::get_max_series_iterations<Policy>();
  606. boost::math::detail::hypergeometric_1F1_recurrence_b_coefficients<T> coef(a, b + 1, z);
  607. T ratio = boost::math::tools::function_ratio_from_backwards_recurrence(coef, boost::math::policies::get_epsilon<T, Policy>(), max_iter);
  608. boost::math::policies::check_series_iterations<T>("boost::math::hypergeometric_1F1_from_function_ratio_negative_b_positive_a<%1%>(%1%,%1%,%1%)", max_iter, pol);
  609. //
  610. // We need to use A&S 13.4.3 to convert a ratio for M(a, b + 1, z) / M(a, b, z)
  611. // to M(a+1, b+1, z) / M(a, b, z)
  612. //
  613. // We have: (a-b)M(a, b+1, z) - aM(a+1, b+1, z) + bM(a, b, z) = 0
  614. // and therefore: M(a + 1, b + 1, z) / M(a, b, z) = ((a - b)M(a, b + 1, z) / M(a, b, z) + b) / a
  615. //
  616. ratio = ((a - b) * ratio + b) / a;
  617. //
  618. // Let M2 = M(1+a-b, 2-b, z)
  619. // This is going to be a mighty big number:
  620. //
  621. int local_scaling = 0;
  622. T M2 = boost::math::detail::hypergeometric_1F1_imp(T(1 + a - b), T(2 - b), z, pol, local_scaling);
  623. log_scaling -= local_scaling; // all the M2 terms are in the denominator
  624. //
  625. // Let M3 = M(1+a-b + 1, 2-b + 1, z)
  626. // We don't use the ratio to get this as it's not clear that it's reliable:
  627. //
  628. int local_scaling2 = 0;
  629. T M3 = boost::math::detail::hypergeometric_1F1_imp(T(2 + a - b), T(3 - b), z, pol, local_scaling2);
  630. //
  631. // M2 and M3 must be identically scaled:
  632. //
  633. if (local_scaling != local_scaling2)
  634. {
  635. M3 *= exp(T(local_scaling2 - local_scaling));
  636. }
  637. //
  638. // Get the RHS of the Wronksian:
  639. //
  640. int fz = itrunc(z);
  641. log_scaling += fz;
  642. T rhs = (1 - b) * exp(z - fz);
  643. //
  644. // We need to divide that by:
  645. // [(a-b+1)z/(2-b) M2(a+1,b+1,z) + (1-b) M2(a,b,z) - a/b z^b R(a,b,z) M2(a,b,z) ]
  646. // Note that at this stage, both M3 and M2 are scaled by exp(local_scaling).
  647. //
  648. T lhs = (a - b + 1) * z * M3 / (2 - b) + (1 - b) * M2 - a * z * ratio * M2 / b;
  649. return rhs / lhs;
  650. }
  651. } } } // namespaces
  652. #endif // BOOST_HYPERGEOMETRIC_1F1_BY_RATIOS_HPP_