in commons-statistics-inference/src/main/java/org/apache/commons/statistics/inference/KolmogorovSmirnovDistribution.java [189:224]
private static double sfExact(double x, int n) {
if (n * x * x >= 370 || x >= 1) {
// p would underflow, or x is out of the domain
return 0;
}
final double nx = x * n;
if (nx <= 1) {
// x <= 1/(2n)
if (nx <= HALF) {
// Also detects x <= 0 (iff n is positive)
return 1;
}
if (n == 1) {
// Simplification of:
// 1 - (n! (2x - 1/n)^n) == 1 - (2x - 1)
return 2.0 - 2.0 * x;
}
// 1/(2n) < x <= 1/n
// 1 - (n! (2x - 1/n)^n)
final double f = 2 * x - 1.0 / n;
// Switch threshold where (2x - 1/n)^n is sub-normal
// Max factorial threshold is n=170
final double logf = Math.log(f);
if (n <= MAX_FACTORIAL && n * logf > LOG_MIN_NORMAL) {
return 1 - Factorial.doubleValue(n) * Math.pow(f, n);
}
return -Math.expm1(LogFactorial.create().value(n) + n * logf);
}
// 1 - 1/n <= x < 1
if (n - 1 <= nx) {
// 2 * (1-x)^n
return 2 * Math.pow(1 - x, n);
}
return -1;
}