Beispiel #1
0
        /// <summary>
        ///   Natural logarithm of the gamma function.
        /// </summary>
        ///
        public static double Log(double x)
        {
            if (x == 0)
            {
                return(Double.PositiveInfinity);
            }

            double p, q, w, z;

            if (x < -34.0)
            {
                q = -x;
                w = Log(q);
                p = Math.Floor(q);

                if (p == q)
                {
                    throw new OverflowException();
                }

                z = q - p;
                if (z > 0.5)
                {
                    p += 1.0;
                    z  = p - q;
                }
                z = q * Math.Sin(System.Math.PI * z);

                if (z == 0.0)
                {
                    throw new OverflowException();
                }

                z = Constants.LogPI - Math.Log(z) - w;
                return(z);
            }

            if (x < 13.0)
            {
                z = 1.0;
                while (x >= 3.0)
                {
                    x -= 1.0;
                    z *= x;
                }
                while (x < 2.0)
                {
                    if (x == 0.0)
                    {
                        throw new OverflowException();
                    }

                    z /= x;
                    x += 1.0;
                }

                if (z < 0.0)
                {
                    z = -z;
                }

                if (x == 2.0)
                {
                    return(System.Math.Log(z));
                }

                x -= 2.0;

                p = x * Polynomial.Evaluate(x, log_B, 5) / Polynomial.EvaluateSpecial(x, log_C, 6);

                return(Math.Log(z) + p);
            }

            if (x > 2.556348e305)
            {
                throw new OverflowException();
            }

            q = (x - 0.5) * Math.Log(x) - x + 0.91893853320467274178;

            if (x > 1.0e8)
            {
                return(q);
            }

            p = 1.0 / (x * x);

            if (x >= 1000.0)
            {
                q += ((7.9365079365079365079365e-4 * p
                       - 2.7777777777777777777778e-3) * p
                      + 0.0833333333333333333333) / x;
            }
            else
            {
                q += Polynomial.Evaluate(p, log_A, 4) / x;
            }

            return(q);
        }
Beispiel #2
0
        /// <summary>
        ///    Normal (Gaussian) inverse cumulative distribution function.
        /// </summary>
        ///
        /// <remarks>
        /// <para>
        ///    For small arguments <c>0 &lt; y &lt; exp(-2)</c>, the program computes <c>z =
        ///    sqrt( -2.0 * log(y) )</c>;  then the approximation is <c>x = z - log(z)/z  -
        ///    (1/z) P(1/z) / Q(1/z)</c>.</para>
        /// <para>
        ///    There are two rational functions P/Q, one for <c>0 &lt; y &lt; exp(-32)</c> and
        ///    the other for <c>y</c> up to <c>exp(-2)</c>. For larger arguments, <c>w = y - 0.5</c>,
        ///    and  <c>x/sqrt(2pi) = w + w^3 * R(w^2)/S(w^2))</c>.</para>
        /// </remarks>
        ///
        /// <returns>
        ///    Returns the value, <c>x</c>, for which the area under the Normal (Gaussian)
        ///    probability density function (integrated from minus infinity to <c>x</c>) is
        ///    equal to the argument <c>y</c> (assumes mean is zero, variance is one).
        /// </returns>
        ///
        public static double Inverse(double y0)
        {
            if (y0 <= 0.0)
            {
                if (y0 == 0)
                {
                    return(Double.NegativeInfinity);
                }
                throw new ArgumentOutOfRangeException("y0");
            }

            if (y0 >= 1.0)
            {
                if (y0 == 1)
                {
                    return(Double.PositiveInfinity);
                }
                throw new ArgumentOutOfRangeException("y0");
            }


            double s2pi = Math.Sqrt(2.0 * Math.PI);
            int    code = 1;
            double y    = y0;
            double x;



            if (y > 0.8646647167633873)
            {
                y    = 1.0 - y;
                code = 0;
            }

            if (y > 0.1353352832366127)
            {
                y -= 0.5;
                double y2 = y * y;
                x  = y + y * ((y2 * Polynomial.Evaluate(y2, inverse_P0, 4)) / Polynomial.EvaluateSpecial(y2, inverse_Q0, 8));
                x *= s2pi;
                return(x);
            }

            x = Math.Sqrt(-2.0 * Math.Log(y));
            double x0 = x - Math.Log(x) / x;
            double z  = 1.0 / x;
            double x1;

            if (x < 8.0)
            {
                x1 = (z * Polynomial.Evaluate(z, inverse_P1, 8)) / Polynomial.EvaluateSpecial(z, inverse_Q1, 8);
            }
            else
            {
                x1 = (z * Polynomial.Evaluate(z, inverse_P2, 8)) / Polynomial.EvaluateSpecial(z, inverse_Q2, 8);
            }

            x = x0 - x1;

            if (code != 0)
            {
                x = -x;
            }

            return(x);
        }