diff --git a/src/Numerics/Distributions/Chi.cs b/src/Numerics/Distributions/Chi.cs index 7c256b02..d1e504f8 100644 --- a/src/Numerics/Distributions/Chi.cs +++ b/src/Numerics/Distributions/Chi.cs @@ -207,7 +207,7 @@ namespace MathNet.Numerics.Distributions /// public double Density(double x) { - return (Math.Pow(2.0, 1.0 - (_freedom/2.0))*Math.Pow(x, _freedom - 1.0)*Math.Exp(-x*x/2.0))/SpecialFunctions.Gamma(_freedom/2.0); + return PDF(_freedom, x); } /// @@ -218,7 +218,7 @@ namespace MathNet.Numerics.Distributions /// public double DensityLn(double x) { - return ((1.0 - (_freedom/2.0))*Math.Log(2.0)) + ((_freedom - 1.0)*Math.Log(x)) - (x*x/2.0) - SpecialFunctions.GammaLn(_freedom/2.0); + return PDFLn(_freedom, x); } /// @@ -229,7 +229,7 @@ namespace MathNet.Numerics.Distributions /// public double CumulativeDistribution(double x) { - return SpecialFunctions.GammaLowerIncomplete(_freedom/2.0, x*x/2.0)/SpecialFunctions.Gamma(_freedom/2.0); + return CDF(_freedom, x); } /// @@ -317,6 +317,11 @@ namespace MathNet.Numerics.Distributions throw new ArgumentException(Resources.InvalidDistributionParameters); } + if (double.IsPositiveInfinity(freedom) || double.IsPositiveInfinity(x) || x == 0.0) + { + return 0.0; + } + if (freedom > 160.0) { return Math.Exp(PDFLn(freedom, x)); @@ -339,6 +344,11 @@ namespace MathNet.Numerics.Distributions throw new ArgumentException(Resources.InvalidDistributionParameters); } + if (double.IsPositiveInfinity(freedom) || double.IsPositiveInfinity(x) || x == 0.0) + { + return double.NegativeInfinity; + } + return ((1.0 - (freedom/2.0))*Math.Log(2.0)) + ((freedom - 1.0)*Math.Log(x)) - (x*x/2.0) - SpecialFunctions.GammaLn(freedom/2.0); } @@ -356,6 +366,16 @@ namespace MathNet.Numerics.Distributions throw new ArgumentException(Resources.InvalidDistributionParameters); } + if (double.IsPositiveInfinity(x)) + { + return 1.0; + } + + if (double.IsPositiveInfinity(freedom)) + { + return 1.0; + } + return SpecialFunctions.GammaLowerRegularized(freedom/2.0, x*x/2.0); } diff --git a/src/Numerics/Distributions/ChiSquared.cs b/src/Numerics/Distributions/ChiSquared.cs index 75e56f4c..1e74160c 100644 --- a/src/Numerics/Distributions/ChiSquared.cs +++ b/src/Numerics/Distributions/ChiSquared.cs @@ -193,7 +193,7 @@ namespace MathNet.Numerics.Distributions /// public double Density(double x) { - return (Math.Pow(x, (_freedom/2.0) - 1.0)*Math.Exp(-x/2.0))/(Math.Pow(2.0, _freedom/2.0)*SpecialFunctions.Gamma(_freedom/2.0)); + return PDF(_freedom, x); } /// @@ -204,7 +204,7 @@ namespace MathNet.Numerics.Distributions /// public double DensityLn(double x) { - return (-x/2.0) + (((_freedom/2.0) - 1.0)*Math.Log(x)) - ((_freedom/2.0)*Math.Log(2)) - SpecialFunctions.GammaLn(_freedom/2.0); + return PDFLn(_freedom, x); } /// @@ -215,7 +215,19 @@ namespace MathNet.Numerics.Distributions /// public double CumulativeDistribution(double x) { - return SpecialFunctions.GammaLowerRegularized(_freedom/2.0, x/2.0); + return CDF(_freedom, 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(_freedom, p); } /// @@ -322,6 +334,11 @@ namespace MathNet.Numerics.Distributions throw new ArgumentException(Resources.InvalidDistributionParameters); } + if (double.IsPositiveInfinity(freedom) || double.IsPositiveInfinity(x) || x == 0.0) + { + return 0.0; + } + if (freedom > 160.0) { return Math.Exp(PDFLn(freedom, x)); @@ -330,18 +347,6 @@ namespace MathNet.Numerics.Distributions return (Math.Pow(x, (freedom/2.0) - 1.0)*Math.Exp(-x/2.0))/(Math.Pow(2.0, freedom/2.0)*SpecialFunctions.Gamma(freedom/2.0)); } - /// - /// 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(_freedom, p); - } - /// /// Computes the log probability density of the distribution (lnPDF) at x, i.e. ln(∂P(X ≤ x)/∂x). /// @@ -356,6 +361,11 @@ namespace MathNet.Numerics.Distributions throw new ArgumentException(Resources.InvalidDistributionParameters); } + if (double.IsPositiveInfinity(freedom) || double.IsPositiveInfinity(x) || x == 0.0) + { + return double.NegativeInfinity; + } + return (-x/2.0) + (((freedom/2.0) - 1.0)*Math.Log(x)) - ((freedom/2.0)*Math.Log(2)) - SpecialFunctions.GammaLn(freedom/2.0); } @@ -373,6 +383,16 @@ namespace MathNet.Numerics.Distributions throw new ArgumentException(Resources.InvalidDistributionParameters); } + if (double.IsPositiveInfinity(x)) + { + return 1.0; + } + + if (double.IsPositiveInfinity(freedom)) + { + return 1.0; + } + return SpecialFunctions.GammaLowerRegularized(freedom/2.0, x/2.0); } diff --git a/src/UnitTests/DistributionTests/Continuous/ChiSquareTests.cs b/src/UnitTests/DistributionTests/Continuous/ChiSquareTests.cs index ccc2c614..154bd07f 100644 --- a/src/UnitTests/DistributionTests/Continuous/ChiSquareTests.cs +++ b/src/UnitTests/DistributionTests/Continuous/ChiSquareTests.cs @@ -178,75 +178,71 @@ namespace MathNet.Numerics.UnitTests.DistributionTests.Continuous /// /// Validate density. /// - /// Degrees of freedom. - /// Input X value. - [TestCase(1.0, 0.0)] - [TestCase(1.0, 0.1)] - [TestCase(1.0, 1.0)] - [TestCase(1.0, 5.5)] - [TestCase(1.0, 110.1)] - [TestCase(1.0, Double.PositiveInfinity)] - [TestCase(2.0, 0.0)] - [TestCase(2.0, 0.1)] - [TestCase(2.0, 1.0)] - [TestCase(2.0, 5.5)] - [TestCase(2.0, 110.1)] - [TestCase(2.0, Double.PositiveInfinity)] - [TestCase(2.5, 0.0)] - [TestCase(2.5, 0.1)] - [TestCase(2.5, 1.0)] - [TestCase(2.5, 5.5)] - [TestCase(2.5, 110.1)] - [TestCase(2.5, Double.PositiveInfinity)] - [TestCase(Double.PositiveInfinity, 0.0)] - [TestCase(Double.PositiveInfinity, 0.1)] - [TestCase(Double.PositiveInfinity, 1.0)] - [TestCase(Double.PositiveInfinity, 5.5)] - [TestCase(Double.PositiveInfinity, 110.1)] - [TestCase(Double.PositiveInfinity, Double.PositiveInfinity)] - public void ValidateDensity(double dof, double x) + /// Reference: N[PDF[ChiSquaredDistribution[dof],x],20] + [TestCase(1.0, 0.0, 0.0)] + [TestCase(1.0, 0.1, 1.2000389484301359798)] + [TestCase(1.0, 1.0, 0.24197072451914334980)] + [TestCase(1.0, 5.5, 0.010874740337283141714)] + [TestCase(1.0, 110.1, 4.7000792147504127122e-26)] + [TestCase(1.0, Double.PositiveInfinity, 0.0)] + [TestCase(2.0, 0.0, 0.0)] + [TestCase(2.0, 0.1, 0.47561471225035700455)] + [TestCase(2.0, 1.0, 0.30326532985631671180)] + [TestCase(2.0, 5.5, 0.031963930603353786351)] + [TestCase(2.0, 110.1, 6.1810004550085248492e-25)] + [TestCase(2.0, Double.PositiveInfinity, 0.0)] + [TestCase(2.5, 0.0, 0.0)] + [TestCase(2.5, 0.1, 0.24812852712543073541)] + [TestCase(2.5, 1.0, 0.28134822576318228131)] + [TestCase(2.5, 5.5, 0.045412171451573920401)] + [TestCase(2.5, 110.1, 1.8574923023527248767e-24)] + [TestCase(2.5, Double.PositiveInfinity, 0.0)] + [TestCase(Double.PositiveInfinity, 0.0, 0.0)] + [TestCase(Double.PositiveInfinity, 0.1, 0.0)] + [TestCase(Double.PositiveInfinity, 1.0, 0.0)] + [TestCase(Double.PositiveInfinity, 5.5, 0.0)] + [TestCase(Double.PositiveInfinity, 110.1, 0.0)] + [TestCase(Double.PositiveInfinity, Double.PositiveInfinity, 0.0)] + public void ValidateDensity(double dof, double x, double expected) { - var n = new ChiSquared(dof); - double expected = (Math.Pow(x, (dof / 2.0) - 1.0) * Math.Exp(-x / 2.0)) / (Math.Pow(2.0, dof / 2.0) * SpecialFunctions.Gamma(dof / 2.0)); - Assert.AreEqual(expected, n.Density(x)); - Assert.AreEqual(expected, ChiSquared.PDF(dof, x)); + var chiSquared = new ChiSquared(dof); + Assert.That(chiSquared.Density(x), Is.EqualTo(expected).Within(13)); + Assert.That(ChiSquared.PDF(dof, x), Is.EqualTo(expected).Within(13)); } /// /// Validate density log. /// - /// Degrees of freedom. - /// Input X value. - [TestCase(1.0, 0.0)] - [TestCase(1.0, 0.1)] - [TestCase(1.0, 1.0)] - [TestCase(1.0, 5.5)] - [TestCase(1.0, 110.1)] - [TestCase(1.0, Double.PositiveInfinity)] - [TestCase(2.0, 0.0)] - [TestCase(2.0, 0.1)] - [TestCase(2.0, 1.0)] - [TestCase(2.0, 5.5)] - [TestCase(2.0, 110.1)] - [TestCase(2.0, Double.PositiveInfinity)] - [TestCase(2.5, 0.0)] - [TestCase(2.5, 0.1)] - [TestCase(2.5, 1.0)] - [TestCase(2.5, 5.5)] - [TestCase(2.5, 110.1)] - [TestCase(2.5, Double.PositiveInfinity)] - [TestCase(Double.PositiveInfinity, 0.0)] - [TestCase(Double.PositiveInfinity, 0.1)] - [TestCase(Double.PositiveInfinity, 1.0)] - [TestCase(Double.PositiveInfinity, 5.5)] - [TestCase(Double.PositiveInfinity, 110.1)] - [TestCase(Double.PositiveInfinity, Double.PositiveInfinity)] - public void ValidateDensityLn(double dof, double x) + /// Reference: N[Ln[PDF[ChiSquaredDistribution[dof],x]],20] + [TestCase(1.0, 0.0, Double.NegativeInfinity)] + [TestCase(1.0, 0.1, 0.18235401329235010023)] + [TestCase(1.0, 1.0, -1.4189385332046727418)] + [TestCase(1.0, 5.5, -4.5213125793238853591)] + [TestCase(1.0, 110.1, -58.319633055068989881)] + [TestCase(1.0, Double.PositiveInfinity, Double.NegativeInfinity)] + [TestCase(2.0, 0.0, Double.NegativeInfinity)] + [TestCase(2.0, 0.1, -0.74314718055994530942)] + [TestCase(2.0, 1.0, -1.1931471805599453094)] + [TestCase(2.0, 5.5, -3.4431471805599453094)] + [TestCase(2.0, 110.1, -55.743147180559945309)] + [TestCase(2.0, Double.PositiveInfinity, Double.NegativeInfinity)] + [TestCase(2.5, 0.0, Double.NegativeInfinity)] + [TestCase(2.5, 0.1, -1.3938084125266298963)] + [TestCase(2.5, 1.0, -1.2681621392781184753)] + [TestCase(2.5, 5.5, -3.0919751162185121666)] + [TestCase(2.5, 110.1, -54.642814878345959906)] + [TestCase(2.5, Double.PositiveInfinity, Double.NegativeInfinity)] + [TestCase(Double.PositiveInfinity, 0.0, Double.NegativeInfinity)] + [TestCase(Double.PositiveInfinity, 0.1, Double.NegativeInfinity)] + [TestCase(Double.PositiveInfinity, 1.0, Double.NegativeInfinity)] + [TestCase(Double.PositiveInfinity, 5.5, Double.NegativeInfinity)] + [TestCase(Double.PositiveInfinity, 110.1, Double.NegativeInfinity)] + [TestCase(Double.PositiveInfinity, Double.PositiveInfinity, Double.NegativeInfinity)] + public void ValidateDensityLn(double dof, double x, double expected) { - var n = new ChiSquared(dof); - double expected = (-x / 2.0) + (((dof / 2.0) - 1.0) * Math.Log(x)) - ((dof / 2.0) * Math.Log(2)) - SpecialFunctions.GammaLn(dof / 2.0); - Assert.AreEqual(expected, n.DensityLn(x)); - Assert.AreEqual(expected, ChiSquared.PDFLn(dof, x)); + var chiSquared = new ChiSquared(dof); + Assert.That(chiSquared.DensityLn(x), Is.EqualTo(expected).Within(13)); + Assert.That(ChiSquared.PDFLn(dof, x), Is.EqualTo(expected).Within(13)); } /// @@ -293,7 +289,7 @@ namespace MathNet.Numerics.UnitTests.DistributionTests.Continuous /// /// Degrees of freedom. /// Input X value. - /// N[CDF[ChiSquare[dof], x],20] + /// N[CDF[ChiSquaredDistribution[dof],x],20] [TestCase(1.0, 0.0, 0.0)] [TestCase(1.0, 0.1, 0.24817036595415071751)] [TestCase(1.0, 1.0, 0.68268949213708589717)] @@ -314,11 +310,11 @@ namespace MathNet.Numerics.UnitTests.DistributionTests.Continuous [TestCase(20000.0, 1.0, 0.0)] public void ValidateCumulativeDistribution(double dof, double x, double expected) { - var n = new ChiSquared(dof); - Assert.That(n.CumulativeDistribution(x), Is.EqualTo(expected).Within(1e-14)); + var chiSquared = new ChiSquared(dof); + Assert.That(chiSquared.CumulativeDistribution(x), Is.EqualTo(expected).Within(1e-14)); Assert.That(ChiSquared.CDF(dof, x), Is.EqualTo(expected).Within(1e-14)); } - + [TestCase(1.0, 0.0, 0.0)] [TestCase(1.0, 0.24817036595415071751, 0.1)] [TestCase(1.0, 0.68268949213708589717, 1.0)] @@ -340,8 +336,8 @@ namespace MathNet.Numerics.UnitTests.DistributionTests.Continuous [TestCase(100000, 0.1, 99427.302671875732)] public void ValidateInverseCumulativeDistribution(double dof, double x, double expected) { - var n = new ChiSquared(dof); - Assert.That(n.InverseCumulativeDistribution(x), Is.EqualTo(expected).Within(1e-14)); + var chiSquared = new ChiSquared(dof); + Assert.That(chiSquared.InverseCumulativeDistribution(x), Is.EqualTo(expected).Within(1e-14)); Assert.That(ChiSquared.InvCDF(dof, x), Is.EqualTo(expected).Within(1e-14)); } } diff --git a/src/UnitTests/DistributionTests/Continuous/ChiTests.cs b/src/UnitTests/DistributionTests/Continuous/ChiTests.cs index bcee6d10..61d4d1be 100644 --- a/src/UnitTests/DistributionTests/Continuous/ChiTests.cs +++ b/src/UnitTests/DistributionTests/Continuous/ChiTests.cs @@ -174,75 +174,71 @@ namespace MathNet.Numerics.UnitTests.DistributionTests.Continuous /// /// Validate density. /// - /// Degrees of freedom. - /// Input X value. - [TestCase(1.0, 0.0)] - [TestCase(1.0, 0.1)] - [TestCase(1.0, 1.0)] - [TestCase(1.0, 5.5)] - [TestCase(1.0, 110.1)] - [TestCase(1.0, Double.PositiveInfinity)] - [TestCase(2.0, 0.0)] - [TestCase(2.0, 0.1)] - [TestCase(2.0, 1.0)] - [TestCase(2.0, 5.5)] - [TestCase(2.0, 110.1)] - [TestCase(2.0, Double.PositiveInfinity)] - [TestCase(2.5, 0.0)] - [TestCase(2.5, 0.1)] - [TestCase(2.5, 1.0)] - [TestCase(2.5, 5.5)] - [TestCase(2.5, 110.1)] - [TestCase(2.5, Double.PositiveInfinity)] - [TestCase(Double.PositiveInfinity, 0.0)] - [TestCase(Double.PositiveInfinity, 0.1)] - [TestCase(Double.PositiveInfinity, 1.0)] - [TestCase(Double.PositiveInfinity, 5.5)] - [TestCase(Double.PositiveInfinity, 110.1)] - [TestCase(Double.PositiveInfinity, Double.PositiveInfinity)] - public void ValidateDensity(double dof, double x) + /// Reference: N[PDF[ChiDistribution[dof],x],20] + [TestCase(1.0, 0.0, 0.0)] + [TestCase(1.0, 0.1, 0.79390509495402353102)] + [TestCase(1.0, 1.0, 0.48394144903828669960)] + [TestCase(1.0, 5.5, 2.1539520085086552718e-7)] + [TestCase(1.0, 110.1, 4.3743524642224403027e-2633)] + [TestCase(1.0, Double.PositiveInfinity, 0.0)] + [TestCase(2.0, 0.0, 0.0)] + [TestCase(2.0, 0.1, 0.099501247919268231335)] + [TestCase(2.0, 1.0, 0.60653065971263342360)] + [TestCase(2.0, 5.5, 1.4847681768496578863e-6)] + [TestCase(2.0, 110.1, 6.0361640012969793703e-2631)] + [TestCase(2.0, Double.PositiveInfinity, 0.0)] + [TestCase(2.5, 0.0, 0.0)] + [TestCase(2.5, 0.1, 0.029191065334961657461)] + [TestCase(2.5, 1.0, 0.56269645152636456261)] + [TestCase(2.5, 5.5, 3.2304380188895211768e-6)] + [TestCase(2.5, 110.1, 5.8759231594821958799e-2630)] + [TestCase(2.5, Double.PositiveInfinity, 0.0)] + [TestCase(Double.PositiveInfinity, 0.0, 0.0)] + [TestCase(Double.PositiveInfinity, 0.1, 0.0)] + [TestCase(Double.PositiveInfinity, 1.0, 0.0)] + [TestCase(Double.PositiveInfinity, 5.5, 0.0)] + [TestCase(Double.PositiveInfinity, 110.1, 0.0)] + [TestCase(Double.PositiveInfinity, Double.PositiveInfinity, 0.0)] + public void ValidateDensity(double dof, double x, double expected) { - var n = new Chi(dof); - double expected = (Math.Pow(2.0, 1.0 - (dof / 2.0)) * Math.Pow(x, dof - 1.0) * Math.Exp(-x * (x / 2.0))) / SpecialFunctions.Gamma(dof / 2.0); - Assert.AreEqual(expected, n.Density(x)); - Assert.AreEqual(expected, Chi.PDF(dof, x)); + var chi = new Chi(dof); + Assert.That(chi.Density(x), Is.EqualTo(expected).Within(13)); + Assert.That(Chi.PDF(dof, x), Is.EqualTo(expected).Within(13)); } /// /// Validate density log. /// - /// Degrees of freedom. - /// Input X value. - [TestCase(1.0, 0.0)] - [TestCase(1.0, 0.1)] - [TestCase(1.0, 1.0)] - [TestCase(1.0, 5.5)] - [TestCase(1.0, 110.1)] - [TestCase(1.0, Double.PositiveInfinity)] - [TestCase(2.0, 0.0)] - [TestCase(2.0, 0.1)] - [TestCase(2.0, 1.0)] - [TestCase(2.0, 5.5)] - [TestCase(2.0, 110.1)] - [TestCase(2.0, Double.PositiveInfinity)] - [TestCase(2.5, 0.0)] - [TestCase(2.5, 0.1)] - [TestCase(2.5, 1.0)] - [TestCase(2.5, 5.5)] - [TestCase(2.5, 110.1)] - [TestCase(2.5, Double.PositiveInfinity)] - [TestCase(Double.PositiveInfinity, 0.0)] - [TestCase(Double.PositiveInfinity, 0.1)] - [TestCase(Double.PositiveInfinity, 1.0)] - [TestCase(Double.PositiveInfinity, 5.5)] - [TestCase(Double.PositiveInfinity, 110.1)] - [TestCase(Double.PositiveInfinity, Double.PositiveInfinity)] - public void ValidateDensityLn(double dof, double x) + /// Reference: N[Ln[PDF[ChiDistribution[dof],x]],20] + [TestCase(1.0, 0.0, Double.NegativeInfinity)] + [TestCase(1.0, 0.1, -0.23079135264472743236)] + [TestCase(1.0, 1.0, -0.72579135264472743236)] + [TestCase(1.0, 5.5, -15.350791352644727432)] + [TestCase(1.0, 110.1, -6061.2307913526447274)] + [TestCase(1.0, Double.PositiveInfinity, Double.NegativeInfinity)] + [TestCase(2.0, 0.0, Double.NegativeInfinity)] + [TestCase(2.0, 0.1, -2.3075850929940456840)] + [TestCase(2.0, 1.0, -0.5)] + [TestCase(2.0, 5.5, -13.420251907761574765)] + [TestCase(2.0, 110.1, -6056.3036109562713657)] + [TestCase(2.0, Double.PositiveInfinity, Double.NegativeInfinity)] + [TestCase(2.5, 0.0, Double.NegativeInfinity)] + [TestCase(2.5, 0.1, -3.5338925982092416919)] + [TestCase(2.5, 1.0, -0.57501495871817316589)] + [TestCase(2.5, 5.5, -12.642892820360535314)] + [TestCase(2.5, 110.1, -6054.0279313931252217)] + [TestCase(2.5, Double.PositiveInfinity, Double.NegativeInfinity)] + [TestCase(Double.PositiveInfinity, 0.0, Double.NegativeInfinity)] + [TestCase(Double.PositiveInfinity, 0.1, Double.NegativeInfinity)] + [TestCase(Double.PositiveInfinity, 1.0, Double.NegativeInfinity)] + [TestCase(Double.PositiveInfinity, 5.5, Double.NegativeInfinity)] + [TestCase(Double.PositiveInfinity, 110.1, Double.NegativeInfinity)] + [TestCase(Double.PositiveInfinity, Double.PositiveInfinity, Double.NegativeInfinity)] + public void ValidateDensityLn(double dof, double x, double expected) { - var n = new Chi(dof); - double expected = ((1.0 - (dof / 2.0)) * Math.Log(2.0)) + ((dof - 1.0) * Math.Log(x)) - (x * (x / 2.0)) - SpecialFunctions.GammaLn(dof / 2.0); - Assert.AreEqual(expected, n.DensityLn(x)); - Assert.AreEqual(expected, Chi.PDFLn(dof, x)); + var chi = new Chi(dof); + Assert.That(chi.DensityLn(x), Is.EqualTo(expected).Within(13)); + Assert.That(Chi.PDFLn(dof, x), Is.EqualTo(expected).Within(13)); } /// @@ -269,38 +265,39 @@ namespace MathNet.Numerics.UnitTests.DistributionTests.Continuous /// /// Validate cumulative distribution. /// - /// Degrees of freedom. - /// Input X value. - [TestCase(1.0, 0.0)] - [TestCase(1.0, 0.1)] - [TestCase(1.0, 1.0)] - [TestCase(1.0, 5.5)] - [TestCase(1.0, 110.1)] - [TestCase(1.0, Double.PositiveInfinity)] - [TestCase(2.0, 0.0)] - [TestCase(2.0, 0.1)] - [TestCase(2.0, 1.0)] - [TestCase(2.0, 5.5)] - [TestCase(2.0, 110.1)] - [TestCase(2.0, Double.PositiveInfinity)] - [TestCase(2.5, 0.0)] - [TestCase(2.5, 0.1)] - [TestCase(2.5, 1.0)] - [TestCase(2.5, 5.5)] - [TestCase(2.5, 110.1)] - [TestCase(2.5, Double.PositiveInfinity)] - [TestCase(Double.PositiveInfinity, 0.0)] - [TestCase(Double.PositiveInfinity, 0.1)] - [TestCase(Double.PositiveInfinity, 1.0)] - [TestCase(Double.PositiveInfinity, 5.5)] - [TestCase(Double.PositiveInfinity, 110.1)] - [TestCase(Double.PositiveInfinity, Double.PositiveInfinity)] - public void ValidateCumulativeDistribution(double dof, double x) + /// Reference: N[CDF[ChiDistribution[dof],x],20] + [TestCase(1.0, 0.0, 0.0)] + [TestCase(1.0, 0.1, 0.079655674554057962931)] + [TestCase(1.0, 1.0, 0.68268949213708589717)] + [TestCase(1.0, 5.5, 0.99999996202087506822)] + [TestCase(1.0, 110.1, 1.0)] + [TestCase(1.0, Double.PositiveInfinity, 1.0)] + [TestCase(2.0, 0.0, 0.0)] + [TestCase(2.0, 0.1, 0.0049875208073176866474)] + [TestCase(2.0, 1.0, 0.39346934028736657640)] + [TestCase(2.0, 5.5, 0.99999973004214966370)] + [TestCase(2.0, 110.1, 1.0)] + [TestCase(2.0, Double.PositiveInfinity, 1.0)] + [TestCase(2.5, 0.0, 0.0)] + [TestCase(2.5, 0.1, 0.0011702413714030096290)] + [TestCase(2.5, 1.0, 0.28378995266531297417)] + [TestCase(2.5, 5.5, 0.99999940337322804750)] + [TestCase(2.5, 110.1, 1.0)] + [TestCase(2.5, Double.PositiveInfinity, 1.0)] + [TestCase(Double.PositiveInfinity, 0.0, 0.0)] + [TestCase(Double.PositiveInfinity, 0.1, 0.0)] + [TestCase(Double.PositiveInfinity, 1.0, 0.0)] + [TestCase(Double.PositiveInfinity, 5.5, 0.0)] + [TestCase(Double.PositiveInfinity, 110.1, 0.0)] + [TestCase(Double.PositiveInfinity, Double.PositiveInfinity, 1.0)] + public void ValidateCumulativeDistribution(double dof, double x, double expected) { - var n = new Chi(dof); - double expected = SpecialFunctions.GammaLowerIncomplete(dof / 2.0, x * x / 2.0) / SpecialFunctions.Gamma(dof / 2.0); - Assert.AreEqual(expected, n.CumulativeDistribution(x)); - Assert.AreEqual(expected, Chi.CDF(dof, x)); + var chi = new Chi(dof); + Assert.That(chi.CumulativeDistribution(x), Is.EqualTo(expected).Within(13)); + Assert.That(Chi.CDF(dof, x), Is.EqualTo(expected).Within(13)); + //double expected = SpecialFunctions.GammaLowerIncomplete(dof / 2.0, x * x / 2.0) / SpecialFunctions.Gamma(dof / 2.0); + //Assert.AreEqual(expected, n.CumulativeDistribution(x)); + //Assert.AreEqual(expected, Chi.CDF(dof, x)); } } }