[BACK]Return to specfun.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / gnuplot

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>