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