in commons-statistics-inference/src/main/java/org/apache/commons/statistics/inference/UnconditionedExactTest.java [763:810]
private double findExtremeTablesZ(int a, int b, int m, int n, boolean pooled, XYList tableList) {
final double statistic = statisticZ(a, b, m, n, pooled);
// Identify more extreme tables using the alternate hypothesis
final DoublePredicate test;
if (alternative == AlternativeHypothesis.GREATER_THAN) {
test = z -> z >= statistic;
} else if (alternative == AlternativeHypothesis.LESS_THAN) {
test = z -> z <= statistic;
} else {
// two-sided
if (statistic == 0) {
// Early exit: all tables are as extreme
return 0;
}
final double za = Math.abs(statistic);
test = z -> Math.abs(z) >= za;
}
// Precompute factors
final double mn = (double) m + n;
final double norm = 1.0 / m + 1.0 / n;
double z;
// Process all possible tables
for (int i = 0; i <= m; i++) {
final double p0 = (double) i / m;
final double vp0 = p0 * (1 - p0) / m;
for (int j = 0; j <= n; j++) {
final double p1 = (double) j / n;
// Avoid NaN generation 0 / 0 when the variance is 0
if (p0 == p1) {
z = 0;
} else {
final double variance;
if (pooled) {
// Integer sums will not overflow
final double p = (i + j) / mn;
variance = p * (1 - p) * norm;
} else {
variance = vp0 + p1 * (1 - p1) / n;
}
z = (p0 - p1) / Math.sqrt(variance);
}
if (test.test(z)) {
tableList.add(i, j);
}
}
}
return statistic;
}