home *** CD-ROM | disk | FTP | other *** search
- /* XLISP-STAT 2.1 Copyright (c) 1990, by Luke Tierney */
- /* Additions to Xlisp 2.1, Copyright (c) 1989 by David Michael Betz */
- /* You may give out copies of this software; for conditions see the */
- /* file COPYING included with this distribution. */
-
- #include "xlisp.h"
- #include "osdef.h"
- #ifdef ANSI
- #include "xlsproto.h"
- #else
- #include "xlsfun.h"
- #endif ANSI
-
- #define twopi 6.283195307179587
- #define con (twopi / 2.0) * 10.0e-10
-
- double bivnor(ah, ak, r)
- double ah, ak, r;
- {
- /*
- based on alg 4628 comm. acm oct 73
- gives the probability that a bivariate normal exceeds (ah,ak).
- gh and gk are .5 times the right tail areas of ah, ak under a n(0,1)
-
- Tranlated from FORTRAN to ratfor using struct; from ratfor to C by hand.
- */
- double a2, ap, b, cn, conex, ex, g2, gh, gk, gw, h2, h4, rr, s1, s2,
- sgn, sn, sp, sqr, t, temp, w2, wh, wk;
- int is;
-
- temp = -ah;
- normbase(&temp, &gh);
- gh = gh / 2.0;
- temp = -ak;
- normbase(&temp, &gk);
- gk = gk / 2.0;
-
- b = 0;
-
- if (r==0)
- b = 4*gh*gk;
- else {
- rr = 1-r*r;
- if (rr<0)
- return(-1.0);
- if (rr!=0) {
- sqr = sqrt(rr);
- if (ah!=0) {
- b = gh;
- if (ah*ak<0)
- b = b-.5;
- else if (ah*ak==0)
- goto label10;
- }
- else if (ak==0) {
- b = atan(r/sqr)/twopi+.25;
- goto label50;
- }
- b = b+gk;
- if (ah==0)
- goto label20;
- label10:
- wh = -ah;
- wk = (ak/ah-r)/sqr;
- gw = 2*gh;
- is = -1;
- goto label30;
- label20:
- do {
- wh = -ak;
- wk = (ah/ak-r)/sqr;
- gw = 2*gk;
- is = 1;
- label30:
- sgn = -1;
- /* t = 0; not used JKL */
- if (wk!=0) {
- if (fabs(wk)>=1)
- if (fabs(wk)==1) {
- t = wk*gw*(1-gw)/2;
- goto label40;
- }
- else {
- sgn = -sgn;
- wh = wh*wk;
- normbase(&wh, &g2);
- wk = 1/wk;
- if (wk<0)
- b = b+.5;
- b = b-(gw+g2)/2+gw*g2;
- }
- h2 = wh*wh;
- a2 = wk*wk;
- h4 = h2*.5;
- ex = 0;
- if (h4<150.0)
- ex = exp(-h4);
- w2 = h4*ex;
- ap = 1;
- s2 = ap-ex;
- sp = ap;
- s1 = 0;
- sn = s1;
- conex = fabs(con/wk);
- do {
- cn = ap*s2/(sn+sp);
- s1 = s1+cn;
- if (fabs(cn)<=conex)
- break;
- sn = sp;
- sp = sp+1;
- s2 = s2-w2;
- w2 = w2*h4/sp;
- ap = -ap*a2;
- } while (1);
- t = (atan(wk)-wk*s1)/twopi;
- label40:
- b = b+sgn*t;
- }
- if (is>=0)
- break;
- } while(ak!=0);
- }
- else if (r>=0)
- if (ah>=ak)
- b = 2*gh;
- else
- b = 2*gk;
- else if (ah+ak<0)
- b = 2*(gh+gk)-1;
- }
- label50:
- if (b<0)
- b = 0;
- if (b>1)
- b = 1;
-
- return(b);
- }
-