diff --git a/src/Numerics/Distributions/Gamma.cs b/src/Numerics/Distributions/Gamma.cs index 85926ccf..ce573dd6 100644 --- a/src/Numerics/Distributions/Gamma.cs +++ b/src/Numerics/Distributions/Gamma.cs @@ -360,6 +360,18 @@ namespace MathNet.Numerics.Distributions return CDF(_shape, _rate, x); } + /// + /// Computes the inverse of the cumulative distribution function (InvCDF) for the distribution + /// at the given probability. This is also known as the quantile or percent point function. + /// + /// The location at which to compute the inverse cumulative density. + /// the inverse cumulative density at . + /// + public double InverseCumulativeDistribution(double p) + { + return InvCDF(_shape, _rate, p); + } + /// /// Generates a sample from the Gamma distribution. /// @@ -491,6 +503,22 @@ namespace MathNet.Numerics.Distributions return SpecialFunctions.GammaLowerRegularized(shape, x*rate); } + /// + /// Computes the inverse of the cumulative distribution function (InvCDF) for the distribution + /// at the given probability. This is also known as the quantile or percent point function. + /// + /// The location at which to compute the inverse cumulative density. + /// The shape (k, α) of the Gamma distribution. Range: α ≥ 0. + /// The rate or inverse scale (β) of the Gamma distribution. Range: β ≥ 0. + /// the inverse cumulative density at . + /// + public static double InvCDF(double shape, double rate, double p) + { + if (shape < 0.0 || rate < 0.0) throw new ArgumentOutOfRangeException(Resources.InvalidDistributionParameters); + + return SpecialFunctions.GammaLowerRegularizedInv(shape, p)/rate; + } + /// /// Generates a sample from the Gamma distribution. /// diff --git a/src/UnitTests/DistributionTests/Continuous/GammaTests.cs b/src/UnitTests/DistributionTests/Continuous/GammaTests.cs index 8cec7b7c..b4b006f8 100644 --- a/src/UnitTests/DistributionTests/Continuous/GammaTests.cs +++ b/src/UnitTests/DistributionTests/Continuous/GammaTests.cs @@ -498,9 +498,30 @@ namespace MathNet.Numerics.UnitTests.DistributionTests.Continuous [TestCase(10, Double.PositiveInfinity, 10.0, 1.0)] public void ValidateCumulativeDistribution(int shape, double invScale, double x, double cdf) { - var n = new Gamma(shape, invScale); - AssertHelpers.AlmostEqualRelative(cdf, n.CumulativeDistribution(x), 13); - AssertHelpers.AlmostEqualRelative(cdf, Gamma.CDF(shape, invScale, x), 13); + var gamma = new Gamma(shape, invScale); + Assert.That(gamma.CumulativeDistribution(x), Is.EqualTo(cdf).Within(13)); + Assert.That(Gamma.CDF(shape, invScale, x), Is.EqualTo(cdf).Within(13)); + } + + /// + /// Validate inverse cumulative distribution. + /// + /// Shape value. + /// Inverse scale value. + /// Input X value. + /// Expected value. + [TestCase(1, 0.1, 1.0, 0.095162581964040431858607615783064404690935346242622848)] + [TestCase(1, 0.1, 10.0, 0.63212055882855767840447622983853913255418886896823196)] + [TestCase(1, 1.0, 1.0, 0.63212055882855767840447622983853913255418886896823196)] + [TestCase(1, 1.0, 10.0, 0.99995460007023751514846440848443944938976208191113396)] + [TestCase(10, 10.0, 1.0, 0.54207028552814779168583514294066541824736464003242184)] + [TestCase(10, 1.0, 1.0, 0.00000011142547833872067735305068724025236288094949815466035)] + [TestCase(10, 1.0, 10.0, 0.54207028552814779168583514294066541824736464003242184)] + public void ValidateInverseCumulativeDistribution(int shape, double invScale, double x, double cdf) + { + var gamma = new Gamma(shape, invScale); + Assert.That(gamma.InverseCumulativeDistribution(cdf), Is.EqualTo(x).Within(10)); + Assert.That(Gamma.InvCDF(shape, invScale, cdf), Is.EqualTo(x).Within(10)); } } }