gsl_specfunc__expint.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582
  1. /* specfunc/expint.c
  2. *
  3. * Copyright (C) 2007 Brian Gough
  4. * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002 Gerard Jungman
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 3 of the License, or (at
  9. * your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful, but
  12. * WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  19. */
  20. /* Author: G. Jungman */
  21. #include "gsl__config.h"
  22. #include "gsl_math.h"
  23. #include "gsl_errno.h"
  24. #include "gsl_sf_expint.h"
  25. #include "gsl_sf_gamma.h"
  26. #include "gsl_specfunc__error.h"
  27. #include "gsl_specfunc__check.h"
  28. #include "gsl_specfunc__chebyshev.h"
  29. #include "gsl_specfunc__cheb_eval.c"
  30. /*-*-*-*-*-*-*-*-*-*-*-* Private Section *-*-*-*-*-*-*-*-*-*-*-*/
  31. /*
  32. Chebyshev expansions: based on SLATEC e1.f, W. Fullerton
  33. Series for AE11 on the interval -1.00000D-01 to 0.
  34. with weighted error 1.76E-17
  35. log weighted error 16.75
  36. significant figures required 15.70
  37. decimal places required 17.55
  38. Series for AE12 on the interval -2.50000D-01 to -1.00000D-01
  39. with weighted error 5.83E-17
  40. log weighted error 16.23
  41. significant figures required 15.76
  42. decimal places required 16.93
  43. Series for E11 on the interval -4.00000D+00 to -1.00000D+00
  44. with weighted error 1.08E-18
  45. log weighted error 17.97
  46. significant figures required 19.02
  47. decimal places required 18.61
  48. Series for E12 on the interval -1.00000D+00 to 1.00000D+00
  49. with weighted error 3.15E-18
  50. log weighted error 17.50
  51. approx significant figures required 15.8
  52. decimal places required 18.10
  53. Series for AE13 on the interval 2.50000D-01 to 1.00000D+00
  54. with weighted error 2.34E-17
  55. log weighted error 16.63
  56. significant figures required 16.14
  57. decimal places required 17.33
  58. Series for AE14 on the interval 0. to 2.50000D-01
  59. with weighted error 5.41E-17
  60. log weighted error 16.27
  61. significant figures required 15.38
  62. decimal places required 16.97
  63. */
  64. static double AE11_data[39] = {
  65. 0.121503239716065790,
  66. -0.065088778513550150,
  67. 0.004897651357459670,
  68. -0.000649237843027216,
  69. 0.000093840434587471,
  70. 0.000000420236380882,
  71. -0.000008113374735904,
  72. 0.000002804247688663,
  73. 0.000000056487164441,
  74. -0.000000344809174450,
  75. 0.000000058209273578,
  76. 0.000000038711426349,
  77. -0.000000012453235014,
  78. -0.000000005118504888,
  79. 0.000000002148771527,
  80. 0.000000000868459898,
  81. -0.000000000343650105,
  82. -0.000000000179796603,
  83. 0.000000000047442060,
  84. 0.000000000040423282,
  85. -0.000000000003543928,
  86. -0.000000000008853444,
  87. -0.000000000000960151,
  88. 0.000000000001692921,
  89. 0.000000000000607990,
  90. -0.000000000000224338,
  91. -0.000000000000200327,
  92. -0.000000000000006246,
  93. 0.000000000000045571,
  94. 0.000000000000016383,
  95. -0.000000000000005561,
  96. -0.000000000000006074,
  97. -0.000000000000000862,
  98. 0.000000000000001223,
  99. 0.000000000000000716,
  100. -0.000000000000000024,
  101. -0.000000000000000201,
  102. -0.000000000000000082,
  103. 0.000000000000000017
  104. };
  105. static cheb_series AE11_cs = {
  106. AE11_data,
  107. 38,
  108. -1, 1,
  109. 20
  110. };
  111. static double AE12_data[25] = {
  112. 0.582417495134726740,
  113. -0.158348850905782750,
  114. -0.006764275590323141,
  115. 0.005125843950185725,
  116. 0.000435232492169391,
  117. -0.000143613366305483,
  118. -0.000041801320556301,
  119. -0.000002713395758640,
  120. 0.000001151381913647,
  121. 0.000000420650022012,
  122. 0.000000066581901391,
  123. 0.000000000662143777,
  124. -0.000000002844104870,
  125. -0.000000000940724197,
  126. -0.000000000177476602,
  127. -0.000000000015830222,
  128. 0.000000000002905732,
  129. 0.000000000001769356,
  130. 0.000000000000492735,
  131. 0.000000000000093709,
  132. 0.000000000000010707,
  133. -0.000000000000000537,
  134. -0.000000000000000716,
  135. -0.000000000000000244,
  136. -0.000000000000000058
  137. };
  138. static cheb_series AE12_cs = {
  139. AE12_data,
  140. 24,
  141. -1, 1,
  142. 15
  143. };
  144. static double E11_data[19] = {
  145. -16.11346165557149402600,
  146. 7.79407277874268027690,
  147. -1.95540581886314195070,
  148. 0.37337293866277945612,
  149. -0.05692503191092901938,
  150. 0.00721107776966009185,
  151. -0.00078104901449841593,
  152. 0.00007388093356262168,
  153. -0.00000620286187580820,
  154. 0.00000046816002303176,
  155. -0.00000003209288853329,
  156. 0.00000000201519974874,
  157. -0.00000000011673686816,
  158. 0.00000000000627627066,
  159. -0.00000000000031481541,
  160. 0.00000000000001479904,
  161. -0.00000000000000065457,
  162. 0.00000000000000002733,
  163. -0.00000000000000000108
  164. };
  165. static cheb_series E11_cs = {
  166. E11_data,
  167. 18,
  168. -1, 1,
  169. 13
  170. };
  171. static double E12_data[16] = {
  172. -0.03739021479220279500,
  173. 0.04272398606220957700,
  174. -0.13031820798497005440,
  175. 0.01441912402469889073,
  176. -0.00134617078051068022,
  177. 0.00010731029253063780,
  178. -0.00000742999951611943,
  179. 0.00000045377325690753,
  180. -0.00000002476417211390,
  181. 0.00000000122076581374,
  182. -0.00000000005485141480,
  183. 0.00000000000226362142,
  184. -0.00000000000008635897,
  185. 0.00000000000000306291,
  186. -0.00000000000000010148,
  187. 0.00000000000000000315
  188. };
  189. static cheb_series E12_cs = {
  190. E12_data,
  191. 15,
  192. -1, 1,
  193. 10
  194. };
  195. static double AE13_data[25] = {
  196. -0.605773246640603460,
  197. -0.112535243483660900,
  198. 0.013432266247902779,
  199. -0.001926845187381145,
  200. 0.000309118337720603,
  201. -0.000053564132129618,
  202. 0.000009827812880247,
  203. -0.000001885368984916,
  204. 0.000000374943193568,
  205. -0.000000076823455870,
  206. 0.000000016143270567,
  207. -0.000000003466802211,
  208. 0.000000000758754209,
  209. -0.000000000168864333,
  210. 0.000000000038145706,
  211. -0.000000000008733026,
  212. 0.000000000002023672,
  213. -0.000000000000474132,
  214. 0.000000000000112211,
  215. -0.000000000000026804,
  216. 0.000000000000006457,
  217. -0.000000000000001568,
  218. 0.000000000000000383,
  219. -0.000000000000000094,
  220. 0.000000000000000023
  221. };
  222. static cheb_series AE13_cs = {
  223. AE13_data,
  224. 24,
  225. -1, 1,
  226. 15
  227. };
  228. static double AE14_data[26] = {
  229. -0.18929180007530170,
  230. -0.08648117855259871,
  231. 0.00722410154374659,
  232. -0.00080975594575573,
  233. 0.00010999134432661,
  234. -0.00001717332998937,
  235. 0.00000298562751447,
  236. -0.00000056596491457,
  237. 0.00000011526808397,
  238. -0.00000002495030440,
  239. 0.00000000569232420,
  240. -0.00000000135995766,
  241. 0.00000000033846628,
  242. -0.00000000008737853,
  243. 0.00000000002331588,
  244. -0.00000000000641148,
  245. 0.00000000000181224,
  246. -0.00000000000052538,
  247. 0.00000000000015592,
  248. -0.00000000000004729,
  249. 0.00000000000001463,
  250. -0.00000000000000461,
  251. 0.00000000000000148,
  252. -0.00000000000000048,
  253. 0.00000000000000016,
  254. -0.00000000000000005
  255. };
  256. static cheb_series AE14_cs = {
  257. AE14_data,
  258. 25,
  259. -1, 1,
  260. 13
  261. };
  262. /* implementation for E1, allowing for scaling by exp(x) */
  263. static
  264. int expint_E1_impl(const double x, gsl_sf_result * result, const int scale)
  265. {
  266. const double xmaxt = -GSL_LOG_DBL_MIN; /* XMAXT = -LOG (R1MACH(1)) */
  267. const double xmax = xmaxt - log(xmaxt); /* XMAX = XMAXT - LOG(XMAXT) */
  268. /* CHECK_POINTER(result) */
  269. if(x < -xmax && !scale) {
  270. OVERFLOW_ERROR(result);
  271. }
  272. else if(x <= -10.0) {
  273. const double s = 1.0/x * ( scale ? 1.0 : exp(-x) );
  274. gsl_sf_result result_c;
  275. cheb_eval_e(&AE11_cs, 20.0/x+1.0, &result_c);
  276. result->val = s * (1.0 + result_c.val);
  277. result->err = s * result_c.err;
  278. result->err += 2.0 * GSL_DBL_EPSILON * (fabs(x) + 1.0) * fabs(result->val);
  279. return GSL_SUCCESS;
  280. }
  281. else if(x <= -4.0) {
  282. const double s = 1.0/x * ( scale ? 1.0 : exp(-x) );
  283. gsl_sf_result result_c;
  284. cheb_eval_e(&AE12_cs, (40.0/x+7.0)/3.0, &result_c);
  285. result->val = s * (1.0 + result_c.val);
  286. result->err = s * result_c.err;
  287. result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);
  288. return GSL_SUCCESS;
  289. }
  290. else if(x <= -1.0) {
  291. const double ln_term = -log(fabs(x));
  292. const double scale_factor = ( scale ? exp(x) : 1.0 );
  293. gsl_sf_result result_c;
  294. cheb_eval_e(&E11_cs, (2.0*x+5.0)/3.0, &result_c);
  295. result->val = scale_factor * (ln_term + result_c.val);
  296. result->err = scale_factor * (result_c.err + GSL_DBL_EPSILON * fabs(ln_term));
  297. result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);
  298. return GSL_SUCCESS;
  299. }
  300. else if(x == 0.0) {
  301. DOMAIN_ERROR(result);
  302. }
  303. else if(x <= 1.0) {
  304. const double ln_term = -log(fabs(x));
  305. const double scale_factor = ( scale ? exp(x) : 1.0 );
  306. gsl_sf_result result_c;
  307. cheb_eval_e(&E12_cs, x, &result_c);
  308. result->val = scale_factor * (ln_term - 0.6875 + x + result_c.val);
  309. result->err = scale_factor * (result_c.err + GSL_DBL_EPSILON * fabs(ln_term));
  310. result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);
  311. return GSL_SUCCESS;
  312. }
  313. else if(x <= 4.0) {
  314. const double s = 1.0/x * ( scale ? 1.0 : exp(-x) );
  315. gsl_sf_result result_c;
  316. cheb_eval_e(&AE13_cs, (8.0/x-5.0)/3.0, &result_c);
  317. result->val = s * (1.0 + result_c.val);
  318. result->err = s * result_c.err;
  319. result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);
  320. return GSL_SUCCESS;
  321. }
  322. else if(x <= xmax || scale) {
  323. const double s = 1.0/x * ( scale ? 1.0 : exp(-x) );
  324. gsl_sf_result result_c;
  325. cheb_eval_e(&AE14_cs, 8.0/x-1.0, &result_c);
  326. result->val = s * (1.0 + result_c.val);
  327. result->err = s * (GSL_DBL_EPSILON + result_c.err);
  328. result->err += 2.0 * (x + 1.0) * GSL_DBL_EPSILON * fabs(result->val);
  329. if(result->val == 0.0)
  330. UNDERFLOW_ERROR(result);
  331. else
  332. return GSL_SUCCESS;
  333. }
  334. else {
  335. UNDERFLOW_ERROR(result);
  336. }
  337. }
  338. static
  339. int expint_E2_impl(const double x, gsl_sf_result * result, const int scale)
  340. {
  341. const double xmaxt = -GSL_LOG_DBL_MIN;
  342. const double xmax = xmaxt - log(xmaxt);
  343. /* CHECK_POINTER(result) */
  344. if(x < -xmax && !scale) {
  345. OVERFLOW_ERROR(result);
  346. }
  347. else if (x == 0.0) {
  348. result->val = (scale ? 1.0 : 1.0);
  349. result->err = 0.0;
  350. return GSL_SUCCESS;
  351. } else if(x < 100.0) {
  352. const double ex = ( scale ? 1.0 : exp(-x) );
  353. gsl_sf_result result_E1;
  354. int stat_E1 = expint_E1_impl(x, &result_E1, scale);
  355. result->val = ex - x*result_E1.val;
  356. result->err = GSL_DBL_EPSILON*ex + fabs(x) * result_E1.err;
  357. result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);
  358. return stat_E1;
  359. }
  360. else if(x < xmax || scale) {
  361. const double s = ( scale ? 1.0 : exp(-x) );
  362. const double c1 = -2.0;
  363. const double c2 = 6.0;
  364. const double c3 = -24.0;
  365. const double c4 = 120.0;
  366. const double c5 = -720.0;
  367. const double c6 = 5040.0;
  368. const double c7 = -40320.0;
  369. const double c8 = 362880.0;
  370. const double c9 = -3628800.0;
  371. const double c10 = 39916800.0;
  372. const double c11 = -479001600.0;
  373. const double c12 = 6227020800.0;
  374. const double c13 = -87178291200.0;
  375. const double y = 1.0/x;
  376. const double sum6 = c6+y*(c7+y*(c8+y*(c9+y*(c10+y*(c11+y*(c12+y*c13))))));
  377. const double sum = y*(c1+y*(c2+y*(c3+y*(c4+y*(c5+y*sum6)))));
  378. result->val = s * (1.0 + sum)/x;
  379. result->err = 2.0 * (x + 1.0) * GSL_DBL_EPSILON * result->val;
  380. if(result->val == 0.0)
  381. UNDERFLOW_ERROR(result);
  382. else
  383. return GSL_SUCCESS;
  384. }
  385. else {
  386. UNDERFLOW_ERROR(result);
  387. }
  388. }
  389. static
  390. int expint_En_impl(const int n, const double x, gsl_sf_result * result, const int scale)
  391. {
  392. if (n < 0) {
  393. DOMAIN_ERROR(result);
  394. } else if (n == 0) {
  395. if (x == 0) {
  396. DOMAIN_ERROR(result);
  397. } else {
  398. result->val = (scale ? 1.0 : exp(-x)) / x;
  399. result->err = 2 * GSL_DBL_EPSILON * fabs(result->val);
  400. CHECK_UNDERFLOW(result);
  401. return GSL_SUCCESS;
  402. }
  403. } else if (n == 1) {
  404. return expint_E1_impl(x, result, scale);
  405. } else if (n == 2) {
  406. return expint_E2_impl(x, result, scale);
  407. } else {
  408. if(x < 0) {
  409. DOMAIN_ERROR(result);
  410. }
  411. if (x == 0) {
  412. result->val = (scale ? exp(x) : 1 ) * (1/(n-1.0));
  413. result->err = 2 * GSL_DBL_EPSILON * fabs(result->val);
  414. CHECK_UNDERFLOW(result);
  415. return GSL_SUCCESS;
  416. } else {
  417. gsl_sf_result result_g;
  418. double prefactor = pow(x, n-1);
  419. int status = gsl_sf_gamma_inc_e (1-n, x, &result_g);
  420. double scale_factor = ( scale ? exp(x) : 1.0 );
  421. result->val = scale_factor * prefactor * result_g.val;
  422. result->err = 2 * GSL_DBL_EPSILON * fabs(result->val);
  423. result->err += 2 * fabs(scale_factor * prefactor * result_g.err);
  424. if (status == GSL_SUCCESS) CHECK_UNDERFLOW(result);
  425. return status;
  426. }
  427. }
  428. }
  429. /*-*-*-*-*-*-*-*-*-*-*-* Functions with Error Codes *-*-*-*-*-*-*-*-*-*-*-*/
  430. int gsl_sf_expint_E1_e(const double x, gsl_sf_result * result)
  431. {
  432. return expint_E1_impl(x, result, 0);
  433. }
  434. int gsl_sf_expint_E1_scaled_e(const double x, gsl_sf_result * result)
  435. {
  436. return expint_E1_impl(x, result, 1);
  437. }
  438. int gsl_sf_expint_E2_e(const double x, gsl_sf_result * result)
  439. {
  440. return expint_E2_impl(x, result, 0);
  441. }
  442. int gsl_sf_expint_E2_scaled_e(const double x, gsl_sf_result * result)
  443. {
  444. return expint_E2_impl(x, result, 1);
  445. }
  446. int gsl_sf_expint_En_e(const int n, const double x, gsl_sf_result * result)
  447. {
  448. return expint_En_impl(n, x, result, 0);
  449. }
  450. int gsl_sf_expint_En_scaled_e(const int n, const double x, gsl_sf_result * result)
  451. {
  452. return expint_En_impl(n, x, result, 1);
  453. }
  454. int gsl_sf_expint_Ei_e(const double x, gsl_sf_result * result)
  455. {
  456. /* CHECK_POINTER(result) */
  457. {
  458. int status = gsl_sf_expint_E1_e(-x, result);
  459. result->val = -result->val;
  460. return status;
  461. }
  462. }
  463. int gsl_sf_expint_Ei_scaled_e(const double x, gsl_sf_result * result)
  464. {
  465. /* CHECK_POINTER(result) */
  466. {
  467. int status = gsl_sf_expint_E1_scaled_e(-x, result);
  468. result->val = -result->val;
  469. return status;
  470. }
  471. }
  472. #if 0
  473. static double recurse_En(int n, double x, double E1)
  474. {
  475. int i;
  476. double En = E1;
  477. double ex = exp(-x);
  478. for(i=2; i<=n; i++) {
  479. En = 1./(i-1) * (ex - x * En);
  480. }
  481. return En;
  482. }
  483. #endif
  484. /*-*-*-*-*-*-*-*-*-* Functions w/ Natural Prototypes *-*-*-*-*-*-*-*-*-*-*/
  485. #include "gsl_specfunc__eval.h"
  486. double gsl_sf_expint_E1(const double x)
  487. {
  488. EVAL_RESULT(gsl_sf_expint_E1_e(x, &result));
  489. }
  490. double gsl_sf_expint_E1_scaled(const double x)
  491. {
  492. EVAL_RESULT(gsl_sf_expint_E1_scaled_e(x, &result));
  493. }
  494. double gsl_sf_expint_E2(const double x)
  495. {
  496. EVAL_RESULT(gsl_sf_expint_E2_e(x, &result));
  497. }
  498. double gsl_sf_expint_E2_scaled(const double x)
  499. {
  500. EVAL_RESULT(gsl_sf_expint_E2_scaled_e(x, &result));
  501. }
  502. double gsl_sf_expint_En(const int n, const double x)
  503. {
  504. EVAL_RESULT(gsl_sf_expint_En_e(n, x, &result));
  505. }
  506. double gsl_sf_expint_En_scaled(const int n, const double x)
  507. {
  508. EVAL_RESULT(gsl_sf_expint_En_scaled_e(n, x, &result));
  509. }
  510. double gsl_sf_expint_Ei(const double x)
  511. {
  512. EVAL_RESULT(gsl_sf_expint_Ei_e(x, &result));
  513. }
  514. double gsl_sf_expint_Ei_scaled(const double x)
  515. {
  516. EVAL_RESULT(gsl_sf_expint_Ei_scaled_e(x, &result));
  517. }