diff options
Diffstat (limited to 'libm/ldouble/stdtrl.c')
| -rw-r--r-- | libm/ldouble/stdtrl.c | 225 | 
1 files changed, 225 insertions, 0 deletions
| diff --git a/libm/ldouble/stdtrl.c b/libm/ldouble/stdtrl.c new file mode 100644 index 000000000..4218d4133 --- /dev/null +++ b/libm/ldouble/stdtrl.c @@ -0,0 +1,225 @@ +/*							stdtrl.c + * + *	Student's t distribution + * + * + * + * SYNOPSIS: + * + * long double p, t, stdtrl(); + * int k; + * + * p = stdtrl( k, t ); + * + * + * DESCRIPTION: + * + * Computes the integral from minus infinity to t of the Student + * t distribution with integer k > 0 degrees of freedom: + * + *                                      t + *                                      - + *                                     | | + *              -                      |         2   -(k+1)/2 + *             | ( (k+1)/2 )           |  (     x   ) + *       ----------------------        |  ( 1 + --- )        dx + *                     -               |  (      k  ) + *       sqrt( k pi ) | ( k/2 )        | + *                                   | | + *                                    - + *                                   -inf. + *  + * Relation to incomplete beta integral: + * + *        1 - stdtr(k,t) = 0.5 * incbet( k/2, 1/2, z ) + * where + *        z = k/(k + t**2). + * + * For t < -1.6, this is the method of computation.  For higher t, + * a direct method is derived from integration by parts. + * Since the function is symmetric about t=0, the area under the + * right tail of the density is found by calling the function + * with -t instead of t. + *  + * ACCURACY: + * + * Tested at random 1 <= k <= 100.  The "domain" refers to t. + *                      Relative error: + * arithmetic   domain     # trials      peak         rms + *    IEEE     -100,-1.6    10000       5.7e-18     9.8e-19 + *    IEEE     -1.6,100     10000       3.8e-18     1.0e-19 + */ + +/*							stdtril.c + * + *	Functional inverse of Student's t distribution + * + * + * + * SYNOPSIS: + * + * long double p, t, stdtril(); + * int k; + * + * t = stdtril( k, p ); + * + * + * DESCRIPTION: + * + * Given probability p, finds the argument t such that stdtrl(k,t) + * is equal to p. + *  + * ACCURACY: + * + * Tested at random 1 <= k <= 100.  The "domain" refers to p: + *                      Relative error: + * arithmetic   domain     # trials      peak         rms + *    IEEE       0,1        3500       4.2e-17     4.1e-18 + */ + + +/* +Cephes Math Library Release 2.3:  January, 1995 +Copyright 1984, 1995 by Stephen L. Moshier +*/ + +#include <math.h> + +extern long double PIL, MACHEPL, MAXNUML; +#ifdef ANSIPROT +extern long double sqrtl ( long double ); +extern long double atanl ( long double ); +extern long double incbetl ( long double, long double, long double ); +extern long double incbil ( long double, long double, long double ); +extern long double fabsl ( long double ); +#else +long double sqrtl(), atanl(), incbetl(), incbil(), fabsl(); +#endif + +long double stdtrl( k, t ) +int k; +long double t; +{ +long double x, rk, z, f, tz, p, xsqk; +int j; + +if( k <= 0 ) +	{ +	mtherr( "stdtrl", DOMAIN ); +	return(0.0L); +	} + +if( t == 0.0L ) +	return( 0.5L ); + +if( t < -1.6L ) +	{ +	rk = k; +	z = rk / (rk + t * t); +	p = 0.5L * incbetl( 0.5L*rk, 0.5L, z ); +	return( p ); +	} + +/*	compute integral from -t to + t */ + +if( t < 0.0L ) +	x = -t; +else +	x = t; + +rk = k;	/* degrees of freedom */ +z = 1.0L + ( x * x )/rk; + +/* test if k is odd or even */ +if( (k & 1) != 0) +	{ + +	/*	computation for odd k	*/ + +	xsqk = x/sqrtl(rk); +	p = atanl( xsqk ); +	if( k > 1 ) +		{ +		f = 1.0L; +		tz = 1.0L; +		j = 3; +		while(  (j<=(k-2)) && ( (tz/f) > MACHEPL )  ) +			{ +			tz *= (j-1)/( z * j ); +			f += tz; +			j += 2; +			} +		p += f * xsqk/z; +		} +	p *= 2.0L/PIL; +	} + + +else +	{ + +	/*	computation for even k	*/ + +	f = 1.0L; +	tz = 1.0L; +	j = 2; + +	while(  ( j <= (k-2) ) && ( (tz/f) > MACHEPL )  ) +		{ +		tz *= (j - 1)/( z * j ); +		f += tz; +		j += 2; +		} +	p = f * x/sqrtl(z*rk); +	} + +/*	common exit	*/ + + +if( t < 0.0L ) +	p = -p;	/* note destruction of relative accuracy */ + +	p = 0.5L + 0.5L * p; +return(p); +} + + +long double stdtril( k, p ) +int k; +long double p; +{ +long double t, rk, z; +int rflg; + +if( k <= 0 || p <= 0.0L || p >= 1.0L ) +	{ +	mtherr( "stdtril", DOMAIN ); +	return(0.0L); +	} + +rk = k; + +if( p > 0.25L && p < 0.75L ) +	{ +	if( p == 0.5L ) +		return( 0.0L ); +	z = 1.0L - 2.0L * p; +	z = incbil( 0.5L, 0.5L*rk, fabsl(z) ); +	t = sqrtl( rk*z/(1.0L-z) ); +	if( p < 0.5L ) +		t = -t; +	return( t ); +	} +rflg = -1; +if( p >= 0.5L) +	{ +	p = 1.0L - p; +	rflg = 1; +	} +z = incbil( 0.5L*rk, 0.5L, 2.0L*p ); + +if( MAXNUML * z < rk ) +	return(rflg* MAXNUML); +t = sqrtl( rk/z - rk ); +return( rflg * t ); +} | 
