Polevl() public static method

Evaluates polynomial of degree N
public static Polevl ( double x, double coef, int n ) : double
x double
coef double
n int
return double
示例#1
0
        /// <summary>
        ///   Gamma function as computed by Stirling's formula.
        /// </summary>
        ///
        public static double Stirling(double x)
        {
            double[] STIR =
            {
                7.87311395793093628397E-4,
                -2.29549961613378126380E-4,
                -2.68132617805781232825E-3,
                3.47222221605458667310E-3,
                8.33333333333482257126E-2,
            };

            double MAXSTIR = 143.01608;

            double w = 1.0 / x;
            double y = Math.Exp(x);

            w = 1.0 + w * Special.Polevl(w, STIR, 4);

            if (x > MAXSTIR)
            {
                double v = Math.Pow(x, 0.5 * x - 0.25);
                y = v * (v / y);
            }
            else
            {
                y = System.Math.Pow(x, x - 0.5) / y;
            }

            y = Constants.Sqrt2PI * y * w;
            return(y);
        }
示例#2
0
        /// <summary>
        ///   Gamma function as computed by Stirling's formula.
        /// </summary>
        ///
        public static double Stirling(double x)
        {
            double MAXSTIR = 143.01608;

            double w = 1.0 / x;
            double y = Math.Exp(x);

            w = 1.0 + w * Special.Polevl(w, STIR, 4);

            if (x > MAXSTIR)
            {
                double v = Math.Pow(x, 0.5 * x - 0.25);

                if (Double.IsPositiveInfinity(v) && Double.IsPositiveInfinity(y))
                {
                    // lim x -> inf { (x^(0.5*x - 0.25)) * (x^(0.5*x - 0.25) / exp(x))  }
                    y = Double.PositiveInfinity;
                }
                else
                {
                    y = v * (v / y);
                }
            }
            else
            {
                y = System.Math.Pow(x, x - 0.5) / y;
            }

            y = Constants.Sqrt2PI * y * w;
            return(y);
        }
示例#3
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;

            double[] P0 =
            {
                -59.963350101410789,
                98.001075418599967,
                -56.676285746907027,
                13.931260938727968,
                -1.2391658386738125
            };

            double[] Q0 =
            {
                1.9544885833814176,
                4.6762791289888153,
                86.360242139089053,
                -225.46268785411937,
                200.26021238006066,
                -82.037225616833339,
                15.90562251262117,
                -1.1833162112133
            };

            double[] P1 =
            {
                4.0554489230596245,
                31.525109459989388,
                57.162819224642128,
                44.080507389320083,
                14.684956192885803,
                2.1866330685079025,
                -0.14025607917135449,
                -0.035042462682784818,
                -0.00085745678515468545
            };

            double[] Q1 =
            {
                15.779988325646675,
                45.390763512887922,
                41.317203825467203,
                15.04253856929075,
                2.5046494620830941,
                -0.14218292285478779,
                -0.038080640769157827,
                -0.00093325948089545744
            };

            double[] P2 =
            {
                3.2377489177694603,
                6.9152288906898418,
                3.9388102529247444,
                1.3330346081580755,
                0.20148538954917908,
                0.012371663481782003,
                0.00030158155350823543,
                2.6580697468673755E-06,
                6.2397453918498331E-09
            };

            double[] Q2 =
            {
                6.02427039364742,
                3.6798356385616087,
                1.3770209948908132,
                0.21623699359449663,
                0.013420400608854318,
                0.00032801446468212774,
                2.8924786474538068E-06,
                6.7901940800998127E-09
            };

            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 * Special.Polevl(y2, P0, 4)) / Special.P1evl(y2, 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 * Special.Polevl(z, P1, 8)) / Special.P1evl(z, Q1, 8);
            }
            else
            {
                x1 = (z * Special.Polevl(z, P2, 8)) / Special.P1evl(z, Q2, 8);
            }

            x = x0 - x1;

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

            return(x);
        }
示例#4
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;

            double[] A =
            {
                8.11614167470508450300E-4,
                -5.95061904284301438324E-4,
                7.93650340457716943945E-4,
                -2.77777777730099687205E-3,
                8.33333333333331927722E-2
            };

            double[] B =
            {
                -1.37825152569120859100E3,
                -3.88016315134637840924E4,
                -3.31612992738871184744E5,
                -1.16237097492762307383E6,
                -1.72173700820839662146E6,
                -8.53555664245765465627E5
            };

            double[] C =
            {
                -3.51815701436523470549E2,
                -1.70642106651881159223E4,
                -2.20528590553854454839E5,
                -1.13933444367982507207E6,
                -2.53252307177582951285E6,
                -2.01889141433532773231E6
            };

            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 * Special.Polevl(x, B, 5) / Special.P1evl(x, 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 += Special.Polevl(p, A, 4) / x;
            }

            return(q);
        }
