| 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, 1995Copyright 1984, 1995 by Stephen L. Moshier*/#include <math.h>#define MAXGAML 1755.455Lstatic long double big = 9.223372036854775808e18L;static long double biginv = 1.084202172485504434007e-19L;extern long double MACHEPL, MINLOGL, MAXLOGL;#ifdef ANSIPROTextern 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 );#elselong double gammal(), lgaml(), expl(), logl(), fabsl(), powl();static long double incbcfl(), incbdl(), pseriesl();#endiflong 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);}
 |