//        [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));
 }
Example #4
0
 /// <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);
        }