Accord.Statistics.Distributions.Univariate.KolmogorovSmirnovDistribution.CumulativeFunction C# (CSharp) Method

CumulativeFunction() public static method

Computes the Cumulative Distribution Function (CDF) for the Kolmogorov-Smirnov statistic's distribution.

This function computes the cumulative probability P[Dn <= x] of the Kolmogorov-Smirnov distribution using multiple methods as suggested by Richard Simard (2010).

Simard partitioned the problem of evaluating the CDF using multiple approximation and asymptotic methods in order to achieve a best compromise between speed and precision. This function follows the same partitioning as Simard, which is described in the table below.

For n <= 140 and: 1/n > x >= 1-1/nUses the Ruben-Gambino formula. 1/n < nx² < 0.754693Uses the Durbin matrix algorithm. 0.754693 <= nx² < 4Uses the Pomeranz algorithm. 4 <= nx² < 18Uses the complementary distribution function. nx² >= 18Returns the constant 1. For 140 < n <= 10^5 nx² >= 18Returns the constant 1. nx^(3/2) < 1.4Durbin matrix algorithm. nx^(3/2) > 1.4Pelz-Good asymptotic series. For n > 10^5 nx² >= 18Returns the constant 1. nx² < 18Pelz-Good asymptotic series.
public static CumulativeFunction ( double n, double x ) : double
n double The sample size.
x double The Kolmogorov-Smirnov statistic.
return double
        public static double CumulativeFunction(double n, double x)
        {
            if (Double.IsNaN(x))
                throw new ArgumentOutOfRangeException("x");

            double nxx = n * x * x; // nx²

            int nn = (int)Math.Ceiling(n);

            // First of all, check if the given values do not represent
            // a special case. There are some combination of values for
            // which the distribution has a known, exact solution.

            // Ruben-Gambino
            if (x >= 1.0 || nxx >= 18.0)
                return 1.0;

            if (x <= 0.5 / n)
                return 0.0;

            if (n == 1)
                return 2.0 * x - 1.0;

            if (x <= 1.0 / n)
                return (n <= 20) ? Special.Factorial(n) * Math.Pow(2.0 * x - 1.0 / n, n)
                    : Math.Exp(Special.LogFactorial(n) + n * Math.Log(2.0 * x - 1.0 / n));

            if (x >= 1.0 - 1.0 / n)
                return 1.0 - 2.0 * Math.Pow(1.0 - x, n);

            // This is not a special case. Continue processing to
            //  select the most adequate method for the given inputs

            if (n <= 140)
            {
                // This is the first case (i) as referred in Simard's
                // paper. Use exact algorithms depending on nx² with
                // at least 13 to 15 decimal digits of precision.

                // Durbin
                if (nxx < 0.754693)
                    return Durbin(nn, x);

                // Pomeranz
                if (nxx < 4.0)
                    return Pomeranz(nn, x);

                // Complementary CDF
                return 1.0 - ComplementaryDistributionFunction(n, x);
            }
            else
            {
                if (n <= 100000)
                {
                    // This is the second case (ii) referred in Simard's
                    // paper. Use either the Durbin approximation or the
                    // Pelz-Good asymptotic series depending on nx^(3/2).

                    // Obs:
                    //
                    //   x^(3/2) = x^(1 + 1/2) = x*x^(1/2) = x*sqrt(x)
                    //
                    //          (n*x)      * sqrt(x) <= 1.40
                    //   sqrt((n*x)*(n*x)) * sqrt(x) <= 1.40
                    //   sqrt((n*x)*(n*x)  *      x) <= 1.40
                    //        (n*x)*(n*x)  *      x  <= 1.96
                    //       
                    //    n*n*x*x*x <= 1.96
                    //

                    if (n * nxx * x <= 1.96)
                        return Durbin(nn, x);
                    else return PelzGood(n, x);
                }
                else
                {
                    // This is the third case (iii) as referred in Simard's
                    // paper. Use only the Pelz-Good asymptotic series.
                    return PelzGood(n, x);
                }
            }
        }