home *** CD-ROM | disk | FTP | other *** search
-
- /*
- YAMP - Yet Another Matrix Program
- Version: 1.6
- Author: Mark Von Tress, Ph.D.
- Date: 01/11/93
-
- Copyright(c) Mark Von Tress 1993
- Portions of this code are (c) 1991 by Allen I. Holub and are used by
- permission
-
- DISCLAIMER: THIS PROGRAM IS PROVIDED AS IS, WITHOUT ANY
- WARRANTY, EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
- TO FITNESS FOR A PARTICULAR PURPOSE. THE AUTHOR DISCLAIMS
- ALL LIABILITY FOR DIRECT OR CONSEQUENTIAL DAMAGES RESULTING
- FROM USE OF THIS PROGRAM.
-
- */
-
-
- #include "math.h"
- #include "stdio.h"
- #include "stdlib.h"
- #include "dist.h"
-
- void nrerror(char error_text[])
- {
-
- printf("Numerical Recipes run-time error...\n");
- printf("%s\n", error_text);
- printf("...now exiting to system...\n");
- exit(1);
- }
- double safelog( double x )
- {
- if(!x) return -HUGE_VAL;
- return log(x);
- }
-
- double gammln(double xx)
- {
- double x, tmp, ser;
- static double cof[6] = { 76.18009173, - 86.50532033, 24.01409822,
- - 1.231739516, 0.120858003e-2, - 0.536382e-5 };
- int j;
-
- x = xx - 1.0;
- tmp = x + 5.5;
- tmp -= (x + 0.5) *safelog(tmp);
- ser = 1.0;
- for (j = 0; j <= 5; j++) {
- x += 1.0;
- ser += cof[j] / x;
- }
- return - tmp + safelog(2.50662827465*ser);
- }
-
- #define ITMAX 100
- #define EPS 3.0e-9
-
- double betacf(double a, double b, double x)
- {
- double qap, qam, qab, em, tem, d;
- double bz, bm = 1.0, bp, bpp;
- double az = 1.0, am = 1.0, ap, app, aold;
- int m;
-
- qab = a + b;
- qap = a + 1.0;
- qam = a - 1.0;
- bz = 1.0- qab*x / qap;
- for (m = 1; m <= ITMAX; m++) {
- em = (double) m;
- tem = em + em;
- d = em*(b - em) *x / ((qam + tem) *(a + tem));
- ap = az + d*am;
- bp = bz + d*bm;
- d = -(a + em) *(qab + em) *x / ((qap + tem) *(a + tem));
- app = ap + d*az;
- bpp = bp + d*bz;
- aold = az;
- am = ap / bpp;
- bm = bp / bpp;
- az = app / bpp;
- bz = 1.0;
- if (fabs(az - aold) < (EPS*fabs(az))) return az;
- }
- nrerror("BETACF: a or b too big, or ITMAX too small");
- }
-
- #undef ITMAX
- #undef EPS
-
- double betai(double a, double b, double x)
- {
- double bt;
-
- if (x < 0.0 || x > 1.0) nrerror("BETAI: Bad x");
- if (x == 0.0 || x == 1.0) return exp(x);
- else
- bt = (gammln(a + b) - gammln(a) - gammln(b)
- + a*safelog(x) + b*safelog(1.0-x) );
-
- if (x < (a + 1.0) / (a + b + 2.0))
- return (exp(bt + safelog(betacf(a, b, x)) - safelog(a)));
- else
- return (1.0-exp(bt + safelog(betacf(b, a, 1.0-x)) - safelog(b)));
- }
-
-
- double dmin(double x, double y)
- {
- return ((x < y) ? x : y);
- }
-
- double dmax(double x, double y)
- {
- return ((x > y) ? x : y);
- }
-
- double addlogc(double a, double b)
- /* function to add two numbers a1 and b1 */
- /* where a=log(a1) and b=log(b1) */
- {
- double del, sum;
- del = dmax(a, b);
- sum = safelog(exp(a - del) + exp(b - del)) + del;
- return (sum);
- }
-
- #define DMINEXP - 307
- #define DMAXEXP 308
- double ncbeta(double x, double a, double b, double lam)
- {
- /* noncentral beta distribution function
- Vic Norton, Appl. Statist (1983), 32, #1, pp 84-85
- this algorithm has been modified to work in logrithms
- */
- double s, r, p, n = 0, minn, elam;
- double eps = 0.0000001, nmax = 500, leps;
-
- if ((a <= 0) || (b <= 0) || (x < 0) || (lam < 0))
- nrerror("NCBETA: non-positive parameter");
-
- s = safelog(betai(a, b, x));
- if (lam <= exp(DMINEXP)) return exp(s); /* lam is too close to zero */
-
- r = safelog(lam);
- if (lam > DMAXEXP) elam = exp(- DMAXEXP); else elam = exp(- lam);
- leps = safelog(eps);
- do {
- n += 1;
- p = safelog(betai((a + n), b, x));
- s = addlogc(s, (r + p));
- r += safelog(lam / (n + 1.0));
- minn = (1 < (elam + lam / (n + 2))) ? 0 : safelog(lam / (n + 2)) - lam;
- } while (((r + p + minn) > leps) && (n < nmax));
- return (exp(- lam + s));
- } /* ncbeta */
- #undef DMINEXP
- #undef DMAXEXP
-
- double ncf(double f, double n1, double n2, double lam)
- {
- double x, a, b, nc, lam2;
-
- if ((n1 <= 0) || (n2 <= 0) || (f < 0) || (lam < 0.0))
- nrerror("NCF: non-positive parameter");
- if (f == 0.0) return 0.0;
- a = 0.5*n1;
- b = 0.5*n2;
- x = a*f / (a*f + b);
- lam2 = 0.5*lam;
- nc = ncbeta(x, a, b, lam2);
- return (nc);
- } /* non central f distribution using continuous degrees of freedom */
-
-
- double probf(double f, double n1, double n2)
- {
- double a, b, x, lam2, nc;
- if ((n1 <= 0.0) || (n2 <= 0.0) || (f < 0.0))
- nrerror("PROBF: non-positive parameter");
- if (f == 0.0) return (0.0);
- a = 0.5*n1;
- b = 0.5*n2;
- x = a*f / (a*f + b);
-
- nc = ncbeta(x, a, b, 0.0);
- return (nc);
- } /* central f distribution using continuous degrees of freedom */
-
-
- /****************************** begin inverse ncentral f */
- /* uses zbrak, and rtbis */
-
-
- /*********************** normal distribution functions */
-
- double probnormi(double u) /* abramowitz and stegun 26.2.23 */
- /* u in [0,1] -> returns normal quantiles */
- {
- double c0 = 2.515517, c1 = 0.802853, c2 = 0.010328;
- double d1 = 1.432788, d2 = 0.189269, d3 = 0.001308;
- double t, xp, num, den, ut;
- double crit = 5;
- if (u < 0.000001) return (- crit);
- if (u > 0.999999) return (crit);
- ut = ((u > 0.5) ? (1.0-u) : (u));
- t = sqrt(- safelog(ut*ut));
- num = (c2*t + c1) *t + c0;
- den = ((d3*t + d2) *t + d1) *t + 1.0;
- xp = t - num / den;
- return (((u <= 0.5) ? (- xp) : xp));
- }
-
- double erfc(double x)
- {
- float t, z, ans;
-
- z = fabs(x);
- t = 1.0 / (1.0+0.5*z);
- ans = t*exp(- z*z - 1.26551223+ t*(1.00002368+ t*(0.37409196
- + t*( 0.09678418 +
- + t*(- 0.18628806 + t*(0.27886807+ t*(- 1.13520398
- + t*( 1.48851587
- + t*(- 0.82215223 + t*0.17087277)))))))));
- ans = (x >= 0.0) ? ans : 2.0-ans;
- return (1.0 - ans);
- }
- double probnorm(double x)
- {
- return ((1.0+erfc((x) / 1414213562373095E-15)) * 0.5);
- }
-
- /**************************** normal distribution functions */
- double cinv0(double p, double v)
- /* approximate inverse chisquare */
- {
- double xp, chip;
-
- xp = probnormi(p);
- chip = 1.0 - 2.0 / (9.0*v) + xp*sqrt(2.0 / (9.0*v));
- chip = v*chip*chip*chip;
- if (chip < 0) chip = 2.0*p*exp(2.0*gammln((0.5*v + 1.0)) / v);
- return chip;
- }
-
-
- #define JMAX 75
-
- double rtbis(double x1, double x2, double xacc, double v1,
- double v2, double lam, double p,
- double (*func) (double x1, double v1, double v2, double lam))
- {
- int j;
- double dx, f, fmid, xmid, rtb;
-
- f = (*func) (x1, v1, v2, lam) - p;
- fmid = (*func) (x2, v1, v2, lam) - p;
- if (f*fmid >= 0.0)
- nrerror("RTBIS: Root must be bracketed for bisection");
- rtb = f < 0.0 ? (dx = x2 - x1, x1) : (dx = x1 - x2, x2);
- for (j = 1; j <= JMAX; j++) {
- fmid = (*func) ((xmid = rtb + (dx *= 0.5)), v1, v2, lam) - p;
- if (fmid <= 0.0) rtb = xmid;
- if (fabs(dx) < xacc || fmid == 0.0) return rtb;
- }
- nrerror("RTBIS: Too many bisections");
- }
-
- #undef JMAX
-
-
- #define FACTOR 1.6
- #define NTRY 75
-
- int zbrac(double *x1, double *x2, double p, double v1,
- double v2, double lam,
- double (*func) (double x1, double v1, double v2, double lam))
- {
- int j;
- double f1, f2;
-
- if (*x1 == *x2) nrerror("ZBRAC: Bad initial range");
- f1 = (*func) (*x1, v1, v2, lam) - p;
- f2 = (*func) (*x2, v1, v2, lam) - p;
- for (j = 1; j <= NTRY; j++) {
- if (f1*f2 < 0.0) return 1;
- if (fabs(f1) < fabs(f2))
- f1 = (*func) ((*x1 += FACTOR*(*x1 - *x2)), v1, v2, lam) - p;
- else
- f2 = (*func) ((*x2 += FACTOR*(*x2 - *x1)), v1, v2, lam) - p;
- }
- return 0;
- }
-
- #undef FACTOR
- #undef NTRY
-
- double ncfinv(double p, double v1, double v2, double lam)
- {
- double brak1, brak2, ncfi;
- double xacc = 0.00001;
-
- if ((p < 0.0) || (p >= 1.0) || (v1 <= 0.0) || (v2 <= 0.0) || (lam < 0.0)){
- printf("p, df1, df2, lam: %f %f %f %f\n", p, v1, v2, lam);
- nrerror("NCFINV: invalid parameter");
- }
-
- if (p == 0.0) return 0.0;
-
- brak1 = 0.000001;
- brak2 = 2.0*cinv0(p, v1) / v1;
-
- if (!zbrac(&brak1, &brak2, p, v1, v2, lam, ncf))
- nrerror("NCFINV: braketts not found");
-
- ncfi = rtbis(brak1, brak2, xacc, v1, v2, lam, p, ncf);
-
- return (ncfi);
- }
- double probfi(double p, double n1, double n2)
- {
- if ((p < 0.0) || (p >= 1.0) || (n1 <= 0.0) || (n2 <= 0.0)) {
- printf("p, df1, df2, lam: %f %f %f\n", p, n1, n2);
- nrerror("PROBFI: invalid parameter");
- }
- return (ncfinv(p, n1, n2, 0.0));
- }
-
- /****************************************** end ncfinv */
-
- /************************************ non-central t distribution */
-
-
- double nct(double t, double df, double nc)
- {
- double u = -0.2257913526, prob, f, g, q, r, s, a;
- double tcnt = 0.0, p = 1.0, v = 0.0, w = 0.0, h, y, one = 1.0E7;
- if ((df <= 0)) nrerror("NCT: non-positive parameter in nct");
- if ( nc == 0 ) return probt(t, df);
-
- prob = (1.0+erfc((- nc) / 1414213562373095E-15)) * 0.5;
- y = t*t;
- f = (t < 0.0) ? - 1.0 : 1.0;
- g = (nc < 0.0) ? - 1.0 : 1.0;
- q = fabs(nc);
- r = safelog(0.5) - q*q*0.5;
- q = safelog(q);
- s = f;
- for (;;) {
- tcnt++;
- a = probf((y / tcnt), tcnt, df);
- if (a <= 0.0) break;
- h = exp(r + w + safelog(a));
- prob += s*h;
- if (prob >= (one * h)) break;
- r += q;
- p = -p;
- if (p < 0.0) {
- u -= safelog(tcnt);
- w = u;
- s = g;
- } else {
- v -= safelog(tcnt);
- w = v;
- s = f;
- }
- } /* end for */
- return prob;
- } /* non central t distribution using continuous degrees of freedom */
-
-
- double probt(double t, double n1)
- {
- double x;
- if ((n1 <= 0)) nrerror("PROBT: non-positive parameter");
- x = (t < 0) ? 0.5*(1.0- probf(t*t, 1.0, n1))
- : 0.5*(1.0+ probf(t*t, 1.0, n1));
- return (x);
- }
- double probti(double p, double df)
- {
- double one = 1.0, tx, q4;
- if (df <= 0.0) nrerror("PROBTI: negative degrees of freedom");
- if ((p < 0) || p > 1.0) nrerror("PROBTI: invalid probability p");
- tx = 2.0*p - 1.0;
- if (tx == 0.0) return tx;
- q4 = probfi(fabs(tx), one, df);
- tx = (tx < 0.0) ? - sqrt(q4) : sqrt(q4);
- return tx;
- }
-
- double ncti(double p, double df, double nc)
- /* inverse non central t */
- {
- double tncx, q1, s, d1, r;
- int cnt = 0;
- if (df <= 0) nrerror("NCTI: negative degrees of freedom");
- if ((p < 0) || p > 1.0) nrerror("NCTI: invalid probability p");
-
- tncx = probti(p, df) + nc;
- q1 = nc / df;
- if (df == 0.0) return tncx;
- if (nc < 0.0) q1 = -q1;
- L1 :
- r = nct(tncx, df, nc) - p;
- L2 :
- cnt++;
- tncx -=(r < 0.0) ? - q1 : q1;
- s = nct(tncx, df, nc) - p;
- if ((r*s == 0.0) || (cnt > 100)) return tncx;
- if (r*s < 0.0) goto L3;
- r = s;
- goto L2;
- L3 :
- d1 = q1 / ((double) fabs((1.0 - (r / s))));
- tncx += (r < 0.0) ? - d1 : d1;
- q1 /= 64.0;
- if ((d1 <= 1.0E-6) || (cnt > 100)) return tncx;
- goto L1;
- }
- /*********************************** end non-central t */
- /*********************************** gamma, chi-square and nc */
-
- #define ITMAX 100
- #define EPS 3.0e-7
-
- void gcf(double *gammcf, double a, double x, double *gln)
- {
- int n;
- double gold = 0.0, g, fac = 1.0, b1 = 1.0;
- double b0 = 0.0, anf, ana, an, a1, a0 = 1.0;
-
- *gln = gammln(a);
- a1 = x;
- for (n = 1; n <= ITMAX; n++) {
- an = (double) n;
- ana = an - a;
- a0 = (a1 + a0*ana) *fac;
- b0 = (b1 + b0*ana) *fac;
- anf = an*fac;
- a1 = x*a0 + anf*a1;
- b1 = x*b0 + anf*b1;
- if (a1) {
- fac = 1.0 / a1;
- g = b1*fac;
- if (fabs((g - gold) / g) < EPS) {
- *gammcf = exp(- x + a*safelog(x) - (*gln)) *g;
- return;
- }
- gold = g;
- }
- }
- nrerror("GCF: a too large, ITMAX too small");
- }
-
- #undef ITMAX
- #undef EPS
-
-
- #define ITMAX 100
- #define EPS 3.0e-7
-
- void gser(double *gamser, double a, double x, double *gln)
- {
- int n;
- double sum, del, ap;
-
- *gln = gammln(a);
- if (x <= 0.0) {
- if (x < 0.0) nrerror("GSER: x less than 0");
- *gamser = 0.0;
- return;
- } else {
- ap = a;
- del = sum = 1.0 / a;
- for (n = 1; n <= ITMAX; n++) {
- ap += 1.0;
- del *= x / ap;
- sum += del;
- if (fabs(del) < fabs(sum) *EPS) {
- *gamser = sum*exp(- x + a*safelog(x) - (*gln));
- return;
- }
- }
- nrerror("GSER: a too large, ITMAX too small");
- return;
- }
- }
-
- #undef ITMAX
- #undef EPS
-
- double gammp(double x, double a, double b)
- /* change from numerical recipes */
- {
- double gamser, gammcf, gln;
-
- x /= b;
- if (x < 0.0 || a <= 0.0 || b <= 0.0)
- nrerror("GAMMP: Invalid arguments");
- if (x < (a + 1.0)) {
- gser(&gamser, a, x, &gln);
- return gamser;
- } else {
- gcf(&gammcf, a, x, &gln);
- return 1.0- gammcf;
- }
- }
- double ncgamma(double x, double a, double b, double lam)
- /* algorithm AS 170 */
- {
- double eps = 1.0e-8, sum = 0, term = 0.0, c = 1.0, t = 0.0;
-
- if (x < 0.0 || a <= 0.0 || b <= 0.0 || lam < 0.0)
- nrerror("NCGAMMA: Invalid arguments");
- lam /= b;
- sum = gammp(x, a, b);
- do {
- t++;
- c *= lam / t;
- a++;
- term = c * gammp(x, a, b);
- sum += term;
- } while (term >= eps);
- return (exp(safelog(sum) - lam));
- }
- double probchi(double x, double df)
- {
- if (x < 0.0 || df <= 0.0)
- nrerror("PROBCHI: Invalid arguments");
- return (gammp(x, (0.5*df), 2.0));
- }
- double ncchi(double x, double df, double lam)
- {
- if (x < 0.0 || df <= 0.0 || lam <= 0.0)
- nrerror("NCCHI: Invalid arguments");
- return (ncgamma(x, (0.5*df), 2.0, lam));
- }
-
- double ncgammai(double p, double a, double b, double lam)
- {
- double brak1, brak2, ncgamm;
- double xacc = 0.000001;
-
- if ((p < 0.0) || (p >= 1.0) || (a <= 0.0) || (b <= 0.0) || (lam < 0.0)){
- printf("p, a, b, lam: %f %f %f %f\n", p, a, b, lam);
- nrerror("NCGAMMAI: invalid parameter");
- }
-
- if (p == 0.0) return 0.0;
-
- brak1 = 0.000001;
- brak2 = 2.0*cinv0(p, a) / a;
-
- if (!zbrac(&brak1, &brak2, p, a, b, lam, ncgamma))
- nrerror("ZBRAK: braketts not found");
-
- ncgamm = rtbis(brak1, brak2, xacc, a, b, lam, p, ncgamma);
-
- return (ncgamm);
- }
- double ncchii(double p, double a, double lam)
- {
-
- if ((p < 0.0) || (p >= 1.0) || (a <= 0.0) || (lam < 0.0)) {
- printf("p, a, lam: %f %f %f\n", p, a, lam);
- nrerror("NCCHII: invalid parameter");
- }
- return (ncgammai(p, (0.5*a), 2.0, lam));
- }
- double probchii(double p, double df)
- {
- if ((p < 0.0) || (p >= 1.0) || (df <= 0.0)) {
- printf("p, df: %f %f\n", p, df);
- nrerror("PROBCHII: invalid parameter");
- }
- return (ncgammai(p, (0.5*df), 2.0, 0.0));
- }
-