/* hypergf.c
*
* Confluent hypergeometric function
*
*
*
* SYNOPSIS :
*
* float a , b , x , y , hypergf ( ) ;
*
* y = hypergf ( a , b , x ) ;
*
*
*
* DESCRIPTION :
*
* Computes the confluent hypergeometric function
*
* 1 2
* a x a ( a + 1 ) x
* F ( a , b ; x ) = 1 + - - - - + - - - - - - - - - + . . .
* 1 1 b 1 ! b ( b + 1 ) 2 !
*
* Many higher transcendental functions are special cases of
* this power series .
*
* As is evident from the formula , b must not be a negative
* integer or zero unless a is an integer with 0 > = a > b .
*
* The routine attempts both a direct summation of the series
* and an asymptotic expansion . In each case error due to
* roundoff , cancellation , and nonconvergence is estimated .
* The result with smaller estimated error is returned .
*
*
*
* ACCURACY :
*
* Tested at random points ( a , b , x ) , all three variables
* ranging from 0 to 30 .
* Relative error :
* arithmetic domain # trials peak rms
* IEEE 0 , 5 10000 6 . 6 e - 7 1 . 3 e - 7
* IEEE 0 , 30 30000 1 . 1 e - 5 6 . 5 e - 7
*
* Larger errors can be observed when b is near a negative
* integer or zero . Certain combinations of arguments yield
* serious cancellation error in the power series summation
* and also are not in the region of near convergence of the
* asymptotic series . An error message is printed if the
* self - estimated relative error is greater than 1 . 0 e - 3 .
*
*/
/* hyperg.c */
/*
Cephes Math Library Release 2 . 1 : November , 1988
Copyright 1984 , 1987 , 1988 by Stephen L . Moshier
Direct inquiries to 30 Frost Street , Cambridge , MA 02140
*/
#include "mconf.h"
extern float MAXNUMF, MACHEPF;
#define fabsf(x) ( (x) < 0 ? -(x) : (x) )
#ifdef ANSIC
float expf(float );
float hyp2f0f(float , float , float , int , float *);
static float hy1f1af(float , float , float , float *);
static float hy1f1pf(float , float , float , float *);
float logf(float ), gammaf(float ), lgamf(float );
#else
float expf(), hyp2f0f();
float logf(), gammaf(), lgamf();
static float hy1f1pf(), hy1f1af();
#endif
#ifdef ANSIC
float hypergf( float aa, float bb, float xx )
#else
float hypergf( aa, bb, xx)
double aa, bb, xx;
#endif
{
float a, b, x, asum, psum, acanc, pcanc, temp;
a = aa;
b = bb;
x = xx;
/* See if a Kummer transformation will help */
temp = b - a;
if ( fabsf(temp) < 0 .001 * fabsf(a) )
return ( expf(x) * hypergf( temp, b, -x ) );
psum = hy1f1pf( a, b, x, &pcanc );
if ( pcanc < 1 .0 e-6 )
goto done;
/* try asymptotic series */
asum = hy1f1af( a, b, x, &acanc );
/* Pick the result with less estimated error */
if ( acanc < pcanc )
{
pcanc = acanc;
psum = asum;
}
done:
if ( pcanc > 1 .0 e-3 )
mtherr( "hyperg" , PLOSS );
return ( psum );
}
/* Power series summation for confluent hypergeometric function */
#ifdef ANSIC
static float hy1f1pf( float aa, float bb, float xx, float *err )
#else
static float hy1f1pf( aa, bb, xx, err )
double aa, bb, xx;
float *err;
#endif
{
float a, b, x, n, a0, sum, t, u, temp;
float an, bn, maxt, pcanc;
a = aa;
b = bb;
x = xx;
/* set up for power series summation */
an = a;
bn = b;
a0 = 1 .0 ;
sum = 1 .0 ;
n = 1 .0 ;
t = 1 .0 ;
maxt = 0 .0 ;
while ( t > MACHEPF )
{
if ( bn == 0 ) /* check bn first since if both */
{
mtherr( "hypergf" , SING );
return ( MAXNUMF ); /* an and bn are zero it is */
}
if ( an == 0 ) /* a singularity */
return ( sum );
if ( n > 200 )
goto pdone;
u = x * ( an / (bn * n) );
/* check for blowup */
temp = fabsf(u);
if ( (temp > 1 .0 ) && (maxt > (MAXNUMF/temp)) )
{
pcanc = 1 .0 ; /* estimate 100% error */
goto blowup;
}
a0 *= u;
sum += a0;
t = fabsf(a0);
if ( t > maxt )
maxt = t;
/*
if ( ( maxt / fabsf ( sum ) ) > 1 . 0 e17 )
{
pcanc = 1 . 0 ;
goto blowup ;
}
*/
an += 1 .0 ;
bn += 1 .0 ;
n += 1 .0 ;
}
pdone:
/* estimate error due to roundoff and cancellation */
if ( sum != 0 .0 )
maxt /= fabsf(sum);
maxt *= MACHEPF; /* this way avoids multiply overflow */
pcanc = fabsf( MACHEPF * n + maxt );
blowup:
*err = pcanc;
return ( sum );
}
/* hy1f1a() */
/* asymptotic formula for hypergeometric function:
*
* ( - a
* - - ( | z |
* | ( b ) ( - - - - - - - - 2 f0 ( a , 1 + a - b , - 1 / x )
* ( - -
* ( | ( b - a )
*
*
* x a - b )
* e | x | )
* + - - - - - - - - 2 f0 ( b - a , 1 - a , 1 / x ) )
* - - )
* | ( a ) )
*/
#ifdef ANSIC
static float hy1f1af( float aa, float bb, float xx, float *err )
#else
static float hy1f1af( aa, bb, xx, err )
double aa, bb, xx;
float *err;
#endif
{
float a, b, x, h1, h2, t, u, temp, acanc, asum, err1, err2;
a = aa;
b = bb;
x = xx;
if ( x == 0 )
{
acanc = 1 .0 ;
asum = MAXNUMF;
goto adone;
}
temp = logf( fabsf(x) );
t = x + temp * (a-b);
u = -temp * a;
if ( b > 0 )
{
temp = lgamf(b);
t += temp;
u += temp;
}
h1 = hyp2f0f( a, a-b+1 , -1 .0 /x, 1 , &err1 );
temp = expf(u) / gammaf(b-a);
h1 *= temp;
err1 *= temp;
h2 = hyp2f0f( b-a, 1 .0 -a, 1 .0 /x, 2 , &err2 );
if ( a < 0 )
temp = expf(t) / gammaf(a);
else
temp = expf( t - lgamf(a) );
h2 *= temp;
err2 *= temp;
if ( x < 0 .0 )
asum = h1;
else
asum = h2;
acanc = fabsf(err1) + fabsf(err2);
if ( b < 0 )
{
temp = gammaf(b);
asum *= temp;
acanc *= fabsf(temp);
}
if ( asum != 0 .0 )
acanc /= fabsf(asum);
acanc *= 30 .0 ; /* fudge factor, since error of asymptotic formula
* often seems this much larger than advertised */
adone:
*err = acanc;
return ( asum );
}
/* hyp2f0() */
#ifdef ANSIC
float hyp2f0f(float aa, float bb, float xx, int type, float *err)
#else
float hyp2f0f( aa, bb, xx, type, err )
double aa, bb, xx;
int type; /* determines what converging factor to use */
float *err;
#endif
{
float a, b, x, a0, alast, t, tlast, maxt;
float n, an, bn, u, sum, temp;
a = aa;
b = bb;
x = xx;
an = a;
bn = b;
a0 = 1 .0 ;
alast = 1 .0 ;
sum = 0 .0 ;
n = 1 .0 ;
t = 1 .0 ;
tlast = 1 .0 e9;
maxt = 0 .0 ;
do
{
if ( an == 0 )
goto pdone;
if ( bn == 0 )
goto pdone;
u = an * (bn * x / n);
/* check for blowup */
temp = fabsf(u);
if ( (temp > 1 .0 ) && (maxt > (MAXNUMF/temp)) )
goto error;
a0 *= u;
t = fabsf(a0);
/* terminating condition for asymptotic series */
if ( t > tlast )
goto ndone;
tlast = t;
sum += alast; /* the sum is one term behind */
alast = a0;
if ( n > 200 )
goto ndone;
an += 1 .0 ;
bn += 1 .0 ;
n += 1 .0 ;
if ( t > maxt )
maxt = t;
}
while ( t > MACHEPF );
pdone: /* series converged! */
/* estimate error due to roundoff and cancellation */
*err = fabsf( MACHEPF * (n + maxt) );
alast = a0;
goto done;
ndone: /* series did not converge */
/* The following "Converging factors" are supposed to improve accuracy,
* but do not actually seem to accomplish very much. */
n -= 1 .0 ;
x = 1 .0 /x;
switch ( type ) /* "type" given as subroutine argument */
{
case 1 :
alast *= ( 0 .5 + (0 .125 + 0 .25 *b - 0 .5 *a + 0 .25 *x - 0 .25 *n)/x );
break ;
case 2 :
alast *= 2 .0 /3 .0 - b + 2 .0 *a + x - n;
break ;
default :
;
}
/* estimate error due to roundoff, cancellation, and nonconvergence */
*err = MACHEPF * (n + maxt) + fabsf( a0 );
done:
sum += alast;
return ( sum );
/* series blew up: */
error:
*err = MAXNUMF;
mtherr( "hypergf" , TLOSS );
return ( sum );
}
Messung V0.5 in Prozent C=93 H=79 G=86
¤ Dauer der Verarbeitung: 0.12 Sekunden
(vorverarbeitet am 2026-06-14)
¤
*© Formatika GbR, Deutschland