| /* This code was taken from http://www.fourmilab.ch/random/ where it states that: |
| |
| This software is in the public domain. Permission to use, copy, modify, and distribute |
| this software and its documentation for any purpose and without fee is hereby granted, |
| without any conditions or restrictions. This software is provided “as is” without |
| express or implied warranty. */ |
| |
| /* |
| |
| Compute probability of measured Chi Square value. |
| |
| This code was developed by Gary Perlman of the Wang |
| Institute (full citation below) and has been minimally |
| modified for use in this program. |
| |
| */ |
| |
| #include <math.h> |
| |
| /*HEADER |
| Module: z.c |
| Purpose: compute approximations to normal z distribution probabilities |
| Programmer: Gary Perlman |
| Organization: Wang Institute, Tyngsboro, MA 01879 |
| Copyright: none |
| Tabstops: 4 |
| */ |
| |
| #define Z_MAX 6.0 /* maximum meaningful z value */ |
| |
| /*FUNCTION poz: probability of normal z value */ |
| /*ALGORITHM |
| Adapted from a polynomial approximation in: |
| Ibbetson D, Algorithm 209 |
| Collected Algorithms of the CACM 1963 p. 616 |
| Note: |
| This routine has six digit accuracy, so it is only useful for absolute |
| z values < 6. For z values >= to 6.0, poz() returns 0.0. |
| */ |
| static double /*VAR returns cumulative probability from -oo to z */ |
| poz(const double z) /*VAR normal z value */ |
| { |
| double y, x, w; |
| |
| if (z == 0.0) { |
| x = 0.0; |
| } else { |
| y = 0.5 * fabs(z); |
| if (y >= (Z_MAX * 0.5)) { |
| x = 1.0; |
| } else if (y < 1.0) { |
| w = y * y; |
| x = ((((((((0.000124818987 * w |
| -0.001075204047) * w +0.005198775019) * w |
| -0.019198292004) * w +0.059054035642) * w |
| -0.151968751364) * w +0.319152932694) * w |
| -0.531923007300) * w +0.797884560593) * y * 2.0; |
| } else { |
| y -= 2.0; |
| x = (((((((((((((-0.000045255659 * y |
| +0.000152529290) * y -0.000019538132) * y |
| -0.000676904986) * y +0.001390604284) * y |
| -0.000794620820) * y -0.002034254874) * y |
| +0.006549791214) * y -0.010557625006) * y |
| +0.011630447319) * y -0.009279453341) * y |
| +0.005353579108) * y -0.002141268741) * y |
| +0.000535310849) * y +0.999936657524; |
| } |
| } |
| return (z > 0.0 ? ((x + 1.0) * 0.5) : ((1.0 - x) * 0.5)); |
| } |
| |
| /* |
| Module: chisq.c |
| Purpose: compute approximations to chisquare distribution probabilities |
| Contents: pochisq() |
| Uses: poz() in z.c (Algorithm 209) |
| Programmer: Gary Perlman |
| Organization: Wang Institute, Tyngsboro, MA 01879 |
| Copyright: none |
| Tabstops: 4 |
| */ |
| |
| #define LOG_SQRT_PI 0.5723649429247000870717135 /* log (sqrt (pi)) */ |
| #define I_SQRT_PI 0.5641895835477562869480795 /* 1 / sqrt (pi) */ |
| #define BIGX 20.0 /* max value to represent exp (x) */ |
| #define ex(x) (((x) < -BIGX) ? 0.0 : exp(x)) |
| |
| /*FUNCTION pochisq: probability of chi sqaure value */ |
| /*ALGORITHM Compute probability of chi square value. |
| Adapted from: |
| Hill, I. D. and Pike, M. C. Algorithm 299 |
| Collected Algorithms for the CACM 1967 p. 243 |
| Updated for rounding errors based on remark in |
| ACM TOMS June 1985, page 185 |
| */ |
| |
| double pochisq( |
| const double ax, /* obtained chi-square value */ |
| const int df /* degrees of freedom */ |
| ) |
| { |
| double x = ax; |
| double a, y, s; |
| double e, c, z; |
| int even; /* true if df is an even number */ |
| |
| if (x <= 0.0 || df < 1) { |
| return 1.0; |
| } |
| |
| a = 0.5 * x; |
| even = (2 * (df / 2)) == df; |
| y = 0.0; |
| if (df > 1) { |
| y = ex(-a); |
| } |
| s = (even ? y : (2.0 * poz(-sqrt(x)))); |
| if (df > 2) { |
| x = 0.5 * (df - 1.0); |
| z = (even ? 1.0 : 0.5); |
| if (a > BIGX) { |
| e = (even ? 0.0 : LOG_SQRT_PI); |
| c = log(a); |
| while (z <= x) { |
| e = log(z) + e; |
| s += ex(c * z - a - e); |
| z += 1.0; |
| } |
| return (s); |
| } else { |
| e = (even ? 1.0 : (I_SQRT_PI / sqrt(a))); |
| c = 0.0; |
| while (z <= x) { |
| e = e * (a / z); |
| c = c + e; |
| z += 1.0; |
| } |
| return (c * y + s); |
| } |
| } else { |
| return s; |
| } |
| } |