private static double distributionFunctionLowerTail(double t, double df, double delta)
{
double alnrpi = 0.57236494292470008707;
double errmax = 1.0E-10;
int itrmax = 100;
double r2pi = 0.79788456080286535588;
if (df <= 0.0)
{
throw new ArgumentOutOfRangeException("df",
"Degrees of freedom must be positive.");
}
double del;
bool negdel;
if (t < 0.0)
{
del = -delta;
negdel = true;
}
else
{
del = delta;
negdel = false;
}
// Initialize twin series.
double en = 1.0;
double x = t * t / (t * t + df);
if (Double.IsNaN(x))
x = 1;
double value = 0;
if (x <= 0.0)
{
// upper tail of normal cumulative function
value += Normal.Complemented(del);
if (negdel)
value = 1.0 - value;
return value;
}
double lambda = del * del;
double p = 0.5 * Math.Exp(-0.5 * lambda);
double q = r2pi * p * del;
double s = 0.5 - p;
double a = 0.5;
double b = 0.5 * df;
double rxb = Math.Pow(1.0 - x, b);
double albeta = alnrpi + Gamma.Log(b) - Gamma.Log(a + b);
double xodd = Beta.Incomplete(a, b, x);
double godd = 2.0 * rxb * Math.Exp(a * Math.Log(x) - albeta);
double xeven = 1.0 - rxb;
double geven = b * x * rxb;
value = p * xodd + q * xeven;
// Repeat until convergence.
while (true)
{
a = a + 1.0;
xodd = xodd - godd;
xeven = xeven - geven;
godd = godd * x * (a + b - 1.0) / a;
geven = geven * x * (a + b - 0.5) / (a + 0.5);
p = p * lambda / (2.0 * en);
q = q * lambda / (2.0 * en + 1.0);
s = s - p;
en = en + 1.0;
value = value + p * xodd + q * xeven;
double errbd = 2.0 * s * (xodd - godd);
if (errbd <= errmax || Double.IsNaN(errbd))
break;
if (itrmax < en)
throw new ConvergenceException("Maximum number of iterations reached.");
}
// upper tail of normal cumulative function
value = value + Normal.Complemented(del);
if (negdel)
value = 1.0 - value;
return value;
}