📄 dcdflib.c
字号:
# include <cstdlib># include <iostream># include <iomanip># include <cmath># include <ctime>using namespace std;# include "dcdflib.H"//****************************************************************************80double algdiv ( double *a, double *b )//****************************************************************************80//// Purpose:// // ALGDIV computes ln ( Gamma ( B ) / Gamma ( A + B ) ) when 8 <= B.//// Discussion://// In this algorithm, DEL(X) is the function defined by//// ln ( Gamma(X) ) = ( X - 0.5 ) * ln ( X ) - X + 0.5 * ln ( 2 * PI ) // + DEL(X).//// Parameters://// Input, double *A, *B, define the arguments.//// Output, double ALGDIV, the value of ln(Gamma(B)/Gamma(A+B)).//{ static double algdiv; static double c; static double c0 = 0.833333333333333e-01; static double c1 = -0.277777777760991e-02; static double c2 = 0.793650666825390e-03; static double c3 = -0.595202931351870e-03; static double c4 = 0.837308034031215e-03; static double c5 = -0.165322962780713e-02; static double d; static double h; static double s11; static double s3; static double s5; static double s7; static double s9; static double t; static double T1; static double u; static double v; static double w; static double x; static double x2; if ( *b <= *a ) { h = *b / *a; c = 1.0e0 / ( 1.0e0 + h ); x = h / ( 1.0e0 + h ); d = *a + ( *b - 0.5e0 ); } else { h = *a / *b; c = h / ( 1.0e0 + h ); x = 1.0e0 / ( 1.0e0 + h ); d = *b + ( *a - 0.5e0 ); }//// SET SN = (1 - X**N)/(1 - X)// x2 = x * x; s3 = 1.0e0 + ( x + x2 ); s5 = 1.0e0 + ( x + x2 * s3 ); s7 = 1.0e0 + ( x + x2 * s5 ); s9 = 1.0e0 + ( x + x2 * s7 ); s11 = 1.0e0 + ( x + x2 * s9 );//// SET W = DEL(B) - DEL(A + B)// t = pow ( 1.0e0 / *b, 2.0 ); w = (((( c5 * s11 * t + c4 * s9 ) * t + c3 * s7 ) * t + c2 * s5 ) * t + c1 * s3 ) * t + c0; w *= ( c / *b );//// COMBINE THE RESULTS// T1 = *a / *b; u = d * alnrel ( &T1 ); v = *a * ( log ( *b ) - 1.0e0 ); if ( v < u ) { algdiv = w - v - u; } else { algdiv = w - u - v; } return algdiv;}//****************************************************************************80double alnrel ( double *a )//****************************************************************************80//// Purpose:// // ALNREL evaluates the function ln ( 1 + A ).//// Modified://// 17 November 2006//// Reference://// Armido DiDinato, Alfred Morris,// Algorithm 708: // Significant Digit Computation of the Incomplete Beta Function Ratios,// ACM Transactions on Mathematical Software,// Volume 18, 1993, pages 360-373.//// Parameters://// Input, double *A, the argument.//// Output, double ALNREL, the value of ln ( 1 + A ).//{ double alnrel; static double p1 = -0.129418923021993e+01; static double p2 = 0.405303492862024e+00; static double p3 = -0.178874546012214e-01; static double q1 = -0.162752256355323e+01; static double q2 = 0.747811014037616e+00; static double q3 = -0.845104217945565e-01; double t; double t2; double w; double x; if ( fabs ( *a ) <= 0.375e0 ) { t = *a / ( *a + 2.0e0 ); t2 = t * t; w = (((p3*t2+p2)*t2+p1)*t2+1.0e0)/(((q3*t2+q2)*t2+q1)*t2+1.0e0); alnrel = 2.0e0 * t * w; } else { x = 1.0e0 + *a; alnrel = log ( x ); } return alnrel;}//****************************************************************************80double apser ( double *a, double *b, double *x, double *eps )//****************************************************************************80//// Purpose:// // APSER computes the incomplete beta ratio I(SUB(1-X))(B,A).//// Discussion://// APSER is used only for cases where//// A <= min ( EPS, EPS * B ), // B * X <= 1, and // X <= 0.5.//// Parameters://// Input, double *A, *B, *X, the parameters of teh// incomplete beta ratio.//// Input, double *EPS, a tolerance.//// Output, double APSER, the computed value of the// incomplete beta ratio.//{ static double g = 0.577215664901533e0; static double apser,aj,bx,c,j,s,t,tol; bx = *b**x; t = *x-bx; if(*b**eps > 2.e-2) goto S10; c = log(*x)+psi(b)+g+t; goto S20;S10: c = log(bx)+g+t;S20: tol = 5.0e0**eps*fabs(c); j = 1.0e0; s = 0.0e0;S30: j = j + 1.0e0; t = t * (*x-bx/j); aj = t/j; s = s + aj; if(fabs(aj) > tol) goto S30; apser = -(*a*(c+s)); return apser;}//****************************************************************************80double bcorr ( double *a0, double *b0 )//****************************************************************************80//// Purpose:// // BCORR evaluates DEL(A0) + DEL(B0) - DEL(A0 + B0).//// Discussion://// The function DEL(A) is a remainder term that is used in the expression://// ln ( Gamma ( A ) ) = ( A - 0.5 ) * ln ( A ) // - A + 0.5 * ln ( 2 * PI ) + DEL ( A ),//// or, in other words, DEL ( A ) is defined as://// DEL ( A ) = ln ( Gamma ( A ) ) - ( A - 0.5 ) * ln ( A ) // + A + 0.5 * ln ( 2 * PI ).//// Parameters://// Input, double *A0, *B0, the arguments.// It is assumed that 8 <= A0 and 8 <= B0.//// Output, double *BCORR, the value of the function.//{ static double c0 = 0.833333333333333e-01; static double c1 = -0.277777777760991e-02; static double c2 = 0.793650666825390e-03; static double c3 = -0.595202931351870e-03; static double c4 = 0.837308034031215e-03; static double c5 = -0.165322962780713e-02; static double bcorr,a,b,c,h,s11,s3,s5,s7,s9,t,w,x,x2; a = fifdmin1 ( *a0, *b0 ); b = fifdmax1 ( *a0, *b0 ); h = a / b; c = h / ( 1.0e0 + h ); x = 1.0e0 / ( 1.0e0 + h ); x2 = x * x;//// SET SN = (1 - X**N)/(1 - X)// s3 = 1.0e0 + ( x + x2 ); s5 = 1.0e0 + ( x + x2 * s3 ); s7 = 1.0e0 + ( x + x2 * s5 ); s9 = 1.0e0 + ( x + x2 * s7 ); s11 = 1.0e0 + ( x + x2 * s9 );//// SET W = DEL(B) - DEL(A + B)// t = pow ( 1.0e0 / b, 2.0 ); w = (((( c5 * s11 * t + c4 * s9 ) * t + c3 * s7 ) * t + c2 * s5 ) * t + c1 * s3 ) * t + c0; w *= ( c / b );//// COMPUTE DEL(A) + W// t = pow ( 1.0e0 / a, 2.0 ); bcorr = ((((( c5 * t + c4 ) * t + c3 ) * t + c2 ) * t + c1 ) * t + c0 ) / a + w; return bcorr;}//****************************************************************************80**double beta ( double a, double b )//****************************************************************************80**//// Purpose://// BETA evaluates the beta function.//// Modified://// 03 December 1999//// Author://// John Burkardt//// Parameters://// Input, double A, B, the arguments of the beta function.//// Output, double BETA, the value of the beta function.//{ return ( exp ( beta_log ( &a, &b ) ) );}//****************************************************************************80double beta_asym ( double *a, double *b, double *lambda, double *eps )//****************************************************************************80//// Purpose://// BETA_ASYM computes an asymptotic expansion for IX(A,B), for large A and B.//// Parameters://// Input, double *A, *B, the parameters of the function.// A and B should be nonnegative. It is assumed that both A and B// are greater than or equal to 15.//// Input, double *LAMBDA, the value of ( A + B ) * Y - B.// It is assumed that 0 <= LAMBDA.//// Input, double *EPS, the tolerance.//{ static double e0 = 1.12837916709551e0; static double e1 = .353553390593274e0; static int num = 20;//// NUM IS THE MAXIMUM VALUE THAT N CAN TAKE IN THE DO LOOP// ENDING AT STATEMENT 50. IT IS REQUIRED THAT NUM BE EVEN.// THE ARRAYS A0, B0, C, D HAVE DIMENSION NUM + 1.// E0 = 2/SQRT(PI)// E1 = 2**(-3/2)// static int K3 = 1; static double value; static double bsum,dsum,f,h,h2,hn,j0,j1,r,r0,r1,s,sum,t,t0,t1,u,w,w0,z,z0, z2,zn,znm1; static int i,im1,imj,j,m,mm1,mmj,n,np1; static double a0[21],b0[21],c[21],d[21],T1,T2; value = 0.0e0; if(*a >= *b) goto S10; h = *a/ *b; r0 = 1.0e0/(1.0e0+h); r1 = (*b-*a)/ *b; w0 = 1.0e0/sqrt(*a*(1.0e0+h)); goto S20;S10: h = *b/ *a; r0 = 1.0e0/(1.0e0+h); r1 = (*b-*a)/ *a; w0 = 1.0e0/sqrt(*b*(1.0e0+h));S20: T1 = -(*lambda/ *a); T2 = *lambda/ *b; f = *a*rlog1(&T1)+*b*rlog1(&T2); t = exp(-f); if(t == 0.0e0) return value; z0 = sqrt(f); z = 0.5e0*(z0/e1); z2 = f+f; a0[0] = 2.0e0/3.0e0*r1; c[0] = -(0.5e0*a0[0]); d[0] = -c[0]; j0 = 0.5e0/e0 * error_fc ( &K3, &z0 ); j1 = e1; sum = j0+d[0]*w0*j1; s = 1.0e0; h2 = h*h; hn = 1.0e0; w = w0; znm1 = z; zn = z2; for ( n = 2; n <= num; n += 2 ) { hn = h2*hn; a0[n-1] = 2.0e0*r0*(1.0e0+h*hn)/((double)n+2.0e0); np1 = n+1; s += hn; a0[np1-1] = 2.0e0*r1*s/((double)n+3.0e0); for ( i = n; i <= np1; i++ ) { r = -(0.5e0*((double)i+1.0e0)); b0[0] = r*a0[0]; for ( m = 2; m <= i; m++ ) { bsum = 0.0e0; mm1 = m-1; for ( j = 1; j <= mm1; j++ ) { mmj = m-j; bsum += (((double)j*r-(double)mmj)*a0[j-1]*b0[mmj-1]); } b0[m-1] = r*a0[m-1]+bsum/(double)m; } c[i-1] = b0[i-1]/((double)i+1.0e0); dsum = 0.0e0; im1 = i-1; for ( j = 1; j <= im1; j++ ) { imj = i-j; dsum += (d[imj-1]*c[j-1]); } d[i-1] = -(dsum+c[i-1]); } j0 = e1*znm1+((double)n-1.0e0)*j0; j1 = e1*zn+(double)n*j1; znm1 = z2*znm1; zn = z2*zn; w = w0*w; t0 = d[n-1]*w*j0; w = w0*w; t1 = d[np1-1]*w*j1; sum += (t0+t1); if(fabs(t0)+fabs(t1) <= *eps*sum) goto S80; }S80: u = exp(-bcorr(a,b)); value = e0*t*u*sum; return value;}//****************************************************************************80double beta_frac ( double *a, double *b, double *x, double *y, double *lambda, double *eps )//****************************************************************************80//// Purpose:// // BETA_FRAC evaluates a continued fraction expansion for IX(A,B).//// Parameters://// Input, double *A, *B, the parameters of the function.// A and B should be nonnegative. It is assumed that both A and// B are greater than 1.//// Input, double *X, *Y. X is the argument of the// function, and should satisy 0 <= X <= 1. Y should equal 1 - X.//// Input, double *LAMBDA, the value of ( A + B ) * Y - B.//// Input, double *EPS, a tolerance.//// Output, double BETA_FRAC, the value of the continued// fraction approximation for IX(A,B).//{ static double bfrac,alpha,an,anp1,beta,bn,bnp1,c,c0,c1,e,n,p,r,r0,s,t,w,yp1; bfrac = beta_rcomp ( a, b, x, y ); if ( bfrac == 0.0e0 ) { return bfrac; } c = 1.0e0+*lambda; c0 = *b/ *a; c1 = 1.0e0+1.0e0/ *a; yp1 = *y+1.0e0; n = 0.0e0; p = 1.0e0; s = *a+1.0e0; an = 0.0e0; bn = anp1 = 1.0e0; bnp1 = c/c1; r = c1/c;//// CONTINUED FRACTION CALCULATION//S10: n += 1.0e0; t = n/ *a; w = n*(*b-n)**x; e = *a/s; alpha = p*(p+c0)*e*e*(w**x); e = (1.0e0+t)/(c1+t+t); beta = n+w/s+e*(c+n*yp1); p = 1.0e0+t; s += 2.0e0;//// UPDATE AN, BN, ANP1, AND BNP1// t = alpha*an+beta*anp1; an = anp1; anp1 = t; t = alpha*bn+beta*bnp1; bn = bnp1; bnp1 = t; r0 = r; r = anp1/bnp1; if ( fabs(r-r0) <= (*eps) * r ) { goto S20; }//// RESCALE AN, BN, ANP1, AND BNP1// an /= bnp1; bn /= bnp1; anp1 = r; bnp1 = 1.0e0; goto S10;//// TERMINATION//S20: bfrac *= r; return bfrac;}//****************************************************************************80void beta_grat ( double *a, double *b, double *x, double *y, double *w, double *eps,int *ierr )//****************************************************************************80//// Purpose:// // BETA_GRAT evaluates an asymptotic expansion for IX(A,B).//// Parameters://// Input, double *A, *B, the parameters of the function.// A and B should be nonnegative. It is assumed that 15 <= A // and B <= 1, and that B is less than A.//// Input, double *X, *Y. X is the argument of the// function, and should satisy 0 <= X <= 1. Y should equal 1 - X.//// Input/output, double *W, a quantity to which the// result of the computation is to be added on output.//// Input, double *EPS, a tolerance.//// Output, int *IERR, an error flag, which is 0 if no error
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -