From 7f689263aaca5983659dea08a8ad01a8b137e783 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 5 Apr 2026 12:15:25 +0000 Subject: [PATCH 1/2] Fix ChiSquared.InvCDF scale parameter bug; add InvCDF tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ChiSquared.InvCDF delegates to Gamma.InvCDF, but was passing beta = 1/2 (rate) while FSharp.Stats Gamma uses the *scale* parameterisation (Mean = alpha * scale). The correct scale for Chi-squared(dof) = Gamma(alpha=dof/2, scale=2) is 2.0, not 0.5. The wrong value caused InvCDF to return quantiles that were roughly 4× too small. Also adds a testList "ChiSquared.InvCDF tests" with: - boundary checks (p=0 → 0, p=1 → +∞) - round-trip tests (CDF(InvCDF(p)) ≈ p) at p=0.5, 0.95, 0.01 - known-value tests derived from the existing CDF reference values All 1201 tests pass. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../Distributions/Continuous/ChiSquared.fs | 5 +- .../DistributionsContinuous.fs | 59 +++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) diff --git a/src/FSharp.Stats/Distributions/Continuous/ChiSquared.fs b/src/FSharp.Stats/Distributions/Continuous/ChiSquared.fs index 44aa14ac..5fdc11a8 100644 --- a/src/FSharp.Stats/Distributions/Continuous/ChiSquared.fs +++ b/src/FSharp.Stats/Distributions/Continuous/ChiSquared.fs @@ -140,8 +140,11 @@ type ChiSquared = /// The probability value in [0.0, 1.0]. /// The quantile corresponding to the cumulative probability p. static member InvCDF (dof: float) (p: float) : float = + // Chi-squared(dof) = Gamma(alpha=dof/2, scale=2). + // FSharp.Stats Gamma uses the scale parameterisation (Mean = alpha * scale), + // so the correct scale is 2.0, not 1/2. let alpha = dof / 2.0 - let beta = 1. / 2.0 + let beta = 2.0 Gamma.InvCDF alpha beta p /// Returns the support of the exponential distribution: [0, Positive Infinity). diff --git a/tests/FSharp.Stats.Tests/DistributionsContinuous.fs b/tests/FSharp.Stats.Tests/DistributionsContinuous.fs index 6d13c751..c674cad2 100644 --- a/tests/FSharp.Stats.Tests/DistributionsContinuous.fs +++ b/tests/FSharp.Stats.Tests/DistributionsContinuous.fs @@ -618,6 +618,65 @@ let chiSquaredTests = Expect.floatClose Accuracy.veryHigh (testCase.PDF -1.) 0. "Should be equal" Expect.isTrue (Ops.isNan <| testCase.PDF nan) "Should be equal" ] + + // Tests for ChiSquared.InvCDF (the percentile-point function). + // Reference values from standard chi-square tables (and CDF values already tested above). + testList "ChiSquared.InvCDF tests" [ + + test "ChiSquared.InvCDF returns 0.0 for p=0.0" { + let x = Continuous.ChiSquared.InvCDF 5. 0. + Expect.floatClose Accuracy.high x 0. "InvCDF(p=0) should be 0" + } + + test "ChiSquared.InvCDF returns +∞ for p=1.0" { + let x = Continuous.ChiSquared.InvCDF 5. 1. + Expect.isTrue (x = infinity) "InvCDF(p=1) should be +infinity" + } + + // Round-trip tests: CDF(InvCDF(p)) ≈ p + test "ChiSquared.InvCDF round-trip dof=5 p=0.5" { + let dof = 5. + let p = 0.5 + let x = Continuous.ChiSquared.InvCDF dof p + let p2 = Continuous.ChiSquared.CDF dof x + Expect.floatClose Accuracy.high p p2 "CDF(InvCDF(0.5)) ≈ 0.5" + } + + test "ChiSquared.InvCDF round-trip dof=1 p=0.95" { + let dof = 1. + let p = 0.95 + let x = Continuous.ChiSquared.InvCDF dof p + let p2 = Continuous.ChiSquared.CDF dof x + Expect.floatClose Accuracy.high p p2 "CDF(InvCDF(0.95)) ≈ 0.95" + } + + test "ChiSquared.InvCDF round-trip dof=10 p=0.01" { + let dof = 10. + let p = 0.01 + let x = Continuous.ChiSquared.InvCDF dof p + let p2 = Continuous.ChiSquared.CDF dof x + Expect.floatClose Accuracy.high p p2 "CDF(InvCDF(0.01)) ≈ 0.01" + } + + // Known-value tests derived from the CDF cases tested above + // (Williams 1984 table: CDF(20, 12.443) ≈ 0.1 → InvCDF(20, 0.1) ≈ 12.443) + test "ChiSquared.InvCDF known value dof=20 p=0.1" { + let x = Continuous.ChiSquared.InvCDF 20. 0.1 + Expect.floatClose Accuracy.low x 12.443 "InvCDF(20, 0.1) should be ≈ 12.443" + } + + // CDF(3, 1.424) ≈ 0.3 → InvCDF(3, 0.3) ≈ 1.424 + test "ChiSquared.InvCDF known value dof=3 p=0.3" { + let x = Continuous.ChiSquared.InvCDF 3. 0.3 + Expect.floatClose Accuracy.low x 1.424 "InvCDF(3, 0.3) should be ≈ 1.424" + } + + // CDF(100, 129.561) ≈ 0.975 → InvCDF(100, 0.975) ≈ 129.561 + test "ChiSquared.InvCDF known value dof=100 p=0.975" { + let x = Continuous.ChiSquared.InvCDF 100. 0.975 + Expect.floatClose Accuracy.low x 129.561 "InvCDF(100, 0.975) should be ≈ 129.561" + } + ] ] //Test ommitted due to long runtime of CodeCov From 80f09b7699d29da44938ae24d25cba4b4c2a4c19 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 5 Apr 2026 12:15:28 +0000 Subject: [PATCH 2/2] ci: trigger checks