123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406 |
- /* incbetl.c
- *
- * Incomplete beta integral
- *
- *
- * SYNOPSIS:
- *
- * long double a, b, x, y, incbetl();
- *
- * y = incbetl( a, b, x );
- *
- *
- * DESCRIPTION:
- *
- * Returns incomplete beta integral of the arguments, evaluated
- * from zero to x. The function is defined as
- *
- * x
- * - -
- * | (a+b) | | a-1 b-1
- * ----------- | t (1-t) dt.
- * - - | |
- * | (a) | (b) -
- * 0
- *
- * The domain of definition is 0 <= x <= 1. In this
- * implementation a and b are restricted to positive values.
- * The integral from x to 1 may be obtained by the symmetry
- * relation
- *
- * 1 - incbet( a, b, x ) = incbet( b, a, 1-x ).
- *
- * The integral is evaluated by a continued fraction expansion
- * or, when b*x is small, by a power series.
- *
- * ACCURACY:
- *
- * Tested at random points (a,b,x) with x between 0 and 1.
- * arithmetic domain # trials peak rms
- * IEEE 0,5 20000 4.5e-18 2.4e-19
- * IEEE 0,100 100000 3.9e-17 1.0e-17
- * Half-integer a, b:
- * IEEE .5,10000 100000 3.9e-14 4.4e-15
- * Outputs smaller than the IEEE gradual underflow threshold
- * were excluded from these statistics.
- *
- * ERROR MESSAGES:
- *
- * message condition value returned
- * incbetl domain x<0, x>1 0.0
- */
- /*
- Cephes Math Library, Release 2.3: January, 1995
- Copyright 1984, 1995 by Stephen L. Moshier
- */
- #include <math.h>
- #define MAXGAML 1755.455L
- static long double big = 9.223372036854775808e18L;
- static long double biginv = 1.084202172485504434007e-19L;
- extern long double MACHEPL, MINLOGL, MAXLOGL;
- #ifdef ANSIPROT
- extern long double gammal ( long double );
- extern long double lgaml ( long double );
- extern long double expl ( long double );
- extern long double logl ( long double );
- extern long double fabsl ( long double );
- extern long double powl ( long double, long double );
- static long double incbcfl( long double, long double, long double );
- static long double incbdl( long double, long double, long double );
- static long double pseriesl( long double, long double, long double );
- #else
- long double gammal(), lgaml(), expl(), logl(), fabsl(), powl();
- static long double incbcfl(), incbdl(), pseriesl();
- #endif
- long double incbetl( aa, bb, xx )
- long double aa, bb, xx;
- {
- long double a, b, t, x, w, xc, y;
- int flag;
- if( aa <= 0.0L || bb <= 0.0L )
- goto domerr;
- if( (xx <= 0.0L) || ( xx >= 1.0L) )
- {
- if( xx == 0.0L )
- return( 0.0L );
- if( xx == 1.0L )
- return( 1.0L );
- domerr:
- mtherr( "incbetl", DOMAIN );
- return( 0.0L );
- }
- flag = 0;
- if( (bb * xx) <= 1.0L && xx <= 0.95L)
- {
- t = pseriesl(aa, bb, xx);
- goto done;
- }
- w = 1.0L - xx;
- /* Reverse a and b if x is greater than the mean. */
- if( xx > (aa/(aa+bb)) )
- {
- flag = 1;
- a = bb;
- b = aa;
- xc = xx;
- x = w;
- }
- else
- {
- a = aa;
- b = bb;
- xc = w;
- x = xx;
- }
- if( flag == 1 && (b * x) <= 1.0L && x <= 0.95L)
- {
- t = pseriesl(a, b, x);
- goto done;
- }
- /* Choose expansion for optimal convergence */
- y = x * (a+b-2.0L) - (a-1.0L);
- if( y < 0.0L )
- w = incbcfl( a, b, x );
- else
- w = incbdl( a, b, x ) / xc;
- /* Multiply w by the factor
- a b _ _ _
- x (1-x) | (a+b) / ( a | (a) | (b) ) . */
- y = a * logl(x);
- t = b * logl(xc);
- if( (a+b) < MAXGAML && fabsl(y) < MAXLOGL && fabsl(t) < MAXLOGL )
- {
- t = powl(xc,b);
- t *= powl(x,a);
- t /= a;
- t *= w;
- t *= gammal(a+b) / (gammal(a) * gammal(b));
- goto done;
- }
- else
- {
- /* Resort to logarithms. */
- y += t + lgaml(a+b) - lgaml(a) - lgaml(b);
- y += logl(w/a);
- if( y < MINLOGL )
- t = 0.0L;
- else
- t = expl(y);
- }
- done:
- if( flag == 1 )
- {
- if( t <= MACHEPL )
- t = 1.0L - MACHEPL;
- else
- t = 1.0L - t;
- }
- return( t );
- }
- /* Continued fraction expansion #1
- * for incomplete beta integral
- */
- static long double incbcfl( a, b, x )
- long double a, b, x;
- {
- long double xk, pk, pkm1, pkm2, qk, qkm1, qkm2;
- long double k1, k2, k3, k4, k5, k6, k7, k8;
- long double r, t, ans, thresh;
- int n;
- k1 = a;
- k2 = a + b;
- k3 = a;
- k4 = a + 1.0L;
- k5 = 1.0L;
- k6 = b - 1.0L;
- k7 = k4;
- k8 = a + 2.0L;
- pkm2 = 0.0L;
- qkm2 = 1.0L;
- pkm1 = 1.0L;
- qkm1 = 1.0L;
- ans = 1.0L;
- r = 1.0L;
- n = 0;
- thresh = 3.0L * MACHEPL;
- do
- {
-
- xk = -( x * k1 * k2 )/( k3 * k4 );
- pk = pkm1 + pkm2 * xk;
- qk = qkm1 + qkm2 * xk;
- pkm2 = pkm1;
- pkm1 = pk;
- qkm2 = qkm1;
- qkm1 = qk;
- xk = ( x * k5 * k6 )/( k7 * k8 );
- pk = pkm1 + pkm2 * xk;
- qk = qkm1 + qkm2 * xk;
- pkm2 = pkm1;
- pkm1 = pk;
- qkm2 = qkm1;
- qkm1 = qk;
- if( qk != 0.0L )
- r = pk/qk;
- if( r != 0.0L )
- {
- t = fabsl( (ans - r)/r );
- ans = r;
- }
- else
- t = 1.0L;
- if( t < thresh )
- goto cdone;
- k1 += 1.0L;
- k2 += 1.0L;
- k3 += 2.0L;
- k4 += 2.0L;
- k5 += 1.0L;
- k6 -= 1.0L;
- k7 += 2.0L;
- k8 += 2.0L;
- if( (fabsl(qk) + fabsl(pk)) > big )
- {
- pkm2 *= biginv;
- pkm1 *= biginv;
- qkm2 *= biginv;
- qkm1 *= biginv;
- }
- if( (fabsl(qk) < biginv) || (fabsl(pk) < biginv) )
- {
- pkm2 *= big;
- pkm1 *= big;
- qkm2 *= big;
- qkm1 *= big;
- }
- }
- while( ++n < 400 );
- mtherr( "incbetl", PLOSS );
- cdone:
- return(ans);
- }
- /* Continued fraction expansion #2
- * for incomplete beta integral
- */
- static long double incbdl( a, b, x )
- long double a, b, x;
- {
- long double xk, pk, pkm1, pkm2, qk, qkm1, qkm2;
- long double k1, k2, k3, k4, k5, k6, k7, k8;
- long double r, t, ans, z, thresh;
- int n;
- k1 = a;
- k2 = b - 1.0L;
- k3 = a;
- k4 = a + 1.0L;
- k5 = 1.0L;
- k6 = a + b;
- k7 = a + 1.0L;
- k8 = a + 2.0L;
- pkm2 = 0.0L;
- qkm2 = 1.0L;
- pkm1 = 1.0L;
- qkm1 = 1.0L;
- z = x / (1.0L-x);
- ans = 1.0L;
- r = 1.0L;
- n = 0;
- thresh = 3.0L * MACHEPL;
- do
- {
-
- xk = -( z * k1 * k2 )/( k3 * k4 );
- pk = pkm1 + pkm2 * xk;
- qk = qkm1 + qkm2 * xk;
- pkm2 = pkm1;
- pkm1 = pk;
- qkm2 = qkm1;
- qkm1 = qk;
- xk = ( z * k5 * k6 )/( k7 * k8 );
- pk = pkm1 + pkm2 * xk;
- qk = qkm1 + qkm2 * xk;
- pkm2 = pkm1;
- pkm1 = pk;
- qkm2 = qkm1;
- qkm1 = qk;
- if( qk != 0.0L )
- r = pk/qk;
- if( r != 0.0L )
- {
- t = fabsl( (ans - r)/r );
- ans = r;
- }
- else
- t = 1.0L;
- if( t < thresh )
- goto cdone;
- k1 += 1.0L;
- k2 -= 1.0L;
- k3 += 2.0L;
- k4 += 2.0L;
- k5 += 1.0L;
- k6 += 1.0L;
- k7 += 2.0L;
- k8 += 2.0L;
- if( (fabsl(qk) + fabsl(pk)) > big )
- {
- pkm2 *= biginv;
- pkm1 *= biginv;
- qkm2 *= biginv;
- qkm1 *= biginv;
- }
- if( (fabsl(qk) < biginv) || (fabsl(pk) < biginv) )
- {
- pkm2 *= big;
- pkm1 *= big;
- qkm2 *= big;
- qkm1 *= big;
- }
- }
- while( ++n < 400 );
- mtherr( "incbetl", PLOSS );
- cdone:
- return(ans);
- }
- /* Power series for incomplete gamma integral.
- Use when b*x is small. */
- static long double pseriesl( a, b, x )
- long double a, b, x;
- {
- long double s, t, u, v, n, t1, z, ai;
- ai = 1.0L / a;
- u = (1.0L - b) * x;
- v = u / (a + 1.0L);
- t1 = v;
- t = u;
- n = 2.0L;
- s = 0.0L;
- z = MACHEPL * ai;
- while( fabsl(v) > z )
- {
- u = (n - b) * x / n;
- t *= u;
- v = t / (a + n);
- s += v;
- n += 1.0L;
- }
- s += t1;
- s += ai;
- u = a * logl(x);
- if( (a+b) < MAXGAML && fabsl(u) < MAXLOGL )
- {
- t = gammal(a+b)/(gammal(a)*gammal(b));
- s = s * t * powl(x,a);
- }
- else
- {
- t = lgaml(a+b) - lgaml(a) - lgaml(b) + u + logl(s);
- if( t < MINLOGL )
- s = 0.0L;
- else
- s = expl(t);
- }
- return(s);
- }
|