bessel_k0.hpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519
  1. // Copyright (c) 2006 Xiaogang Zhang
  2. // Copyright (c) 2017 John Maddock
  3. // Use, modification and distribution are subject to the
  4. // Boost 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_MATH_BESSEL_K0_HPP
  7. #define BOOST_MATH_BESSEL_K0_HPP
  8. #ifdef _MSC_VER
  9. #pragma once
  10. #pragma warning(push)
  11. #pragma warning(disable:4702) // Unreachable code (release mode only warning)
  12. #endif
  13. #include <boost/math/tools/rational.hpp>
  14. #include <boost/math/tools/big_constant.hpp>
  15. #include <boost/math/policies/error_handling.hpp>
  16. #include <boost/assert.hpp>
  17. #if defined(__GNUC__) && defined(BOOST_MATH_USE_FLOAT128)
  18. //
  19. // This is the only way we can avoid
  20. // warning: non-standard suffix on floating constant [-Wpedantic]
  21. // when building with -Wall -pedantic. Neither __extension__
  22. // nor #pragma dianostic ignored work :(
  23. //
  24. #pragma GCC system_header
  25. #endif
  26. // Modified Bessel function of the second kind of order zero
  27. // minimax rational approximations on intervals, see
  28. // Russon and Blair, Chalk River Report AECL-3461, 1969,
  29. // as revised by Pavel Holoborodko in "Rational Approximations
  30. // for the Modified Bessel Function of the Second Kind - K0(x)
  31. // for Computations with Double Precision", see
  32. // http://www.advanpix.com/2015/11/25/rational-approximations-for-the-modified-bessel-function-of-the-second-kind-k0-for-computations-with-double-precision/
  33. //
  34. // The actual coefficients used are our own derivation (by JM)
  35. // since we extend to both greater and lesser precision than the
  36. // references above. We can also improve performance WRT to
  37. // Holoborodko without loss of precision.
  38. namespace boost { namespace math { namespace detail{
  39. template <typename T>
  40. T bessel_k0(const T& x);
  41. template <class T, class tag>
  42. struct bessel_k0_initializer
  43. {
  44. struct init
  45. {
  46. init()
  47. {
  48. do_init(tag());
  49. }
  50. static void do_init(const mpl::int_<113>&)
  51. {
  52. bessel_k0(T(0.5));
  53. bessel_k0(T(1.5));
  54. }
  55. static void do_init(const mpl::int_<64>&)
  56. {
  57. bessel_k0(T(0.5));
  58. bessel_k0(T(1.5));
  59. }
  60. template <class U>
  61. static void do_init(const U&){}
  62. void force_instantiate()const{}
  63. };
  64. static const init initializer;
  65. static void force_instantiate()
  66. {
  67. initializer.force_instantiate();
  68. }
  69. };
  70. template <class T, class tag>
  71. const typename bessel_k0_initializer<T, tag>::init bessel_k0_initializer<T, tag>::initializer;
  72. template <typename T, int N>
  73. T bessel_k0_imp(const T& x, const mpl::int_<N>&)
  74. {
  75. BOOST_ASSERT(0);
  76. return 0;
  77. }
  78. template <typename T>
  79. T bessel_k0_imp(const T& x, const mpl::int_<24>&)
  80. {
  81. BOOST_MATH_STD_USING
  82. if(x <= 1)
  83. {
  84. // Maximum Deviation Found : 2.358e-09
  85. // Expected Error Term : -2.358e-09
  86. // Maximum Relative Change in Control Points : 9.552e-02
  87. // Max Error found at float precision = Poly : 4.448220e-08
  88. static const T Y = 1.137250900268554688f;
  89. static const T P[] =
  90. {
  91. -1.372508979104259711e-01f,
  92. 2.622545986273687617e-01f,
  93. 5.047103728247919836e-03f
  94. };
  95. static const T Q[] =
  96. {
  97. 1.000000000000000000e+00f,
  98. -8.928694018000029415e-02f,
  99. 2.985980684180969241e-03f
  100. };
  101. T a = x * x / 4;
  102. a = (tools::evaluate_rational(P, Q, a) + Y) * a + 1;
  103. // Maximum Deviation Found: 1.346e-09
  104. // Expected Error Term : -1.343e-09
  105. // Maximum Relative Change in Control Points : 2.405e-02
  106. // Max Error found at float precision = Poly : 1.354814e-07
  107. static const T P2[] = {
  108. 1.159315158e-01f,
  109. 2.789828686e-01f,
  110. 2.524902861e-02f,
  111. 8.457241514e-04f,
  112. 1.530051997e-05f
  113. };
  114. return tools::evaluate_polynomial(P2, T(x * x)) - log(x) * a;
  115. }
  116. else
  117. {
  118. // Maximum Deviation Found: 1.587e-08
  119. // Expected Error Term : 1.531e-08
  120. // Maximum Relative Change in Control Points : 9.064e-02
  121. // Max Error found at float precision = Poly : 5.065020e-08
  122. static const T P[] =
  123. {
  124. 2.533141220e-01f,
  125. 5.221502603e-01f,
  126. 6.380180669e-02f,
  127. -5.934976547e-02f
  128. };
  129. static const T Q[] =
  130. {
  131. 1.000000000e+00f,
  132. 2.679722431e+00f,
  133. 1.561635813e+00f,
  134. 1.573660661e-01f
  135. };
  136. if(x < tools::log_max_value<T>())
  137. return ((tools::evaluate_rational(P, Q, T(1 / x)) + 1) * exp(-x) / sqrt(x));
  138. else
  139. {
  140. T ex = exp(-x / 2);
  141. return ((tools::evaluate_rational(P, Q, T(1 / x)) + 1) * ex / sqrt(x)) * ex;
  142. }
  143. }
  144. }
  145. template <typename T>
  146. T bessel_k0_imp(const T& x, const mpl::int_<53>&)
  147. {
  148. BOOST_MATH_STD_USING
  149. if(x <= 1)
  150. {
  151. // Maximum Deviation Found: 6.077e-17
  152. // Expected Error Term : -6.077e-17
  153. // Maximum Relative Change in Control Points : 7.797e-02
  154. // Max Error found at double precision = Poly : 1.003156e-16
  155. static const T Y = 1.137250900268554688;
  156. static const T P[] =
  157. {
  158. -1.372509002685546267e-01,
  159. 2.574916117833312855e-01,
  160. 1.395474602146869316e-02,
  161. 5.445476986653926759e-04,
  162. 7.125159422136622118e-06
  163. };
  164. static const T Q[] =
  165. {
  166. 1.000000000000000000e+00,
  167. -5.458333438017788530e-02,
  168. 1.291052816975251298e-03,
  169. -1.367653946978586591e-05
  170. };
  171. T a = x * x / 4;
  172. a = (tools::evaluate_polynomial(P, a) / tools::evaluate_polynomial(Q, a) + Y) * a + 1;
  173. // Maximum Deviation Found: 3.429e-18
  174. // Expected Error Term : 3.392e-18
  175. // Maximum Relative Change in Control Points : 2.041e-02
  176. // Max Error found at double precision = Poly : 2.513112e-16
  177. static const T P2[] =
  178. {
  179. 1.159315156584124484e-01,
  180. 2.789828789146031732e-01,
  181. 2.524892993216121934e-02,
  182. 8.460350907213637784e-04,
  183. 1.491471924309617534e-05,
  184. 1.627106892422088488e-07,
  185. 1.208266102392756055e-09,
  186. 6.611686391749704310e-12
  187. };
  188. return tools::evaluate_polynomial(P2, T(x * x)) - log(x) * a;
  189. }
  190. else
  191. {
  192. // Maximum Deviation Found: 4.316e-17
  193. // Expected Error Term : 9.570e-18
  194. // Maximum Relative Change in Control Points : 2.757e-01
  195. // Max Error found at double precision = Poly : 1.001560e-16
  196. static const T Y = 1;
  197. static const T P[] =
  198. {
  199. 2.533141373155002416e-01,
  200. 3.628342133984595192e+00,
  201. 1.868441889406606057e+01,
  202. 4.306243981063412784e+01,
  203. 4.424116209627428189e+01,
  204. 1.562095339356220468e+01,
  205. -1.810138978229410898e+00,
  206. -1.414237994269995877e+00,
  207. -9.369168119754924625e-02
  208. };
  209. static const T Q[] =
  210. {
  211. 1.000000000000000000e+00,
  212. 1.494194694879908328e+01,
  213. 8.265296455388554217e+01,
  214. 2.162779506621866970e+02,
  215. 2.845145155184222157e+02,
  216. 1.851714491916334995e+02,
  217. 5.486540717439723515e+01,
  218. 6.118075837628957015e+00,
  219. 1.586261269326235053e-01
  220. };
  221. if(x < tools::log_max_value<T>())
  222. return ((tools::evaluate_rational(P, Q, T(1 / x)) + Y) * exp(-x) / sqrt(x));
  223. else
  224. {
  225. T ex = exp(-x / 2);
  226. return ((tools::evaluate_rational(P, Q, T(1 / x)) + Y) * ex / sqrt(x)) * ex;
  227. }
  228. }
  229. }
  230. template <typename T>
  231. T bessel_k0_imp(const T& x, const mpl::int_<64>&)
  232. {
  233. BOOST_MATH_STD_USING
  234. if(x <= 1)
  235. {
  236. // Maximum Deviation Found: 2.180e-22
  237. // Expected Error Term : 2.180e-22
  238. // Maximum Relative Change in Control Points : 2.943e-01
  239. // Max Error found at float80 precision = Poly : 3.923207e-20
  240. static const T Y = 1.137250900268554687500e+00;
  241. static const T P[] =
  242. {
  243. BOOST_MATH_BIG_CONSTANT(T, 64, -1.372509002685546875002e-01),
  244. BOOST_MATH_BIG_CONSTANT(T, 64, 2.566481981037407600436e-01),
  245. BOOST_MATH_BIG_CONSTANT(T, 64, 1.551881122448948854873e-02),
  246. BOOST_MATH_BIG_CONSTANT(T, 64, 6.646112454323276529650e-04),
  247. BOOST_MATH_BIG_CONSTANT(T, 64, 1.213747930378196492543e-05),
  248. BOOST_MATH_BIG_CONSTANT(T, 64, 9.423709328020389560844e-08)
  249. };
  250. static const T Q[] =
  251. {
  252. BOOST_MATH_BIG_CONSTANT(T, 64, 1.000000000000000000000e+00),
  253. BOOST_MATH_BIG_CONSTANT(T, 64, -4.843828412587773008342e-02),
  254. BOOST_MATH_BIG_CONSTANT(T, 64, 1.088484822515098936140e-03),
  255. BOOST_MATH_BIG_CONSTANT(T, 64, -1.374724008530702784829e-05),
  256. BOOST_MATH_BIG_CONSTANT(T, 64, 8.452665455952581680339e-08)
  257. };
  258. T a = x * x / 4;
  259. a = (tools::evaluate_polynomial(P, a) / tools::evaluate_polynomial(Q, a) + Y) * a + 1;
  260. // Maximum Deviation Found: 2.440e-21
  261. // Expected Error Term : -2.434e-21
  262. // Maximum Relative Change in Control Points : 2.459e-02
  263. // Max Error found at float80 precision = Poly : 1.482487e-19
  264. static const T P2[] =
  265. {
  266. BOOST_MATH_BIG_CONSTANT(T, 64, 1.159315156584124488110e-01),
  267. BOOST_MATH_BIG_CONSTANT(T, 64, 2.764832791416047889734e-01),
  268. BOOST_MATH_BIG_CONSTANT(T, 64, 1.926062887220923354112e-02),
  269. BOOST_MATH_BIG_CONSTANT(T, 64, 3.660777862036966089410e-04),
  270. BOOST_MATH_BIG_CONSTANT(T, 64, 2.094942446930673386849e-06)
  271. };
  272. static const T Q2[] =
  273. {
  274. BOOST_MATH_BIG_CONSTANT(T, 64, 1.000000000000000000000e+00),
  275. BOOST_MATH_BIG_CONSTANT(T, 64, -2.156100313881251616320e-02),
  276. BOOST_MATH_BIG_CONSTANT(T, 64, 2.315993873344905957033e-04),
  277. BOOST_MATH_BIG_CONSTANT(T, 64, -1.529444499350703363451e-06),
  278. BOOST_MATH_BIG_CONSTANT(T, 64, 5.524988589917857531177e-09)
  279. };
  280. return tools::evaluate_rational(P2, Q2, T(x * x)) - log(x) * a;
  281. }
  282. else
  283. {
  284. // Maximum Deviation Found: 4.291e-20
  285. // Expected Error Term : 2.236e-21
  286. // Maximum Relative Change in Control Points : 3.021e-01
  287. //Max Error found at float80 precision = Poly : 8.727378e-20
  288. static const T Y = 1;
  289. static const T P[] =
  290. {
  291. BOOST_MATH_BIG_CONSTANT(T, 64, 2.533141373155002512056e-01),
  292. BOOST_MATH_BIG_CONSTANT(T, 64, 5.417942070721928652715e+00),
  293. BOOST_MATH_BIG_CONSTANT(T, 64, 4.477464607463971754433e+01),
  294. BOOST_MATH_BIG_CONSTANT(T, 64, 1.838745728725943889876e+02),
  295. BOOST_MATH_BIG_CONSTANT(T, 64, 4.009736314927811202517e+02),
  296. BOOST_MATH_BIG_CONSTANT(T, 64, 4.557411293123609803452e+02),
  297. BOOST_MATH_BIG_CONSTANT(T, 64, 2.360222564015361268955e+02),
  298. BOOST_MATH_BIG_CONSTANT(T, 64, 2.385435333168505701022e+01),
  299. BOOST_MATH_BIG_CONSTANT(T, 64, -1.750195760942181592050e+01),
  300. BOOST_MATH_BIG_CONSTANT(T, 64, -4.059789241612946683713e+00),
  301. BOOST_MATH_BIG_CONSTANT(T, 64, -1.612783121537333908889e-01)
  302. };
  303. static const T Q[] =
  304. {
  305. BOOST_MATH_BIG_CONSTANT(T, 64, 1.000000000000000000000e+00),
  306. BOOST_MATH_BIG_CONSTANT(T, 64, 2.200669254769325861404e+01),
  307. BOOST_MATH_BIG_CONSTANT(T, 64, 1.900177593527144126549e+02),
  308. BOOST_MATH_BIG_CONSTANT(T, 64, 8.361003989965786932682e+02),
  309. BOOST_MATH_BIG_CONSTANT(T, 64, 2.041319870804843395893e+03),
  310. BOOST_MATH_BIG_CONSTANT(T, 64, 2.828491555113790345068e+03),
  311. BOOST_MATH_BIG_CONSTANT(T, 64, 2.190342229261529076624e+03),
  312. BOOST_MATH_BIG_CONSTANT(T, 64, 9.003330795963812219852e+02),
  313. BOOST_MATH_BIG_CONSTANT(T, 64, 1.773371397243777891569e+02),
  314. BOOST_MATH_BIG_CONSTANT(T, 64, 1.368634935531158398439e+01),
  315. BOOST_MATH_BIG_CONSTANT(T, 64, 2.543310879400359967327e-01)
  316. };
  317. if(x < tools::log_max_value<T>())
  318. return ((tools::evaluate_rational(P, Q, T(1 / x)) + Y) * exp(-x) / sqrt(x));
  319. else
  320. {
  321. T ex = exp(-x / 2);
  322. return ((tools::evaluate_rational(P, Q, T(1 / x)) + Y) * ex / sqrt(x)) * ex;
  323. }
  324. }
  325. }
  326. template <typename T>
  327. T bessel_k0_imp(const T& x, const mpl::int_<113>&)
  328. {
  329. BOOST_MATH_STD_USING
  330. if(x <= 1)
  331. {
  332. // Maximum Deviation Found: 5.682e-37
  333. // Expected Error Term : 5.682e-37
  334. // Maximum Relative Change in Control Points : 6.094e-04
  335. // Max Error found at float128 precision = Poly : 5.338213e-35
  336. static const T Y = 1.137250900268554687500000000000000000e+00f;
  337. static const T P[] =
  338. {
  339. BOOST_MATH_BIG_CONSTANT(T, 113, -1.372509002685546875000000000000000006e-01),
  340. BOOST_MATH_BIG_CONSTANT(T, 113, 2.556212905071072782462974351698081303e-01),
  341. BOOST_MATH_BIG_CONSTANT(T, 113, 1.742459135264203478530904179889103929e-02),
  342. BOOST_MATH_BIG_CONSTANT(T, 113, 8.077860530453688571555479526961318918e-04),
  343. BOOST_MATH_BIG_CONSTANT(T, 113, 1.868173911669241091399374307788635148e-05),
  344. BOOST_MATH_BIG_CONSTANT(T, 113, 2.496405768838992243478709145123306602e-07),
  345. BOOST_MATH_BIG_CONSTANT(T, 113, 1.752489221949580551692915881999762125e-09),
  346. BOOST_MATH_BIG_CONSTANT(T, 113, 5.243010555737173524710512824955368526e-12)
  347. };
  348. static const T Q[] =
  349. {
  350. BOOST_MATH_BIG_CONSTANT(T, 113, 1.000000000000000000000000000000000000e+00),
  351. BOOST_MATH_BIG_CONSTANT(T, 113, -4.095631064064621099785696980653193721e-02),
  352. BOOST_MATH_BIG_CONSTANT(T, 113, 8.313880983725212151967078809725835532e-04),
  353. BOOST_MATH_BIG_CONSTANT(T, 113, -1.095229912293480063501285562382835142e-05),
  354. BOOST_MATH_BIG_CONSTANT(T, 113, 1.022828799511943141130509410251996277e-07),
  355. BOOST_MATH_BIG_CONSTANT(T, 113, -6.860874007419812445494782795829046836e-10),
  356. BOOST_MATH_BIG_CONSTANT(T, 113, 3.107297802344970725756092082686799037e-12),
  357. BOOST_MATH_BIG_CONSTANT(T, 113, -7.460529579244623559164763757787600944e-15)
  358. };
  359. T a = x * x / 4;
  360. a = (tools::evaluate_rational(P, Q, a) + Y) * a + 1;
  361. // Maximum Deviation Found: 5.173e-38
  362. // Expected Error Term : 5.105e-38
  363. // Maximum Relative Change in Control Points : 9.734e-03
  364. // Max Error found at float128 precision = Poly : 1.688806e-34
  365. static const T P2[] =
  366. {
  367. BOOST_MATH_BIG_CONSTANT(T, 113, 1.159315156584124488107200313757741370e-01),
  368. BOOST_MATH_BIG_CONSTANT(T, 113, 2.789828789146031122026800078439435369e-01),
  369. BOOST_MATH_BIG_CONSTANT(T, 113, 2.524892993216269451266750049024628432e-02),
  370. BOOST_MATH_BIG_CONSTANT(T, 113, 8.460350907082229957222453839935101823e-04),
  371. BOOST_MATH_BIG_CONSTANT(T, 113, 1.491471929926042875260452849503857976e-05),
  372. BOOST_MATH_BIG_CONSTANT(T, 113, 1.627105610481598430816014719558896866e-07),
  373. BOOST_MATH_BIG_CONSTANT(T, 113, 1.208426165007797264194914898538250281e-09),
  374. BOOST_MATH_BIG_CONSTANT(T, 113, 6.508697838747354949164182457073784117e-12),
  375. BOOST_MATH_BIG_CONSTANT(T, 113, 2.659784680639805301101014383907273109e-14),
  376. BOOST_MATH_BIG_CONSTANT(T, 113, 8.531090131964391104248859415958109654e-17),
  377. BOOST_MATH_BIG_CONSTANT(T, 113, 2.205195117066478034260323124669936314e-19),
  378. BOOST_MATH_BIG_CONSTANT(T, 113, 4.692219280289030165761119775783115426e-22),
  379. BOOST_MATH_BIG_CONSTANT(T, 113, 8.362350161092532344171965861545860747e-25),
  380. BOOST_MATH_BIG_CONSTANT(T, 113, 1.277990623924628999539014980773738258e-27)
  381. };
  382. return tools::evaluate_polynomial(P2, T(x * x)) - log(x) * a;
  383. }
  384. else
  385. {
  386. // Maximum Deviation Found: 1.462e-34
  387. // Expected Error Term : 4.917e-40
  388. // Maximum Relative Change in Control Points : 3.385e-01
  389. // Max Error found at float128 precision = Poly : 1.567573e-34
  390. static const T Y = 1;
  391. static const T P[] =
  392. {
  393. BOOST_MATH_BIG_CONSTANT(T, 113, 2.533141373155002512078826424055226265e-01),
  394. BOOST_MATH_BIG_CONSTANT(T, 113, 2.001949740768235770078339977110749204e+01),
  395. BOOST_MATH_BIG_CONSTANT(T, 113, 6.991516715983883248363351472378349986e+02),
  396. BOOST_MATH_BIG_CONSTANT(T, 113, 1.429587951594593159075690819360687720e+04),
  397. BOOST_MATH_BIG_CONSTANT(T, 113, 1.911933815201948768044660065771258450e+05),
  398. BOOST_MATH_BIG_CONSTANT(T, 113, 1.769943016204926614862175317962439875e+06),
  399. BOOST_MATH_BIG_CONSTANT(T, 113, 1.170866154649560750500954150401105606e+07),
  400. BOOST_MATH_BIG_CONSTANT(T, 113, 5.634687099724383996792011977705727661e+07),
  401. BOOST_MATH_BIG_CONSTANT(T, 113, 1.989524036456492581597607246664394014e+08),
  402. BOOST_MATH_BIG_CONSTANT(T, 113, 5.160394785715328062088529400178080360e+08),
  403. BOOST_MATH_BIG_CONSTANT(T, 113, 9.778173054417826368076483100902201433e+08),
  404. BOOST_MATH_BIG_CONSTANT(T, 113, 1.335667778588806892764139643950439733e+09),
  405. BOOST_MATH_BIG_CONSTANT(T, 113, 1.283635100080306980206494425043706838e+09),
  406. BOOST_MATH_BIG_CONSTANT(T, 113, 8.300616188213640626577036321085025855e+08),
  407. BOOST_MATH_BIG_CONSTANT(T, 113, 3.277591957076162984986406540894621482e+08),
  408. BOOST_MATH_BIG_CONSTANT(T, 113, 5.564360536834214058158565361486115932e+07),
  409. BOOST_MATH_BIG_CONSTANT(T, 113, -1.043505161612403359098596828115690596e+07),
  410. BOOST_MATH_BIG_CONSTANT(T, 113, -7.217035248223503605127967970903027314e+06),
  411. BOOST_MATH_BIG_CONSTANT(T, 113, -1.422938158797326748375799596769964430e+06),
  412. BOOST_MATH_BIG_CONSTANT(T, 113, -1.229125746200586805278634786674745210e+05),
  413. BOOST_MATH_BIG_CONSTANT(T, 113, -4.201632288615609937883545928660649813e+03),
  414. BOOST_MATH_BIG_CONSTANT(T, 113, -3.690820607338480548346746717311811406e+01)
  415. };
  416. static const T Q[] =
  417. {
  418. BOOST_MATH_BIG_CONSTANT(T, 113, 1.000000000000000000000000000000000000e+00),
  419. BOOST_MATH_BIG_CONSTANT(T, 113, 7.964877874035741452203497983642653107e+01),
  420. BOOST_MATH_BIG_CONSTANT(T, 113, 2.808929943826193766839360018583294769e+03),
  421. BOOST_MATH_BIG_CONSTANT(T, 113, 5.814524004679994110944366890912384139e+04),
  422. BOOST_MATH_BIG_CONSTANT(T, 113, 7.897794522506725610540209610337355118e+05),
  423. BOOST_MATH_BIG_CONSTANT(T, 113, 7.456339470955813675629523617440433672e+06),
  424. BOOST_MATH_BIG_CONSTANT(T, 113, 5.057818717813969772198911392875127212e+07),
  425. BOOST_MATH_BIG_CONSTANT(T, 113, 2.513821619536852436424913886081133209e+08),
  426. BOOST_MATH_BIG_CONSTANT(T, 113, 9.255938846873380596038513316919990776e+08),
  427. BOOST_MATH_BIG_CONSTANT(T, 113, 2.537077551699028079347581816919572141e+09),
  428. BOOST_MATH_BIG_CONSTANT(T, 113, 5.176769339768120752974843214652367321e+09),
  429. BOOST_MATH_BIG_CONSTANT(T, 113, 7.828722317390455845253191337207432060e+09),
  430. BOOST_MATH_BIG_CONSTANT(T, 113, 8.698864296569996402006511705803675890e+09),
  431. BOOST_MATH_BIG_CONSTANT(T, 113, 7.007803261356636409943826918468544629e+09),
  432. BOOST_MATH_BIG_CONSTANT(T, 113, 4.016564631288740308993071395104715469e+09),
  433. BOOST_MATH_BIG_CONSTANT(T, 113, 1.595893010619754750655947035567624730e+09),
  434. BOOST_MATH_BIG_CONSTANT(T, 113, 4.241241839120481076862742189989406856e+08),
  435. BOOST_MATH_BIG_CONSTANT(T, 113, 7.168778094393076220871007550235840858e+07),
  436. BOOST_MATH_BIG_CONSTANT(T, 113, 7.156200301360388147635052029404211109e+06),
  437. BOOST_MATH_BIG_CONSTANT(T, 113, 3.752130382550379886741949463587008794e+05),
  438. BOOST_MATH_BIG_CONSTANT(T, 113, 8.370574966987293592457152146806662562e+03),
  439. BOOST_MATH_BIG_CONSTANT(T, 113, 4.871254714311063594080644835895740323e+01)
  440. };
  441. if(x < tools::log_max_value<T>())
  442. return ((tools::evaluate_rational(P, Q, T(1 / x)) + Y) * exp(-x) / sqrt(x));
  443. else
  444. {
  445. T ex = exp(-x / 2);
  446. return ((tools::evaluate_rational(P, Q, T(1 / x)) + Y) * ex / sqrt(x)) * ex;
  447. }
  448. }
  449. }
  450. template <typename T>
  451. T bessel_k0_imp(const T& x, const mpl::int_<0>&)
  452. {
  453. if(boost::math::tools::digits<T>() <= 24)
  454. return bessel_k0_imp(x, mpl::int_<24>());
  455. else if(boost::math::tools::digits<T>() <= 53)
  456. return bessel_k0_imp(x, mpl::int_<53>());
  457. else if(boost::math::tools::digits<T>() <= 64)
  458. return bessel_k0_imp(x, mpl::int_<64>());
  459. else if(boost::math::tools::digits<T>() <= 113)
  460. return bessel_k0_imp(x, mpl::int_<113>());
  461. BOOST_ASSERT(0);
  462. return 0;
  463. }
  464. template <typename T>
  465. inline T bessel_k0(const T& x)
  466. {
  467. typedef mpl::int_<
  468. ((std::numeric_limits<T>::digits == 0) || (std::numeric_limits<T>::radix != 2)) ?
  469. 0 :
  470. std::numeric_limits<T>::digits <= 24 ?
  471. 24 :
  472. std::numeric_limits<T>::digits <= 53 ?
  473. 53 :
  474. std::numeric_limits<T>::digits <= 64 ?
  475. 64 :
  476. std::numeric_limits<T>::digits <= 113 ?
  477. 113 : -1
  478. > tag_type;
  479. bessel_k0_initializer<T, tag_type>::force_instantiate();
  480. return bessel_k0_imp(x, tag_type());
  481. }
  482. }}} // namespaces
  483. #ifdef _MSC_VER
  484. #pragma warning(pop)
  485. #endif
  486. #endif // BOOST_MATH_BESSEL_K0_HPP