gsl_specfunc__erfc.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466
  1. /* specfunc/erfc.c
  2. *
  3. * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 Gerard Jungman
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 3 of the License, or (at
  8. * your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful, but
  11. * WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. * General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, write to the Free Software
  17. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  18. */
  19. /* Author: J. Theiler (modifications by G. Jungman) */
  20. /*
  21. * See Hart et al, Computer Approximations, John Wiley and Sons, New York (1968)
  22. * (This applies only to the erfc8 stuff, which is the part
  23. * of the original code that survives. I have replaced much of
  24. * the other stuff with Chebyshev fits. These are simpler and
  25. * more precise than the original approximations. [GJ])
  26. */
  27. #include "gsl__config.h"
  28. #include "gsl_math.h"
  29. #include "gsl_errno.h"
  30. #include "gsl_sf_exp.h"
  31. #include "gsl_sf_erf.h"
  32. #include "gsl_specfunc__check.h"
  33. #include "gsl_specfunc__chebyshev.h"
  34. #include "gsl_specfunc__cheb_eval.c"
  35. #define LogRootPi_ 0.57236494292470008706
  36. static double erfc8_sum(double x)
  37. {
  38. /* estimates erfc(x) valid for 8 < x < 100 */
  39. /* This is based on index 5725 in Hart et al */
  40. static double P[] = {
  41. 2.97886562639399288862,
  42. 7.409740605964741794425,
  43. 6.1602098531096305440906,
  44. 5.019049726784267463450058,
  45. 1.275366644729965952479585264,
  46. 0.5641895835477550741253201704
  47. };
  48. static double Q[] = {
  49. 3.3690752069827527677,
  50. 9.608965327192787870698,
  51. 17.08144074746600431571095,
  52. 12.0489519278551290360340491,
  53. 9.396034016235054150430579648,
  54. 2.260528520767326969591866945,
  55. 1.0
  56. };
  57. double num=0.0, den=0.0;
  58. int i;
  59. num = P[5];
  60. for (i=4; i>=0; --i) {
  61. num = x*num + P[i];
  62. }
  63. den = Q[6];
  64. for (i=5; i>=0; --i) {
  65. den = x*den + Q[i];
  66. }
  67. return num/den;
  68. }
  69. inline
  70. static double erfc8(double x)
  71. {
  72. double e;
  73. e = erfc8_sum(x);
  74. e *= exp(-x*x);
  75. return e;
  76. }
  77. inline
  78. static double log_erfc8(double x)
  79. {
  80. double e;
  81. e = erfc8_sum(x);
  82. e = log(e) - x*x;
  83. return e;
  84. }
  85. #if 0
  86. /* Abramowitz+Stegun, 7.2.14 */
  87. static double erfcasympsum(double x)
  88. {
  89. int i;
  90. double e = 1.;
  91. double coef = 1.;
  92. for (i=1; i<5; ++i) {
  93. /* coef *= -(2*i-1)/(2*x*x); ??? [GJ] */
  94. coef *= -(2*i+1)/(i*(4*x*x*x*x));
  95. e += coef;
  96. /*
  97. if (fabs(coef) < 1.0e-15) break;
  98. if (fabs(coef) > 1.0e10) break;
  99. [GJ]: These tests are not useful. This function is only
  100. used below. Took them out; they gum up the pipeline.
  101. */
  102. }
  103. return e;
  104. }
  105. #endif /* 0 */
  106. /* Abramowitz+Stegun, 7.1.5 */
  107. static int erfseries(double x, gsl_sf_result * result)
  108. {
  109. double coef = x;
  110. double e = coef;
  111. double del;
  112. int k;
  113. for (k=1; k<30; ++k) {
  114. coef *= -x*x/k;
  115. del = coef/(2.0*k+1.0);
  116. e += del;
  117. }
  118. result->val = 2.0 / M_SQRTPI * e;
  119. result->err = 2.0 / M_SQRTPI * (fabs(del) + GSL_DBL_EPSILON);
  120. return GSL_SUCCESS;
  121. }
  122. /* Chebyshev fit for erfc((t+1)/2), -1 < t < 1
  123. */
  124. static double erfc_xlt1_data[20] = {
  125. 1.06073416421769980345174155056,
  126. -0.42582445804381043569204735291,
  127. 0.04955262679620434040357683080,
  128. 0.00449293488768382749558001242,
  129. -0.00129194104658496953494224761,
  130. -0.00001836389292149396270416979,
  131. 0.00002211114704099526291538556,
  132. -5.23337485234257134673693179020e-7,
  133. -2.78184788833537885382530989578e-7,
  134. 1.41158092748813114560316684249e-8,
  135. 2.72571296330561699984539141865e-9,
  136. -2.06343904872070629406401492476e-10,
  137. -2.14273991996785367924201401812e-11,
  138. 2.22990255539358204580285098119e-12,
  139. 1.36250074650698280575807934155e-13,
  140. -1.95144010922293091898995913038e-14,
  141. -6.85627169231704599442806370690e-16,
  142. 1.44506492869699938239521607493e-16,
  143. 2.45935306460536488037576200030e-18,
  144. -9.29599561220523396007359328540e-19
  145. };
  146. static cheb_series erfc_xlt1_cs = {
  147. erfc_xlt1_data,
  148. 19,
  149. -1, 1,
  150. 12
  151. };
  152. /* Chebyshev fit for erfc(x) exp(x^2), 1 < x < 5, x = 2t + 3, -1 < t < 1
  153. */
  154. static double erfc_x15_data[25] = {
  155. 0.44045832024338111077637466616,
  156. -0.143958836762168335790826895326,
  157. 0.044786499817939267247056666937,
  158. -0.013343124200271211203618353102,
  159. 0.003824682739750469767692372556,
  160. -0.001058699227195126547306482530,
  161. 0.000283859419210073742736310108,
  162. -0.000073906170662206760483959432,
  163. 0.000018725312521489179015872934,
  164. -4.62530981164919445131297264430e-6,
  165. 1.11558657244432857487884006422e-6,
  166. -2.63098662650834130067808832725e-7,
  167. 6.07462122724551777372119408710e-8,
  168. -1.37460865539865444777251011793e-8,
  169. 3.05157051905475145520096717210e-9,
  170. -6.65174789720310713757307724790e-10,
  171. 1.42483346273207784489792999706e-10,
  172. -3.00141127395323902092018744545e-11,
  173. 6.22171792645348091472914001250e-12,
  174. -1.26994639225668496876152836555e-12,
  175. 2.55385883033257575402681845385e-13,
  176. -5.06258237507038698392265499770e-14,
  177. 9.89705409478327321641264227110e-15,
  178. -1.90685978789192181051961024995e-15,
  179. 3.50826648032737849245113757340e-16
  180. };
  181. static cheb_series erfc_x15_cs = {
  182. erfc_x15_data,
  183. 24,
  184. -1, 1,
  185. 16
  186. };
  187. /* Chebyshev fit for erfc(x) x exp(x^2), 5 < x < 10, x = (5t + 15)/2, -1 < t < 1
  188. */
  189. static double erfc_x510_data[20] = {
  190. 1.11684990123545698684297865808,
  191. 0.003736240359381998520654927536,
  192. -0.000916623948045470238763619870,
  193. 0.000199094325044940833965078819,
  194. -0.000040276384918650072591781859,
  195. 7.76515264697061049477127605790e-6,
  196. -1.44464794206689070402099225301e-6,
  197. 2.61311930343463958393485241947e-7,
  198. -4.61833026634844152345304095560e-8,
  199. 8.00253111512943601598732144340e-9,
  200. -1.36291114862793031395712122089e-9,
  201. 2.28570483090160869607683087722e-10,
  202. -3.78022521563251805044056974560e-11,
  203. 6.17253683874528285729910462130e-12,
  204. -9.96019290955316888445830597430e-13,
  205. 1.58953143706980770269506726000e-13,
  206. -2.51045971047162509999527428316e-14,
  207. 3.92607828989125810013581287560e-15,
  208. -6.07970619384160374392535453420e-16,
  209. 9.12600607264794717315507477670e-17
  210. };
  211. static cheb_series erfc_x510_cs = {
  212. erfc_x510_data,
  213. 19,
  214. -1, 1,
  215. 12
  216. };
  217. #if 0
  218. inline
  219. static double
  220. erfc_asymptotic(double x)
  221. {
  222. return exp(-x*x)/x * erfcasympsum(x) / M_SQRTPI;
  223. }
  224. inline
  225. static double
  226. log_erfc_asymptotic(double x)
  227. {
  228. return log(erfcasympsum(x)/x) - x*x - LogRootPi_;
  229. }
  230. #endif /* 0 */
  231. /*-*-*-*-*-*-*-*-*-*-*-* Functions with Error Codes *-*-*-*-*-*-*-*-*-*-*-*/
  232. int gsl_sf_erfc_e(double x, gsl_sf_result * result)
  233. {
  234. const double ax = fabs(x);
  235. double e_val, e_err;
  236. /* CHECK_POINTER(result) */
  237. if(ax <= 1.0) {
  238. double t = 2.0*ax - 1.0;
  239. gsl_sf_result c;
  240. cheb_eval_e(&erfc_xlt1_cs, t, &c);
  241. e_val = c.val;
  242. e_err = c.err;
  243. }
  244. else if(ax <= 5.0) {
  245. double ex2 = exp(-x*x);
  246. double t = 0.5*(ax-3.0);
  247. gsl_sf_result c;
  248. cheb_eval_e(&erfc_x15_cs, t, &c);
  249. e_val = ex2 * c.val;
  250. e_err = ex2 * (c.err + 2.0*fabs(x)*GSL_DBL_EPSILON);
  251. }
  252. else if(ax < 10.0) {
  253. double exterm = exp(-x*x) / ax;
  254. double t = (2.0*ax - 15.0)/5.0;
  255. gsl_sf_result c;
  256. cheb_eval_e(&erfc_x510_cs, t, &c);
  257. e_val = exterm * c.val;
  258. e_err = exterm * (c.err + 2.0*fabs(x)*GSL_DBL_EPSILON + GSL_DBL_EPSILON);
  259. }
  260. else {
  261. e_val = erfc8(ax);
  262. e_err = (x*x + 1.0) * GSL_DBL_EPSILON * fabs(e_val);
  263. }
  264. if(x < 0.0) {
  265. result->val = 2.0 - e_val;
  266. result->err = e_err;
  267. result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);
  268. }
  269. else {
  270. result->val = e_val;
  271. result->err = e_err;
  272. result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);
  273. }
  274. return GSL_SUCCESS;
  275. }
  276. int gsl_sf_log_erfc_e(double x, gsl_sf_result * result)
  277. {
  278. /* CHECK_POINTER(result) */
  279. if(x*x < 10.0*GSL_ROOT6_DBL_EPSILON) {
  280. const double y = x / M_SQRTPI;
  281. /* series for -1/2 Log[Erfc[Sqrt[Pi] y]] */
  282. const double c3 = (4.0 - M_PI)/3.0;
  283. const double c4 = 2.0*(1.0 - M_PI/3.0);
  284. const double c5 = -0.001829764677455021; /* (96.0 - 40.0*M_PI + 3.0*M_PI*M_PI)/30.0 */
  285. const double c6 = 0.02629651521057465; /* 2.0*(120.0 - 60.0*M_PI + 7.0*M_PI*M_PI)/45.0 */
  286. const double c7 = -0.01621575378835404;
  287. const double c8 = 0.00125993961762116;
  288. const double c9 = 0.00556964649138;
  289. const double c10 = -0.0045563339802;
  290. const double c11 = 0.0009461589032;
  291. const double c12 = 0.0013200243174;
  292. const double c13 = -0.00142906;
  293. const double c14 = 0.00048204;
  294. double series = c8 + y*(c9 + y*(c10 + y*(c11 + y*(c12 + y*(c13 + c14*y)))));
  295. series = y*(1.0 + y*(1.0 + y*(c3 + y*(c4 + y*(c5 + y*(c6 + y*(c7 + y*series)))))));
  296. result->val = -2.0 * series;
  297. result->err = 2.0 * GSL_DBL_EPSILON * fabs(result->val);
  298. return GSL_SUCCESS;
  299. }
  300. /*
  301. don't like use of log1p(); added above series stuff for small x instead, should be ok [GJ]
  302. else if (fabs(x) < 1.0) {
  303. gsl_sf_result result_erf;
  304. gsl_sf_erf_e(x, &result_erf);
  305. result->val = log1p(-result_erf.val);
  306. result->err = 2.0 * GSL_DBL_EPSILON * fabs(result->val);
  307. return GSL_SUCCESS;
  308. }
  309. */
  310. else if(x > 8.0) {
  311. result->val = log_erfc8(x);
  312. result->err = 2.0 * GSL_DBL_EPSILON * fabs(result->val);
  313. return GSL_SUCCESS;
  314. }
  315. else {
  316. gsl_sf_result result_erfc;
  317. gsl_sf_erfc_e(x, &result_erfc);
  318. result->val = log(result_erfc.val);
  319. result->err = fabs(result_erfc.err / result_erfc.val);
  320. result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);
  321. return GSL_SUCCESS;
  322. }
  323. }
  324. int gsl_sf_erf_e(double x, gsl_sf_result * result)
  325. {
  326. /* CHECK_POINTER(result) */
  327. if(fabs(x) < 1.0) {
  328. return erfseries(x, result);
  329. }
  330. else {
  331. gsl_sf_result result_erfc;
  332. gsl_sf_erfc_e(x, &result_erfc);
  333. result->val = 1.0 - result_erfc.val;
  334. result->err = result_erfc.err;
  335. result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);
  336. return GSL_SUCCESS;
  337. }
  338. }
  339. int gsl_sf_erf_Z_e(double x, gsl_sf_result * result)
  340. {
  341. /* CHECK_POINTER(result) */
  342. {
  343. const double ex2 = exp(-x*x/2.0);
  344. result->val = ex2 / (M_SQRT2 * M_SQRTPI);
  345. result->err = fabs(x * result->val) * GSL_DBL_EPSILON;
  346. result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);
  347. CHECK_UNDERFLOW(result);
  348. return GSL_SUCCESS;
  349. }
  350. }
  351. int gsl_sf_erf_Q_e(double x, gsl_sf_result * result)
  352. {
  353. /* CHECK_POINTER(result) */
  354. {
  355. gsl_sf_result result_erfc;
  356. int stat = gsl_sf_erfc_e(x/M_SQRT2, &result_erfc);
  357. result->val = 0.5 * result_erfc.val;
  358. result->err = 0.5 * result_erfc.err;
  359. result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);
  360. return stat;
  361. }
  362. }
  363. int gsl_sf_hazard_e(double x, gsl_sf_result * result)
  364. {
  365. if(x < 25.0)
  366. {
  367. gsl_sf_result result_ln_erfc;
  368. const int stat_l = gsl_sf_log_erfc_e(x/M_SQRT2, &result_ln_erfc);
  369. const double lnc = -0.22579135264472743236; /* ln(sqrt(2/pi)) */
  370. const double arg = lnc - 0.5*x*x - result_ln_erfc.val;
  371. const int stat_e = gsl_sf_exp_e(arg, result);
  372. result->err += 3.0 * (1.0 + fabs(x)) * GSL_DBL_EPSILON * fabs(result->val);
  373. result->err += fabs(result_ln_erfc.err * result->val);
  374. return GSL_ERROR_SELECT_2(stat_l, stat_e);
  375. }
  376. else
  377. {
  378. const double ix2 = 1.0/(x*x);
  379. const double corrB = 1.0 - 9.0*ix2 * (1.0 - 11.0*ix2);
  380. const double corrM = 1.0 - 5.0*ix2 * (1.0 - 7.0*ix2 * corrB);
  381. const double corrT = 1.0 - ix2 * (1.0 - 3.0*ix2*corrM);
  382. result->val = x / corrT;
  383. result->err = 2.0 * GSL_DBL_EPSILON * fabs(result->val);
  384. return GSL_SUCCESS;
  385. }
  386. }
  387. /*-*-*-*-*-*-*-*-*-* Functions w/ Natural Prototypes *-*-*-*-*-*-*-*-*-*-*/
  388. #include "gsl_specfunc__eval.h"
  389. double gsl_sf_erfc(double x)
  390. {
  391. EVAL_RESULT(gsl_sf_erfc_e(x, &result));
  392. }
  393. double gsl_sf_log_erfc(double x)
  394. {
  395. EVAL_RESULT(gsl_sf_log_erfc_e(x, &result));
  396. }
  397. double gsl_sf_erf(double x)
  398. {
  399. EVAL_RESULT(gsl_sf_erf_e(x, &result));
  400. }
  401. double gsl_sf_erf_Z(double x)
  402. {
  403. EVAL_RESULT(gsl_sf_erf_Z_e(x, &result));
  404. }
  405. double gsl_sf_erf_Q(double x)
  406. {
  407. EVAL_RESULT(gsl_sf_erf_Q_e(x, &result));
  408. }
  409. double gsl_sf_hazard(double x)
  410. {
  411. EVAL_RESULT(gsl_sf_hazard_e(x, &result));
  412. }