using System;
namespace Legalsoft.Truffer
{
/// <summary>
/// Kolmogorov-Smirnov累积分布函数
/// Kolmogorov-Smirnov cumulative distribution functions
/// and their inverses.
/// </summary>
public class KSdist
{
public double pks(double z)
{
if (z < 0.0)
{
throw new Exception("bad z in KSdist");
}
if (z < 0.042)
{
return 0.0;
}
if (z < 1.18)
{
double y = Math.Exp(-1.23370055013616983 / Globals.SQR(z));
return 2.25675833419102515 * Math.Sqrt(-Math.Log(y)) * (y + Math.Pow(y, 9) + Math.Pow(y, 25) + Math.Pow(y, 49));
}
else
{
double x = Math.Exp(-2.0 * Globals.SQR(z));
return 1.0 - 2.0 * (x - Math.Pow(x, 4) + Math.Pow(x, 9));
}
}
public double qks(double z)
{
if (z < 0.0)
{
throw new Exception("bad z in KSdist");
}
//if (z == 0.0)
if (Math.Abs(z) <= float.Epsilon)
{
return 1.0;
}
if (z < 1.18)
{
return 1.0 - pks(z);
}
double x = Math.Exp(-2.0 * Globals.SQR(z));
return 2.0 * (x - Math.Pow(x, 4) + Math.Pow(x, 9));
}
public double invqks(double q)
{
if (q <= 0.0 || q > 1.0)
{
throw new Exception("bad q in KSdist");
}
//if (q == 1.0)
if (Math.Abs(q) <= float.Epsilon)
{
return 0.0;
}
if (q > 0.3)
{
double f = -0.392699081698724155 * Globals.SQR(1.0 - q);
double y = Integrals.invxlogx(f);
double t;
do
{
double yp = y;
double logy = Math.Log(y);
double ff = f / Globals.SQR(1.0 + Math.Pow(y, 4) + Math.Pow(y, 12));
double u = (y * logy - ff) / (1.0 + logy);
t = u / Math.Max(0.5, 1.0 - 0.5 * u / (y * (1.0 + logy)));
y = y - (t);
} while (Math.Abs(t / y) > 1.0e-15);
return 1.57079632679489662 / Math.Sqrt(-Math.Log(y));
}
else
{
double x = 0.03;
double xp;
do
{
xp = x;
x = 0.5 * q + Math.Pow(x, 4) - Math.Pow(x, 9);
if (x > 0.06)
{
x += Math.Pow(x, 16) - Math.Pow(x, 25);
}
} while (Math.Abs((xp - x) / x) > 1.0e-15);
return Math.Sqrt(-0.5 * Math.Log(x));
}
}
public double invpks(double p)
{
return invqks(1.0 - p);
}
}
}