📄 incbetf.c
字号:
/* incbetf.c * * Incomplete beta integral * * * SYNOPSIS: * * float a, b, x, y, incbetf(); * * y = incbetf( 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. * If a < 1, the function calls itself recursively after a * transformation to increase a to a+1. * * ACCURACY: * * Tested at random points (a,b,x) with a and b in the indicated * interval and x between 0 and 1. * * arithmetic domain # trials peak rms * Relative error: * IEEE 0,30 10000 3.7e-5 5.1e-6 * IEEE 0,100 10000 1.7e-4 2.5e-5 * The useful domain for relative error is limited by underflow * of the single precision exponential function. * Absolute error: * IEEE 0,30 100000 2.2e-5 9.6e-7 * IEEE 0,100 10000 6.5e-5 3.7e-6 * * Larger errors may occur for extreme ratios of a and b. * * ERROR MESSAGES: * message condition value returned * incbetf domain x<0, x>1 0.0 *//*Cephes Math Library, Release 2.2: July, 1992Copyright 1984, 1987, 1992 by Stephen L. MoshierDirect inquiries to 30 Frost Street, Cambridge, MA 02140*/#include <math.h>#ifdef ANSICfloat lgamf(float), expf(float), logf(float);static float incbdf(float, float, float);static float incbcff(float, float, float);float incbpsf(float, float, float);#elsefloat lgamf(), expf(), logf();float incbpsf();static float incbcff(), incbdf();#endif#define fabsf(x) ( (x) < 0 ? -(x) : (x) )/* BIG = 1/MACHEPF */#define BIG 16777216.extern float MACHEPF, MAXLOGF;#define MINLOGF (-MAXLOGF)float incbetf( float aaa, float bbb, float xxx ){float aa, bb, xx, ans, a, b, t, x, onemx;int flag;aa = aaa;bb = bbb;xx = xxx;if( (xx <= 0.0) || ( xx >= 1.0) ) { if( xx == 0.0 ) return(0.0); if( xx == 1.0 ) return( 1.0 ); mtherr( "incbetf", DOMAIN ); return( 0.0 ); }onemx = 1.0 - xx;/* transformation for small aa */if( aa <= 1.0 ) { ans = incbetf( aa+1.0, bb, xx ); t = aa*logf(xx) + bb*logf( 1.0-xx ) + lgamf(aa+bb) - lgamf(aa+1.0) - lgamf(bb); if( t > MINLOGF ) ans += expf(t); return( ans ); }/* see if x is greater than the mean */if( xx > (aa/(aa+bb)) ) { flag = 1; a = bb; b = aa; t = xx; x = onemx; }else { flag = 0; a = aa; b = bb; t = onemx; x = xx; }/* transformation for small aa *//*if( a <= 1.0 ) { ans = a*logf(x) + b*logf( onemx ) + lgamf(a+b) - lgamf(a+1.0) - lgamf(b); t = incbetf( a+1.0, b, x ); if( ans > MINLOGF ) t += expf(ans); goto bdone; }*//* Choose expansion for optimal convergence */if( b > 10.0 ) {if( fabsf(b*x/a) < 0.3 ) { t = incbpsf( a, b, x ); goto bdone; } }ans = x * (a+b-2.0)/(a-1.0);if( ans < 1.0 ) { ans = incbcff( a, b, x ); t = b * logf( t ); }else { ans = incbdf( a, b, x ); t = (b-1.0) * logf(t); }t += a*logf(x) + lgamf(a+b) - lgamf(a) - lgamf(b);t += logf( ans/a );if( t < MINLOGF ) { t = 0.0; if( flag == 0 ) { mtherr( "incbetf", UNDERFLOW ); } }else { t = expf(t); }bdone:if( flag ) t = 1.0 - t;return( t );}/* Continued fraction expansion #1 * for incomplete beta integral */static float incbcff( float aa, float bb, float xx ){float a, b, x, xk, pk, pkm1, pkm2, qk, qkm1, qkm2;float k1, k2, k3, k4, k5, k6, k7, k8;float r, t, ans;static float big = BIG;int n;a = aa;b = bb;x = xx;k1 = a;k2 = a + b;k3 = a;k4 = a + 1.0;k5 = 1.0;k6 = b - 1.0;k7 = k4;k8 = a + 2.0;pkm2 = 0.0;qkm2 = 1.0;pkm1 = 1.0;qkm1 = 1.0;ans = 1.0;r = 0.0;n = 0;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 ) r = pk/qk; if( r != 0 ) { t = fabsf( (ans - r)/r ); ans = r; } else t = 1.0; if( t < MACHEPF ) goto cdone; k1 += 1.0; k2 += 1.0; k3 += 2.0; k4 += 2.0; k5 += 1.0; k6 -= 1.0; k7 += 2.0; k8 += 2.0; if( (fabsf(qk) + fabsf(pk)) > big ) { pkm2 *= MACHEPF; pkm1 *= MACHEPF; qkm2 *= MACHEPF; qkm1 *= MACHEPF; } if( (fabsf(qk) < MACHEPF) || (fabsf(pk) < MACHEPF) ) { pkm2 *= big; pkm1 *= big; qkm2 *= big; qkm1 *= big; } }while( ++n < 100 );cdone:return(ans);}/* Continued fraction expansion #2 * for incomplete beta integral */static float incbdf( float aa, float bb, float xx ){float a, b, x, xk, pk, pkm1, pkm2, qk, qkm1, qkm2;float k1, k2, k3, k4, k5, k6, k7, k8;float r, t, ans, z;static float big = BIG;int n;a = aa;b = bb;x = xx;k1 = a;k2 = b - 1.0;k3 = a;k4 = a + 1.0;k5 = 1.0;k6 = a + b;k7 = a + 1.0;;k8 = a + 2.0;pkm2 = 0.0;qkm2 = 1.0;pkm1 = 1.0;qkm1 = 1.0;z = x / (1.0-x);ans = 1.0;r = 0.0;n = 0;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 ) r = pk/qk; if( r != 0 ) { t = fabsf( (ans - r)/r ); ans = r; } else t = 1.0; if( t < MACHEPF ) goto cdone; k1 += 1.0; k2 -= 1.0; k3 += 2.0; k4 += 2.0; k5 += 1.0; k6 += 1.0; k7 += 2.0; k8 += 2.0; if( (fabsf(qk) + fabsf(pk)) > big ) { pkm2 *= MACHEPF; pkm1 *= MACHEPF; qkm2 *= MACHEPF; qkm1 *= MACHEPF; } if( (fabsf(qk) < MACHEPF) || (fabsf(pk) < MACHEPF) ) { pkm2 *= big; pkm1 *= big; qkm2 *= big; qkm1 *= big; } }while( ++n < 100 );cdone:return(ans);}/* power series */float incbpsf( float aa, float bb, float xx ){float a, b, x, t, u, y, s;a = aa;b = bb;x = xx;y = a * logf(x) + (b-1.0)*logf(1.0-x) - logf(a);y -= lgamf(a) + lgamf(b);y += lgamf(a+b);t = x / (1.0 - x);s = 0.0;u = 1.0;do { b -= 1.0; if( b == 0.0 ) break; a += 1.0; u *= t*b/a; s += u; }while( fabsf(u) > MACHEPF );if( y < MINLOGF ) { mtherr( "incbetf", UNDERFLOW ); s = 0.0; }else s = expf(y) * (1.0 + s);/*printf( "incbpsf: %.4e\n", s );*/return(s);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -