fix(stats): hold the Student-t tails past t-squared overflow

Assisted-by: GLM 5.3 Flash
This commit is contained in:
2026-09-27 17:03:36 +02:00
parent 2f9358c512
commit 275de79123
6 changed files with 113 additions and 10 deletions
+30
View File
@@ -219,6 +219,36 @@ func TestNoncentralUnderflowSurvival(t *testing.T) {
}
}
// TestNoncentralTCDFHugeFiniteT pins the far corner of the signed axis: a
// finite t whose square overflows drives the beta argument to Inf/Inf, a
// NaN the incomplete beta refused under its own name. The CDF there is 1
// below rounding for t on the δ side and 0 above it, the same limits the
// central law answers.
func TestNoncentralTCDFHugeFiniteT(t *testing.T) {
for _, c := range []struct {
tv float64
df int
delta float64
want float64
}{
{1e200, 3, 2, 1},
{1e155, 1, 0.5, 1},
{-1e200, 5, 1, 0},
{-1e155, 2, -3, 0},
} {
got, err := NoncentralTCDF(c.tv, c.df, c.delta)
if err != nil {
t.Fatalf("NoncentralTCDF(%g, %d, %g): %v", c.tv, c.df, c.delta, err)
}
if math.IsNaN(got) || got < 0 || got > 1 {
t.Fatalf("NoncentralTCDF(%g, %d, %g) = %g, want a probability", c.tv, c.df, c.delta, got)
}
if math.Abs(got-c.want) > 1e-15 {
t.Fatalf("NoncentralTCDF(%g, %d, %g) = %.17g, want %g", c.tv, c.df, c.delta, got, c.want)
}
}
}
// TestNoncentralTIdentityReductions pins the exact corners: δ = 0 is
// the central Student t, t = 0 is Φ(−δ), and the two reflection
// identities of the law hold to rounding.