示例#5
0
        public const double GammaMax = 171.624376956302725; // TODO: Rename to Max

        /// <summary>
        ///   Gamma function of the specified value.
        /// </summary>
        ///
        public static double Function(double x)
        {
            double[] P =
            {
                1.60119522476751861407E-4,
                1.19135147006586384913E-3,
                1.04213797561761569935E-2,
                4.76367800457137231464E-2,
                2.07448227648435975150E-1,
                4.94214826801497100753E-1,
                9.99999999999999996796E-1
            };

            double[] Q =
            {
                -2.31581873324120129819E-5,
                5.39605580493303397842E-4,
                -4.45641913851797240494E-3,
                1.18139785222060435552E-2,
                3.58236398605498653373E-2,
                -2.34591795718243348568E-1,
                7.14304917030273074085E-2,
                1.00000000000000000320E0
            };

            double p, z;

            double q = System.Math.Abs(x);

            if (q > 33.0)
            {
                if (x < 0.0)
                {
                    p = System.Math.Floor(q);

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

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

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

                    z = System.Math.Abs(z);
                    z = System.Math.PI / (z * Stirling(q));

                    return(-z);
                }
                else
                {
                    return(Stirling(x));
                }
            }

            z = 1.0;
            while (x >= 3.0)
            {
                x -= 1.0;
                z *= x;
            }

            while (x < 0.0)
            {
                if (x == 0.0)
                {
                    throw new ArithmeticException();
                }
                else if (x > -1.0E-9)
                {
                    return(z / ((1.0 + 0.5772156649015329 * x) * x));
                }
                z /= x;
                x += 1.0;
            }

            while (x < 2.0)
            {
                if (x == 0.0)
                {
                    throw new ArithmeticException();
                }
                else if (x < 1.0E-9)
                {
                    return(z / ((1.0 + 0.5772156649015329 * x) * x));
                }

                z /= x;
                x += 1.0;
            }

            if ((x == 2.0) || (x == 3.0))
            {
                return(z);
            }

            x -= 2.0;
            p  = Special.Polevl(x, P, 6);
            q  = Special.Polevl(x, Q, 7);
            return(z * p / q);
        }
示例#6
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 * Special.Polevl(x, log_B, 5) / Special.P1evl(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 += Special.Polevl(p, log_A, 4) / x;
            }

            return(q);
        }
示例#7
0
        /// <summary>
        ///   Gamma function of the specified value.
        /// </summary>
        ///
        public static double Function(double x)
        {
            double p, z;

            double q = System.Math.Abs(x);

            if (q > 33.0)
            {
                if (x < 0.0)
                {
                    p = System.Math.Floor(q);

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

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

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

                    z = System.Math.Abs(z);
                    z = System.Math.PI / (z * Stirling(q));

                    return(-z);
                }
                else
                {
                    return(Stirling(x));
                }
            }

            z = 1.0;
            while (x >= 3.0)
            {
                x -= 1.0;
                z *= x;
            }

            while (x < 0.0)
            {
                if (x == 0.0)
                {
                    throw new ArithmeticException();
                }
                else if (x > -1.0E-9)
                {
                    return(z / ((1.0 + 0.5772156649015329 * x) * x));
                }
                z /= x;
                x += 1.0;
            }

            while (x < 2.0)
            {
                if (x == 0.0)
                {
                    throw new ArithmeticException();
                }
                else if (x < 1.0E-9)
                {
                    return(z / ((1.0 + 0.5772156649015329 * x) * x));
                }

                z /= x;
                x += 1.0;
            }

            if ((x == 2.0) || (x == 3.0))
            {
                return(z);
            }

            x -= 2.0;
            p  = Special.Polevl(x, gamma_P, 6);
            q  = Special.Polevl(x, gamma_Q, 7);
            return(z * p / q);
        }
示例#8
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 * Special.Polevl(y2, inverse_P0, 4)) / Special.P1evl(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 * Special.Polevl(z, inverse_P1, 8)) / Special.P1evl(z, inverse_Q1, 8);
            }
            else
            {
                x1 = (z * Special.Polevl(z, inverse_P2, 8)) / Special.P1evl(z, inverse_Q2, 8);
            }

            x = x0 - x1;

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

            return(x);
        }