Annotation of OpenXM_contrib/gnuplot/specfun.c, Revision 1.1
1.1 ! maekawa 1: #ifndef lint
! 2: static char *RCSid = "$Id: specfun.c,v 1.21 1998/04/14 00:16:20 drd Exp $";
! 3: #endif
! 4:
! 5:
! 6: /* GNUPLOT - specfun.c */
! 7:
! 8: /*[
! 9: * Copyright 1986 - 1993, 1998 Thomas Williams, Colin Kelley
! 10: *
! 11: * Permission to use, copy, and distribute this software and its
! 12: * documentation for any purpose with or without fee is hereby granted,
! 13: * provided that the above copyright notice appear in all copies and
! 14: * that both that copyright notice and this permission notice appear
! 15: * in supporting documentation.
! 16: *
! 17: * Permission to modify the software is granted, but not the right to
! 18: * distribute the complete modified source code. Modifications are to
! 19: * be distributed as patches to the released version. Permission to
! 20: * distribute binaries produced by compiling modified sources is granted,
! 21: * provided you
! 22: * 1. distribute the corresponding source modifications from the
! 23: * released version in the form of a patch file along with the binaries,
! 24: * 2. add special version identification to distinguish your version
! 25: * in addition to the base release version number,
! 26: * 3. provide your name and address as the primary contact for the
! 27: * support of your modified version, and
! 28: * 4. retain our contact information in regard to use of the base
! 29: * software.
! 30: * Permission to distribute the released version of the source code along
! 31: * with corresponding source modifications in the form of a patch file is
! 32: * granted with same provisions 2 through 4 for binary distributions.
! 33: *
! 34: * This software is provided "as is" without express or implied warranty
! 35: * to the extent permitted by applicable law.
! 36: ]*/
! 37:
! 38: /*
! 39: * AUTHORS
! 40: *
! 41: * Original Software:
! 42: * Jos van der Woude, jvdwoude@hut.nl
! 43: *
! 44: */
! 45:
! 46: #include "plot.h"
! 47: #include "fnproto.h"
! 48:
! 49:
! 50: extern struct value stack[STACK_DEPTH];
! 51: extern int s_p;
! 52: extern double zero;
! 53:
! 54: #define ITMAX 200
! 55:
! 56: #ifdef FLT_EPSILON
! 57: # define MACHEPS FLT_EPSILON /* 1.0E-08 */
! 58: #else
! 59: # define MACHEPS 1.0E-08
! 60: #endif
! 61:
! 62: /* AS239 value, e^-88 = 2^-127 */
! 63: #define MINEXP -88.0
! 64:
! 65: #ifdef FLT_MAX
! 66: # define OFLOW FLT_MAX /* 1.0E+37 */
! 67: #else
! 68: # define OFLOW 1.0E+37
! 69: #endif
! 70:
! 71: /* AS239 value for igamma(a,x>=XBIG) = 1.0 */
! 72: #define XBIG 1.0E+08
! 73:
! 74: /*
! 75: * Mathematical constants
! 76: */
! 77: #define LNPI 1.14472988584940016
! 78: #define LNSQRT2PI 0.9189385332046727
! 79: #ifdef PI
! 80: # undef PI
! 81: #endif
! 82: #define PI 3.14159265358979323846
! 83: #define PNT68 0.6796875
! 84: #define SQRT_TWO 1.41421356237309504880168872420969809 /* JG */
! 85:
! 86: /* Prefer lgamma */
! 87: #ifndef GAMMA
! 88: # ifdef HAVE_LGAMMA
! 89: # define GAMMA(x) lgamma (x)
! 90: # elif defined(HAVE_GAMMA)
! 91: # define GAMMA(x) gamma (x)
! 92: # else
! 93: # undef GAMMA
! 94: # endif
! 95: #endif
! 96:
! 97: #ifndef GAMMA
! 98: int signgam = 0;
! 99: #else
! 100: extern int signgam; /* this is not always declared in math.h */
! 101: #endif
! 102:
! 103: /* Global variables, not visible outside this file */
! 104: static long Xm1 = 2147483563L;
! 105: static long Xm2 = 2147483399L;
! 106: static long Xa1 = 40014L;
! 107: static long Xa2 = 40692L;
! 108:
! 109: /* Local function declarations, not visible outside this file */
! 110: static double confrac __PROTO((double a, double b, double x));
! 111: static double ibeta __PROTO((double a, double b, double x));
! 112: static double igamma __PROTO((double a, double x));
! 113: static double ranf __PROTO((double init));
! 114: static double inverse_normal_func __PROTO((double p));
! 115: static double inverse_error_func __PROTO((double p));
! 116:
! 117: #ifndef GAMMA
! 118: /* Provide GAMMA function for those who do not already have one */
! 119: static double lngamma __PROTO((double z));
! 120: static double lgamneg __PROTO((double z));
! 121: static double lgampos __PROTO((double z));
! 122:
! 123: /**
! 124: * from statlib, Thu Jan 23 15:02:27 EST 1992 ***
! 125: *
! 126: * This file contains two algorithms for the logarithm of the gamma function.
! 127: * Algorithm AS 245 is the faster (but longer) and gives an accuracy of about
! 128: * 10-12 significant decimal digits except for small regions around X = 1 and
! 129: * X = 2, where the function goes to zero.
! 130: * The second algorithm is not part of the AS algorithms. It is slower but
! 131: * gives 14 or more significant decimal digits accuracy, except around X = 1
! 132: * and X = 2. The Lanczos series from which this algorithm is derived is
! 133: * interesting in that it is a convergent series approximation for the gamma
! 134: * function, whereas the familiar series due to De Moivre (and usually wrongly
! 135: * called Stirling's approximation) is only an asymptotic approximation, as
! 136: * is the true and preferable approximation due to Stirling.
! 137: *
! 138: * Uses Lanczos-type approximation to ln(gamma) for z > 0. Reference: Lanczos,
! 139: * C. 'A precision approximation of the gamma function', J. SIAM Numer.
! 140: * Anal., B, 1, 86-96, 1964. Accuracy: About 14 significant digits except for
! 141: * small regions in the vicinity of 1 and 2.
! 142: *
! 143: * Programmer: Alan Miller CSIRO Division of Mathematics & Statistics
! 144: *
! 145: * Latest revision - 17 April 1988
! 146: *
! 147: * Additions: Translated from fortran to C, code added to handle values z < 0.
! 148: * The global variable signgam contains the sign of the gamma function.
! 149: *
! 150: * IMPORTANT: The signgam variable contains garbage until AFTER the call to
! 151: * lngamma().
! 152: *
! 153: * Permission granted to distribute freely for non-commercial purposes only
! 154: * Copyright (c) 1992 Jos van der Woude, jvdwoude@hut.nl
! 155: */
! 156:
! 157: /* Local data, not visible outside this file
! 158: static double a[] =
! 159: {
! 160: 0.9999999999995183E+00,
! 161: 0.6765203681218835E+03,
! 162: -.1259139216722289E+04,
! 163: 0.7713234287757674E+03,
! 164: -.1766150291498386E+03,
! 165: 0.1250734324009056E+02,
! 166: -.1385710331296526E+00,
! 167: 0.9934937113930748E-05,
! 168: 0.1659470187408462E-06,
! 169: }; */
! 170:
! 171: /* from Ray Toy */
! 172: static double GPFAR a[] =
! 173: {
! 174: .99999999999980993227684700473478296744476168282198,
! 175: 676.52036812188509856700919044401903816411251975244084,
! 176: -1259.13921672240287047156078755282840836424300664868028,
! 177: 771.32342877765307884865282588943070775227268469602500,
! 178: -176.61502916214059906584551353999392943274507608117860,
! 179: 12.50734327868690481445893685327104972970563021816420,
! 180: -.13857109526572011689554706984971501358032683492780,
! 181: .00000998436957801957085956266828104544089848531228,
! 182: .00000015056327351493115583383579667028994545044040,
! 183: };
! 184:
! 185: static double lgamneg(z)
! 186: double z;
! 187: {
! 188: double tmp;
! 189:
! 190: /* Use reflection formula, then call lgampos() */
! 191: tmp = sin(z * PI);
! 192:
! 193: if (fabs(tmp) < MACHEPS) {
! 194: tmp = 0.0;
! 195: } else if (tmp < 0.0) {
! 196: tmp = -tmp;
! 197: signgam = -1;
! 198: }
! 199: return LNPI - lgampos(1.0 - z) - log(tmp);
! 200:
! 201: }
! 202:
! 203: static double lgampos(z)
! 204: double z;
! 205: {
! 206: double sum;
! 207: double tmp;
! 208: int i;
! 209:
! 210: sum = a[0];
! 211: for (i = 1, tmp = z; i < 9; i++) {
! 212: sum += a[i] / tmp;
! 213: tmp++;
! 214: }
! 215:
! 216: return log(sum) + LNSQRT2PI - z - 6.5 + (z - 0.5) * log(z + 6.5);
! 217: }
! 218:
! 219: static double lngamma(z)
! 220: double z;
! 221: {
! 222: signgam = 1;
! 223:
! 224: if (z <= 0.0)
! 225: return lgamneg(z);
! 226: else
! 227: return lgampos(z);
! 228: }
! 229:
! 230: # define GAMMA(x) lngamma ((x))
! 231: #endif /* !GAMMA */
! 232:
! 233: void f_erf()
! 234: {
! 235: struct value a;
! 236: double x;
! 237:
! 238: x = real(pop(&a));
! 239:
! 240: #ifdef HAVE_ERF
! 241: x = erf(x);
! 242: #else
! 243: {
! 244: int fsign;
! 245: fsign = x >= 0 ? 1 : 0;
! 246: x = igamma(0.5, (x)*(x));
! 247: if (x == -1.0) {
! 248: undefined = TRUE;
! 249: x = 0.0;
! 250: } else {
! 251: if (fsign == 0)
! 252: x = -x;
! 253: }
! 254: }
! 255: #endif
! 256: push(Gcomplex(&a, x, 0.0));
! 257: }
! 258:
! 259: void f_erfc()
! 260: {
! 261: struct value a;
! 262: double x;
! 263:
! 264: x = real(pop(&a));
! 265: #ifdef HAVE_ERFC
! 266: x = erfc(x);
! 267: #else
! 268: {
! 269: int fsign;
! 270: fsign = x >= 0 ? 1 : 0;
! 271: x = igamma(0.5, (x)*(x));
! 272: if (x == 1.0) {
! 273: undefined = TRUE;
! 274: x = 0.0;
! 275: } else {
! 276: x = fsign > 0 ? 1.0 - x : 1.0 + x ;
! 277: }
! 278: }
! 279: #endif
! 280: push(Gcomplex(&a, x, 0.0));
! 281: }
! 282:
! 283: void f_ibeta()
! 284: {
! 285: struct value a;
! 286: double x;
! 287: double arg1;
! 288: double arg2;
! 289:
! 290: x = real(pop(&a));
! 291: arg2 = real(pop(&a));
! 292: arg1 = real(pop(&a));
! 293:
! 294: x = ibeta(arg1, arg2, x);
! 295: if (x == -1.0) {
! 296: undefined = TRUE;
! 297: push(Ginteger(&a, 0));
! 298: } else
! 299: push(Gcomplex(&a, x, 0.0));
! 300: }
! 301:
! 302: void f_igamma()
! 303: {
! 304: struct value a;
! 305: double x;
! 306: double arg1;
! 307:
! 308: x = real(pop(&a));
! 309: arg1 = real(pop(&a));
! 310:
! 311: x = igamma(arg1, x);
! 312: if (x == -1.0) {
! 313: undefined = TRUE;
! 314: push(Ginteger(&a, 0));
! 315: } else
! 316: push(Gcomplex(&a, x, 0.0));
! 317: }
! 318:
! 319: void f_gamma()
! 320: {
! 321: register double y;
! 322: struct value a;
! 323:
! 324: y = GAMMA(real(pop(&a)));
! 325: if (y > 88.0) {
! 326: undefined = TRUE;
! 327: push(Ginteger(&a, 0));
! 328: } else
! 329: push(Gcomplex(&a, signgam * gp_exp(y), 0.0));
! 330: }
! 331:
! 332: void f_lgamma()
! 333: {
! 334: struct value a;
! 335:
! 336: push(Gcomplex(&a, GAMMA(real(pop(&a))), 0.0));
! 337: }
! 338:
! 339: #ifndef BADRAND
! 340:
! 341: void f_rand()
! 342: {
! 343: struct value a;
! 344:
! 345: push(Gcomplex(&a, ranf(real(pop(&a))), 0.0));
! 346: }
! 347:
! 348: #else /* BADRAND */
! 349:
! 350: /* Use only to observe the effect of a "bad" random number generator. */
! 351: void f_rand()
! 352: {
! 353: struct value a;
! 354:
! 355: static unsigned int y = 0;
! 356: unsigned int maxran = 1000;
! 357:
! 358: (void) real(pop(&a));
! 359: y = (781 * y + 387) % maxran;
! 360:
! 361: push(Gcomplex(&a, (double) y / maxran, 0.0));
! 362: }
! 363:
! 364: #endif /* BADRAND */
! 365:
! 366: /** ibeta.c
! 367: *
! 368: * DESCRIB Approximate the incomplete beta function Ix(a, b).
! 369: *
! 370: * _
! 371: * |(a + b) /x (a-1) (b-1)
! 372: * Ix(a, b) = -_-------_--- * | t * (1 - t) dt (a,b > 0)
! 373: * |(a) * |(b) /0
! 374: *
! 375: *
! 376: *
! 377: * CALL p = ibeta(a, b, x)
! 378: *
! 379: * double a > 0
! 380: * double b > 0
! 381: * double x [0, 1]
! 382: *
! 383: * WARNING none
! 384: *
! 385: * RETURN double p [0, 1]
! 386: * -1.0 on error condition
! 387: *
! 388: * XREF lngamma()
! 389: *
! 390: * BUGS none
! 391: *
! 392: * REFERENCE The continued fraction expansion as given by
! 393: * Abramowitz and Stegun (1964) is used.
! 394: *
! 395: * Permission granted to distribute freely for non-commercial purposes only
! 396: * Copyright (c) 1992 Jos van der Woude, jvdwoude@hut.nl
! 397: */
! 398:
! 399: static double ibeta(a, b, x)
! 400: double a, b, x;
! 401: {
! 402: /* Test for admissibility of arguments */
! 403: if (a <= 0.0 || b <= 0.0)
! 404: return -1.0;
! 405: if (x < 0.0 || x > 1.0)
! 406: return -1.0;;
! 407:
! 408: /* If x equals 0 or 1, return x as prob */
! 409: if (x == 0.0 || x == 1.0)
! 410: return x;
! 411:
! 412: /* Swap a, b if necessarry for more efficient evaluation */
! 413: return a < x * (a + b) ? 1.0 - confrac(b, a, 1.0 - x) : confrac(a, b, x);
! 414: }
! 415:
! 416: static double confrac(a, b, x)
! 417: double a, b, x;
! 418: {
! 419: double Alo = 0.0;
! 420: double Ahi;
! 421: double Aev;
! 422: double Aod;
! 423: double Blo = 1.0;
! 424: double Bhi = 1.0;
! 425: double Bod = 1.0;
! 426: double Bev = 1.0;
! 427: double f;
! 428: double fold;
! 429: double Apb = a + b;
! 430: double d;
! 431: int i;
! 432: int j;
! 433:
! 434: /* Set up continued fraction expansion evaluation. */
! 435: Ahi = gp_exp(GAMMA(Apb) + a * log(x) + b * log(1.0 - x) -
! 436: GAMMA(a + 1.0) - GAMMA(b));
! 437:
! 438: /*
! 439: * Continued fraction loop begins here. Evaluation continues until
! 440: * maximum iterations are exceeded, or convergence achieved.
! 441: */
! 442: for (i = 0, j = 1, f = Ahi; i <= ITMAX; i++, j++) {
! 443: d = a + j + i;
! 444: Aev = -(a + i) * (Apb + i) * x / d / (d - 1.0);
! 445: Aod = j * (b - j) * x / d / (d + 1.0);
! 446: Alo = Bev * Ahi + Aev * Alo;
! 447: Blo = Bev * Bhi + Aev * Blo;
! 448: Ahi = Bod * Alo + Aod * Ahi;
! 449: Bhi = Bod * Blo + Aod * Bhi;
! 450:
! 451: if (fabs(Bhi) < MACHEPS)
! 452: Bhi = 0.0;
! 453:
! 454: if (Bhi != 0.0) {
! 455: fold = f;
! 456: f = Ahi / Bhi;
! 457: if (fabs(f - fold) < fabs(f) * MACHEPS)
! 458: return f;
! 459: }
! 460: }
! 461:
! 462: return -1.0;
! 463: }
! 464:
! 465: /** igamma.c
! 466: *
! 467: * DESCRIB Approximate the incomplete gamma function P(a, x).
! 468: *
! 469: * 1 /x -t (a-1)
! 470: * P(a, x) = -_--- * | e * t dt (a > 0)
! 471: * |(a) /0
! 472: *
! 473: * CALL p = igamma(a, x)
! 474: *
! 475: * double a > 0
! 476: * double x >= 0
! 477: *
! 478: * WARNING none
! 479: *
! 480: * RETURN double p [0, 1]
! 481: * -1.0 on error condition
! 482: *
! 483: * XREF lngamma()
! 484: *
! 485: * BUGS Values 0 <= x <= 1 may lead to inaccurate results.
! 486: *
! 487: * REFERENCE ALGORITHM AS239 APPL. STATIST. (1988) VOL. 37, NO. 3
! 488: *
! 489: * Permission granted to distribute freely for non-commercial purposes only
! 490: * Copyright (c) 1992 Jos van der Woude, jvdwoude@hut.nl
! 491: */
! 492:
! 493: /* Global variables, not visible outside this file */
! 494: static double pn1, pn2, pn3, pn4, pn5, pn6;
! 495:
! 496: static double igamma(a, x)
! 497: double a, x;
! 498: {
! 499: double arg;
! 500: double aa;
! 501: double an;
! 502: double b;
! 503: int i;
! 504:
! 505: /* Check that we have valid values for a and x */
! 506: if (x < 0.0 || a <= 0.0)
! 507: return -1.0;
! 508:
! 509: /* Deal with special cases */
! 510: if (x == 0.0)
! 511: return 0.0;
! 512: if (x > XBIG)
! 513: return 1.0;
! 514:
! 515: /* Check value of factor arg */
! 516: arg = a * log(x) - x - GAMMA(a + 1.0);
! 517: if (arg < MINEXP)
! 518: return -1.0;
! 519: arg = gp_exp(arg);
! 520:
! 521: /* Choose infinite series or continued fraction. */
! 522:
! 523: if ((x > 1.0) && (x >= a + 2.0)) {
! 524: /* Use a continued fraction expansion */
! 525:
! 526: double rn;
! 527: double rnold;
! 528:
! 529: aa = 1.0 - a;
! 530: b = aa + x + 1.0;
! 531: pn1 = 1.0;
! 532: pn2 = x;
! 533: pn3 = x + 1.0;
! 534: pn4 = x * b;
! 535: rnold = pn3 / pn4;
! 536:
! 537: for (i = 1; i <= ITMAX; i++) {
! 538:
! 539: aa++;
! 540: b += 2.0;
! 541: an = aa * (double) i;
! 542:
! 543: pn5 = b * pn3 - an * pn1;
! 544: pn6 = b * pn4 - an * pn2;
! 545:
! 546: if (pn6 != 0.0) {
! 547:
! 548: rn = pn5 / pn6;
! 549: if (fabs(rnold - rn) <= GPMIN(MACHEPS, MACHEPS * rn))
! 550: return 1.0 - arg * rn * a;
! 551:
! 552: rnold = rn;
! 553: }
! 554: pn1 = pn3;
! 555: pn2 = pn4;
! 556: pn3 = pn5;
! 557: pn4 = pn6;
! 558:
! 559: /* Re-scale terms in continued fraction if terms are large */
! 560: if (fabs(pn5) >= OFLOW) {
! 561:
! 562: pn1 /= OFLOW;
! 563: pn2 /= OFLOW;
! 564: pn3 /= OFLOW;
! 565: pn4 /= OFLOW;
! 566: }
! 567: }
! 568: } else {
! 569: /* Use Pearson's series expansion. */
! 570:
! 571: for (i = 0, aa = a, an = b = 1.0; i <= ITMAX; i++) {
! 572:
! 573: aa++;
! 574: an *= x / aa;
! 575: b += an;
! 576: if (an < b * MACHEPS)
! 577: return arg * b;
! 578: }
! 579: }
! 580: return -1.0;
! 581: }
! 582:
! 583: /***********************************************************************
! 584: double ranf(double init)
! 585: RANDom number generator as a Function
! 586: Returns a random floating point number from a uniform distribution
! 587: over 0 - 1 (endpoints of this interval are not returned) using a
! 588: large integer generator.
! 589: This is a transcription from Pascal to Fortran of routine
! 590: Uniform_01 from the paper
! 591: L'Ecuyer, P. and Cote, S. "Implementing a Random Number Package
! 592: with Splitting Facilities." ACM Transactions on Mathematical
! 593: Software, 17:98-111 (1991)
! 594:
! 595: GeNerate LarGe Integer
! 596: Returns a random integer following a uniform distribution over
! 597: (1, 2147483562) using the generator.
! 598: This is a transcription from Pascal to Fortran of routine
! 599: Random from the paper
! 600: L'Ecuyer, P. and Cote, S. "Implementing a Random Number Package
! 601: with Splitting Facilities." ACM Transactions on Mathematical
! 602: Software, 17:98-111 (1991)
! 603: ***********************************************************************/
! 604: static double ranf(init)
! 605: double init;
! 606: {
! 607:
! 608: long k, z;
! 609: static int firsttime = 1;
! 610: static long s1, s2;
! 611:
! 612: /* (Re)-Initialize seeds if necessary */
! 613: if (init < 0.0 || firsttime == 1) {
! 614: firsttime = 0;
! 615: s1 = 1234567890L;
! 616: s2 = 1234567890L;
! 617: }
! 618: /* Generate pseudo random integers */
! 619: k = s1 / 53668L;
! 620: s1 = Xa1 * (s1 - k * 53668L) - k * 12211;
! 621: if (s1 < 0)
! 622: s1 += Xm1;
! 623: k = s2 / 52774L;
! 624: s2 = Xa2 * (s2 - k * 52774L) - k * 3791;
! 625: if (s2 < 0)
! 626: s2 += Xm2;
! 627: z = s1 - s2;
! 628: if (z < 1)
! 629: z += (Xm1 - 1);
! 630:
! 631: /*
! 632: * 4.656613057E-10 is 1/Xm1. Xm1 is set at the top of this file and is
! 633: * currently 2147483563. If Xm1 changes, change this also.
! 634: */
! 635: return (double) 4.656613057E-10 *z;
! 636: }
! 637:
! 638: /* ----------------------------------------------------------------
! 639: Following to specfun.c made by John Grosh (jgrosh@arl.mil)
! 640: on 28 OCT 1992.
! 641: ---------------------------------------------------------------- */
! 642:
! 643: void f_normal()
! 644: { /* Normal or Gaussian Probability Function */
! 645: struct value a;
! 646: double x;
! 647:
! 648: /* ref. Abramowitz and Stegun 1964, "Handbook of Mathematical
! 649: Functions", Applied Mathematics Series, vol 55,
! 650: Chapter 26, page 934, Eqn. 26.2.29 and Jos van der Woude
! 651: code found above */
! 652:
! 653: x = real(pop(&a));
! 654:
! 655: x = 0.5 * SQRT_TWO * x;
! 656: #ifdef HAVE_ERF
! 657: x = 0.5 * (1.0 + erf(x));
! 658: #else
! 659: {
! 660: int fsign;
! 661: fsign = x >= 0 ? 1 : 0;
! 662: x = igamma(0.5, (x)*(x));
! 663: if (x == 1.0) {
! 664: undefined = TRUE;
! 665: x = 0.0;
! 666: } else {
! 667: if (fsign == 0)
! 668: x = -(x);
! 669: x = 0.5 * (1.0 + x);
! 670: }
! 671: }
! 672: #endif
! 673: push(Gcomplex(&a, x, 0.0));
! 674: }
! 675:
! 676: void f_inverse_normal()
! 677: { /* Inverse normal distribution function */
! 678: struct value a;
! 679: double x;
! 680:
! 681: x = real(pop(&a));
! 682:
! 683: if (x <= 0.0 || x >= 1.0) {
! 684: undefined = TRUE;
! 685: push(Gcomplex(&a, 0.0, 0.0));
! 686: } else {
! 687: push(Gcomplex(&a, inverse_normal_func(x), 0.0));
! 688: }
! 689: }
! 690:
! 691:
! 692: void f_inverse_erf()
! 693: { /* Inverse error function */
! 694: struct value a;
! 695: double x;
! 696:
! 697: x = real(pop(&a));
! 698:
! 699: if (fabs(x) >= 1.0) {
! 700: undefined = TRUE;
! 701: push(Gcomplex(&a, 0.0, 0.0));
! 702: } else {
! 703: push(Gcomplex(&a, inverse_error_func(x), 0.0));
! 704: }
! 705: }
! 706:
! 707: static double inverse_normal_func(p)
! 708: double p;
! 709: {
! 710: /*
! 711: Source: This routine was derived (using f2c) from the
! 712: FORTRAN subroutine MDNRIS found in
! 713: ACM Algorithm 602 obtained from netlib.
! 714:
! 715: MDNRIS code contains the 1978 Copyright
! 716: by IMSL, INC. . Since MDNRIS has been
! 717: submitted to netlib it may be used with
! 718: the restriction that it may only be
! 719: used for noncommercial purposes and that
! 720: IMSL be acknowledged as the copyright-holder
! 721: of the code.
! 722: */
! 723:
! 724: /* Initialized data */
! 725: static double eps = 1e-10;
! 726: static double g0 = 1.851159e-4;
! 727: static double g1 = -.002028152;
! 728: static double g2 = -.1498384;
! 729: static double g3 = .01078639;
! 730: static double h0 = .09952975;
! 731: static double h1 = .5211733;
! 732: static double h2 = -.06888301;
! 733: static double sqrt2 = 1.414213562373095;
! 734:
! 735: /* Local variables */
! 736: static double a, w, x;
! 737: static double sd, wi, sn, y;
! 738:
! 739: /* Note: 0.0 < p < 1.0 */
! 740:
! 741: /* p too small, compute y directly */
! 742: if (p <= eps) {
! 743: a = p + p;
! 744: w = sqrt(-(double) log(a + (a - a * a)));
! 745:
! 746: /* use a rational function in 1.0 / w */
! 747: wi = 1.0 / w;
! 748: sn = ((g3 * wi + g2) * wi + g1) * wi;
! 749: sd = ((wi + h2) * wi + h1) * wi + h0;
! 750: y = w + w * (g0 + sn / sd);
! 751: y = -y * sqrt2;
! 752: } else {
! 753: x = 1.0 - (p + p);
! 754: y = inverse_error_func(x);
! 755: y = -sqrt2 * y;
! 756: }
! 757: return (y);
! 758: }
! 759:
! 760:
! 761: static double inverse_error_func(p)
! 762: double p;
! 763: {
! 764: /*
! 765: Source: This routine was derived (using f2c) from the
! 766: FORTRAN subroutine MERFI found in
! 767: ACM Algorithm 602 obtained from netlib.
! 768:
! 769: MDNRIS code contains the 1978 Copyright
! 770: by IMSL, INC. . Since MERFI has been
! 771: submitted to netlib, it may be used with
! 772: the restriction that it may only be
! 773: used for noncommercial purposes and that
! 774: IMSL be acknowledged as the copyright-holder
! 775: of the code.
! 776: */
! 777:
! 778:
! 779:
! 780: /* Initialized data */
! 781: static double a1 = -.5751703;
! 782: static double a2 = -1.896513;
! 783: static double a3 = -.05496261;
! 784: static double b0 = -.113773;
! 785: static double b1 = -3.293474;
! 786: static double b2 = -2.374996;
! 787: static double b3 = -1.187515;
! 788: static double c0 = -.1146666;
! 789: static double c1 = -.1314774;
! 790: static double c2 = -.2368201;
! 791: static double c3 = .05073975;
! 792: static double d0 = -44.27977;
! 793: static double d1 = 21.98546;
! 794: static double d2 = -7.586103;
! 795: static double e0 = -.05668422;
! 796: static double e1 = .3937021;
! 797: static double e2 = -.3166501;
! 798: static double e3 = .06208963;
! 799: static double f0 = -6.266786;
! 800: static double f1 = 4.666263;
! 801: static double f2 = -2.962883;
! 802: static double g0 = 1.851159e-4;
! 803: static double g1 = -.002028152;
! 804: static double g2 = -.1498384;
! 805: static double g3 = .01078639;
! 806: static double h0 = .09952975;
! 807: static double h1 = .5211733;
! 808: static double h2 = -.06888301;
! 809:
! 810: /* Local variables */
! 811: static double a, b, f, w, x, y, z, sigma, z2, sd, wi, sn;
! 812:
! 813: x = p;
! 814:
! 815: /* determine sign of x */
! 816: if (x > 0)
! 817: sigma = 1.0;
! 818: else
! 819: sigma = -1.0;
! 820:
! 821: /* Note: -1.0 < x < 1.0 */
! 822:
! 823: z = fabs(x);
! 824:
! 825: /* z between 0.0 and 0.85, approx. f by a
! 826: rational function in z */
! 827:
! 828: if (z <= 0.85) {
! 829: z2 = z * z;
! 830: f = z + z * (b0 + a1 * z2 / (b1 + z2 + a2
! 831: / (b2 + z2 + a3 / (b3 + z2))));
! 832:
! 833: /* z greater than 0.85 */
! 834: } else {
! 835: a = 1.0 - z;
! 836: b = z;
! 837:
! 838: /* reduced argument is in (0.85,1.0),
! 839: obtain the transformed variable */
! 840:
! 841: w = sqrt(-(double) log(a + a * b));
! 842:
! 843: /* w greater than 4.0, approx. f by a
! 844: rational function in 1.0 / w */
! 845:
! 846: if (w >= 4.0) {
! 847: wi = 1.0 / w;
! 848: sn = ((g3 * wi + g2) * wi + g1) * wi;
! 849: sd = ((wi + h2) * wi + h1) * wi + h0;
! 850: f = w + w * (g0 + sn / sd);
! 851:
! 852: /* w between 2.5 and 4.0, approx.
! 853: f by a rational function in w */
! 854:
! 855: } else if (w < 4.0 && w > 2.5) {
! 856: sn = ((e3 * w + e2) * w + e1) * w;
! 857: sd = ((w + f2) * w + f1) * w + f0;
! 858: f = w + w * (e0 + sn / sd);
! 859:
! 860: /* w between 1.13222 and 2.5, approx. f by
! 861: a rational function in w */
! 862: } else if (w <= 2.5 && w > 1.13222) {
! 863: sn = ((c3 * w + c2) * w + c1) * w;
! 864: sd = ((w + d2) * w + d1) * w + d0;
! 865: f = w + w * (c0 + sn / sd);
! 866: }
! 867: }
! 868: y = sigma * f;
! 869: return (y);
! 870: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>