Ejemplo n.º 1
0
        private static void Gamma_Temme(double a, double x, out double P, out double Q)
        {
            double u = Math.Log(x / a);

            // compute argument of error function, which is almost (x-a)/sqrt(a)

            double dz = 1.0;
            double z  = dz;

            for (int i = 3; true; i++)
            {
                if (i > Global.SeriesMax)
                {
                    throw new NonconvergenceException();
                }
                double z_old = z;
                dz *= u / i;
                z  += dz;
                if (z == z_old)
                {
                    break;
                }
            }
            z = u * Math.Sqrt(a * z / 2.0);

            // the first approximation is just the almost-Gaussian one

            if (z > 0)
            {
                Q = AdvancedMath.Erfc(z) / 2.0;
                P = 1.0 - Q;
            }
            else
            {
                P = AdvancedMath.Erfc(-z) / 2.0;
                Q = 1.0 - P;
            }

            // compute Temme's correction to the Gaussian approximation

            double R0 = Math.Exp(-z * z) / Math.Sqrt(Global.TwoPI * a);

            double S0 = 0.0;
            double ai = 1.0;

            for (int i = 0; i < TemmeD.Length; i++)
            {
                double dS = 0.0;
                double uj = 1.0;
                for (int j = 0; j < TemmeD[i].Length; j++)
                {
                    dS += TemmeD[i][j] * uj;
                    uj *= u;
                }
                S0 += dS / ai;
                ai *= a;
            }

            double R = R0 * S0;

            Q = Q + R;
            P = P - R;
        }