public static double PelzGood(double n, double x)
{
const int maxTerms = 20;
const double eps = 1.0e-10;
const double PI2 = Math.PI * Math.PI;
const double PI4 = PI2 * PI2;
double sqrtN = Math.Sqrt(n);
double z = sqrtN * x;
double z2 = z * z;
double z3 = z2 * z;
double z4 = z2 * z2;
double z6 = z4 * z2;
double z7 = z4 * z3;
double z8 = z4 * z4;
double z10 = z8 * z2;
double pz = -PI2 / (2 * z2);
double term;
double k0 = 0; // Evaluate K0(z)
for (int k = 0; k <= maxTerms; k++)
{
double h = (k + 0.5);
k0 += term = Math.Exp(h * h * pz);
if (term <= eps * k0) break;
}
double k1 = 0; // Evaluate K1(z)
for (int k = 0; k <= maxTerms; k++)
{
double hh = (k + 0.5) * (k + 0.5);
k1 += term = (PI2 * hh - z2) * Math.Exp(hh * pz);
if (Math.Abs(term) <= eps * Math.Abs(k1)) break;
}
double k2a = 0; // Evaluate 1st part of K2(z)
for (int k = 0; k <= maxTerms; k++)
{
double hh = (k + 0.5) * (k + 0.5);
k2a += term = (6 * z6 + 2 * z4
+ PI2 * (2 * z4 - 5 * z2) * hh
+ PI4 * (1 - 2 * z2) * hh * hh) * Math.Exp(hh * pz);
if (Math.Abs(term) <= eps * Math.Abs(k2a)) break;
}
double k2b = 0; // Evaluate 2nd part of K2(z)
for (int k = 1; k <= maxTerms; k++)
{
double kk = k * k;
k2b += term = PI2 * kk * Math.Exp(kk * pz);
if (term <= eps * k2b) break;
}
double k3a = 0; // Evaluate 1st part of K3(z)
for (int k = 0; k <= maxTerms; k++)
{
double hh = (k + 0.5) * (k + 0.5);
k3a += term = (-30 * z6 - 90 * z8
+ PI2 * (135 * z4 - 96 * z6) * hh
+ PI4 * (212 * z4 - 60 * z2) * hh * hh
+ PI2 * PI4 * hh * hh * hh * (5 - 30 * z2)) * Math.Exp(hh * pz);
if (Math.Abs(term) <= eps * Math.Abs(k3a)) break;
}
double k3b = 0; // Evaluate 2nd part of K3(z)
for (int k = 1; k <= maxTerms; k++)
{
double kk = k * k;
k3b += term = (3 * PI2 * kk * z2 - PI4 * kk * kk) * Math.Exp(kk * pz);
if (Math.Abs(term) <= eps * Math.Abs(k3b)) break;
}
// Evaluate the P[sqrt(N) * Dn <= z | H0]
double sum = k0 * (Constants.Sqrt2PI / z)
+ k1 * (Constants.SqrtHalfPI / (sqrtN * 3.0 * z4))
+ k2a * (Constants.SqrtHalfPI / (n * 36.0 * z7))
- k2b * (Constants.SqrtHalfPI / (n * 18.0 * z3))
+ k3a * (Constants.SqrtHalfPI / (n * sqrtN * 3240.0 * z10))
+ k3b * (Constants.SqrtHalfPI / (n * sqrtN * 108.0 * z6));
return sum;
}