| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996 |
- /****************************************************************************
- * chi2.c
- *
- * This module contains the function for the chi square distribution.
- *
- * All functions in this module are taken from the Cephes math library.
- *
- * Cephes Math Library Release 2.0: April, 1987
- * Copyright 1984, 1987 by Stephen L. Moshier
- * Direct inquiries to 30 Frost Street, Cambridge, MA 02140
- *
- * from Persistence of Vision(tm) Ray Tracer
- * Copyright 1996,1999 Persistence of Vision Team
- *---------------------------------------------------------------------------
- * NOTICE: This source code file is provided so that users may experiment
- * with enhancements to POV-Ray and to port the software to platforms other
- * than those supported by the POV-Ray Team. There are strict rules under
- * which you are permitted to use this file. The rules are in the file
- * named POVLEGAL.DOC which should be distributed with this file.
- * If POVLEGAL.DOC is not available or for more info please contact the POV-Ray
- * Team Coordinator by email to team-coord@povray.org or visit us on the web at
- * http://www.povray.org. The latest version of POV-Ray may be found at this site.
- *
- * This program is based on the popular DKB raytracer version 2.12.
- * DKBTrace was originally written by David K. Buck.
- * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
- *
- *****************************************************************************/
- #include "frame.h"
- #include "povproto.h"
- #include "chi2.h"
- /*
- Cephes Math Library Release 2.0: April, 1987
- Copyright 1984, 1987 by Stephen L. Moshier
- Direct inquiries to 30 Frost Street, Cambridge, MA 02140
- */
- /*****************************************************************************
- * Local preprocessor defines
- ******************************************************************************/
- #define MAXLGM 2.556348e305
- #define BIG 1.44115188075855872E+17
- #define MACHEP 1.38777878078144567553E-17 /* 2**-56 */
- #define MAXLOG 8.8029691931113054295988E1 /* log(2**127) */
- #define MAXNUM 1.701411834604692317316873e38 /* 2**127 */
- #define LOGPI 1.14472988584940017414
- /*****************************************************************************
- * Local typedefs
- ******************************************************************************/
- /*****************************************************************************
- * Local variables
- ******************************************************************************/
- static int sgngam = 0;
- /*
- * A[]: Stirling's formula expansion of log gamma
- * B[], C[]: log gamma function between 2 and 3
- */
- static DBL A[] =
- {
- 8.11614167470508450300E-4,
- -5.95061904284301438324E-4,
- 7.93650340457716943945E-4,
- -2.77777777730099687205E-3,
- 8.33333333333331927722E-2
- };
- static DBL B[] =
- {
- -1.37825152569120859100E3,
- -3.88016315134637840924E4,
- -3.31612992738871184744E5,
- -1.16237097492762307383E6,
- -1.72173700820839662146E6,
- -8.53555664245765465627E5
- };
- static DBL C[] =
- {
- 1.00000000000000000000E0,
- -3.51815701436523470549E2,
- -1.70642106651881159223E4,
- -2.20528590553854454839E5,
- -1.13933444367982507207E6,
- -2.53252307177582951285E6,
- -2.01889141433532773231E6
- };
- /* log(sqrt(2pi)) */
- static DBL LS2PI = 0.91893853320467274178;
- /* sqrt(2pi) */
- static DBL s2pi = 2.50662827463100050242E0;
- /* approximation for 0 <= |y - 0.5| <= 3/8 */
- static DBL P0[5] =
- {
- -5.99633501014107895267E1,
- 9.80010754185999661536E1,
- -5.66762857469070293439E1,
- 1.39312609387279679503E1,
- -1.23916583867381258016E0,
- };
- static DBL Q0[8] =
- {
- /* 1.00000000000000000000E0,*/
- 1.95448858338141759834E0,
- 4.67627912898881538453E0,
- 8.63602421390890590575E1,
- -2.25462687854119370527E2,
- 2.00260212380060660359E2,
- -8.20372256168333339912E1,
- 1.59056225126211695515E1,
- -1.18331621121330003142E0,
- };
- /*
- * Approximation for interval z = sqrt(-2 log y ) between 2 and 8
- * i.e., y between exp(-2) = .135 and exp(-32) = 1.27e-14.
- */
- static DBL P1[9] =
- {
- 4.05544892305962419923E0,
- 3.15251094599893866154E1,
- 5.71628192246421288162E1,
- 4.40805073893200834700E1,
- 1.46849561928858024014E1,
- 2.18663306850790267539E0,
- -1.40256079171354495875E-1,
- -3.50424626827848203418E-2,
- -8.57456785154685413611E-4,
- };
- static DBL Q1[8] =
- {
- /* 1.00000000000000000000E0,*/
- 1.57799883256466749731E1,
- 4.53907635128879210584E1,
- 4.13172038254672030440E1,
- 1.50425385692907503408E1,
- 2.50464946208309415979E0,
- -1.42182922854787788574E-1,
- -3.80806407691578277194E-2,
- -9.33259480895457427372E-4,
- };
- /*
- * Approximation for interval z = sqrt(-2 log y ) between 8 and 64
- * i.e., y between exp(-32) = 1.27e-14 and exp(-2048) = 3.67e-890.
- */
- static DBL P2[9] =
- {
- 3.23774891776946035970E0,
- 6.91522889068984211695E0,
- 3.93881025292474443415E0,
- 1.33303460815807542389E0,
- 2.01485389549179081538E-1,
- 1.23716634817820021358E-2,
- 3.01581553508235416007E-4,
- 2.65806974686737550832E-6,
- 6.23974539184983293730E-9,
- };
- static DBL Q2[8] =
- {
- /* 1.00000000000000000000E0,*/
- 6.02427039364742014255E0,
- 3.67983563856160859403E0,
- 1.37702099489081330271E0,
- 2.16236993594496635890E-1,
- 1.34204006088543189037E-2,
- 3.28014464682127739104E-4,
- 2.89247864745380683936E-6,
- 6.79019408009981274425E-9,
- };
- /*****************************************************************************
- * Static functions
- ******************************************************************************/
- static DBL igami (DBL a, DBL y0);
- static DBL lgam (DBL x);
- static DBL polevl (DBL x, DBL * coef, int N);
- static DBL p1evl (DBL x, DBL * coef, int N);
- static DBL igamc (DBL a, DBL x);
- static DBL igam (DBL a, DBL x);
- static DBL ndtri (DBL y0);
- /* chdtri()
- *
- * Inverse of complemented Chi-square distribution
- *
- *
- *
- * SYNOPSIS:
- *
- * DBL df, x, y, chdtri();
- *
- * x = chdtri( df, y );
- *
- *
- *
- *
- * DESCRIPTION:
- *
- * Finds the Chi-square argument x such that the integral
- * from x to infinity of the Chi-square density is equal
- * to the given cumulative probability y.
- *
- * This is accomplished using the inverse gamma integral
- * function and the relation
- *
- * x/2 = igami( df/2, y );
- *
- *
- *
- *
- * ACCURACY:
- *
- * See igami.c.
- *
- * ERROR MESSAGES:
- *
- * message condition value returned
- * chdtri domain y < 0 or y > 1 0.0
- * v < 1
- *
- */
- DBL chdtri(DBL df, DBL y)
- {
- DBL x;
- if ((y < 0.0) || (y > 1.0) || (df < 1.0))
- {
- Error("Illegal values fd=%f and y=%f in chdtri().\n", df, y);
- return (0.0);
- }
- x = igami(0.5 * df, y);
- return (2.0 * x);
- }
- /* lgam()
- *
- * Natural logarithm of gamma function
- *
- *
- *
- * SYNOPSIS:
- *
- * DBL x, y, lgam();
- * extern int sgngam;
- *
- * y = lgam( x );
- *
- *
- *
- * DESCRIPTION:
- *
- * Returns the base e (2.718...) logarithm of the absolute
- * value of the gamma function of the argument.
- * The sign (+1 or -1) of the gamma function is returned in a
- * global (extern) variable named sgngam.
- *
- * For arguments greater than 13, the logarithm of the gamma
- * function is approximated by the logarithmic version of
- * Stirling's formula using a polynomial approximation of
- * degree 4. Arguments between -33 and +33 are reduced by
- * recurrence to the interval [2,3] of a rational approximation.
- * The cosecant reflection formula is employed for arguments
- * less than -33.
- *
- * Arguments greater than MAXLGM return MAXNUM and an error
- * message. MAXLGM = 2.035093e36 for DEC
- * arithmetic or 2.556348e305 for IEEE arithmetic.
- *
- *
- *
- * ACCURACY:
- *
- *
- * arithmetic domain # trials peak rms
- * DEC 0, 3 7000 5.2e-17 1.3e-17
- * DEC 2.718, 2.035e36 5000 3.9e-17 9.9e-18
- * IEEE 0, 3 28000 5.4e-16 1.1e-16
- * IEEE 2.718, 2.556e305 40000 3.5e-16 8.3e-17
- * The error criterion was relative when the function magnitude
- * was greater than one but absolute when it was less than one.
- *
- * The following test used the relative error criterion, though
- * at certain points the relative error could be much higher than
- * indicated.
- * IEEE -200, -4 10000 4.8e-16 1.3e-16
- *
- */
- static DBL lgam(DBL x)
- {
- DBL p, q, w, z;
- int i;
- sgngam = 1;
- if (x < -34.0)
- {
- q = -x;
- w = lgam(q); /* note this modifies sgngam! */
- p = floor(q);
- if (p == q)
- {
- goto loverf;
- }
- i = p;
- if ((i & 1) == 0)
- {
- sgngam = -1;
- }
- else
- {
- sgngam = 1;
- }
- z = q - p;
- if (z > 0.5)
- {
- p += 1.0;
- z = p - q;
- }
- z = q * sin(M_PI * z);
- if (z == 0.0)
- {
- goto loverf;
- }
- /* z = log(M_PI) - log( z ) - w;*/
- z = LOGPI - log(z) - w;
- return (z);
- }
- if (x < 13.0)
- {
- z = 1.0;
- while (x >= 3.0)
- {
- x -= 1.0;
- z *= x;
- }
- while (x < 2.0)
- {
- if (x == 0.0)
- {
- goto loverf;
- }
- z /= x;
- x += 1.0;
- }
- if (z < 0.0)
- {
- sgngam = -1;
- z = -z;
- }
- else
- {
- sgngam = 1;
- }
- if (x == 2.0)
- {
- return (log(z));
- }
- x -= 2.0;
- p = x * polevl(x, B, 5) / p1evl(x, C, 6);
- return (log(z) + p);
- }
- if (x > MAXLGM)
- {
- loverf:
- /*
- mtherr("lgam", OVERFLOW);
- */
- return (sgngam * MAXNUM);
- }
- q = (x - 0.5) * log(x) - x + LS2PI;
- if (x > 1.0e8)
- {
- return (q);
- }
- p = 1.0 / (x * x);
- if (x >= 1000.0)
- {
- q += ((7.9365079365079365079365e-4 * p -
- 2.7777777777777777777778e-3) * p +
- 0.0833333333333333333333) / x;
- }
- else
- {
- q += polevl(p, A, 4) / x;
- }
- return (q);
- }
- /* igamc()
- *
- * Complemented incomplete gamma integral
- *
- *
- *
- * SYNOPSIS:
- *
- * DBL a, x, y, igamc();
- *
- * y = igamc( a, x );
- *
- *
- *
- * DESCRIPTION:
- *
- * The function is defined by
- *
- *
- * igamc(a,x) = 1 - igam(a,x)
- *
- * inf.
- * -
- * 1 | | -t a-1
- * = ----- | e t dt.
- * - | |
- * | (a) -
- * x
- *
- *
- * In this implementation both arguments must be positive.
- * The integral is evaluated by either a power series or
- * continued fraction expansion, depending on the relative
- * values of a and x.
- *
- *
- *
- * ACCURACY:
- *
- * Relative error:
- * arithmetic domain # trials peak rms
- * DEC 0,30 2000 2.7e-15 4.0e-16
- * IEEE 0,30 60000 1.4e-12 6.3e-15
- *
- */
- static DBL igamc(DBL a, DBL x)
- {
- DBL ans, c, yc, ax, y, z;
- DBL pk, pkm1, pkm2, qk, qkm1, qkm2;
- DBL r, t;
- if ((x <= 0) || (a <= 0))
- {
- return (1.0);
- }
- if ((x < 1.0) || (x < a))
- {
- return (1.0 - igam(a, x));
- }
- ax = a * log(x) - x - lgam(a);
- if (ax < -MAXLOG)
- {
- /*
- mtherr("igamc", UNDERFLOW);
- */
- return (0.0);
- }
- ax = exp(ax);
- /* continued fraction */
- y = 1.0 - a;
- z = x + y + 1.0;
- c = 0.0;
- pkm2 = 1.0;
- qkm2 = x;
- pkm1 = x + 1.0;
- qkm1 = z * x;
- ans = pkm1 / qkm1;
- do
- {
- c += 1.0;
- y += 1.0;
- z += 2.0;
- yc = y * c;
- pk = pkm1 * z - pkm2 * yc;
- qk = qkm1 * z - qkm2 * yc;
- if (qk != 0)
- {
- r = pk / qk;
- t = fabs((ans - r) / r);
- ans = r;
- }
- else
- {
- t = 1.0;
- }
- pkm2 = pkm1;
- pkm1 = pk;
- qkm2 = qkm1;
- qkm1 = qk;
- if (fabs(pk) > BIG)
- {
- pkm2 /= BIG;
- pkm1 /= BIG;
- qkm2 /= BIG;
- qkm1 /= BIG;
- }
- }
- while (t > MACHEP);
- return (ans * ax);
- }
- /* igam.c
- *
- * Incomplete gamma integral
- *
- *
- *
- * SYNOPSIS:
- *
- * DBL a, x, y, igam();
- *
- * y = igam( a, x );
- *
- *
- *
- * DESCRIPTION:
- *
- * The function is defined by
- *
- * x
- * -
- * 1 | | -t a-1
- * igam(a,x) = ----- | e t dt.
- * - | |
- * | (a) -
- * 0
- *
- *
- * In this implementation both arguments must be positive.
- * The integral is evaluated by either a power series or
- * continued fraction expansion, depending on the relative
- * values of a and x.
- *
- *
- *
- * ACCURACY:
- *
- * Relative error:
- * arithmetic domain # trials peak rms
- * DEC 0,30 4000 4.4e-15 6.3e-16
- * IEEE 0,30 10000 3.6e-14 5.1e-15
- *
- */
- /* left tail of incomplete gamma function:
- *
- * inf. k
- * a -x - x
- * x e > ----------
- * - -
- * k=0 | (a+k+1)
- *
- */
- static DBL igam(DBL a, DBL x)
- {
- DBL ans, ax, c, r;
- if ((x <= 0) || (a <= 0))
- {
- return (0.0);
- }
- if ((x > 1.0) && (x > a))
- {
- return (1.0 - igamc(a, x));
- }
- /* Compute x**a * exp(-x) / gamma(a) */
- ax = a * log(x) - x - lgam(a);
- if (ax < -MAXLOG)
- {
- /*
- mtherr("igam", UNDERFLOW);
- */
- return (0.0);
- }
- ax = exp(ax);
- /* power series */
- r = a;
- c = 1.0;
- ans = 1.0;
- do
- {
- r += 1.0;
- c *= x / r;
- ans += c;
- }
- while (c / ans > MACHEP);
- return (ans * ax / a);
- }
- /* igami()
- *
- * Inverse of complemented imcomplete gamma integral
- *
- *
- *
- * SYNOPSIS:
- *
- * DBL a, x, y, igami();
- *
- * x = igami( a, y );
- *
- *
- *
- * DESCRIPTION:
- *
- * Given y, the function finds x such that
- *
- * igamc( a, x ) = y.
- *
- * Starting with the approximate value
- *
- * 3
- * x = a t
- *
- * where
- *
- * t = 1 - d - ndtri(y) sqrt(d)
- *
- * and
- *
- * d = 1/9a,
- *
- * the routine performs up to 10 Newton iterations to find the
- * root of igamc(a,x) - y = 0.
- *
- *
- * ACCURACY:
- *
- * Tested for a ranging from 0.5 to 30 and x from 0 to 0.5.
- *
- * Relative error:
- * arithmetic domain # trials peak rms
- * DEC 0,0.5 3400 8.8e-16 1.3e-16
- * IEEE 0,0.5 10000 1.1e-14 1.0e-15
- *
- */
- static DBL igami(DBL a, DBL y0)
- {
- DBL d, y, x0, lgm;
- int i;
- /* approximation to inverse function */
- d = 1.0 / (9.0 * a);
- y = (1.0 - d - ndtri(y0) * sqrt(d));
- x0 = a * y * y * y;
- lgm = lgam(a);
- for (i = 0; i < 10; i++)
- {
- if (x0 <= 0.0)
- {
- /*
- mtherr("igami", UNDERFLOW);
- */
- return (0.0);
- }
- y = igamc(a, x0);
- /* compute the derivative of the function at this point */
- d = (a - 1.0) * log(x0) - x0 - lgm;
- if (d < -MAXLOG)
- {
- /*
- mtherr("igami", UNDERFLOW);
- */
- goto done;
- }
- d = -exp(d);
- /* compute the step to the next approximation of x */
- if (d == 0.0)
- {
- goto done;
- }
- d = (y - y0) / d;
- x0 = x0 - d;
- if (i < 3)
- {
- continue;
- }
- if (fabs(d / x0) < 2.0 * MACHEP)
- {
- goto done;
- }
- }
- done:
- return (x0);
- }
- /* ndtri.c
- *
- * Inverse of Normal distribution function
- *
- *
- *
- * SYNOPSIS:
- *
- * DBL x, y, ndtri();
- *
- * x = ndtri( y );
- *
- *
- *
- * DESCRIPTION:
- *
- * Returns the argument, x, for which the area under the
- * Gaussian probability density function (integrated from
- * minus infinity to x) is equal to y.
- *
- *
- * For small arguments 0 < y < exp(-2), the program computes
- * z = sqrt( -2.0 * log(y) ); then the approximation is
- * x = z - log(z)/z - (1/z) P(1/z) / Q(1/z).
- * There are two rational functions P/Q, one for 0 < y < exp(-32)
- * and the other for y up to exp(-2). For larger arguments,
- * w = y - 0.5, and x/sqrt(2pi) = w + w**3 R(w**2)/S(w**2)).
- *
- *
- * ACCURACY:
- *
- * Relative error:
- * arithmetic domain # trials peak rms
- * DEC 0.125, 1 5500 9.5e-17 2.1e-17
- * DEC 6e-39, 0.135 3500 5.7e-17 1.3e-17
- * IEEE 0.125, 1 20000 7.2e-16 1.3e-16
- * IEEE 3e-308, 0.135 50000 4.6e-16 9.8e-17
- *
- *
- * ERROR MESSAGES:
- *
- * message condition value returned
- * ndtri domain x <= 0 -MAXNUM
- * ndtri domain x >= 1 MAXNUM
- *
- */
- static DBL ndtri(DBL y0)
- {
- DBL x, y, z, y2, x0, x1;
- int code;
- if (y0 <= 0.0)
- {
- /*
- mtherr("ndtri", DOMAIN);
- */
- return (-MAXNUM);
- }
- if (y0 >= 1.0)
- {
- /*
- mtherr("ndtri", DOMAIN);
- */
- return (MAXNUM);
- }
- code = 1;
- y = y0;
- if (y > (1.0 - 0.13533528323661269189)) /* 0.135... = exp(-2) */
- {
- y = 1.0 - y;
- code = 0;
- }
- if (y > 0.13533528323661269189)
- {
- y = y - 0.5;
- y2 = y * y;
- x = y + y * (y2 * polevl(y2, P0, 4) / p1evl(y2, Q0, 8));
- x = x * s2pi;
- return (x);
- }
- x = sqrt(-2.0 * log(y));
- x0 = x - log(x) / x;
- z = 1.0 / x;
- if (x < 8.0) /* y > exp(-32) = 1.2664165549e-14 */
- {
- x1 = z * polevl(z, P1, 8) / p1evl(z, Q1, 8);
- }
- else
- {
- x1 = z * polevl(z, P2, 8) / p1evl(z, Q2, 8);
- }
- x = x0 - x1;
- if (code != 0)
- {
- x = -x;
- }
- return (x);
- }
- /* polevl.c
- * p1evl.c
- *
- * Evaluate polynomial
- *
- *
- *
- * SYNOPSIS:
- *
- * int N;
- * DBL x, y, coef[N+1], polevl[];
- *
- * y = polevl( x, coef, N );
- *
- *
- *
- * DESCRIPTION:
- *
- * Evaluates polynomial of degree N:
- *
- * 2 N
- * y = C + C x + C x +...+ C x
- * 0 1 2 N
- *
- * Coefficients are stored in reverse order:
- *
- * coef[0] = C , ..., coef[N] = C .
- * N 0
- *
- * The function p1evl() assumes that coef[N] = 1.0 and is
- * omitted from the array. Its calling arguments are
- * otherwise the same as polevl().
- *
- *
- * SPEED:
- *
- * In the interest of speed, there are no checks for out
- * of bounds arithmetic. This routine is used by most of
- * the functions in the library. Depending on available
- * equipment features, the user may wish to rewrite the
- * program in microcode or assembly language.
- *
- */
- static DBL polevl(DBL x, DBL coef[], int N)
- {
- DBL ans;
- int i;
- DBL *p;
- p = coef;
- ans = *p++;
- i = N;
- do
- {
- ans = ans * x + *p++;
- }
- while (--i);
- return (ans);
- }
- /* p1evl() */
- /* N
- * Evaluate polynomial when coefficient of x is 1.0.
- * Otherwise same as polevl.
- */
- static DBL p1evl(DBL x, DBL coef[], int N)
- {
- DBL ans;
- DBL *p;
- int i;
- p = coef;
- ans = x + *p++;
- i = N - 1;
- do
- {
- ans = ans * x + *p++;
- }
- while (--i);
- return (ans);
- }
|