/*							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 );
}