blob: 3fe4f66ae074116debf421e8362a3bde35700d7a [file] [log] [blame]
NingSun0c89b3c2018-02-08 08:34:03 -08001/* This code was taken from http://www.fourmilab.ch/random/ where it states that:
2
3 This software is in the public domain. Permission to use, copy, modify, and distribute
4 this software and its documentation for any purpose and without fee is hereby granted,
5 without any conditions or restrictions. This software is provided “as is” without
6 express or implied warranty. */
7
8/*
9
10 Compute probability of measured Chi Square value.
11
12 This code was developed by Gary Perlman of the Wang
13 Institute (full citation below) and has been minimally
14 modified for use in this program.
15
16*/
17
18#include <math.h>
19
20/*HEADER
21 Module: z.c
22 Purpose: compute approximations to normal z distribution probabilities
23 Programmer: Gary Perlman
24 Organization: Wang Institute, Tyngsboro, MA 01879
25 Copyright: none
26 Tabstops: 4
27*/
28
29#define Z_MAX 6.0 /* maximum meaningful z value */
30
31/*FUNCTION poz: probability of normal z value */
32/*ALGORITHM
33 Adapted from a polynomial approximation in:
34 Ibbetson D, Algorithm 209
35 Collected Algorithms of the CACM 1963 p. 616
36 Note:
37 This routine has six digit accuracy, so it is only useful for absolute
38 z values < 6. For z values >= to 6.0, poz() returns 0.0.
39*/
40static double /*VAR returns cumulative probability from -oo to z */
41poz(const double z) /*VAR normal z value */
42{
43 double y, x, w;
44
45 if (z == 0.0) {
46 x = 0.0;
47 } else {
48 y = 0.5 * fabs(z);
49 if (y >= (Z_MAX * 0.5)) {
50 x = 1.0;
51 } else if (y < 1.0) {
52 w = y * y;
53 x = ((((((((0.000124818987 * w
54 -0.001075204047) * w +0.005198775019) * w
55 -0.019198292004) * w +0.059054035642) * w
56 -0.151968751364) * w +0.319152932694) * w
57 -0.531923007300) * w +0.797884560593) * y * 2.0;
58 } else {
59 y -= 2.0;
60 x = (((((((((((((-0.000045255659 * y
61 +0.000152529290) * y -0.000019538132) * y
62 -0.000676904986) * y +0.001390604284) * y
63 -0.000794620820) * y -0.002034254874) * y
64 +0.006549791214) * y -0.010557625006) * y
65 +0.011630447319) * y -0.009279453341) * y
66 +0.005353579108) * y -0.002141268741) * y
67 +0.000535310849) * y +0.999936657524;
68 }
69 }
70 return (z > 0.0 ? ((x + 1.0) * 0.5) : ((1.0 - x) * 0.5));
71}
72
73/*
74 Module: chisq.c
75 Purpose: compute approximations to chisquare distribution probabilities
76 Contents: pochisq()
77 Uses: poz() in z.c (Algorithm 209)
78 Programmer: Gary Perlman
79 Organization: Wang Institute, Tyngsboro, MA 01879
80 Copyright: none
81 Tabstops: 4
82*/
83
84#define LOG_SQRT_PI 0.5723649429247000870717135 /* log (sqrt (pi)) */
85#define I_SQRT_PI 0.5641895835477562869480795 /* 1 / sqrt (pi) */
86#define BIGX 20.0 /* max value to represent exp (x) */
87#define ex(x) (((x) < -BIGX) ? 0.0 : exp(x))
88
89/*FUNCTION pochisq: probability of chi sqaure value */
90/*ALGORITHM Compute probability of chi square value.
91 Adapted from:
92 Hill, I. D. and Pike, M. C. Algorithm 299
93 Collected Algorithms for the CACM 1967 p. 243
94 Updated for rounding errors based on remark in
95 ACM TOMS June 1985, page 185
96*/
97
98double pochisq(
99 const double ax, /* obtained chi-square value */
100 const int df /* degrees of freedom */
101 )
102{
103 double x = ax;
104 double a, y, s;
105 double e, c, z;
106 int even; /* true if df is an even number */
107
108 if (x <= 0.0 || df < 1) {
109 return 1.0;
110 }
111
112 a = 0.5 * x;
113 even = (2 * (df / 2)) == df;
114 y = 0.0;
115 if (df > 1) {
116 y = ex(-a);
117 }
118 s = (even ? y : (2.0 * poz(-sqrt(x))));
119 if (df > 2) {
120 x = 0.5 * (df - 1.0);
121 z = (even ? 1.0 : 0.5);
122 if (a > BIGX) {
123 e = (even ? 0.0 : LOG_SQRT_PI);
124 c = log(a);
125 while (z <= x) {
126 e = log(z) + e;
127 s += ex(c * z - a - e);
128 z += 1.0;
129 }
130 return (s);
131 } else {
132 e = (even ? 1.0 : (I_SQRT_PI / sqrt(a)));
133 c = 0.0;
134 while (z <= x) {
135 e = e * (a / z);
136 c = c + e;
137 z += 1.0;
138 }
139 return (c * y + s);
140 }
141 } else {
142 return s;
143 }
144}