/************************************************************************* Chi-square distribution Returns the area under the left hand tail (from 0 to x) of the Chi square probability density function with v degrees of freedom. x - 1 | | v/2-1 -t/2 P( x | v ) = ----------- | t e dt v/2 - | | 2 | (v/2) - 0 where x is the Chi-square variable. The incomplete gamma integral is used, according to the formula y = chdtr( v, x ) = igam( v/2.0, x/2.0 ). The arguments must both be positive. ACCURACY: See incomplete gamma function Cephes Math Library Release 2.8: June, 2000 Copyright 1984, 1987, 2000 by Stephen L. Moshier *************************************************************************/ double chisquaredistribution(double v, double x) { double result; ap::ap_error::make_assertion(ap::fp_greater_eq(x,0)&&ap::fp_greater_eq(v,1), "Domain error in ChiSquareDistribution"); result = incompletegamma(v/2.0, x/2.0); return result; }
/************************************************************************* Complemented incomplete gamma integral 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: Tested at random a, x. a x Relative error: arithmetic domain domain # trials peak rms IEEE 0.5,100 0,100 200000 1.9e-14 1.7e-15 IEEE 0.01,0.5 0,100 200000 1.4e-13 1.6e-15 Cephes Math Library Release 2.8: June, 2000 Copyright 1985, 1987, 2000 by Stephen L. Moshier *************************************************************************/ double incompletegammac(double a, double x) { double result; double igammaepsilon; double igammabignumber; double igammabignumberinv; double ans; double ax; double c; double yc; double r; double t; double y; double z; double pk; double pkm1; double pkm2; double qk; double qkm1; double qkm2; double tmp; igammaepsilon = 0.000000000000001; igammabignumber = 4503599627370496.0; igammabignumberinv = 2.22044604925031308085*0.0000000000000001; if( ap::fp_less_eq(x,0)||ap::fp_less_eq(a,0) ) { result = 1; return result; } if( ap::fp_less(x,1)||ap::fp_less(x,a) ) { result = 1-incompletegamma(a, x); return result; } ax = a*log(x)-x-lngamma(a, tmp); if( ap::fp_less(ax,-709.78271289338399) ) { result = 0; return result; } ax = exp(ax); y = 1-a; z = x+y+1; c = 0; pkm2 = 1; qkm2 = x; pkm1 = x+1; qkm1 = z*x; ans = pkm1/qkm1; do { c = c+1; y = y+1; z = z+2; yc = y*c; pk = pkm1*z-pkm2*yc; qk = qkm1*z-qkm2*yc; if( ap::fp_neq(qk,0) ) { r = pk/qk; t = fabs((ans-r)/r); ans = r; } else { t = 1; } pkm2 = pkm1; pkm1 = pk; qkm2 = qkm1; qkm1 = qk; if( ap::fp_greater(fabs(pk),igammabignumber) ) { pkm2 = pkm2*igammabignumberinv; pkm1 = pkm1*igammabignumberinv; qkm2 = qkm2*igammabignumberinv; qkm1 = qkm1*igammabignumberinv; } } while(ap::fp_greater(t,igammaepsilon)); result = ans*ax; return result; }