bessel_i1.hpp 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592
  1. // Copyright (c) 2017 John Maddock
  2. // Use, modification and distribution are subject to the
  3. // Boost Software License, Version 1.0. (See accompanying file
  4. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. // Modified Bessel function of the first kind of order zero
  6. // we use the approximating forms derived in:
  7. // "Rational Approximations for the Modified Bessel Function of the First Kind - I1(x) for Computations with Double Precision"
  8. // by Pavel Holoborodko,
  9. // see http://www.advanpix.com/2015/11/12/rational-approximations-for-the-modified-bessel-function-of-the-first-kind-i1-for-computations-with-double-precision/
  10. // The actual coefficients used are our own, and extend Pavel's work to precision's other than double.
  11. #ifndef BOOST_MATH_BESSEL_I1_HPP
  12. #define BOOST_MATH_BESSEL_I1_HPP
  13. #ifdef _MSC_VER
  14. #pragma once
  15. #endif
  16. #include <boost/math/tools/rational.hpp>
  17. #include <boost/math/tools/big_constant.hpp>
  18. #include <boost/assert.hpp>
  19. #if defined(__GNUC__) && defined(BOOST_MATH_USE_FLOAT128)
  20. //
  21. // This is the only way we can avoid
  22. // warning: non-standard suffix on floating constant [-Wpedantic]
  23. // when building with -Wall -pedantic. Neither __extension__
  24. // nor #pragma dianostic ignored work :(
  25. //
  26. #pragma GCC system_header
  27. #endif
  28. // Modified Bessel function of the first kind of order one
  29. // minimax rational approximations on intervals, see
  30. // Blair and Edwards, Chalk River Report AECL-4928, 1974
  31. namespace boost { namespace math { namespace detail{
  32. template <typename T>
  33. T bessel_i1(const T& x);
  34. template <class T, class tag>
  35. struct bessel_i1_initializer
  36. {
  37. struct init
  38. {
  39. init()
  40. {
  41. do_init(tag());
  42. }
  43. static void do_init(const mpl::int_<64>&)
  44. {
  45. bessel_i1(T(1));
  46. bessel_i1(T(15));
  47. bessel_i1(T(80));
  48. bessel_i1(T(101));
  49. }
  50. static void do_init(const mpl::int_<113>&)
  51. {
  52. bessel_i1(T(1));
  53. bessel_i1(T(10));
  54. bessel_i1(T(14));
  55. bessel_i1(T(19));
  56. bessel_i1(T(34));
  57. bessel_i1(T(99));
  58. bessel_i1(T(101));
  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_i1_initializer<T, tag>::init bessel_i1_initializer<T, tag>::initializer;
  72. template <typename T, int N>
  73. T bessel_i1_imp(const T&, const mpl::int_<N>&)
  74. {
  75. BOOST_ASSERT(0);
  76. return 0;
  77. }
  78. template <typename T>
  79. T bessel_i1_imp(const T& x, const mpl::int_<24>&)
  80. {
  81. BOOST_MATH_STD_USING
  82. if(x < 7.75)
  83. {
  84. //Max error in interpolated form : 1.348e-08
  85. // Max Error found at float precision = Poly : 1.469121e-07
  86. static const float P[] = {
  87. 8.333333221e-02f,
  88. 6.944453712e-03f,
  89. 3.472097211e-04f,
  90. 1.158047174e-05f,
  91. 2.739745142e-07f,
  92. 5.135884609e-09f,
  93. 5.262251502e-11f,
  94. 1.331933703e-12f
  95. };
  96. T a = x * x / 4;
  97. T Q[3] = { 1, 0.5f, boost::math::tools::evaluate_polynomial(P, a) };
  98. return x * boost::math::tools::evaluate_polynomial(Q, a) / 2;
  99. }
  100. else
  101. {
  102. // Max error in interpolated form: 9.000e-08
  103. // Max Error found at float precision = Poly: 1.044345e-07
  104. static const float P[] = {
  105. 3.98942115977513013e-01f,
  106. -1.49581264836620262e-01f,
  107. -4.76475741878486795e-02f,
  108. -2.65157315524784407e-02f,
  109. -1.47148600683672014e-01f
  110. };
  111. T ex = exp(x / 2);
  112. T result = ex * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);
  113. result *= ex;
  114. return result;
  115. }
  116. }
  117. template <typename T>
  118. T bessel_i1_imp(const T& x, const mpl::int_<53>&)
  119. {
  120. BOOST_MATH_STD_USING
  121. if(x < 7.75)
  122. {
  123. // Bessel I0 over[10 ^ -16, 7.75]
  124. // Max error in interpolated form: 5.639e-17
  125. // Max Error found at double precision = Poly: 1.795559e-16
  126. static const double P[] = {
  127. 8.333333333333333803e-02,
  128. 6.944444444444341983e-03,
  129. 3.472222222225921045e-04,
  130. 1.157407407354987232e-05,
  131. 2.755731926254790268e-07,
  132. 4.920949692800671435e-09,
  133. 6.834657311305621830e-11,
  134. 7.593969849687574339e-13,
  135. 6.904822652741917551e-15,
  136. 5.220157095351373194e-17,
  137. 3.410720494727771276e-19,
  138. 1.625212890947171108e-21,
  139. 1.332898928162290861e-23
  140. };
  141. T a = x * x / 4;
  142. T Q[3] = { 1, 0.5f, boost::math::tools::evaluate_polynomial(P, a) };
  143. return x * boost::math::tools::evaluate_polynomial(Q, a) / 2;
  144. }
  145. else if(x < 500)
  146. {
  147. // Max error in interpolated form: 1.796e-16
  148. // Max Error found at double precision = Poly: 2.898731e-16
  149. static const double P[] = {
  150. 3.989422804014406054e-01,
  151. -1.496033551613111533e-01,
  152. -4.675104253598537322e-02,
  153. -4.090895951581637791e-02,
  154. -5.719036414430205390e-02,
  155. -1.528189554374492735e-01,
  156. 3.458284470977172076e+00,
  157. -2.426181371595021021e+02,
  158. 1.178785865993440669e+04,
  159. -4.404655582443487334e+05,
  160. 1.277677779341446497e+07,
  161. -2.903390398236656519e+08,
  162. 5.192386898222206474e+09,
  163. -7.313784438967834057e+10,
  164. 8.087824484994859552e+11,
  165. -6.967602516005787001e+12,
  166. 4.614040809616582764e+13,
  167. -2.298849639457172489e+14,
  168. 8.325554073334618015e+14,
  169. -2.067285045778906105e+15,
  170. 3.146401654361325073e+15,
  171. -2.213318202179221945e+15
  172. };
  173. return exp(x) * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);
  174. }
  175. else
  176. {
  177. // Max error in interpolated form: 1.320e-19
  178. // Max Error found at double precision = Poly: 7.065357e-17
  179. static const double P[] = {
  180. 3.989422804014314820e-01,
  181. -1.496033551467584157e-01,
  182. -4.675105322571775911e-02,
  183. -4.090421597376992892e-02,
  184. -5.843630344778927582e-02
  185. };
  186. T ex = exp(x / 2);
  187. T result = ex * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);
  188. result *= ex;
  189. return result;
  190. }
  191. }
  192. template <typename T>
  193. T bessel_i1_imp(const T& x, const mpl::int_<64>&)
  194. {
  195. BOOST_MATH_STD_USING
  196. if(x < 7.75)
  197. {
  198. // Bessel I0 over[10 ^ -16, 7.75]
  199. // Max error in interpolated form: 8.086e-21
  200. // Max Error found at float80 precision = Poly: 7.225090e-20
  201. static const T P[] = {
  202. BOOST_MATH_BIG_CONSTANT(T, 64, 8.33333333333333333340071817e-02),
  203. BOOST_MATH_BIG_CONSTANT(T, 64, 6.94444444444444442462728070e-03),
  204. BOOST_MATH_BIG_CONSTANT(T, 64, 3.47222222222222318886683883e-04),
  205. BOOST_MATH_BIG_CONSTANT(T, 64, 1.15740740740738880709555060e-05),
  206. BOOST_MATH_BIG_CONSTANT(T, 64, 2.75573192240046222242685145e-07),
  207. BOOST_MATH_BIG_CONSTANT(T, 64, 4.92094986131253986838697503e-09),
  208. BOOST_MATH_BIG_CONSTANT(T, 64, 6.83465258979924922633502182e-11),
  209. BOOST_MATH_BIG_CONSTANT(T, 64, 7.59405830675154933645967137e-13),
  210. BOOST_MATH_BIG_CONSTANT(T, 64, 6.90369179710633344508897178e-15),
  211. BOOST_MATH_BIG_CONSTANT(T, 64, 5.23003610041709452814262671e-17),
  212. BOOST_MATH_BIG_CONSTANT(T, 64, 3.35291901027762552549170038e-19),
  213. BOOST_MATH_BIG_CONSTANT(T, 64, 1.83991379419781823063672109e-21),
  214. BOOST_MATH_BIG_CONSTANT(T, 64, 8.87732714140192556332037815e-24),
  215. BOOST_MATH_BIG_CONSTANT(T, 64, 3.32120654663773147206454247e-26),
  216. BOOST_MATH_BIG_CONSTANT(T, 64, 1.95294659305369207813486871e-28)
  217. };
  218. T a = x * x / 4;
  219. T Q[3] = { 1, 0.5f, boost::math::tools::evaluate_polynomial(P, a) };
  220. return x * boost::math::tools::evaluate_polynomial(Q, a) / 2;
  221. }
  222. else if(x < 20)
  223. {
  224. // Max error in interpolated form: 4.258e-20
  225. // Max Error found at float80 precision = Poly: 2.851105e-19
  226. // Maximum Deviation Found : 3.887e-20
  227. // Expected Error Term : 3.887e-20
  228. // Maximum Relative Change in Control Points : 1.681e-04
  229. static const T P[] = {
  230. BOOST_MATH_BIG_CONSTANT(T, 64, 3.98942260530218897338680e-01),
  231. BOOST_MATH_BIG_CONSTANT(T, 64, -1.49599542849073670179540e-01),
  232. BOOST_MATH_BIG_CONSTANT(T, 64, -4.70492865454119188276875e-02),
  233. BOOST_MATH_BIG_CONSTANT(T, 64, -3.12389893307392002405869e-02),
  234. BOOST_MATH_BIG_CONSTANT(T, 64, 1.49696126385202602071197e-01),
  235. BOOST_MATH_BIG_CONSTANT(T, 64, -3.84206507612717711565967e+01),
  236. BOOST_MATH_BIG_CONSTANT(T, 64, 2.14748094784412558689584e+03),
  237. BOOST_MATH_BIG_CONSTANT(T, 64, -7.70652726663596993005669e+04),
  238. BOOST_MATH_BIG_CONSTANT(T, 64, 2.01659736164815617174439e+06),
  239. BOOST_MATH_BIG_CONSTANT(T, 64, -4.04740659606466305607544e+07),
  240. BOOST_MATH_BIG_CONSTANT(T, 64, 6.38383394696382837263656e+08),
  241. BOOST_MATH_BIG_CONSTANT(T, 64, -8.00779638649147623107378e+09),
  242. BOOST_MATH_BIG_CONSTANT(T, 64, 8.02338237858684714480491e+10),
  243. BOOST_MATH_BIG_CONSTANT(T, 64, -6.41198553664947312995879e+11),
  244. BOOST_MATH_BIG_CONSTANT(T, 64, 4.05915186909564986897554e+12),
  245. BOOST_MATH_BIG_CONSTANT(T, 64, -2.00907636964168581116181e+13),
  246. BOOST_MATH_BIG_CONSTANT(T, 64, 7.60855263982359981275199e+13),
  247. BOOST_MATH_BIG_CONSTANT(T, 64, -2.12901817219239205393806e+14),
  248. BOOST_MATH_BIG_CONSTANT(T, 64, 4.14861794397709807823575e+14),
  249. BOOST_MATH_BIG_CONSTANT(T, 64, -5.02808138522587680348583e+14),
  250. BOOST_MATH_BIG_CONSTANT(T, 64, 2.85505477056514919387171e+14)
  251. };
  252. return exp(x) * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);
  253. }
  254. else if(x < 100)
  255. {
  256. // Bessel I0 over [15, 50]
  257. // Maximum Deviation Found: 2.444e-20
  258. // Expected Error Term : 2.438e-20
  259. // Maximum Relative Change in Control Points : 2.101e-03
  260. // Max Error found at float80 precision = Poly : 6.029974e-20
  261. static const T P[] = {
  262. BOOST_MATH_BIG_CONSTANT(T, 64, 3.98942280401431675205845e-01),
  263. BOOST_MATH_BIG_CONSTANT(T, 64, -1.49603355149968887210170e-01),
  264. BOOST_MATH_BIG_CONSTANT(T, 64, -4.67510486284376330257260e-02),
  265. BOOST_MATH_BIG_CONSTANT(T, 64, -4.09071458907089270559464e-02),
  266. BOOST_MATH_BIG_CONSTANT(T, 64, -5.75278280327696940044714e-02),
  267. BOOST_MATH_BIG_CONSTANT(T, 64, -1.10591299500956620739254e-01),
  268. BOOST_MATH_BIG_CONSTANT(T, 64, -2.77061766699949309115618e-01),
  269. BOOST_MATH_BIG_CONSTANT(T, 64, -5.42683771801837596371638e-01),
  270. BOOST_MATH_BIG_CONSTANT(T, 64, -9.17021412070404158464316e+00),
  271. BOOST_MATH_BIG_CONSTANT(T, 64, 1.04154379346763380543310e+02),
  272. BOOST_MATH_BIG_CONSTANT(T, 64, -1.43462345357478348323006e+03),
  273. BOOST_MATH_BIG_CONSTANT(T, 64, 9.98109660274422449523837e+03),
  274. BOOST_MATH_BIG_CONSTANT(T, 64, -3.74438822767781410362757e+04)
  275. };
  276. return exp(x) * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);
  277. }
  278. else
  279. {
  280. // Bessel I0 over[100, INF]
  281. // Max error in interpolated form: 2.456e-20
  282. // Max Error found at float80 precision = Poly: 5.446356e-20
  283. static const T P[] = {
  284. BOOST_MATH_BIG_CONSTANT(T, 64, 3.98942280401432677958445e-01),
  285. BOOST_MATH_BIG_CONSTANT(T, 64, -1.49603355150537411254359e-01),
  286. BOOST_MATH_BIG_CONSTANT(T, 64, -4.67510484842456251368526e-02),
  287. BOOST_MATH_BIG_CONSTANT(T, 64, -4.09071676503922479645155e-02),
  288. BOOST_MATH_BIG_CONSTANT(T, 64, -5.75256179814881566010606e-02),
  289. BOOST_MATH_BIG_CONSTANT(T, 64, -1.10754910257965227825040e-01),
  290. BOOST_MATH_BIG_CONSTANT(T, 64, -2.67858639515616079840294e-01),
  291. BOOST_MATH_BIG_CONSTANT(T, 64, -9.17266479586791298924367e-01)
  292. };
  293. T ex = exp(x / 2);
  294. T result = ex * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);
  295. result *= ex;
  296. return result;
  297. }
  298. }
  299. template <typename T>
  300. T bessel_i1_imp(const T& x, const mpl::int_<113>&)
  301. {
  302. BOOST_MATH_STD_USING
  303. if(x < 7.75)
  304. {
  305. // Bessel I0 over[10 ^ -34, 7.75]
  306. // Max error in interpolated form: 1.835e-35
  307. // Max Error found at float128 precision = Poly: 1.645036e-34
  308. static const T P[] = {
  309. BOOST_MATH_BIG_CONSTANT(T, 113, 8.3333333333333333333333333333333331804098e-02),
  310. BOOST_MATH_BIG_CONSTANT(T, 113, 6.9444444444444444444444444444445418303082e-03),
  311. BOOST_MATH_BIG_CONSTANT(T, 113, 3.4722222222222222222222222222119082346591e-04),
  312. BOOST_MATH_BIG_CONSTANT(T, 113, 1.1574074074074074074074074078415867655987e-05),
  313. BOOST_MATH_BIG_CONSTANT(T, 113, 2.7557319223985890652557318255143448192453e-07),
  314. BOOST_MATH_BIG_CONSTANT(T, 113, 4.9209498614260519022423916850415000626427e-09),
  315. BOOST_MATH_BIG_CONSTANT(T, 113, 6.8346525853139609753354247043900442393686e-11),
  316. BOOST_MATH_BIG_CONSTANT(T, 113, 7.5940584281266233060080535940234144302217e-13),
  317. BOOST_MATH_BIG_CONSTANT(T, 113, 6.9036894801151120925605467963949641957095e-15),
  318. BOOST_MATH_BIG_CONSTANT(T, 113, 5.2300677879659941472662086395055636394839e-17),
  319. BOOST_MATH_BIG_CONSTANT(T, 113, 3.3526075563884539394691458717439115962233e-19),
  320. BOOST_MATH_BIG_CONSTANT(T, 113, 1.8420920639497841692288943167036233338434e-21),
  321. BOOST_MATH_BIG_CONSTANT(T, 113, 8.7718669711748690065381181691546032291365e-24),
  322. BOOST_MATH_BIG_CONSTANT(T, 113, 3.6549445715236427401845636880769861424730e-26),
  323. BOOST_MATH_BIG_CONSTANT(T, 113, 1.3437296196812697924703896979250126739676e-28),
  324. BOOST_MATH_BIG_CONSTANT(T, 113, 4.3912734588619073883015937023564978854893e-31),
  325. BOOST_MATH_BIG_CONSTANT(T, 113, 1.2839967682792395867255384448052781306897e-33),
  326. BOOST_MATH_BIG_CONSTANT(T, 113, 3.3790094235693528861015312806394354114982e-36),
  327. BOOST_MATH_BIG_CONSTANT(T, 113, 8.0423861671932104308662362292359563970482e-39),
  328. BOOST_MATH_BIG_CONSTANT(T, 113, 1.7493858979396446292135661268130281652945e-41),
  329. BOOST_MATH_BIG_CONSTANT(T, 113, 3.2786079392547776769387921361408303035537e-44),
  330. BOOST_MATH_BIG_CONSTANT(T, 113, 8.2335693685833531118863552173880047183822e-47)
  331. };
  332. T a = x * x / 4;
  333. T Q[3] = { 1, 0.5f, boost::math::tools::evaluate_polynomial(P, a) };
  334. return x * boost::math::tools::evaluate_polynomial(Q, a) / 2;
  335. }
  336. else if(x < 11)
  337. {
  338. // Max error in interpolated form: 8.574e-36
  339. // Maximum Deviation Found : 4.689e-36
  340. // Expected Error Term : 3.760e-36
  341. // Maximum Relative Change in Control Points : 5.204e-03
  342. // Max Error found at float128 precision = Poly : 2.882561e-34
  343. static const T P[] = {
  344. BOOST_MATH_BIG_CONSTANT(T, 113, 8.333333333333333326889717360850080939e-02),
  345. BOOST_MATH_BIG_CONSTANT(T, 113, 6.944444444444444511272790848815114507e-03),
  346. BOOST_MATH_BIG_CONSTANT(T, 113, 3.472222222222221892451965054394153443e-04),
  347. BOOST_MATH_BIG_CONSTANT(T, 113, 1.157407407407408437378868534321538798e-05),
  348. BOOST_MATH_BIG_CONSTANT(T, 113, 2.755731922398566216824909767320161880e-07),
  349. BOOST_MATH_BIG_CONSTANT(T, 113, 4.920949861426434829568192525456800388e-09),
  350. BOOST_MATH_BIG_CONSTANT(T, 113, 6.834652585308926245465686943255486934e-11),
  351. BOOST_MATH_BIG_CONSTANT(T, 113, 7.594058428179852047689599244015979196e-13),
  352. BOOST_MATH_BIG_CONSTANT(T, 113, 6.903689479655006062822949671528763738e-15),
  353. BOOST_MATH_BIG_CONSTANT(T, 113, 5.230067791254403974475987777406992984e-17),
  354. BOOST_MATH_BIG_CONSTANT(T, 113, 3.352607536815161679702105115200693346e-19),
  355. BOOST_MATH_BIG_CONSTANT(T, 113, 1.842092161364672561828681848278567885e-21),
  356. BOOST_MATH_BIG_CONSTANT(T, 113, 8.771862912600611801856514076709932773e-24),
  357. BOOST_MATH_BIG_CONSTANT(T, 113, 3.654958704184380914803366733193713605e-26),
  358. BOOST_MATH_BIG_CONSTANT(T, 113, 1.343688672071130980471207297730607625e-28),
  359. BOOST_MATH_BIG_CONSTANT(T, 113, 4.392252844664709532905868749753463950e-31),
  360. BOOST_MATH_BIG_CONSTANT(T, 113, 1.282086786672692641959912811902298600e-33),
  361. BOOST_MATH_BIG_CONSTANT(T, 113, 3.408812012322547015191398229942864809e-36),
  362. BOOST_MATH_BIG_CONSTANT(T, 113, 7.681220437734066258673404589233009892e-39),
  363. BOOST_MATH_BIG_CONSTANT(T, 113, 2.072417451640733785626701738789290055e-41),
  364. BOOST_MATH_BIG_CONSTANT(T, 113, 1.352218520142636864158849446833681038e-44),
  365. BOOST_MATH_BIG_CONSTANT(T, 113, 1.407918492276267527897751358794783640e-46)
  366. };
  367. T a = x * x / 4;
  368. T Q[3] = { 1, 0.5f, boost::math::tools::evaluate_polynomial(P, a) };
  369. return x * boost::math::tools::evaluate_polynomial(Q, a) / 2;
  370. }
  371. else if(x < 15)
  372. {
  373. //Max error in interpolated form: 7.599e-36
  374. // Maximum Deviation Found : 1.766e-35
  375. // Expected Error Term : 1.021e-35
  376. // Maximum Relative Change in Control Points : 6.228e-03
  377. static const T P[] = {
  378. BOOST_MATH_BIG_CONSTANT(T, 113, 8.333333333333255774414858563409941233e-02),
  379. BOOST_MATH_BIG_CONSTANT(T, 113, 6.944444444444897867884955912228700291e-03),
  380. BOOST_MATH_BIG_CONSTANT(T, 113, 3.472222222220954970397343617150959467e-04),
  381. BOOST_MATH_BIG_CONSTANT(T, 113, 1.157407407409660682751155024932538578e-05),
  382. BOOST_MATH_BIG_CONSTANT(T, 113, 2.755731922369973706427272809014190998e-07),
  383. BOOST_MATH_BIG_CONSTANT(T, 113, 4.920949861702265600960449699129258153e-09),
  384. BOOST_MATH_BIG_CONSTANT(T, 113, 6.834652583208361401197752793379677147e-11),
  385. BOOST_MATH_BIG_CONSTANT(T, 113, 7.594058441128280500819776168239988143e-13),
  386. BOOST_MATH_BIG_CONSTANT(T, 113, 6.903689413939268702265479276217647209e-15),
  387. BOOST_MATH_BIG_CONSTANT(T, 113, 5.230068069012898202890718644753625569e-17),
  388. BOOST_MATH_BIG_CONSTANT(T, 113, 3.352606552027491657204243201021677257e-19),
  389. BOOST_MATH_BIG_CONSTANT(T, 113, 1.842095100698532984651921750204843362e-21),
  390. BOOST_MATH_BIG_CONSTANT(T, 113, 8.771789051329870174925649852681844169e-24),
  391. BOOST_MATH_BIG_CONSTANT(T, 113, 3.655114381199979536997025497438385062e-26),
  392. BOOST_MATH_BIG_CONSTANT(T, 113, 1.343415732516712339472538688374589373e-28),
  393. BOOST_MATH_BIG_CONSTANT(T, 113, 4.396177019032432392793591204647901390e-31),
  394. BOOST_MATH_BIG_CONSTANT(T, 113, 1.277563309255167951005939802771456315e-33),
  395. BOOST_MATH_BIG_CONSTANT(T, 113, 3.449201419305514579791370198046544736e-36),
  396. BOOST_MATH_BIG_CONSTANT(T, 113, 7.415430703400740634202379012388035255e-39),
  397. BOOST_MATH_BIG_CONSTANT(T, 113, 2.195458831864936225409005027914934499e-41),
  398. BOOST_MATH_BIG_CONSTANT(T, 113, 8.829726762743879793396637797534668039e-45),
  399. BOOST_MATH_BIG_CONSTANT(T, 113, 1.698302711685624490806751012380215488e-46),
  400. BOOST_MATH_BIG_CONSTANT(T, 113, -2.062520475425422618494185821587228317e-49),
  401. BOOST_MATH_BIG_CONSTANT(T, 113, 6.732372906742845717148185173723304360e-52)
  402. };
  403. T a = x * x / 4;
  404. T Q[3] = { 1, 0.5f, boost::math::tools::evaluate_polynomial(P, a) };
  405. return x * boost::math::tools::evaluate_polynomial(Q, a) / 2;
  406. }
  407. else if(x < 20)
  408. {
  409. // Max error in interpolated form: 8.864e-36
  410. // Max Error found at float128 precision = Poly: 8.522841e-35
  411. static const T P[] = {
  412. BOOST_MATH_BIG_CONSTANT(T, 113, 3.989422793693152031514179994954750043e-01),
  413. BOOST_MATH_BIG_CONSTANT(T, 113, -1.496029423752889591425633234009799670e-01),
  414. BOOST_MATH_BIG_CONSTANT(T, 113, -4.682975926820553021482820043377990241e-02),
  415. BOOST_MATH_BIG_CONSTANT(T, 113, -3.138871171577224532369979905856458929e-02),
  416. BOOST_MATH_BIG_CONSTANT(T, 113, -8.765350219426341341990447005798111212e-01),
  417. BOOST_MATH_BIG_CONSTANT(T, 113, 5.321389275507714530941178258122955540e+01),
  418. BOOST_MATH_BIG_CONSTANT(T, 113, -2.727748393898888756515271847678850411e+03),
  419. BOOST_MATH_BIG_CONSTANT(T, 113, 1.123040820686242586086564998713862335e+05),
  420. BOOST_MATH_BIG_CONSTANT(T, 113, -3.784112378374753535335272752884808068e+06),
  421. BOOST_MATH_BIG_CONSTANT(T, 113, 1.054920416060932189433079126269416563e+08),
  422. BOOST_MATH_BIG_CONSTANT(T, 113, -2.450129415468060676827180524327749553e+09),
  423. BOOST_MATH_BIG_CONSTANT(T, 113, 4.758831882046487398739784498047935515e+10),
  424. BOOST_MATH_BIG_CONSTANT(T, 113, -7.736936520262204842199620784338052937e+11),
  425. BOOST_MATH_BIG_CONSTANT(T, 113, 1.051128683324042629513978256179115439e+13),
  426. BOOST_MATH_BIG_CONSTANT(T, 113, -1.188008285959794869092624343537262342e+14),
  427. BOOST_MATH_BIG_CONSTANT(T, 113, 1.108530004906954627420484180793165669e+15),
  428. BOOST_MATH_BIG_CONSTANT(T, 113, -8.441516828490144766650287123765318484e+15),
  429. BOOST_MATH_BIG_CONSTANT(T, 113, 5.158251664797753450664499268756393535e+16),
  430. BOOST_MATH_BIG_CONSTANT(T, 113, -2.467314522709016832128790443932896401e+17),
  431. BOOST_MATH_BIG_CONSTANT(T, 113, 8.896222045367960462945885220710294075e+17),
  432. BOOST_MATH_BIG_CONSTANT(T, 113, -2.273382139594876997203657902425653079e+18),
  433. BOOST_MATH_BIG_CONSTANT(T, 113, 3.669871448568623680543943144842394531e+18),
  434. BOOST_MATH_BIG_CONSTANT(T, 113, -2.813923031370708069940575240509912588e+18)
  435. };
  436. return exp(x) * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);
  437. }
  438. else if(x < 35)
  439. {
  440. // Max error in interpolated form: 6.028e-35
  441. // Max Error found at float128 precision = Poly: 1.368313e-34
  442. static const T P[] = {
  443. BOOST_MATH_BIG_CONSTANT(T, 113, 3.989422804012941975429616956496046931e-01),
  444. BOOST_MATH_BIG_CONSTANT(T, 113, -1.496033550576049830976679315420681402e-01),
  445. BOOST_MATH_BIG_CONSTANT(T, 113, -4.675107835141866009896710750800622147e-02),
  446. BOOST_MATH_BIG_CONSTANT(T, 113, -4.090104965125365961928716504473692957e-02),
  447. BOOST_MATH_BIG_CONSTANT(T, 113, -5.842241652296980863361375208605487570e-02),
  448. BOOST_MATH_BIG_CONSTANT(T, 113, -1.063604828033747303936724279018650633e-02),
  449. BOOST_MATH_BIG_CONSTANT(T, 113, -9.113375972811586130949401996332817152e+00),
  450. BOOST_MATH_BIG_CONSTANT(T, 113, 6.334748570425075872639817839399823709e+02),
  451. BOOST_MATH_BIG_CONSTANT(T, 113, -3.759150758768733692594821032784124765e+04),
  452. BOOST_MATH_BIG_CONSTANT(T, 113, 1.863672813448915255286274382558526321e+06),
  453. BOOST_MATH_BIG_CONSTANT(T, 113, -7.798248643371718775489178767529282534e+07),
  454. BOOST_MATH_BIG_CONSTANT(T, 113, 2.769963173932801026451013022000669267e+09),
  455. BOOST_MATH_BIG_CONSTANT(T, 113, -8.381780137198278741566746511015220011e+10),
  456. BOOST_MATH_BIG_CONSTANT(T, 113, 2.163891337116820832871382141011952931e+12),
  457. BOOST_MATH_BIG_CONSTANT(T, 113, -4.764325864671438675151635117936912390e+13),
  458. BOOST_MATH_BIG_CONSTANT(T, 113, 8.925668307403332887856809510525154955e+14),
  459. BOOST_MATH_BIG_CONSTANT(T, 113, -1.416692606589060039334938090985713641e+16),
  460. BOOST_MATH_BIG_CONSTANT(T, 113, 1.892398600219306424294729851605944429e+17),
  461. BOOST_MATH_BIG_CONSTANT(T, 113, -2.107232903741874160308537145391245060e+18),
  462. BOOST_MATH_BIG_CONSTANT(T, 113, 1.930223393531877588898224144054112045e+19),
  463. BOOST_MATH_BIG_CONSTANT(T, 113, -1.427759576167665663373350433236061007e+20),
  464. BOOST_MATH_BIG_CONSTANT(T, 113, 8.306019279465532835530812122374386654e+20),
  465. BOOST_MATH_BIG_CONSTANT(T, 113, -3.653753000392125229440044977239174472e+21),
  466. BOOST_MATH_BIG_CONSTANT(T, 113, 1.140760686989511568435076842569804906e+22),
  467. BOOST_MATH_BIG_CONSTANT(T, 113, -2.249149337812510200795436107962504749e+22),
  468. BOOST_MATH_BIG_CONSTANT(T, 113, 2.101619088427348382058085685849420866e+22)
  469. };
  470. return exp(x) * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);
  471. }
  472. else if(x < 100)
  473. {
  474. // Max error in interpolated form: 5.494e-35
  475. // Max Error found at float128 precision = Poly: 1.214651e-34
  476. static const T P[] = {
  477. BOOST_MATH_BIG_CONSTANT(T, 113, 3.989422804014326779399307367861631577e-01),
  478. BOOST_MATH_BIG_CONSTANT(T, 113, -1.496033551505372542086590873271571919e-01),
  479. BOOST_MATH_BIG_CONSTANT(T, 113, -4.675104848454290286276466276677172664e-02),
  480. BOOST_MATH_BIG_CONSTANT(T, 113, -4.090716742397105403027549796269213215e-02),
  481. BOOST_MATH_BIG_CONSTANT(T, 113, -5.752570419098513588311026680089351230e-02),
  482. BOOST_MATH_BIG_CONSTANT(T, 113, -1.107369803696534592906420980901195808e-01),
  483. BOOST_MATH_BIG_CONSTANT(T, 113, -2.699214194000085622941721628134575121e-01),
  484. BOOST_MATH_BIG_CONSTANT(T, 113, -7.953006169077813678478720427604462133e-01),
  485. BOOST_MATH_BIG_CONSTANT(T, 113, -2.746618809476524091493444128605380593e+00),
  486. BOOST_MATH_BIG_CONSTANT(T, 113, -1.084446249943196826652788161656973391e+01),
  487. BOOST_MATH_BIG_CONSTANT(T, 113, -5.020325182518980633783194648285500554e+01),
  488. BOOST_MATH_BIG_CONSTANT(T, 113, -1.510195971266257573425196228564489134e+02),
  489. BOOST_MATH_BIG_CONSTANT(T, 113, -5.241661863814900938075696173192225056e+03),
  490. BOOST_MATH_BIG_CONSTANT(T, 113, 1.323374362891993686413568398575539777e+05),
  491. BOOST_MATH_BIG_CONSTANT(T, 113, -4.112838452096066633754042734723911040e+06),
  492. BOOST_MATH_BIG_CONSTANT(T, 113, 9.369270194978310081563767560113534023e+07),
  493. BOOST_MATH_BIG_CONSTANT(T, 113, -1.704295412488936504389347368131134993e+09),
  494. BOOST_MATH_BIG_CONSTANT(T, 113, 2.320829576277038198439987439508754886e+10),
  495. BOOST_MATH_BIG_CONSTANT(T, 113, -2.258818139077875493434420764260185306e+11),
  496. BOOST_MATH_BIG_CONSTANT(T, 113, 1.396791306321498426110315039064592443e+12),
  497. BOOST_MATH_BIG_CONSTANT(T, 113, -4.217617301585849875301440316301068439e+12)
  498. };
  499. return exp(x) * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);
  500. }
  501. else
  502. {
  503. // Bessel I0 over[100, INF]
  504. // Max error in interpolated form: 6.081e-35
  505. // Max Error found at float128 precision = Poly: 1.407151e-34
  506. static const T P[] = {
  507. BOOST_MATH_BIG_CONSTANT(T, 113, 3.9894228040143267793994605993438200208417e-01),
  508. BOOST_MATH_BIG_CONSTANT(T, 113, -1.4960335515053725422747977247811372936584e-01),
  509. BOOST_MATH_BIG_CONSTANT(T, 113, -4.6751048484542891946087411826356811991039e-02),
  510. BOOST_MATH_BIG_CONSTANT(T, 113, -4.0907167423975030452875828826630006305665e-02),
  511. BOOST_MATH_BIG_CONSTANT(T, 113, -5.7525704189964886494791082898669060345483e-02),
  512. BOOST_MATH_BIG_CONSTANT(T, 113, -1.1073698056568248642163476807108190176386e-01),
  513. BOOST_MATH_BIG_CONSTANT(T, 113, -2.6992139012879749064623499618582631684228e-01),
  514. BOOST_MATH_BIG_CONSTANT(T, 113, -7.9530409594026597988098934027440110587905e-01),
  515. BOOST_MATH_BIG_CONSTANT(T, 113, -2.7462844478733532517044536719240098183686e+00),
  516. BOOST_MATH_BIG_CONSTANT(T, 113, -1.0870711340681926669381449306654104739256e+01),
  517. BOOST_MATH_BIG_CONSTANT(T, 113, -4.8510175413216969245241059608553222505228e+01),
  518. BOOST_MATH_BIG_CONSTANT(T, 113, -2.4094682286011573747064907919522894740063e+02),
  519. BOOST_MATH_BIG_CONSTANT(T, 113, -1.3128845936764406865199641778959502795443e+03),
  520. BOOST_MATH_BIG_CONSTANT(T, 113, -8.1655901321962541203257516341266838487359e+03),
  521. BOOST_MATH_BIG_CONSTANT(T, 113, -3.8019591025686295090160445920753823994556e+04),
  522. BOOST_MATH_BIG_CONSTANT(T, 113, -6.7008089049178178697338128837158732831105e+05)
  523. };
  524. T ex = exp(x / 2);
  525. T result = ex * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);
  526. result *= ex;
  527. return result;
  528. }
  529. }
  530. template <typename T>
  531. T bessel_i1_imp(const T& x, const mpl::int_<0>&)
  532. {
  533. if(boost::math::tools::digits<T>() <= 24)
  534. return bessel_i1_imp(x, mpl::int_<24>());
  535. else if(boost::math::tools::digits<T>() <= 53)
  536. return bessel_i1_imp(x, mpl::int_<53>());
  537. else if(boost::math::tools::digits<T>() <= 64)
  538. return bessel_i1_imp(x, mpl::int_<64>());
  539. else if(boost::math::tools::digits<T>() <= 113)
  540. return bessel_i1_imp(x, mpl::int_<113>());
  541. BOOST_ASSERT(0);
  542. return 0;
  543. }
  544. template <typename T>
  545. inline T bessel_i1(const T& x)
  546. {
  547. typedef mpl::int_<
  548. ((std::numeric_limits<T>::digits == 0) || (std::numeric_limits<T>::radix != 2)) ?
  549. 0 :
  550. std::numeric_limits<T>::digits <= 24 ?
  551. 24 :
  552. std::numeric_limits<T>::digits <= 53 ?
  553. 53 :
  554. std::numeric_limits<T>::digits <= 64 ?
  555. 64 :
  556. std::numeric_limits<T>::digits <= 113 ?
  557. 113 : -1
  558. > tag_type;
  559. bessel_i1_initializer<T, tag_type>::force_instantiate();
  560. return bessel_i1_imp(x, tag_type());
  561. }
  562. }}} // namespaces
  563. #endif // BOOST_MATH_BESSEL_I1_HPP