home *** CD-ROM | disk | FTP | other *** search
- /* ndtri.c
- *
- * Inverse of Normal distribution function
- *
- *
- *
- * SYNOPSIS:
- *
- * double 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) - log(sqrt(2pi)))/z - P(-z)/Q(-z).
- * There are two rational functions P/Q, one for 0 < y < 2e-40
- * and the other for y up to exp(-2). For larger arguments,
- * z = y - 0.5, and x = sqrt(2pi) (z + z**3 P4(z**2)/Q8(z**2)).
- *
- *
- * ACCURACY:
- *
- * Relative error:
- * arithmetic range # trials peak rms
- * DEC 0.125, 1 11000 7.6e-17 1.6e-17
- * DEC 6e-39, 0.135 10000 6.0e-17 1.3e-17
- * IEEE 0.125, 1 6500 7.1e-16 1.3e-16
- * IEEE 3e-308, 0.135 5000 4.1e-16 9.5e-17
- *
- *
- * ERROR MESSAGES:
- *
- * message condition value returned
- * ndtri domain x <= 0 -MAXNUM
- * ndtri domain x >= 1 MAXNUM
- *
- */
-
-
- /*
- Cephes Math Library Release 2.0: April, 1987
- Copyright 1984, 1987 by Stephen L. Moshier
- Direct inquiries to 30 Frost Street, Cambridge, MA 02140
- */
-
- #include "mconf.h"
- extern double MAXNUM;
-
- #ifdef UNK
- static double P0[] = {
- -5.99633501014107891266E1,
- 9.80010754185999654266E1,
- -5.66762857469070288892E1,
- 1.39312609387279678315E1,
- -1.23916583867381256906E0
- };
- static double Q0[] = {
- /* 1.00000000000000000000E0, */
- 1.95448858338141759078E0,
- 4.67627912898881536003E0,
- 8.63602421390890584914E1,
- -2.25462687854119368911E2,
- 2.00260212380060658814E2,
- -8.20372256168333333195E1,
- 1.59056225126211694148E1,
- -1.18331621121330002082E0
- };
- static double P1[] = {
- -8.06295164062928296467E-7,
- -1.24053576627339949494E-4,
- 6.49932444421283598941E-3,
- -1.75578085015445987182E1,
- 1.13340546911064577348E3,
- -1.55308233703367942177E4,
- 5.96478957762231923216E4,
- -1.34118762557568719035E5,
- 1.33922736098486867793E5,
- -7.68504745178723676740E4
- };
- static double Q1[] = {
- /* 1.00000000000000000000E0,*/
- -1.47602102962036448989E2,
- 4.36545092375268950884E3,
- -4.06167070356628991869E4,
- 1.54083842563020896864E5,
- -3.52535896087944211765E5,
- 3.74088548110300571177E5,
- -2.40053383557002665939E5,
- 3.38930498523655775059E4,
- 9.17564445564876422447E2
- };
- static double P2[] = {
- 8.94084651318768121212E-8,
- 5.74305670024326318968E-5,
- 2.89444514333676761949E-2,
- -1.42646079401864981264E1,
- 5.65275920555989502947E2,
- 1.20932159059563133049E3,
- -7.30662837143628743787E4
- };
- static double Q2[] = {
- /* 1.00000000000000000000E0,*/
- -9.42696522534933841013E1,
- 1.32905713172348184767E3,
- 1.30035792204994811143E4,
- -1.45436997023716148384E5,
- 8.82097696844164863759E4,
- 5.20585037820295592936E4
- };
- /* -log(sqrt(2pi)) */
- static double lstpi = -9.18938533204672741780E-1;
- /* sqrt(2pi) */
- static double s2pi = 2.50662827463100050242E0;
- #endif
-
- #ifdef DEC
- static short P0[] = {
- 0141557,0155170,0071360,0120550,
- 0041704,0000214,0172417,0067307,
- 0141542,0132204,0040066,0156722,
- 0041136,0163161,0157276,0007746,
- 0140236,0116374,0073666,0051764
- };
- static short Q0[] = {
- /*0040200,0000000,0000000,0000000,*/
- 0040372,0026256,0110403,0123707,
- 0040625,0122024,0020277,0026661,
- 0041654,0134161,0124134,0007243,
- 0142141,0073162,0133021,0131371,
- 0042110,0041235,0043516,0057766,
- 0141644,0011417,0036155,0137305,
- 0041176,0076556,0004043,0125427,
- 0140227,0073347,0152776,0067251
- };
- static short P1[] = {
- 0133130,0070056,0104154,0123744,
- 0135002,0012140,0157600,0156617,
- 0036324,0174110,0173614,0163423,
- 0141214,0073144,0046674,0102277,
- 0042615,0126371,0115133,0034141,
- 0143562,0125513,0020627,0172034,
- 0044150,0177745,0050627,0027445,
- 0144402,0174660,0146676,0041276,
- 0044402,0144257,0016074,0151757,
- 0144226,0014474,0136400,0065630
- };
- static short Q1[] = {
- /*0040200,0000000,0000000,0000000,*/
- 0142023,0115043,0065562,0142562,
- 0043210,0065633,0076751,0113124,
- 0144036,0124265,0000112,0004502,
- 0044426,0074365,0166215,0071345,
- 0144654,0021374,0126300,0117727,
- 0044666,0124421,0105036,0116362,
- 0144552,0066530,0106062,0125647,
- 0044004,0062414,0141437,0163711,
- 0042545,0062037,0160112,0060416
- };
- static short P2[] = {
- 0032300,0000322,0151003,0072465,
- 0034560,0160632,0006537,0051737,
- 0036755,0016352,0004722,0136054,
- 0141144,0035725,0104425,0147223,
- 0042415,0050650,0127261,0010470,
- 0042627,0025112,0074134,0057002,
- 0144216,0132444,0050300,0111372
- };
- static short Q2[] = {
- /*0040200,0000000,0000000,0000000,*/
- 0141674,0105017,0156064,0013764,
- 0042646,0020724,0002750,0076546,
- 0043513,0027121,0017455,0134707,
- 0144416,0003477,0147474,0107614,
- 0044254,0044342,0102404,0155206,
- 0044113,0055200,0173733,0166505
- };
- static short lstp[] = {0140153,0037616,0041445,0172645};
- #define lstpi *(double *)lstp
- static short s2p[] = {0040440,0066230,0177661,0034055};
- #define s2pi *(double *)s2p
- #endif
-
- #ifdef IBMPC
- static short P0[] = {
- 0x142d,0x0e5e,0xfb4f,0xc04d,
- 0xedd9,0x9ea1,0x8011,0x4058,
- 0xdbba,0x8806,0x5690,0xc04c,
- 0xc1fd,0x3bd7,0xdcce,0x402b,
- 0xca7e,0x8ef6,0xd39f,0xbff3
- };
- static short Q0[] = {
- /*0x0000,0x0000,0x0000,0x3ff0,*/
- 0x74f9,0xd220,0x4595,0x3fff,
- 0xe5b6,0x8417,0xb482,0x4012,
- 0x81d4,0x350b,0x970e,0x4055,
- 0x365f,0x56c2,0x2ece,0xc06c,
- 0xcbff,0xa8e9,0x0853,0x4069,
- 0xb7d9,0xe78d,0x8261,0xc054,
- 0x7563,0xc104,0xcfad,0x402f,
- 0xcdd5,0xfabf,0xeedc,0xbff2
- };
- static short P1[] = {
- 0x94fd,0xd10d,0x0e05,0xbeab,
- 0x1bb2,0x1bf0,0x428c,0xbf20,
- 0x9ce2,0x1ef1,0x9f09,0x3f7a,
- 0x9098,0x89b7,0x8ecc,0xc031,
- 0x670c,0x334b,0xb59f,0x4091,
- 0xfe84,0x6432,0x5569,0xc0ce,
- 0xe5e5,0xaa32,0x1ffc,0x40ed,
- 0xc858,0x19b7,0x5f36,0xc100,
- 0x9a7e,0xe387,0x5915,0x4100,
- 0x0d73,0x97a0,0xc327,0xc0f2
- };
- static short Q1[] = {
- /*0x0000,0x0000,0x0000,0x3ff0,*/
- 0x58ae,0x6d6e,0x7344,0xc062,
- 0x32cb,0x6fbd,0x0d73,0x40b1,
- 0x4128,0xa009,0xd516,0xc0e3,
- 0xae5d,0xbd91,0xcf1e,0x4102,
- 0x13fb,0x9598,0x845f,0xc115,
- 0xd39e,0x3143,0xd522,0x4116,
- 0x5575,0x1186,0x4dab,0xc10d,
- 0xfcf9,0x9863,0x8ca1,0x40e0,
- 0x4c22,0xfc09,0xac83,0x408c
- };
- static short P2[] = {
- 0x6ea7,0x5a40,0x001a,0x3e78,
- 0xea7c,0x41ab,0x1c33,0x3f0e,
- 0x5785,0x413a,0xa39d,0x3f9d,
- 0xb9d2,0xb122,0x877a,0xc02c,
- 0x2227,0x15d6,0xaa35,0x4081,
- 0x8bc0,0x4f0b,0xe549,0x4092,
- 0x125f,0x8a18,0xd6a4,0xc0f1
- };
- static short Q2[] = {
- /*0x0000,0x0000,0x0000,0x3ff0,*/
- 0x82ff,0xfb86,0x9141,0xc057,
- 0x0fad,0x80bd,0xc43a,0x4094,
- 0xb739,0x23e5,0x65ca,0x40c9,
- 0x91f2,0xf9e7,0xc0e7,0xc101,
- 0x9b51,0x50a0,0x891c,0x40f5,
- 0x7da9,0x1efb,0x6b50,0x40e9
- };
- static short lstp[] = {0xbeb5,0xc864,0x67f1,0xbfed};
- #define lstpi *(double *)lstp
- static short s2p[] = {0x2706,0x1ff6,0x0d93,0x4004};
- #define s2pi *(double *)s2p
- #endif
-
- #ifdef MIEEE
- static short P0[] = {
- 0xc04d,0xfb4f,0x0e5e,0x142d,
- 0x4058,0x8011,0x9ea1,0xedd9,
- 0xc04c,0x5690,0x8806,0xdbba,
- 0x402b,0xdcce,0x3bd7,0xc1fd,
- 0xbff3,0xd39f,0x8ef6,0xca7e
- };
- static short Q0[] = {
- 0x3fff,0x4595,0xd220,0x74f9,
- 0x4012,0xb482,0x8417,0xe5b6,
- 0x4055,0x970e,0x350b,0x81d4,
- 0xc06c,0x2ece,0x56c2,0x365f,
- 0x4069,0x0853,0xa8e9,0xcbff,
- 0xc054,0x8261,0xe78d,0xb7d9,
- 0x402f,0xcfad,0xc104,0x7563,
- 0xbff2,0xeedc,0xfabf,0xcdd5
- };
- static short P1[] = {
- 0xbeab,0x0e05,0xd10d,0x94fd,
- 0xbf20,0x428c,0x1bf0,0x1bb2,
- 0x3f7a,0x9f09,0x1ef1,0x9ce2,
- 0xc031,0x8ecc,0x89b7,0x9098,
- 0x4091,0xb59f,0x334b,0x670c,
- 0xc0ce,0x5569,0x6432,0xfe84,
- 0x40ed,0x1ffc,0xaa32,0xe5e5,
- 0xc100,0x5f36,0x19b7,0xc858,
- 0x4100,0x5915,0xe387,0x9a7e,
- 0xc0f2,0xc327,0x97a0,0x0d73
- };
- static short Q1[] = {
- 0xc062,0x7344,0x6d6e,0x58ae,
- 0x40b1,0x0d73,0x6fbd,0x32cb,
- 0xc0e3,0xd516,0xa009,0x4128,
- 0x4102,0xcf1e,0xbd91,0xae5d,
- 0xc115,0x845f,0x9598,0x13fb,
- 0x4116,0xd522,0x3143,0xd39e,
- 0xc10d,0x4dab,0x1186,0x5575,
- 0x40e0,0x8ca1,0x9863,0xfcf9,
- 0x408c,0xac83,0xfc09,0x4c22
- };
- static short P2[] = {
- 0x3e78,0x001a,0x5a40,0x6ea7,
- 0x3f0e,0x1c33,0x41ab,0xea7c,
- 0x3f9d,0xa39d,0x413a,0x5785,
- 0xc02c,0x877a,0xb122,0xb9d2,
- 0x4081,0xaa35,0x15d6,0x2227,
- 0x4092,0xe549,0x4f0b,0x8bc0,
- 0xc0f1,0xd6a4,0x8a18,0x125f
- };
- static short Q2[] = {
- 0xc057,0x9141,0xfb86,0x82ff,
- 0x4094,0xc43a,0x80bd,0x0fad,
- 0x40c9,0x65ca,0x23e5,0xb739,
- 0xc101,0xc0e7,0xf9e7,0x91f2,
- 0x40f5,0x891c,0x50a0,0x9b51,
- 0x40e9,0x6b50,0x1efb,0x7da9
- };
- static short lstp[] = {
- 0xbfed,0x67f1,0xc864,0xbeb5
- };
- #define lstpi *(double *)lstp
- static short s2p[] = {
- 0x4004,0x0d93,0x1ff6,0x2706
- };
- #define s2pi *(double *)s2p
- #endif
-
-
- double ndtri(y0)
- double y0;
- {
- double d, x, y, y2, x0, x1;
- int code;
- double polevl(), p1evl(), log(), sqrt();
-
- 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) - lstpi)/x;
-
- x = -x;
- if( x > -13.5 ) /* y > 2.6602064e-40 */
- x1 = polevl( x, P1, 9 )/p1evl( x, Q1, 9 );
- else
- x1 = polevl( x, P2, 6 )/p1evl( x, Q2, 6 );
- x = x0 - x1;
- if( code != 0 )
- x = -x;
- return( x );
- }
-