// [TestCase(0.99999999999999999, 8.4937932241095980744447188132289548161213991737094E+0)] public void GetInverseCdfValue_TestCase_BenchmarkResult(double probability, double expected) { double actual = StandardNormalDistribution.GetInverseCdfValue(probability); Assert.That(actual, Is.EqualTo(expected).Within(1E-7)); // low tolerance only! }
public void GetCdfValue_TestCase_BenchmarkResult(double x, double expected) { double actual = StandardNormalDistribution.GetCdfValue(x); Assert.That(actual, Is.EqualTo(expected).Within(1E-14)); }
/// <summary>Gets a specific value of the cummulative distribution function. /// </summary> /// <param name="x">The value where to evaluate.</param> /// <returns>The specified value of the cummulative distribution function.</returns> public double GetCdfValue(double x) { return(StandardNormalDistribution.GetCdfValue((x - Mu) / Sigma)); }
/// <summary>Gets a specific value of the inverse of the cumulative distribution function. /// </summary> /// <param name="probability">The probability where to evaluate.</param> /// <returns>The specified value of the inverse of the cumulative distribution function.</returns> public double GetInverseCdfValue(double probability) { return(Math.Exp(StandardNormalDistribution.GetInverseCdfValue(probability) * Sigma + Mu) + Shift); }
/// <summary>Evaluate the cummulative distribution function of a bivariate normal random variable /// at a given point. /// </summary> /// <param name="a">The first part of the evaluation point.</param> /// <param name="b">The second part of the evaluation point.</param> /// <param name="rho">The correlation coefficient.</param> /// <returns>Returns the value of the double-integral /// <para> /// N_2(a,b,\rho) = \frac{1}{ 2\pi \sqrt{1-\rho^2}} * \int_{-\infty}^a \int_{-\infty}^b exp\bigl[ - \frac{ x^2 - 2 \rho xy +y^2}{2 (1-\rho^2)} \bigr] dy dx. /// </para></returns> /// <remarks>This function is based on the method described by /// Drezner, Z and G.O. Wesolowsky, (1989), On the computation of the bivariate normal integral, /// Journal of Statist. Comput. Simul. 35, pp. 101-107, /// with major modifications for double precision, and for |R| close to 1. /// This implementation is based on the Fortran function BVND of A. Genz, /// http://www.sci.wsu.edu/math/faculty/genz/homepage.</remarks> public static double StandardCDFValue(double a, double b, double rho) { double cdfValue = 0.0; double absOfRho = Math.Abs(rho); int gaussLegendreRule; if (absOfRho < 0.3) { gaussLegendreRule = (int)eGaussLegendreRule.GaussLegendre6; } else if (absOfRho < 0.75) { gaussLegendreRule = (int)eGaussLegendreRule.GaussLegendre12; } else { gaussLegendreRule = (int)eGaussLegendreRule.GaussLegendre20; } int numberOfEvaluations = sm_GaussWeights[gaussLegendreRule].Length; double[] gaussLegendreWeights = sm_GaussWeights[gaussLegendreRule]; double[] gaussLegendreEvaluationPoints = sm_GaussEvaluationPoints[gaussLegendreRule]; double aTimesb = a * b; if (absOfRho < 0.925) { if (absOfRho > 0) { double halfOfaSquarePlusbSquare = (a * a + b * b) / 2; double rhoAsin = Math.Asin(rho); for (int i = 0; i < numberOfEvaluations; i++) { for (int j = -1; j <= 2; j += 2) { double tempValue = Math.Sin(rhoAsin * (j * gaussLegendreEvaluationPoints[i] + 1) / 2); cdfValue = cdfValue + gaussLegendreWeights[i] * Math.Exp((tempValue * aTimesb - halfOfaSquarePlusbSquare) / (1 - tempValue * tempValue)); } } cdfValue *= rhoAsin / (2 * MathConsts.TwoPi); } return(cdfValue + StandardNormalDistribution.GetCdfValue(a) * StandardNormalDistribution.GetCdfValue(b)); } else { if (rho < 0) { aTimesb = -aTimesb; } if (absOfRho < 1) { double AS = (1 - rho) * (1 + rho); double A = Math.Sqrt(AS); double BS = (a - b) * (a - b); double C = (4 - aTimesb) / 8; double D = (12 - aTimesb) / 16; double ASR = -(BS / AS + aTimesb) / 2; if (ASR > -100) { cdfValue = A * Math.Exp(ASR) * (1 - C * (BS - AS) * (1 - D * BS / 5) / 3 + C * D * AS * AS / 5); } if (-aTimesb < 100) { double B = Math.Sqrt(BS); cdfValue = cdfValue - Math.Exp(-aTimesb / 2) * MathConsts.SqrtTwoPi * StandardNormalDistribution.GetCdfValue(-B / A) * B * (1 - C * BS * (1 - D * BS / 5) / 3); } A = A / 2; for (int i = 0; i < numberOfEvaluations; i++) { for (int j = -1; j <= 2; j += 2) { double XS = (A * (j * gaussLegendreEvaluationPoints[i] + 1)) * (A * (j * gaussLegendreEvaluationPoints[i] + 1)); double RS = Math.Sqrt(1 - XS); ASR = -(BS / XS + aTimesb) / 2; if (ASR > -100) { cdfValue = cdfValue + A * gaussLegendreWeights[i] * Math.Exp(ASR) * (Math.Exp(-aTimesb * (1 - RS) / (2 * (1 + RS))) / RS - (1 + C * XS * (1 + D * XS))); } } } cdfValue = -cdfValue / MathConsts.TwoPi; } if (rho > 0) { cdfValue = cdfValue + StandardNormalDistribution.GetCdfValue(Math.Min(a, b)); } else { cdfValue = -cdfValue; if (b < a) { cdfValue = cdfValue + StandardNormalDistribution.GetCdfValue(-b) - StandardNormalDistribution.GetCdfValue(-a); } } } return(cdfValue); }