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

OneSideUpperTail() public static method

Computes the Upper Tail of the P[Dn >= x] distribution.
This function approximates the upper tail of the P[Dn >= x] distribution using the one-sided Kolmogorov-Smirnov statistic.
public static OneSideUpperTail ( double n, double x ) : double
n double
x double
return double
        public static double OneSideUpperTail(double n, double x)
        {
            if (n > 200000)
            {
                // Use an asymptotic formula for n too high
                double t = (6 * n * x + 1.0);
                double z = t * t / (18 * n);
                double v = (1.0 - (2 * z * z - 4 * z - 1.0) / (18 * n)) * Math.Exp(-z);

                if (v <= 0.0) return 0.0;
                if (v >= 1.0) return 1.0;
                else return 1.0 * v;
            }
            else
            {
                // Use Smirnov's stable formula for computing Pn+, the upper tail of
                // the one-sided Kolmogorov's statistic Dn+. This upper tail of the
                // one-sided statistic can then be used to approximate the upper tail
                // Pn of the Kolmogorov statistic Dn with Pn ~ 2*Pn+.

                int jmax = (int)(n * (1.0 - x));
                if ((1.0 - x - (double)jmax / n) <= 0.0)
                    jmax--;

                // Initialize
                int jdiv = (n > 3000) ? 2 : 3;
                int jstart = jmax / jdiv + 1;

                double logBinomial = Special.LogBinomial(n, jstart);
                double LOGJMAX = logBinomial;
                double EPSILON = 1.0E-12;


                // Start computing the series
                double sum = 0;

                for (int j = jstart; j <= jmax; j++)
                {
                    double q = (double)j / n + x;
                    double term = logBinomial + (j - 1) * Math.Log(q) + (n - j) * Special.Log1p(-q);
                    double t = Math.Exp(term);

                    sum += t;
                    logBinomial += Math.Log((double)(n - j) / (j + 1));

                    if (t <= sum * EPSILON)
                        break;
                }

                jstart = jmax / jdiv;
                logBinomial = LOGJMAX + Math.Log((double)(jstart + 1) / (n - jstart));

                for (int j = jstart; j > 0; j--)
                {
                    double q = (double)j / n + x;
                    double term = logBinomial + (j - 1) * Math.Log(q) + (n - j) * Special.Log1p(-q);
                    double t = Math.Exp(term);

                    sum += t;
                    logBinomial += Math.Log((double)j / (n - j + 1));

                    if (t <= sum * EPSILON)
                        break;
                }


                return sum * x + Math.Exp(n * Special.Log1p(-x));
            }
        }