double critchi (int df, double p) /* Perlman. arguments interchanged */ { double minchisq = 0.0; double maxchisq = 100.0*p; double chisqval, z, y ;; if (p <= 0.0) return (maxchisq); else if (p >= 1.0) return (0.0); if (df==1) { z = zprob(0.5*p) ; return z*z ; } if (df==2) { y = -log(p) ; return 2*y ; } chisqval = df / sqrt (p); /* fair first value */ while (maxchisq - minchisq > CHI_EPSILON) { if (rtlchsq (df, chisqval) < p) maxchisq = chisqval; else minchisq = chisqval; chisqval = (maxchisq + minchisq) * 0.5; } return (chisqval); }
double zprob(double ptail) /** inverse normal */ { double z, p, t, plog; double ylo, yhi, ya, yb ; int i, k ; if (ztable == NULL) setzptable() ; if (ptail==0.5) return 0.0 ; if (ptail>0.5) { z = zprob(1.0-ptail) ; return -z ; } if ((ptail>.40) && (ptail < .50)) return znewt(0.0, ptail) ; if (ptail<ptiny) { z = zzprob(ptail) ; return znewt(z,ptail) ; } /** replace by binary or interpolating search */ plog = -log(ptail) ; k = firstgt(plog, ptable, numbox) ; if (k==0) return ztable[0] ; if (k==numbox) return ztable[numbox-1] ; ylo = ptable[k-1] ; yhi = ptable[k] ; ya = (yhi-plog) ; yb = plog-ylo ; z = (ya*ztable[k-1]+yb*ztable[k])/(ya+yb) ; if (isnan(z)) fatalx("zprob bug %15.9f %15.9f\n", z, ptail) ; t = znewt(z, ptail) ; if (isnan(t)) fatalx("zprob bug %15.9f %15.9f\n", z, ptail) ; return t ; }
double rantruncnorm(double T, int upper) { double u ; if (upper==0) return -rantruncnorm(-T, 1) ; u = DRAND2() ; if (u==0.0) u = 0.5 ; // tiny hack u *= ntail(T) ; if (u==0.0) return MAX(T, 50.0) ; return zprob(u) ; }
/* Returns the (1-tailed) probability value associated with the provided chi-square value and df. Adapted from chisq.c in Gary Perlman's |Stat. */ double chicdf(double chisq, int df) { const double BIG = 20.0; double const pi = 3.141592653589793; double a,c,e,s,y,z; bool even = false; int k = df /2; if (chisq <=0 || df < 1) return 1.0; a = 0.5 * chisq; if (df==(k*2)) even = true; if (df > 1) y = _exp(-a); if (even) s = y; else s = 2.0 * zprob(-sqrt(chisq)); if (df > 2) { double chisq1 = 0.5 * (df - 1.0); if (even) z = 1.0; else z = 0.5; if (a > BIG) { if (even) e = 0.0; else e = log(sqrt(pi)); c = log(a); while (z <= chisq) { e = log(z) + e; s = s + _exp(c*z-a-e); z = z + 1.0; } return s; } else { if (even) e = 1.0; else e = 1.0 / sqrt(pi) / sqrt(a); c = 0.0; while (z <= chisq) { e = e * (a/float(z)); c = c + e; z = z + 1.0; } return (c*y+s); } } else return s; }