/Src/Dependencies/Boost/boost/math/special_functions/expint.hpp

http://hadesmem.googlecode.com/ · C++ Header · 1514 lines · 1362 code · 73 blank · 79 comment · 79 complexity · 059c86b2d9afef875120a8e41f92b35f MD5 · raw file

Large files are truncated click here to view the full file

  1. // Copyright John Maddock 2007.
  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. #ifndef BOOST_MATH_EXPINT_HPP
  6. #define BOOST_MATH_EXPINT_HPP
  7. #ifdef _MSC_VER
  8. #pragma once
  9. #endif
  10. #include <boost/math/tools/precision.hpp>
  11. #include <boost/math/tools/promotion.hpp>
  12. #include <boost/math/tools/fraction.hpp>
  13. #include <boost/math/tools/series.hpp>
  14. #include <boost/math/policies/error_handling.hpp>
  15. #include <boost/math/special_functions/digamma.hpp>
  16. #include <boost/math/special_functions/log1p.hpp>
  17. #include <boost/math/special_functions/pow.hpp>
  18. namespace boost{ namespace math{
  19. template <class T, class Policy>
  20. inline typename tools::promote_args<T>::type
  21. expint(unsigned n, T z, const Policy& /*pol*/);
  22. namespace detail{
  23. template <class T>
  24. inline T expint_1_rational(const T& z, const mpl::int_<0>&)
  25. {
  26. // this function is never actually called
  27. BOOST_ASSERT(0);
  28. return z;
  29. }
  30. template <class T>
  31. T expint_1_rational(const T& z, const mpl::int_<53>&)
  32. {
  33. BOOST_MATH_STD_USING
  34. T result;
  35. if(z <= 1)
  36. {
  37. // Maximum Deviation Found: 2.006e-18
  38. // Expected Error Term: 2.006e-18
  39. // Max error found at double precision: 2.760e-17
  40. static const T Y = 0.66373538970947265625F;
  41. static const T P[6] = {
  42. 0.0865197248079397976498L,
  43. 0.0320913665303559189999L,
  44. -0.245088216639761496153L,
  45. -0.0368031736257943745142L,
  46. -0.00399167106081113256961L,
  47. -0.000111507792921197858394L
  48. };
  49. static const T Q[6] = {
  50. 1L,
  51. 0.37091387659397013215L,
  52. 0.056770677104207528384L,
  53. 0.00427347600017103698101L,
  54. 0.000131049900798434683324L,
  55. -0.528611029520217142048e-6L
  56. };
  57. result = tools::evaluate_polynomial(P, z)
  58. / tools::evaluate_polynomial(Q, z);
  59. result += z - log(z) - Y;
  60. }
  61. else if(z < -boost::math::tools::log_min_value<T>())
  62. {
  63. // Maximum Deviation Found (interpolated): 1.444e-17
  64. // Max error found at double precision: 3.119e-17
  65. static const T P[11] = {
  66. -0.121013190657725568138e-18L,
  67. -0.999999999999998811143L,
  68. -43.3058660811817946037L,
  69. -724.581482791462469795L,
  70. -6046.8250112711035463L,
  71. -27182.6254466733970467L,
  72. -66598.2652345418633509L,
  73. -86273.1567711649528784L,
  74. -54844.4587226402067411L,
  75. -14751.4895786128450662L,
  76. -1185.45720315201027667L
  77. };
  78. static const T Q[12] = {
  79. 1L,
  80. 45.3058660811801465927L,
  81. 809.193214954550328455L,
  82. 7417.37624454689546708L,
  83. 38129.5594484818471461L,
  84. 113057.05869159631492L,
  85. 192104.047790227984431L,
  86. 180329.498380501819718L,
  87. 86722.3403467334749201L,
  88. 18455.4124737722049515L,
  89. 1229.20784182403048905L,
  90. -0.776491285282330997549L
  91. };
  92. T recip = 1 / z;
  93. result = 1 + tools::evaluate_polynomial(P, recip)
  94. / tools::evaluate_polynomial(Q, recip);
  95. result *= exp(-z) * recip;
  96. }
  97. else
  98. {
  99. result = 0;
  100. }
  101. return result;
  102. }
  103. template <class T>
  104. T expint_1_rational(const T& z, const mpl::int_<64>&)
  105. {
  106. BOOST_MATH_STD_USING
  107. T result;
  108. if(z <= 1)
  109. {
  110. // Maximum Deviation Found: 3.807e-20
  111. // Expected Error Term: 3.807e-20
  112. // Max error found at long double precision: 6.249e-20
  113. static const T Y = 0.66373538970947265625F;
  114. static const T P[6] = {
  115. 0.0865197248079397956816L,
  116. 0.0275114007037026844633L,
  117. -0.246594388074877139824L,
  118. -0.0237624819878732642231L,
  119. -0.00259113319641673986276L,
  120. 0.30853660894346057053e-4L
  121. };
  122. static const T Q[7] = {
  123. 1L,
  124. 0.317978365797784100273L,
  125. 0.0393622602554758722511L,
  126. 0.00204062029115966323229L,
  127. 0.732512107100088047854e-5L,
  128. -0.202872781770207871975e-5L,
  129. 0.52779248094603709945e-7L
  130. };
  131. result = tools::evaluate_polynomial(P, z)
  132. / tools::evaluate_polynomial(Q, z);
  133. result += z - log(z) - Y;
  134. }
  135. else if(z < -boost::math::tools::log_min_value<T>())
  136. {
  137. // Maximum Deviation Found (interpolated): 2.220e-20
  138. // Max error found at long double precision: 1.346e-19
  139. static const T P[14] = {
  140. -0.534401189080684443046e-23L,
  141. -0.999999999999999999905L,
  142. -62.1517806091379402505L,
  143. -1568.45688271895145277L,
  144. -21015.3431990874009619L,
  145. -164333.011755931661949L,
  146. -777917.270775426696103L,
  147. -2244188.56195255112937L,
  148. -3888702.98145335643429L,
  149. -3909822.65621952648353L,
  150. -2149033.9538897398457L,
  151. -584705.537139793925189L,
  152. -65815.2605361889477244L,
  153. -2038.82870680427258038L
  154. };
  155. static const T Q[14] = {
  156. 1L,
  157. 64.1517806091379399478L,
  158. 1690.76044393722763785L,
  159. 24035.9534033068949426L,
  160. 203679.998633572361706L,
  161. 1074661.58459976978285L,
  162. 3586552.65020899358773L,
  163. 7552186.84989547621411L,
  164. 9853333.79353054111434L,
  165. 7689642.74550683631258L,
  166. 3385553.35146759180739L,
  167. 763218.072732396428725L,
  168. 73930.2995984054930821L,
  169. 2063.86994219629165937L
  170. };
  171. T recip = 1 / z;
  172. result = 1 + tools::evaluate_polynomial(P, recip)
  173. / tools::evaluate_polynomial(Q, recip);
  174. result *= exp(-z) * recip;
  175. }
  176. else
  177. {
  178. result = 0;
  179. }
  180. return result;
  181. }
  182. template <class T>
  183. T expint_1_rational(const T& z, const mpl::int_<113>&)
  184. {
  185. BOOST_MATH_STD_USING
  186. T result;
  187. if(z <= 1)
  188. {
  189. // Maximum Deviation Found: 2.477e-35
  190. // Expected Error Term: 2.477e-35
  191. // Max error found at long double precision: 6.810e-35
  192. static const T Y = 0.66373538970947265625F;
  193. static const T P[10] = {
  194. 0.0865197248079397956434879099175975937L,
  195. 0.0369066175910795772830865304506087759L,
  196. -0.24272036838415474665971599314725545L,
  197. -0.0502166331248948515282379137550178307L,
  198. -0.00768384138547489410285101483730424919L,
  199. -0.000612574337702109683505224915484717162L,
  200. -0.380207107950635046971492617061708534e-4L,
  201. -0.136528159460768830763009294683628406e-5L,
  202. -0.346839106212658259681029388908658618e-7L,
  203. -0.340500302777838063940402160594523429e-9L
  204. };
  205. static const T Q[10] = {
  206. 1L,
  207. 0.426568827778942588160423015589537302L,
  208. 0.0841384046470893490592450881447510148L,
  209. 0.0100557215850668029618957359471132995L,
  210. 0.000799334870474627021737357294799839363L,
  211. 0.434452090903862735242423068552687688e-4L,
  212. 0.15829674748799079874182885081231252e-5L,
  213. 0.354406206738023762100882270033082198e-7L,
  214. 0.369373328141051577845488477377890236e-9L,
  215. -0.274149801370933606409282434677600112e-12L
  216. };
  217. result = tools::evaluate_polynomial(P, z)
  218. / tools::evaluate_polynomial(Q, z);
  219. result += z - log(z) - Y;
  220. }
  221. else if(z <= 4)
  222. {
  223. // Max error in interpolated form: 5.614e-35
  224. // Max error found at long double precision: 7.979e-35
  225. static const T Y = 0.70190334320068359375F;
  226. static const T P[17] = {
  227. 0.298096656795020369955077350585959794L,
  228. 12.9314045995266142913135497455971247L,
  229. 226.144334921582637462526628217345501L,
  230. 2070.83670924261732722117682067381405L,
  231. 10715.1115684330959908244769731347186L,
  232. 30728.7876355542048019664777316053311L,
  233. 38520.6078609349855436936232610875297L,
  234. -27606.0780981527583168728339620565165L,
  235. -169026.485055785605958655247592604835L,
  236. -254361.919204983608659069868035092282L,
  237. -195765.706874132267953259272028679935L,
  238. -83352.6826013533205474990119962408675L,
  239. -19251.6828496869586415162597993050194L,
  240. -2226.64251774578542836725386936102339L,
  241. -109.009437301400845902228611986479816L,
  242. -1.51492042209561411434644938098833499L
  243. };
  244. static const T Q[16] = {
  245. 1L,
  246. 46.734521442032505570517810766704587L,
  247. 908.694714348462269000247450058595655L,
  248. 9701.76053033673927362784882748513195L,
  249. 63254.2815292641314236625196594947774L,
  250. 265115.641285880437335106541757711092L,
  251. 732707.841188071900498536533086567735L,
  252. 1348514.02492635723327306628712057794L,
  253. 1649986.81455283047769673308781585991L,
  254. 1326000.828522976970116271208812099L,
  255. 683643.09490612171772350481773951341L,
  256. 217640.505137263607952365685653352229L,
  257. 40288.3467237411710881822569476155485L,
  258. 3932.89353979531632559232883283175754L,
  259. 169.845369689596739824177412096477219L,
  260. 2.17607292280092201170768401876895354L
  261. };
  262. T recip = 1 / z;
  263. result = Y + tools::evaluate_polynomial(P, recip)
  264. / tools::evaluate_polynomial(Q, recip);
  265. result *= exp(-z) * recip;
  266. }
  267. else if(z < -boost::math::tools::log_min_value<T>())
  268. {
  269. // Max error in interpolated form: 4.413e-35
  270. // Max error found at long double precision: 8.928e-35
  271. static const T P[19] = {
  272. -0.559148411832951463689610809550083986e-40L,
  273. -0.999999999999999999999999999999999997L,
  274. -166.542326331163836642960118190147367L,
  275. -12204.639128796330005065904675153652L,
  276. -520807.069767086071806275022036146855L,
  277. -14435981.5242137970691490903863125326L,
  278. -274574945.737064301247496460758654196L,
  279. -3691611582.99810039356254671781473079L,
  280. -35622515944.8255047299363690814678763L,
  281. -248040014774.502043161750715548451142L,
  282. -1243190389769.53458416330946622607913L,
  283. -4441730126135.54739052731990368425339L,
  284. -11117043181899.7388524310281751971366L,
  285. -18976497615396.9717776601813519498961L,
  286. -21237496819711.1011661104761906067131L,
  287. -14695899122092.5161620333466757812848L,
  288. -5737221535080.30569711574295785864903L,
  289. -1077042281708.42654526404581272546244L,
  290. -68028222642.1941480871395695677675137L
  291. };
  292. static const T Q[20] = {
  293. 1L,
  294. 168.542326331163836642960118190147311L,
  295. 12535.7237814586576783518249115343619L,
  296. 544891.263372016404143120911148640627L,
  297. 15454474.7241010258634446523045237762L,
  298. 302495899.896629522673410325891717381L,
  299. 4215565948.38886507646911672693270307L,
  300. 42552409471.7951815668506556705733344L,
  301. 313592377066.753173979584098301610186L,
  302. 1688763640223.4541980740597514904542L,
  303. 6610992294901.59589748057620192145704L,
  304. 18601637235659.6059890851321772682606L,
  305. 36944278231087.2571020964163402941583L,
  306. 50425858518481.7497071917028793820058L,
  307. 45508060902865.0899967797848815980644L,
  308. 25649955002765.3817331501988304758142L,
  309. 8259575619094.6518520988612711292331L,
  310. 1299981487496.12607474362723586264515L,
  311. 70242279152.8241187845178443118302693L,
  312. -37633302.9409263839042721539363416685L
  313. };
  314. T recip = 1 / z;
  315. result = 1 + tools::evaluate_polynomial(P, recip)
  316. / tools::evaluate_polynomial(Q, recip);
  317. result *= exp(-z) * recip;
  318. }
  319. else
  320. {
  321. result = 0;
  322. }
  323. return result;
  324. }
  325. template <class T>
  326. struct expint_fraction
  327. {
  328. typedef std::pair<T,T> result_type;
  329. expint_fraction(unsigned n_, T z_) : b(n_ + z_), i(-1), n(n_){}
  330. std::pair<T,T> operator()()
  331. {
  332. std::pair<T,T> result = std::make_pair(-static_cast<T>((i+1) * (n+i)), b);
  333. b += 2;
  334. ++i;
  335. return result;
  336. }
  337. private:
  338. T b;
  339. int i;
  340. unsigned n;
  341. };
  342. template <class T, class Policy>
  343. inline T expint_as_fraction(unsigned n, T z, const Policy& pol)
  344. {
  345. BOOST_MATH_STD_USING
  346. BOOST_MATH_INSTRUMENT_VARIABLE(z)
  347. boost::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
  348. expint_fraction<T> f(n, z);
  349. T result = tools::continued_fraction_b(
  350. f,
  351. boost::math::policies::get_epsilon<T, Policy>(),
  352. max_iter);
  353. policies::check_series_iterations("boost::math::expint_continued_fraction<%1%>(unsigned,%1%)", max_iter, pol);
  354. BOOST_MATH_INSTRUMENT_VARIABLE(result)
  355. BOOST_MATH_INSTRUMENT_VARIABLE(max_iter)
  356. result = exp(-z) / result;
  357. BOOST_MATH_INSTRUMENT_VARIABLE(result)
  358. return result;
  359. }
  360. template <class T>
  361. struct expint_series
  362. {
  363. typedef T result_type;
  364. expint_series(unsigned k_, T z_, T x_k_, T denom_, T fact_)
  365. : k(k_), z(z_), x_k(x_k_), denom(denom_), fact(fact_){}
  366. T operator()()
  367. {
  368. x_k *= -z;
  369. denom += 1;
  370. fact *= ++k;
  371. return x_k / (denom * fact);
  372. }
  373. private:
  374. unsigned k;
  375. T z;
  376. T x_k;
  377. T denom;
  378. T fact;
  379. };
  380. template <class T, class Policy>
  381. inline T expint_as_series(unsigned n, T z, const Policy& pol)
  382. {
  383. BOOST_MATH_STD_USING
  384. boost::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
  385. BOOST_MATH_INSTRUMENT_VARIABLE(z)
  386. T result = 0;
  387. T x_k = -1;
  388. T denom = T(1) - n;
  389. T fact = 1;
  390. unsigned k = 0;
  391. for(; k < n - 1;)
  392. {
  393. result += x_k / (denom * fact);
  394. denom += 1;
  395. x_k *= -z;
  396. fact *= ++k;
  397. }
  398. BOOST_MATH_INSTRUMENT_VARIABLE(result)
  399. result += pow(-z, static_cast<T>(n - 1))
  400. * (boost::math::digamma(static_cast<T>(n)) - log(z)) / fact;
  401. BOOST_MATH_INSTRUMENT_VARIABLE(result)
  402. expint_series<T> s(k, z, x_k, denom, fact);
  403. result = tools::sum_series(s, policies::get_epsilon<T, Policy>(), max_iter, result);
  404. policies::check_series_iterations("boost::math::expint_series<%1%>(unsigned,%1%)", max_iter, pol);
  405. BOOST_MATH_INSTRUMENT_VARIABLE(result)
  406. BOOST_MATH_INSTRUMENT_VARIABLE(max_iter)
  407. return result;
  408. }
  409. template <class T, class Policy, class Tag>
  410. T expint_imp(unsigned n, T z, const Policy& pol, const Tag& tag)
  411. {
  412. BOOST_MATH_STD_USING
  413. static const char* function = "boost::math::expint<%1%>(unsigned, %1%)";
  414. if(z < 0)
  415. return policies::raise_domain_error<T>(function, "Function requires z >= 0 but got %1%.", z, pol);
  416. if(z == 0)
  417. return n == 1 ? policies::raise_overflow_error<T>(function, 0, pol) : T(1 / (static_cast<T>(n - 1)));
  418. T result;
  419. bool f;
  420. if(n < 3)
  421. {
  422. f = z < 0.5;
  423. }
  424. else
  425. {
  426. f = z < (static_cast<T>(n - 2) / static_cast<T>(n - 1));
  427. }
  428. #ifdef BOOST_MSVC
  429. # pragma warning(push)
  430. # pragma warning(disable:4127) // conditional expression is constant
  431. #endif
  432. if(n == 0)
  433. result = exp(-z) / z;
  434. else if((n == 1) && (Tag::value))
  435. {
  436. result = expint_1_rational(z, tag);
  437. }
  438. else if(f)
  439. result = expint_as_series(n, z, pol);
  440. else
  441. result = expint_as_fraction(n, z, pol);
  442. #ifdef BOOST_MSVC
  443. # pragma warning(pop)
  444. #endif
  445. return result;
  446. }
  447. template <class T>
  448. struct expint_i_series
  449. {
  450. typedef T result_type;
  451. expint_i_series(T z_) : k(0), z_k(1), z(z_){}
  452. T operator()()
  453. {
  454. z_k *= z / ++k;
  455. return z_k / k;
  456. }
  457. private:
  458. unsigned k;
  459. T z_k;
  460. T z;
  461. };
  462. template <class T, class Policy>
  463. T expint_i_as_series(T z, const Policy& pol)
  464. {
  465. BOOST_MATH_STD_USING
  466. T result = log(z); // (log(z) - log(1 / z)) / 2;
  467. result += constants::euler<T>();
  468. expint_i_series<T> s(z);
  469. boost::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
  470. result = tools::sum_series(s, policies::get_epsilon<T, Policy>(), max_iter, result);
  471. policies::check_series_iterations("boost::math::expint_i_series<%1%>(%1%)", max_iter, pol);
  472. return result;
  473. }
  474. template <class T, class Policy, class Tag>
  475. T expint_i_imp(T z, const Policy& pol, const Tag& tag)
  476. {
  477. static const char* function = "boost::math::expint<%1%>(%1%)";
  478. if(z < 0)
  479. return -expint_imp(1, T(-z), pol, tag);
  480. if(z == 0)
  481. return -policies::raise_overflow_error<T>(function, 0, pol);
  482. return expint_i_as_series(z, pol);
  483. }
  484. template <class T, class Policy>
  485. T expint_i_imp(T z, const Policy& pol, const mpl::int_<53>& tag)
  486. {
  487. BOOST_MATH_STD_USING
  488. static const char* function = "boost::math::expint<%1%>(%1%)";
  489. if(z < 0)
  490. return -expint_imp(1, -z, pol, tag);
  491. if(z == 0)
  492. return -policies::raise_overflow_error<T>(function, 0, pol);
  493. T result;
  494. if(z <= 6)
  495. {
  496. // Maximum Deviation Found: 2.852e-18
  497. // Expected Error Term: 2.852e-18
  498. // Max Error found at double precision = Poly: 2.636335e-16 Cheb: 4.187027e-16
  499. static const T P[10] = {
  500. 2.98677224343598593013L,
  501. 0.356343618769377415068L,
  502. 0.780836076283730801839L,
  503. 0.114670926327032002811L,
  504. 0.0499434773576515260534L,
  505. 0.00726224593341228159561L,
  506. 0.00115478237227804306827L,
  507. 0.000116419523609765200999L,
  508. 0.798296365679269702435e-5L,
  509. 0.2777056254402008721e-6L
  510. };
  511. static const T Q[8] = {
  512. 1L,
  513. -1.17090412365413911947L,
  514. 0.62215109846016746276L,
  515. -0.195114782069495403315L,
  516. 0.0391523431392967238166L,
  517. -0.00504800158663705747345L,
  518. 0.000389034007436065401822L,
  519. -0.138972589601781706598e-4L
  520. };
  521. static const T r1 = static_cast<T>(1677624236387711.0L / 4503599627370496.0L);
  522. static const T r2 = 0.131401834143860282009280387409357165515556574352422001206362e-16L;
  523. static const T r = static_cast<T>(0.372507410781366634461991866580119133535689497771654051555657435242200120636201854384926049951548942392L);
  524. T t = (z / 3) - 1;
  525. result = tools::evaluate_polynomial(P, t)
  526. / tools::evaluate_polynomial(Q, t);
  527. t = (z - r1) - r2;
  528. result *= t;
  529. if(fabs(t) < 0.1)
  530. {
  531. result += boost::math::log1p(t / r);
  532. }
  533. else
  534. {
  535. result += log(z / r);
  536. }
  537. }
  538. else if (z <= 10)
  539. {
  540. // Maximum Deviation Found: 6.546e-17
  541. // Expected Error Term: 6.546e-17
  542. // Max Error found at double precision = Poly: 6.890169e-17 Cheb: 6.772128e-17
  543. static const T Y = 1.158985137939453125F;
  544. static const T P[8] = {
  545. 0.00139324086199402804173L,
  546. -0.0349921221823888744966L,
  547. -0.0264095520754134848538L,
  548. -0.00761224003005476438412L,
  549. -0.00247496209592143627977L,
  550. -0.000374885917942100256775L,
  551. -0.554086272024881826253e-4L,
  552. -0.396487648924804510056e-5L
  553. };
  554. static const T Q[8] = {
  555. 1L,
  556. 0.744625566823272107711L,
  557. 0.329061095011767059236L,
  558. 0.100128624977313872323L,
  559. 0.0223851099128506347278L,
  560. 0.00365334190742316650106L,
  561. 0.000402453408512476836472L,
  562. 0.263649630720255691787e-4L
  563. };
  564. T t = z / 2 - 4;
  565. result = Y + tools::evaluate_polynomial(P, t)
  566. / tools::evaluate_polynomial(Q, t);
  567. result *= exp(z) / z;
  568. result += z;
  569. }
  570. else if(z <= 20)
  571. {
  572. // Maximum Deviation Found: 1.843e-17
  573. // Expected Error Term: -1.842e-17
  574. // Max Error found at double precision = Poly: 4.375868e-17 Cheb: 5.860967e-17
  575. static const T Y = 1.0869731903076171875F;
  576. static const T P[9] = {
  577. -0.00893891094356945667451L,
  578. -0.0484607730127134045806L,
  579. -0.0652810444222236895772L,
  580. -0.0478447572647309671455L,
  581. -0.0226059218923777094596L,
  582. -0.00720603636917482065907L,
  583. -0.00155941947035972031334L,
  584. -0.000209750022660200888349L,
  585. -0.138652200349182596186e-4L
  586. };
  587. static const T Q[9] = {
  588. 1L,
  589. 1.97017214039061194971L,
  590. 1.86232465043073157508L,
  591. 1.09601437090337519977L,
  592. 0.438873285773088870812L,
  593. 0.122537731979686102756L,
  594. 0.0233458478275769288159L,
  595. 0.00278170769163303669021L,
  596. 0.000159150281166108755531L
  597. };
  598. T t = z / 5 - 3;
  599. result = Y + tools::evaluate_polynomial(P, t)
  600. / tools::evaluate_polynomial(Q, t);
  601. result *= exp(z) / z;
  602. result += z;
  603. }
  604. else if(z <= 40)
  605. {
  606. // Maximum Deviation Found: 5.102e-18
  607. // Expected Error Term: 5.101e-18
  608. // Max Error found at double precision = Poly: 1.441088e-16 Cheb: 1.864792e-16
  609. static const T Y = 1.03937530517578125F;
  610. static const T P[9] = {
  611. -0.00356165148914447597995L,
  612. -0.0229930320357982333406L,
  613. -0.0449814350482277917716L,
  614. -0.0453759383048193402336L,
  615. -0.0272050837209380717069L,
  616. -0.00994403059883350813295L,
  617. -0.00207592267812291726961L,
  618. -0.000192178045857733706044L,
  619. -0.113161784705911400295e-9L
  620. };
  621. static const T Q[9] = {
  622. 1L,
  623. 2.84354408840148561131L,
  624. 3.6599610090072393012L,
  625. 2.75088464344293083595L,
  626. 1.2985244073998398643L,
  627. 0.383213198510794507409L,
  628. 0.0651165455496281337831L,
  629. 0.00488071077519227853585L
  630. };
  631. T t = z / 10 - 3;
  632. result = Y + tools::evaluate_polynomial(P, t)
  633. / tools::evaluate_polynomial(Q, t);
  634. result *= exp(z) / z;
  635. result += z;
  636. }
  637. else
  638. {
  639. // Max Error found at double precision = 3.381886e-17
  640. static const T exp40 = static_cast<T>(2.35385266837019985407899910749034804508871617254555467236651e17L);
  641. static const T Y= 1.013065338134765625F;
  642. static const T P[6] = {
  643. -0.0130653381347656243849L,
  644. 0.19029710559486576682L,
  645. 94.7365094537197236011L,
  646. -2516.35323679844256203L,
  647. 18932.0850014925993025L,
  648. -38703.1431362056714134L
  649. };
  650. static const T Q[7] = {
  651. 1L,
  652. 61.9733592849439884145L,
  653. -2354.56211323420194283L,
  654. 22329.1459489893079041L,
  655. -70126.245140396567133L,
  656. 54738.2833147775537106L,
  657. 8297.16296356518409347L
  658. };
  659. T t = 1 / z;
  660. result = Y + tools::evaluate_polynomial(P, t)
  661. / tools::evaluate_polynomial(Q, t);
  662. if(z < 41)
  663. result *= exp(z) / z;
  664. else
  665. {
  666. // Avoid premature overflow if we can:
  667. t = z - 40;
  668. if(t > tools::log_max_value<T>())
  669. {
  670. result = policies::raise_overflow_error<T>(function, 0, pol);
  671. }
  672. else
  673. {
  674. result *= exp(z - 40) / z;
  675. if(result > tools::max_value<T>() / exp40)
  676. {
  677. result = policies::raise_overflow_error<T>(function, 0, pol);
  678. }
  679. else
  680. {
  681. result *= exp40;
  682. }
  683. }
  684. }
  685. result += z;
  686. }
  687. return result;
  688. }
  689. template <class T, class Policy>
  690. T expint_i_imp(T z, const Policy& pol, const mpl::int_<64>& tag)
  691. {
  692. BOOST_MATH_STD_USING
  693. static const char* function = "boost::math::expint<%1%>(%1%)";
  694. if(z < 0)
  695. return -expint_imp(1, -z, pol, tag);
  696. if(z == 0)
  697. return -policies::raise_overflow_error<T>(function, 0, pol);
  698. T result;
  699. if(z <= 6)
  700. {
  701. // Maximum Deviation Found: 3.883e-21
  702. // Expected Error Term: 3.883e-21
  703. // Max Error found at long double precision = Poly: 3.344801e-19 Cheb: 4.989937e-19
  704. static const T P[11] = {
  705. 2.98677224343598593764L,
  706. 0.25891613550886736592L,
  707. 0.789323584998672832285L,
  708. 0.092432587824602399339L,
  709. 0.0514236978728625906656L,
  710. 0.00658477469745132977921L,
  711. 0.00124914538197086254233L,
  712. 0.000131429679565472408551L,
  713. 0.11293331317982763165e-4L,
  714. 0.629499283139417444244e-6L,
  715. 0.177833045143692498221e-7L
  716. };
  717. static const T Q[9] = {
  718. 1L,
  719. -1.20352377969742325748L,
  720. 0.66707904942606479811L,
  721. -0.223014531629140771914L,
  722. 0.0493340022262908008636L,
  723. -0.00741934273050807310677L,
  724. 0.00074353567782087939294L,
  725. -0.455861727069603367656e-4L,
  726. 0.131515429329812837701e-5L
  727. };
  728. static const T r1 = static_cast<T>(1677624236387711.0L / 4503599627370496.0L);
  729. static const T r2 = 0.131401834143860282009280387409357165515556574352422001206362e-16L;
  730. static const T r = static_cast<T>(0.372507410781366634461991866580119133535689497771654051555657435242200120636201854384926049951548942392L);
  731. T t = (z / 3) - 1;
  732. result = tools::evaluate_polynomial(P, t)
  733. / tools::evaluate_polynomial(Q, t);
  734. t = (z - r1) - r2;
  735. result *= t;
  736. if(fabs(t) < 0.1)
  737. {
  738. result += boost::math::log1p(t / r);
  739. }
  740. else
  741. {
  742. result += log(z / r);
  743. }
  744. }
  745. else if (z <= 10)
  746. {
  747. // Maximum Deviation Found: 2.622e-21
  748. // Expected Error Term: -2.622e-21
  749. // Max Error found at long double precision = Poly: 1.208328e-20 Cheb: 1.073723e-20
  750. static const T Y = 1.158985137939453125F;
  751. static const T P[9] = {
  752. 0.00139324086199409049399L,
  753. -0.0345238388952337563247L,
  754. -0.0382065278072592940767L,
  755. -0.0156117003070560727392L,
  756. -0.00383276012430495387102L,
  757. -0.000697070540945496497992L,
  758. -0.877310384591205930343e-4L,
  759. -0.623067256376494930067e-5L,
  760. -0.377246883283337141444e-6L
  761. };
  762. static const T Q[10] = {
  763. 1L,
  764. 1.08073635708902053767L,
  765. 0.553681133533942532909L,
  766. 0.176763647137553797451L,
  767. 0.0387891748253869928121L,
  768. 0.0060603004848394727017L,
  769. 0.000670519492939992806051L,
  770. 0.4947357050100855646e-4L,
  771. 0.204339282037446434827e-5L,
  772. 0.146951181174930425744e-7L
  773. };
  774. T t = z / 2 - 4;
  775. result = Y + tools::evaluate_polynomial(P, t)
  776. / tools::evaluate_polynomial(Q, t);
  777. result *= exp(z) / z;
  778. result += z;
  779. }
  780. else if(z <= 20)
  781. {
  782. // Maximum Deviation Found: 3.220e-20
  783. // Expected Error Term: 3.220e-20
  784. // Max Error found at long double precision = Poly: 7.696841e-20 Cheb: 6.205163e-20
  785. static const T Y = 1.0869731903076171875F;
  786. static const T P[10] = {
  787. -0.00893891094356946995368L,
  788. -0.0487562980088748775943L,
  789. -0.0670568657950041926085L,
  790. -0.0509577352851442932713L,
  791. -0.02551800927409034206L,
  792. -0.00892913759760086687083L,
  793. -0.00224469630207344379888L,
  794. -0.000392477245911296982776L,
  795. -0.44424044184395578775e-4L,
  796. -0.252788029251437017959e-5L
  797. };
  798. static const T Q[10] = {
  799. 1L,
  800. 2.00323265503572414261L,
  801. 1.94688958187256383178L,
  802. 1.19733638134417472296L,
  803. 0.513137726038353385661L,
  804. 0.159135395578007264547L,
  805. 0.0358233587351620919881L,
  806. 0.0056716655597009417875L,
  807. 0.000577048986213535829925L,
  808. 0.290976943033493216793e-4L
  809. };
  810. T t = z / 5 - 3;
  811. result = Y + tools::evaluate_polynomial(P, t)
  812. / tools::evaluate_polynomial(Q, t);
  813. result *= exp(z) / z;
  814. result += z;
  815. }
  816. else if(z <= 40)
  817. {
  818. // Maximum Deviation Found: 2.940e-21
  819. // Expected Error Term: -2.938e-21
  820. // Max Error found at long double precision = Poly: 3.419893e-19 Cheb: 3.359874e-19
  821. static const T Y = 1.03937530517578125F;
  822. static const T P[12] = {
  823. -0.00356165148914447278177L,
  824. -0.0240235006148610849678L,
  825. -0.0516699967278057976119L,
  826. -0.0586603078706856245674L,
  827. -0.0409960120868776180825L,
  828. -0.0185485073689590665153L,
  829. -0.00537842101034123222417L,
  830. -0.000920988084778273760609L,
  831. -0.716742618812210980263e-4L,
  832. -0.504623302166487346677e-9L,
  833. 0.712662196671896837736e-10L,
  834. -0.533769629702262072175e-11L
  835. };
  836. static const T Q[9] = {
  837. 1L,
  838. 3.13286733695729715455L,
  839. 4.49281223045653491929L,
  840. 3.84900294427622911374L,
  841. 2.15205199043580378211L,
  842. 0.802912186540269232424L,
  843. 0.194793170017818925388L,
  844. 0.0280128013584653182994L,
  845. 0.00182034930799902922549L
  846. };
  847. T t = z / 10 - 3;
  848. result = Y + tools::evaluate_polynomial(P, t)
  849. / tools::evaluate_polynomial(Q, t);
  850. BOOST_MATH_INSTRUMENT_VARIABLE(result)
  851. result *= exp(z) / z;
  852. BOOST_MATH_INSTRUMENT_VARIABLE(result)
  853. result += z;
  854. BOOST_MATH_INSTRUMENT_VARIABLE(result)
  855. }
  856. else
  857. {
  858. // Maximum Deviation Found: 3.536e-20
  859. // Max Error found at long double precision = Poly: 1.310671e-19 Cheb: 8.630943e-11
  860. static const T exp40 = static_cast<T>(2.35385266837019985407899910749034804508871617254555467236651e17L);
  861. static const T Y= 1.013065338134765625F;
  862. static const T P[9] = {
  863. -0.0130653381347656250004L,
  864. 0.644487780349757303739L,
  865. 143.995670348227433964L,
  866. -13918.9322758014173709L,
  867. 476260.975133624194484L,
  868. -7437102.15135982802122L,
  869. 53732298.8764767916542L,
  870. -160695051.957997452509L,
  871. 137839271.592778020028L
  872. };
  873. static const T Q[9] = {
  874. 1L,
  875. 27.2103343964943718802L,
  876. -8785.48528692879413676L,
  877. 397530.290000322626766L,
  878. -7356441.34957799368252L,
  879. 63050914.5343400957524L,
  880. -246143779.638307701369L,
  881. 384647824.678554961174L,
  882. -166288297.874583961493L
  883. };
  884. T t = 1 / z;
  885. result = Y + tools::evaluate_polynomial(P, t)
  886. / tools::evaluate_polynomial(Q, t);
  887. if(z < 41)
  888. result *= exp(z) / z;
  889. else
  890. {
  891. // Avoid premature overflow if we can:
  892. t = z - 40;
  893. if(t > tools::log_max_value<T>())
  894. {
  895. result = policies::raise_overflow_error<T>(function, 0, pol);
  896. }
  897. else
  898. {
  899. result *= exp(z - 40) / z;
  900. if(result > tools::max_value<T>() / exp40)
  901. {
  902. result = policies::raise_overflow_error<T>(function, 0, pol);
  903. }
  904. else
  905. {
  906. result *= exp40;
  907. }
  908. }
  909. }
  910. result += z;
  911. }
  912. return result;
  913. }
  914. template <class T, class Policy>
  915. T expint_i_imp(T z, const Policy& pol, const mpl::int_<113>& tag)
  916. {
  917. BOOST_MATH_STD_USING
  918. static const char* function = "boost::math::expint<%1%>(%1%)";
  919. if(z < 0)
  920. return -expint_imp(1, -z, pol, tag);
  921. if(z == 0)
  922. return -policies::raise_overflow_error<T>(function, 0, pol);
  923. T result;
  924. if(z <= 6)
  925. {
  926. // Maximum Deviation Found: 1.230e-36
  927. // Expected Error Term: -1.230e-36
  928. // Max Error found at long double precision = Poly: 4.355299e-34 Cheb: 7.512581e-34
  929. static const T P[15] = {
  930. 2.98677224343598593765287235997328555L,
  931. -0.333256034674702967028780537349334037L,
  932. 0.851831522798101228384971644036708463L,
  933. -0.0657854833494646206186773614110374948L,
  934. 0.0630065662557284456000060708977935073L,
  935. -0.00311759191425309373327784154659649232L,
  936. 0.00176213568201493949664478471656026771L,
  937. -0.491548660404172089488535218163952295e-4L,
  938. 0.207764227621061706075562107748176592e-4L,
  939. -0.225445398156913584846374273379402765e-6L,
  940. 0.996939977231410319761273881672601592e-7L,
  941. 0.212546902052178643330520878928100847e-9L,
  942. 0.154646053060262871360159325115980023e-9L,
  943. 0.143971277122049197323415503594302307e-11L,
  944. 0.306243138978114692252817805327426657e-13L
  945. };
  946. static const T Q[15] = {
  947. 1L,
  948. -1.40178870313943798705491944989231793L,
  949. 0.943810968269701047641218856758605284L,
  950. -0.405026631534345064600850391026113165L,
  951. 0.123924153524614086482627660399122762L,
  952. -0.0286364505373369439591132549624317707L,
  953. 0.00516148845910606985396596845494015963L,
  954. -0.000738330799456364820380739850924783649L,
  955. 0.843737760991856114061953265870882637e-4L,
  956. -0.767957673431982543213661388914587589e-5L,
  957. 0.549136847313854595809952100614840031e-6L,
  958. -0.299801381513743676764008325949325404e-7L,
  959. 0.118419479055346106118129130945423483e-8L,
  960. -0.30372295663095470359211949045344607e-10L,
  961. 0.382742953753485333207877784720070523e-12L
  962. };
  963. static const T r1 = static_cast<T>(1677624236387711.0L / 4503599627370496.0L);
  964. static const T r2 = static_cast<T>(266514582277687.0L / 4503599627370496.0L / 4503599627370496.0L);
  965. static const T r3 = static_cast<T>(0.283806480836357377069325311780969887585024578164571984232357e-31L);
  966. static const T r = static_cast<T>(0.372507410781366634461991866580119133535689497771654051555657435242200120636201854384926049951548942392L);
  967. T t = (z / 3) - 1;
  968. result = tools::evaluate_polynomial(P, t)
  969. / tools::evaluate_polynomial(Q, t);
  970. t = ((z - r1) - r2) - r3;
  971. result *= t;
  972. if(fabs(t) < 0.1)
  973. {
  974. result += boost::math::log1p(t / r);
  975. }
  976. else
  977. {
  978. result += log(z / r);
  979. }
  980. }
  981. else if (z <= 10)
  982. {
  983. // Maximum Deviation Found: 7.779e-36
  984. // Expected Error Term: -7.779e-36
  985. // Max Error found at long double precision = Poly: 2.576723e-35 Cheb: 1.236001e-34
  986. static const T Y = 1.158985137939453125F;
  987. static const T P[15] = {
  988. 0.00139324086199409049282472239613554817L,
  989. -0.0338173111691991289178779840307998955L,
  990. -0.0555972290794371306259684845277620556L,
  991. -0.0378677976003456171563136909186202177L,
  992. -0.0152221583517528358782902783914356667L,
  993. -0.00428283334203873035104248217403126905L,
  994. -0.000922782631491644846511553601323435286L,
  995. -0.000155513428088853161562660696055496696L,
  996. -0.205756580255359882813545261519317096e-4L,
  997. -0.220327406578552089820753181821115181e-5L,
  998. -0.189483157545587592043421445645377439e-6L,
  999. -0.122426571518570587750898968123803867e-7L,
  1000. -0.635187358949437991465353268374523944e-9L,
  1001. -0.203015132965870311935118337194860863e-10L,
  1002. -0.384276705503357655108096065452950822e-12L
  1003. };
  1004. static const T Q[15] = {
  1005. 1L,
  1006. 1.58784732785354597996617046880946257L,
  1007. 1.18550755302279446339364262338114098L,
  1008. 0.55598993549661368604527040349702836L,
  1009. 0.184290888380564236919107835030984453L,
  1010. 0.0459658051803613282360464632326866113L,
  1011. 0.0089505064268613225167835599456014705L,
  1012. 0.00139042673882987693424772855926289077L,
  1013. 0.000174210708041584097450805790176479012L,
  1014. 0.176324034009707558089086875136647376e-4L,
  1015. 0.142935845999505649273084545313710581e-5L,
  1016. 0.907502324487057260675816233312747784e-7L,
  1017. 0.431044337808893270797934621235918418e-8L,
  1018. 0.139007266881450521776529705677086902e-9L,
  1019. 0.234715286125516430792452741830364672e-11L
  1020. };
  1021. T t = z / 2 - 4;
  1022. result = Y + tools::evaluate_polynomial(P, t)
  1023. / tools::evaluate_polynomial(Q, t);
  1024. result *= exp(z) / z;
  1025. result += z;
  1026. }
  1027. else if(z <= 18)
  1028. {
  1029. // Maximum Deviation Found: 1.082e-34
  1030. // Expected Error Term: 1.080e-34
  1031. // Max Error found at long double precision = Poly: 1.958294e-34 Cheb: 2.472261e-34
  1032. static const T Y = 1.091579437255859375F;
  1033. static const T P[17] = {
  1034. -0.00685089599550151282724924894258520532L,
  1035. -0.0443313550253580053324487059748497467L,
  1036. -0.071538561252424027443296958795814874L,
  1037. -0.0622923153354102682285444067843300583L,
  1038. -0.0361631270264607478205393775461208794L,
  1039. -0.0153192826839624850298106509601033261L,
  1040. -0.00496967904961260031539602977748408242L,
  1041. -0.00126989079663425780800919171538920589L,
  1042. -0.000258933143097125199914724875206326698L,
  1043. -0.422110326689204794443002330541441956e-4L,
  1044. -0.546004547590412661451073996127115221e-5L,
  1045. -0.546775260262202177131068692199272241e-6L,
  1046. -0.404157632825805803833379568956559215e-7L,
  1047. -0.200612596196561323832327013027419284e-8L,
  1048. -0.502538501472133913417609379765434153e-10L,
  1049. -0.326283053716799774936661568391296584e-13L,
  1050. 0.869226483473172853557775877908693647e-15L
  1051. };
  1052. static const T Q[15] = {
  1053. 1L,
  1054. 2.23227220874479061894038229141871087L,
  1055. 2.40221000361027971895657505660959863L,
  1056. 1.65476320985936174728238416007084214L,
  1057. 0.816828602963895720369875535001248227L,
  1058. 0.306337922909446903672123418670921066L,
  1059. 0.0902400121654409267774593230720600752L,
  1060. 0.0212708882169429206498765100993228086L,
  1061. 0.00404442626252467471957713495828165491L,
  1062. 0.0006195601618842253612635241404054589L,
  1063. 0.755930932686543009521454653994321843e-4L,
  1064. 0.716004532773778954193609582677482803e-5L,
  1065. 0.500881663076471627699290821742924233e-6L,
  1066. 0.233593219218823384508105943657387644e-7L,
  1067. 0.554900353169148897444104962034267682e-9L
  1068. };
  1069. T t = z / 4 - 3.5;
  1070. result = Y + tools::evaluate_polynomial(P, t)
  1071. / tools::evaluate_polynomial(Q, t);
  1072. result *= exp(z) / z;
  1073. result += z;
  1074. }
  1075. else if(z <= 26)
  1076. {
  1077. // Maximum Deviation Found: 3.163e-35
  1078. // Expected Error Term: 3.163e-35
  1079. // Max Error found at long double precision = Poly: 4.158110e-35 Cheb: 5.385532e-35
  1080. static const T Y = 1.051731109619140625F;
  1081. static const T P[14] = {
  1082. -0.00144552494420652573815404828020593565L,
  1083. -0.0126747451594545338365684731262912741L,
  1084. -0.01757394877502366717526779263438073L,
  1085. -0.0126838952395506921945756139424722588L,
  1086. -0.0060045057928894974954756789352443522L,
  1087. -0.00205349237147226126653803455793107903L,
  1088. -0.000532606040579654887676082220195624207L,
  1089. -0.000107344687098019891474772069139014662L,
  1090. -0.169536802705805811859089949943435152e-4L,
  1091. -0.20863311729206543881826553010120078e-5L,
  1092. -0.195670358542116256713560296776654385e-6L,
  1093. -0.133291168587253145439184028259772437e-7L,
  1094. -0.595500337089495614285777067722823397e-9L,
  1095. -0.133141358866324100955927979606981328e-10L
  1096. };
  1097. static const T Q[14] = {
  1098. 1L,
  1099. 1.72490783907582654629537013560044682L,
  1100. 1.44524329516800613088375685659759765L,
  1101. 0.778241785539308257585068744978050181L,
  1102. 0.300520486589206605184097270225725584L,
  1103. 0.0879346899691339661394537806057953957L,
  1104. 0.0200802415843802892793583043470125006L,
  1105. 0.00362842049172586254520256100538273214L,
  1106. 0.000519731362862955132062751246769469957L,
  1107. 0.584092147914050999895178697392282665e-4L,
  1108. 0.501851497707855358002773398333542337e-5L,
  1109. 0.313085677467921096644895738538865537e-6L,
  1110. 0.127552010539733113371132321521204458e-7L,
  1111. 0.25737310826983451144405899970774587e-9L
  1112. };
  1113. T t = z / 4 - 5.5;
  1114. result = Y + tools::evaluate_polynomial(P, t)
  1115. / tools::evaluate_polynomial(Q, t);
  1116. BOOST_MATH_INSTRUMENT_VARIABLE(result)
  1117. result *= exp(z) / z;
  1118. BOOST_MATH_INSTRUMENT_VARIABLE(result)
  1119. result += z;
  1120. BOOST_MATH_INSTRUMENT_VARIABLE(result)
  1121. }
  1122. else if(z <= 42)
  1123. {
  1124. // Maximum Deviation Found: 7.972e-36
  1125. // Expected Error Term: 7.962e-36
  1126. // Max Error found at long double precision = Poly: 1.711721e-34 Cheb: 3.100018e-34
  1127. static const T Y = 1.032726287841796875F;
  1128. static const T P[15] = {
  1129. -0.00141056919297307534690895009969373233L,
  1130. -0.0123384175302540291339020257071411437L,
  1131. -0.0298127270706864057791526083667396115L,
  1132. -0.0390686759471630584626293670260768098L,
  1133. -0.0338226792912607409822059922949035589L,
  1134. -0.0211659736179834946452561197559654582L,
  1135. -0.0100428887460879377373158821400070313L,
  1136. -0.00370717396015165148484022792801682932L,
  1137. -0.0010768667551001624764329000496561659L,
  1138. -0.000246127328761027039347584096573123531L,
  1139. -0.437318110527818613580613051861991198e-4L,
  1140. -0.587532682329299591501065482317771497e-5L,
  1141. -0.565697065670893984610852937110819467e-6L,
  1142. -0.350233957364028523971768887437839573e-7L,
  1143. -0.105428907085424234504608142258423505e-8L
  1144. };
  1145. static const T Q[16] = {
  1146. 1L,
  1147. 3.17261315255467581204685605414005525L,
  1148. 4.85267952971640525245338392887217426L,
  1149. 4.74341914912439861451492872946725151L,
  1150. 3.31108463283559911602405970817931801L,
  1151. 1.74657006336994649386607925179848899L,
  1152. 0.718255607416072737965933040353653244L,
  1153. 0.234037553177354542791975767960643864L,
  1154. 0.0607470145906491602476833515412605389L,
  1155. 0.0125048143774226921434854172947548724L,
  1156. 0.00201034366420433762935768458656609163L,
  1157. 0.000244823338417452367656368849303165721L,
  1158. 0.213511655166983177960471085462540807e-4L,
  1159. 0.119323998465870686327170541547982932e-5L,
  1160. 0.322153582559488797803027773591727565e-7L,
  1161. -0.161635525318683508633792845159942312e-16L
  1162. };
  1163. T t = z / 8 - 4.25;
  1164. result = Y + tools::evaluate_polynomial(P, t)
  1165. / tools::evaluate_polynomial(Q, t);
  1166. BOOST_MATH_INSTRUMENT_VARIABLE(result)
  1167. result *= exp(z) / z;
  1168. BOOST_MATH_INSTRUMENT_VARIABLE(result)
  1169. result += z;
  1170. BOOST_MATH_INSTRUMENT_VARIABLE(result)
  1171. }
  1172. else if(z <= 56)
  1173. {
  1174. // Maximum Deviation Found: 4.469e-36
  1175. // Expected Error Term: 4.468e-36
  1176. // Max Error found at long double precision = Poly: 1.288958e-35 Cheb: 2.304586e-35
  1177. static const T Y = 1.0216197967529296875F;
  1178. static const T P[12] = {
  1179. -0.000322999116096627043476023926572650045L,
  1180. -0.00385606067447365187909164609294113346L,
  1181. -0.00686514524727568176735949971985244415L,
  1182. -0.00606260649593050194602676772589601799L,
  1183. -0.00334382362017147544335054575436194357L,
  1184. -0.00126108534260253075708625583630318043L,
  1185. -0.000337881489347846058951220431209276776L,
  1186. -0.648480902304640018785370650254018022e-4L,
  1187. -0.87652644082970492211455290209092766e-5L,
  1188. -0.794712243338068631557849449519994144e-6L,
  1189. -0.434084023639508143975983454830954835e-7L,
  1190. -0.107839681938752337160494412638656696e-8L
  1191. };
  1192. static const T Q[12] = {
  1193. 1L,
  1194. 2.09913805456661084097134805151524958L,
  1195. 2.07041755535439919593503171320431849L,
  1196. 1.26406517226052371320416108604874734L,
  1197. 0.529689923703770353961553223973435569L,
  1198. 0.159578150879536711042269658656115746L,
  1199. 0.0351720877642000691155202082629857131L,
  1200. 0.00565313621289648752407123620997063122L,
  1201. 0.000646920278540515480093843570291218295L,
  1202. 0.499904084850091676776993523323213591e-4L,
  1203. 0.233740058688179614344680531486267142e-5L,
  1204. 0.498800627828842754845418576305379469e-7L
  1205. };
  1206. T t = z / 7 - 7;
  1207. result = Y + tools::evaluate_polynomial(P, t)
  1208. / tools::evaluate_polynomial(Q, t);
  1209. BOOST_MATH_INSTRUMENT_VARIABLE(result)
  1210. result *= exp(z) / z;
  1211. BOOST_MATH_INSTRUMENT_VARIABLE(result)
  1212. result += z;
  1213. BOOST_MATH_INSTRUMENT_VARIABLE(result)
  1214. }
  1215. else if(z <= 84)
  1216. {
  1217. // Maximum Deviation Found: 5.588e-35
  1218. // Expected Error Term: -5.566e-35
  1219. // Max Error found at long double precision = Poly: 9.976345e-35 Cheb: 8.358865e-35
  1220. static const T Y = 1.015148162841796875F;
  1221. static const T P[11] = {
  1222. -0.000435714784725086961464589957142615216L,
  1223. -0.00432114324353830636009453048419094314L,
  1224. -0.0100740363285526177522819204820582424L,
  1225. -0.0116744115827059174392383504427640362L,
  1226. -0.00816145387784261141360062395898644652L,
  1227. -0.00371380272673500791322744465394211508L,
  1228. -0.00112958263488611536502153195005736563L,
  1229. -0.000228316462389404645183269923754256664L,
  1230. -0.29462181955852860250359064291292577e-4L,
  1231. -0.21972450610957417963227028788460299e-5L,
  1232. -0.720558173805289167524715527536874694e-7L
  1233. };
  1234. static const T Q[11] = {
  1235. 1L,
  1236. 2.95918362458402597039366979529287095L,
  1237. 3.96472247520659077944638411856748924L,
  1238. 3.15563251550528513747923714884142131L,
  1239. 1.64674612007093983894215359287448334L,
  1240. 0.58695020129846594405856226787156424L,
  1241. 0.144358385319329396231755457772362793L,
  1242. 0.024146911506411684815134916238348063L,
  1243. 0.0026257132337460784266874572001650153L,
  1244. 0.000167479843750859222348869769094711093L,
  1245. 0.475673638665358075556452220192497036e-5L
  1246. };
  1247. T t = z / 14 - 5;
  1248. result = Y + tools::evaluate_polynomial(P, t)
  1249. / tools::evaluate_polynomial(Q, t);
  1250. BOOST_MATH_INSTRUMENT_VARIABLE(result)
  1251. result *= exp(z) / z;
  1252. BOOST_MATH_INSTRUMENT_VARIABLE(result)
  1253. result += z;
  1254. BOOST_MATH_INSTRUMENT_VARIABLE(result)
  1255. }
  1256. else if(z <= 210)
  1257. {
  1258. // Maximum Deviation Found: 4.448e-36
  1259. // Expected Error Term: 4.445e-36
  1260. // Max Error found at long double precision = Poly: 2.058532e-35 Cheb: 2.165465e-27
  1261. static const T Y= 1.00849151611328125F;
  1262. static const T P[9] = {
  1263. -0.0084915161132812500000001440233607358L,
  1264. 1.84479378737716028341394223076147872L,
  1265. -130.431146923726715674081563022115568L,
  1266. 4336.26945491571504885214176203512015L,
  1267. -76279.0031974974730095170437591004177L,
  1268. 729577.956271997673695191455111727774L,
  1269. -3661928.69330208734947103004900349266L,
  1270. 8570600.041606912735872059184527855L,
  1271. -6758379.93672362080947905580906028645L
  1272. };
  1273. static const T Q[10] = {
  1274. 1L,
  1275. -99.4868026047611434569541483506091713L,
  1276. 3879.67753690517114249705089803055473L,
  1277. -76495.82413252517165830203774900806L,
  1278. 820773.726408311894342553758526282667L,
  1279. -4803087.64956923577571031564909646579L,
  1280. 14521246.227703545012713173740895477L,
  1281. -19762752.0196769712258527849159393044L,
  1282. 8354144.67882768405803322344185185517L,
  1283. 355076.853106511136734454134915432571L
  1284. };
  1285. T t = 1 / z;
  1286. result = Y + tools::evaluate_polynomial(P, t)
  1287. / tools::evaluate_polynomial(Q, t);
  1288. result *= exp(z) / z;
  1289. result += z;
  1290. }
  1291. else // z > 210
  1292. {
  1293. // Maximum Deviation Found: 3.963e-37
  1294. // Expected Error Term: 3.963e-37
  1295. // Max Error found at long double precision = Poly: 1.248049e-36 Cheb: 2.843486e-29
  1296. static const T exp40 = static_cast<T>(2.35385266837019985407899910749034804508871617254555467236651e17L);
  1297. static const T Y= 1.00252532958984375F;
  1298. static const T P[8] = {
  1299. -0.00252532958984375000000000000000000085L,
  1300. 1.16591386866059087390621952073890359L,
  1301. -67.8483431314018462417456828499277579L,
  1302. 1567.68688154683822956359536287575892L,
  1303. -17335.4683325819116482498725687644986L,
  1304. 93632.6567462673524739954389166550069L,
  1305. -225025.189335919133214440347510936787L,
  1306. 175864.614717440010942804684741336853L
  1307. };
  1308. static const T Q[9] = {
  1309. 1L,
  1310. -65.6998869881600212224652719706425129L,
  1311. 1642.73850032324014781607859416890077L,
  1312. -19937.2610222467322481947237312818575L,
  1313. 124136.267326632742667972126625064538L,
  1314. -384614.251466704550678760562965502293L,
  1315. 523355.035910385688578278384032026998L,
  1316. -217809.552260834025885677791936351294L,
  1317. -8555.81719551123640677261226549550872L
  1318. };
  1319. T t = 1 / z;
  1320. result = Y + tools::evaluate_polynomial(P, t)
  1321. / tools::evaluate_polynomial(Q, t);
  1322. if(z < 41)
  1323. result *= exp(z) / z;
  1324. else
  1325. {
  1326. // Avoid premature overflow if we can:
  1327. t = z - 40;
  1328. if(t > tools::log_max_value<T>())
  1329. {
  1330. result = policies::raise_overflow_error<T>(function, 0, pol);
  1331. }
  1332. else
  1333. {
  1334. result *= exp(z - 40) / z;
  1335. if(result > tools::max_value<T>() / exp40)
  1336. {
  1337. result = policies::raise_overflow_error<T>(function, 0, pol);
  1338. }
  1339. else
  1340. {
  1341. result *= exp40;
  1342. }
  1343. }
  1344. }
  1345. result += z;
  1346. }
  1347. return result;
  1348. }
  1349. template <class T, class Policy>
  1350. inline typename tools::promote_args<T>::type
  1351. expint_forwarder(T z, const Policy& /*pol*/, mpl::true_ const&)
  1352. {
  1353. typedef typename tools::promote_ar