double hyp2f1( a, b, c, x ) double a, b, c, x;
{ double d, d1, d2, e; double p, q, r, s, y, ax; double ia, ib, ic, id, err; int flag, i, aid;
err = 0.0;
ax = fabs(x);
s = 1.0 - x;
flag = 0;
ia = round(a); /* nearest integer to a */
ib = round(b);
if( a <= 0 )
{ if( fabs(a-ia) < EPS ) /* a is a negative integer */
flag |= 1;
}
if( b <= 0 )
{ if( fabs(b-ib) < EPS ) /* b is a negative integer */
flag |= 2;
}
if( ax < 1.0 )
{ if( fabs(b-c) < EPS ) /* b = c */
{
y = pow( s, -a ); /* s to the -a power */ goto hypdon;
} if( fabs(a-c) < EPS ) /* a = c */
{
y = pow( s, -b ); /* s to the -b power */ goto hypdon;
}
}
if( c <= 0.0 )
{
ic = round(c); /* nearest integer to c */ if( fabs(c-ic) < EPS ) /* c is a negative integer */
{ /* check if termination before explosion */ if( (flag & 1) && (ia > ic) ) goto hypok; if( (flag & 2) && (ib > ic) ) goto hypok; goto hypdiv;
}
}
if( flag ) /* function is a polynomial */ goto hypok;
if( ax > 1.0 ) /* series diverges */ goto hypdiv;
p = c - a;
ia = round(p); /* nearest integer to c-a */ if( (ia <= 0.0) && (fabs(p-ia) < EPS) ) /* negative int c - a */
flag |= 4;
r = c - b;
ib = round(r); /* nearest integer to c-b */ if( (ib <= 0.0) && (fabs(r-ib) < EPS) ) /* negative int c - b */
flag |= 8;
d = c - a - b;
id = round(d); /* nearest integer to d */
q = fabs(d-id);
/* Thanks to Christian Burger <BURGER@DMRHRZ11.HRZ.Uni-Marburg.DE>
* for reporting a bug here. */ if( fabs(ax-1.0) < EPS ) /* |x| == 1.0 */
{ if( x > 0.0 )
{ if( flag & 12 ) /* negative int c-a or c-b */
{ if( d >= 0.0 ) goto hypf; else goto hypdiv;
} if( d <= 0.0 ) goto hypdiv;
y = gamma(c)*gamma(d)/(gamma(p)*gamma(r)); goto hypdon;
}
if( d <= -1.0 ) goto hypdiv;
}
/* Conditionally make d > 0 by recurrence on c *AMS55#15.2.27
*/ if( d < 0.0 )
{ /* Try the power series first */
y = hyt2f1( a, b, c, x, &err ); if( err < ETHRESH ) goto hypdon; /* Apply the recurrence if power series fails */
err = 0.0;
aid = 2 - id;
e = c + aid;
d2 = hyp2f1(a,b,e,x);
d1 = hyp2f1(a,b,e+1.0,x);
q = a + b + 1.0; for( i=0; i<aid; i++ )
{
r = e - 1.0;
y = (e*(r-(2.0*e-q)*x)*d2 + (e-a)*(e-b)*x*d1)/(e*r*s);
e = r;
d1 = d2;
d2 = y;
} goto hypdon;
}
if( flag & 12 ) goto hypf; /* negative integer c-a or c-b */
/* Apply transformations for |x| near 1 *thencallthepowerseries
*/ staticdouble hyt2f1( a, b, c, x, loss ) double a, b, c, x; double *loss;
{ double p, q, r, s, t, y, d, err, err1; double ax, id, d1, d2, e, y1; int i, aid;
err = 0.0;
s = 1.0 - x; if( x < -0.5 )
{ if( b > a )
y = pow( s, -a ) * hys2f1( a, c-b, c, -x/s, &err );
d = c - a - b;
id = round(d); /* nearest integer to d */
if( x > 0.9 )
{ if( fabs(d-id) > EPS ) /* test for integer c-a-b */
{ /* Try the power series first */
y = hys2f1( a, b, c, x, &err ); if( err < ETHRESH ) goto done; /* If power series fails, then apply AMS55 #15.3.6 */
q = hys2f1( a, b, 1.0-d, s, &err );
q *= gamma(d) /(gamma(c-a) * gamma(c-b));
r = pow(s,d) * hys2f1( c-a, c-b, d+1.0, s, &err1 );
r *= gamma(-d)/(gamma(a) * gamma(b));
y = q + r;
q = fabs(q); /* estimate cancellation error */
r = fabs(r); if( q > r )
r = q;
err += err1 + (MACHEP*r)/y;
y *= gamma(c); goto done;
} else
{ /* Psi function expansion, AMS55 #15.3.10, #15.3.11, #15.3.12 */ if( id >= 0.0 )
{
e = d;
d1 = d;
d2 = 0.0;
aid = id;
} else
{
e = -d;
d1 = 0.0;
d2 = d;
aid = -id;
}
ax = log(s);
/* sum for t = 0 */
y = psi(1.0) + psi(1.0+e) - psi(a+d1) - psi(b+d1) - ax;
y /= gamma(e+1.0);
p = (a+d1) * (b+d1) * s / gamma(e+2.0); /* Poch for t=1 */
t = 1.0; do
{
r = psi(1.0+t) + psi(1.0+t+e) - psi(a+t+d1)
- psi(b+t+d1) - ax;
q = p * r;
y += q;
p *= s * (a+t+d1) / (t+1.0);
p *= (b+t+d1) / (t+1.0+e);
t += 1.0;
} while( fabs(q/y) > EPS );
if( id == 0.0 )
{
y *= gamma(c)/(gamma(a)*gamma(b)); goto psidon;
}
y1 = 1.0;
if( aid == 1 ) goto nosum;
t = 0.0;
p = 1.0; for( i=1; i<aid; i++ )
{
r = 1.0-e+t;
p *= s * (a+t+d2) * (b+t+d2) / r;
t += 1.0;
p /= t;
y1 += p;
}
nosum:
p = gamma(c);
y1 *= gamma(e) * p / (gamma(a+d1) * gamma(b+d1));
y *= p / (gamma(a+d2) * gamma(b+d2)); if( (aid & 1) != 0 )
y = -y;
q = pow( s, id ); /* s to the id power */ if( id > 0.0 )
y *= q; else
y1 *= q;
y += y1;
psidon: goto done;
}
}
/* Use defining power series if no special cases */
y = hys2f1( a, b, c, x, &err );
done:
*loss = err; return(y);
}
/* Defining power series expansion of Gauss hypergeometric function */
staticdouble hys2f1( a, b, c, x, loss ) double a, b, c, x; double *loss; /* estimates loss of significance */
{ double f, g, h, k, m, s, u, umax; int i;
i = 0;
umax = 0.0;
f = a;
g = b;
h = c;
s = 1.0;
u = 1.0;
k = 0.0; do
{ if( fabs(h) < EPS )
{
*loss = 1.0; return( MAXNUM );
}
m = k + 1.0;
u = u * ((f+k) * (g+k) * x / ((h+k) * m));
s += u;
k = fabs(u); /* remember largest term summed */ if( k > umax )
umax = k;
k = m; if( ++i > 10000 ) /* should never happen */
{
*loss = 1.0; return(s);
}
} while( fabs(u/s) > MACHEP );
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.