| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384 | /*							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.6e-7      1.3e-7 *    IEEE      0,30        30000       1.1e-5      6.5e-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.0e-3. * *//*							hyperg.c *//*Cephes Math Library Release 2.1:  November, 1988Copyright 1984, 1987, 1988 by Stephen L. MoshierDirect inquiries to 30 Frost Street, Cambridge, MA 02140*/#include <math.h>extern float MAXNUMF, MACHEPF;#define fabsf(x) ( (x) < 0 ? -(x) : (x) )#ifdef ANSICfloat 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);#elsefloat expf(), hyp2f0f();float logf(), gammaf(), lgamf();static float hy1f1pf(), hy1f1af();#endiffloat hypergf( float aa, float bb, float xx ){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.0e-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.0e-3 )	mtherr( "hyperg", PLOSS );return( psum );}/* Power series summation for confluent hypergeometric function		*/static float hy1f1pf( float aa, float bb, float xx, float *err ){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.0e17 )		{		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) ( -------- 2f0( a, 1+a-b, -1/x ) *        (  --                            *        ( |  (b-a)                       * * *                                x    a-b                     ) *                               e  |x|                        ) *                             + -------- 2f0( b-a, 1-a, 1/x ) ) *                                --                           ) *                               |  (a)                        ) */static float hy1f1af( float aa, float bb, float xx, float *err ){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()	*/float hyp2f0f(float aa, float bb, float xx, int type, float *err){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.0e9;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 );}
 |