コード例 #1
0
ファイル: PZMath_errno.cs プロジェクト: Josep1984/pzmath
 public static void CheckUnderFlow(SpecialFunctionResult r)
 {
     if (System.Math.Abs(r.Val) < PZMath_machine.PZMath_DBL_MIN)
     {
         string error = "underflow" + PZMath_errno.PZMath_EUNDRFLW;
         throw new ApplicationException(error);
     }
 }
コード例 #2
0
ファイル: Elementary.cs プロジェクト: Josep1984/pzmath
        public static int MultiplyE(double x, double y, ref SpecialFunctionResult result)
        {
            double ax = System.Math.Abs(x);
            double ay = System.Math.Abs(y);

            if (x == 0.0 || y == 0.0)
            {
                /* It is necessary to eliminate this immediately.
                 */
                result.Val = 0.0;
                result.Err = 0.0;
                return PZMath_errno.PZMath_SUCCESS;
            }
            else if ((ax <= 1.0 && ay >= 1.0) || (ay <= 1.0 && ax >= 1.0))
            {
                /* Straddling 1.0 is always safe.
                 */
                result.Val = x * y;
                result.Err = 2.0 * PZMath_machine.PZMath_DBL_EPSILON * System.Math.Abs(result.Val);
                return PZMath_errno.PZMath_SUCCESS;
            }
            else
            {
                double f = 1.0 - 2.0 * PZMath_machine.PZMath_DBL_EPSILON;
                double min = System.Math.Min(System.Math.Abs(x), System.Math.Abs(y));
                double max = System.Math.Max(System.Math.Abs(x), System.Math.Abs(y));
                if (max < 0.9 * PZMath_machine.PZMath_SQRT_DBL_MAX || min < (f * PZMath_machine.PZMath_DBL_MAX) / max)
                {
                    result.Val = x * y;
                    result.Err = 2.0 * PZMath_machine.PZMath_DBL_EPSILON * System.Math.Abs(result.Val);
                    PZMath_errno.CheckUnderFlow(result);
                    return PZMath_errno.PZMath_SUCCESS;
                }
                else
                {
                    PZMath_errno.OverFlowError(ref result);
                }

            }
            return PZMath_errno.PZMath_SUCCESS;
        }
コード例 #3
0
ファイル: Gamma.cs プロジェクト: Josep1984/pzmath
 /*-*-*-*-*-*-*-*-*-*-*-* Functions with Error Codes *-*-*-*-*-*-*-*-*-*-*-*/
 public static int LnGammaE(double x, ref SpecialFunctionResult result)
 {
     if (System.Math.Abs(x - 1.0) < 0.01)
     {
         /* Note that we must amplify the errors
          * from the Pade evaluations because of
          * the way we must pass the argument, i.e.
          * writing (1-x) is a loss of precision
          * when x is near 1.
          */
         int stat = LnGamma1Pade(x - 1.0, ref result);
         result.Err *= 1.0 / (PZMath_machine.PZMath_DBL_EPSILON + System.Math.Abs(x - 1.0));
         return stat;
     }
     else if (System.Math.Abs(x - 2.0) < 0.01)
     {
         int stat = LnGamma2Pade(x - 2.0, ref result);
         result.Err *= 1.0 / (PZMath_machine.PZMath_DBL_EPSILON + System.Math.Abs(x - 2.0));
         return stat;
     }
     else if (x >= 0.5)
     {
         return LnGammaLanczos(x, ref result);
     }
     else if (x == 0.0)
     {
         PZMath_errno.DomainError(ref result);
     }
     else if (System.Math.Abs(x) < 0.02)
     {
         double sgn = 0.0;
         return LnGammaSgn0(x, ref result, ref sgn);
     }
     else if (x > -0.5 / (PZMath_machine.PZMath_DBL_EPSILON * PZMath.M_PI))
     {
         /* Try to extract a fractional
          * part from x.
          */
         double z = 1.0 - x;
         double s = System.Math.Sin(PZMath.M_PI * z);
         double abss = System.Math.Abs(s);
         if (s == 0.0)
         {
             PZMath_errno.DomainError(ref result);
         }
         else if (abss < PZMath.M_PI * 0.015)
         {
             /* x is near a negative integer, -N */
             if (x < int.MinValue + 2.0)
             {
                 result.Val = 0.0;
                 result.Err = 0.0;
                 PZMath_errno.ERROR("error", PZMath_errno.PZMath_EROUND);
             }
             else
             {
                 int N = -(int)(x - 0.5);
                 double eps = x + N;
                 double sgn = 0.0;
                 return LnGammaSgnSing(N, eps, ref result, ref sgn);
             }
         }
         else
         {
             SpecialFunctionResult lg_z = new SpecialFunctionResult();
             LnGammaLanczos(z, ref lg_z);
             result.Val = PZMath.M_LNPI - (System.Math.Log(abss) + lg_z.Val);
             result.Err = 2.0 * PZMath_machine.PZMath_DBL_EPSILON * System.Math.Abs(result.Val) + lg_z.Err;
             return PZMath_errno.PZMath_SUCCESS;
         }
     }
     else
     {
         /* |x| was too large to extract any fractional part */
         result.Val = 0.0;
         result.Err = 0.0;
         PZMath_errno.ERROR("error", PZMath_errno.PZMath_EROUND);
     }
     return PZMath_errno.PZMath_SUCCESS;
 }
コード例 #4
0
ファイル: Zeta.cs プロジェクト: Josep1984/pzmath
        public static int HZetaE(double s, double q, ref SpecialFunctionResult result)
        {
            if (s <= 1.0 || q <= 0.0)
            {
                PZMath_errno.DomainError(ref result);
            }
            else
            {
                double max_bits = 54.0;
                double ln_term0 = -s * System.Math.Log(q);

                if (ln_term0 < PZMath_machine.PZMath_LOG_DBL_MIN + 1.0)
                {
                    PZMath_errno.UnderFlowError(ref result);
                }
                else if (ln_term0 > PZMath_machine.PZMath_LOG_DBL_MAX - 1.0)
                {
                    PZMath_errno.OverFlowError(ref result);
                }
                else if ((s > max_bits && q < 1.0) || (s > 0.5 * max_bits && q < 0.25))
                {
                    result.Val = System.Math.Pow(q, -s);
                    result.Err = 2.0 * PZMath_machine.PZMath_DBL_EPSILON * System.Math.Abs(result.Val);
                    return PZMath_errno.PZMath_SUCCESS;
                }
                else if (s > 0.5 * max_bits && q < 1.0)
                {
                    double p1 = System.Math.Pow(q, -s);
                    double p2 = System.Math.Pow(q / (1.0 + q), s);
                    double p3 = System.Math.Pow(q / (2.0 + q), s);
                    result.Val = p1 * (1.0 + p2 + p3);
                    result.Err = PZMath_machine.PZMath_DBL_EPSILON * (0.5 * s + 2.0) * System.Math.Abs(result.Val);
                    return PZMath_errno.PZMath_SUCCESS;
                }
                else
                {
                    /* Euler-Maclaurin summation formula
                     * [Moshier, p. 400, with several typo corrections]
                     */
                    int jmax = 12;
                    int kmax = 10;
                    int j, k;
                    double pmax = System.Math.Pow(kmax + q, -s);
                    double scp = s;
                    double pcp = pmax / (kmax + q);
                    double ans = pmax * ((kmax + q) / (s - 1.0) + 0.5);

                    for (k = 0; k < kmax; k++)
                    {
                        ans += System.Math.Pow(k + q, -s);
                    }

                    for (j = 0; j <= jmax; j++)
                    {
                        double delta = hzeta_c[j + 1] * scp * pcp;
                        ans += delta;
                        if (System.Math.Abs(delta / ans) < 0.5 * PZMath_machine.PZMath_DBL_EPSILON)
                            break;
                        scp *= (s + 2 * j + 1) * (s + 2 * j + 2);
                        pcp /= (kmax + q) * (kmax + q);
                    }

                    result.Val = ans;
                    result.Err = 2.0 * (jmax + 1.0) * PZMath_machine.PZMath_DBL_EPSILON * System.Math.Abs(ans);
                    return PZMath_errno.PZMath_SUCCESS;
                }
            }

            return PZMath_errno.PZMath_SUCCESS;
        }
コード例 #5
0
ファイル: Gamma.cs プロジェクト: Josep1984/pzmath
 public static int LnGamma2Pade(double eps, ref SpecialFunctionResult result)
 {
     /* Use (2,2) Pade for Log[Gamma[2+eps]]/eps
      * plus a correction series.
      */
     double n1 = 1.000895834786669227164446568;
     double n2 = 4.209376735287755081642901277;
     double d1 = 2.618851904903217274682578255;
     double d2 = 10.85766559900983515322922936;
     double num = (eps + n1) * (eps + n2);
     double den = (eps + d1) * (eps + d2);
     double pade = 2.85337998765781918463568869 * num / den;
     double c0 = 0.0001139406357036744;
     double c1 = -0.0001365435269792533;
     double c2 = 0.0001067287169183665;
     double c3 = -0.0000693271800931282;
     double c4 = 0.0000407220927867950;
     double eps5 = eps * eps * eps * eps * eps;
     double corr = eps5 * (c0 + eps * (c1 + eps * (c2 + eps * (c3 + c4 * eps))));
     result.Val = eps * (pade + corr);
     result.Err = 2.0 * PZMath_machine.PZMath_DBL_EPSILON * System.Math.Abs(result.Val);
     return PZMath_errno.PZMath_SUCCESS;
 }
コード例 #6
0
ファイル: Gamma.cs プロジェクト: Josep1984/pzmath
 public static int GammaInvE(double x, ref SpecialFunctionResult result)
 {
     if (x <= 0.0 && x == System.Math.Floor(x))
     { /* negative integer */
         result.Val = 0.0;
         result.Err = 0.0;
         return PZMath_errno.PZMath_SUCCESS;
     }
     else if (x < 0.5)
     {
         SpecialFunctionResult lng = new SpecialFunctionResult();
         double sgn = 0.0;
         int stat_lng = LnGammaSgnE(x, ref lng, ref sgn);
         if (stat_lng == PZMath_errno.PZMath_EDOM)
         {
             result.Val = 0.0;
             result.Err = 0.0;
             return PZMath_errno.PZMath_SUCCESS;
         }
         else if (stat_lng != PZMath_errno.PZMath_SUCCESS)
         {
             result.Val = 0.0;
             result.Err = 0.0;
             return stat_lng;
         }
         else
         {
             return Exp.ExpMultErrE(-lng.Val, lng.Err, sgn, 0.0, ref result);
         }
     }
     else
     {
         SpecialFunctionResult g = new SpecialFunctionResult();
         int stat_g = GammaXGTHalf(x, ref g);
         if (stat_g == PZMath_errno.PZMath_EOVRFLW)
         {
             PZMath_errno.UnderFlowError(ref result);
         }
         else
         {
             result.Val = 1.0 / g.Val;
             result.Err = System.Math.Abs(g.Err / g.Val) * System.Math.Abs(result.Val);
             result.Err += 2.0 * PZMath_machine.PZMath_DBL_EPSILON * System.Math.Abs(result.Val);
             PZMath_errno.CheckUnderFlow(result);
             return PZMath_errno.PZMath_SUCCESS;
         }
     }
     return PZMath_errno.PZMath_SUCCESS;
 }
コード例 #7
0
ファイル: Gamma.cs プロジェクト: Josep1984/pzmath
 /* series for gammastar(x)
  * double-precision for x > 10.0
  */
 public static int GammaStarSer(double x, ref SpecialFunctionResult result)
 {
     /* Use the Stirling series for the correction to Log(Gamma(x)),
      * which is better behaved and easier to compute than the
      * regular Stirling series for Gamma(x).
      */
     double y = 1.0 / (x * x);
     double c0 = 1.0 / 12.0;
     double c1 = -1.0 / 360.0;
     double c2 = 1.0 / 1260.0;
     double c3 = -1.0 / 1680.0;
     double c4 = 1.0 / 1188.0;
     double c5 = -691.0 / 360360.0;
     double c6 = 1.0 / 156.0;
     double c7 = -3617.0 / 122400.0;
     double ser = c0 + y * (c1 + y * (c2 + y * (c3 + y * (c4 + y * (c5 + y * (c6 + y * c7))))));
     result.Val = System.Math.Exp(ser / x);
     result.Err = 2.0 * PZMath_machine.PZMath_DBL_EPSILON * result.Val * System.Math.Max(1.0, ser / x);
     return PZMath_errno.PZMath_SUCCESS;
 }
コード例 #8
0
ファイル: Gamma.cs プロジェクト: Josep1984/pzmath
        public static int TaylorCoeffE(int n, double x, ref SpecialFunctionResult result)
        {
            if (x < 0.0 || n < 0)
            {
                PZMath_errno.DomainError(ref result);
            }
            else if (n == 0)
            {
                result.Val = 1.0;
                result.Err = 0.0;
                return PZMath_errno.PZMath_SUCCESS;
            }
            else if (n == 1)
            {
                result.Val = x;
                result.Err = 0.0;
                return PZMath_errno.PZMath_SUCCESS;
            }
            else if (x == 0.0)
            {
                result.Val = 0.0;
                result.Err = 0.0;
                return PZMath_errno.PZMath_SUCCESS;
            }
            else
            {
                double log2pi = PZMath.M_LNPI + PZMath.M_LN2;
                double ln_test = n * (System.Math.Log(x) + 1.0) + 1.0 - (n + 0.5) * System.Math.Log(n + 1.0) + 0.5 * log2pi;

                if (ln_test < PZMath_machine.PZMath_LOG_DBL_MIN + 1.0)
                {
                    PZMath_errno.UnderFlowError(ref result);
                }
                else if (ln_test > PZMath_machine.PZMath_LOG_DBL_MAX - 1.0)
                {
                    PZMath_errno.OverFlowError(ref result);
                }
                else
                {
                    double product = 1.0;
                    int k;
                    for (k = 1; k <= n; k++)
                    {
                        product *= (x / k);
                    }
                    result.Val = product;
                    result.Err = n * PZMath_machine.PZMath_DBL_EPSILON * product;
                    PZMath_errno.CheckUnderFlow(result);
                    return PZMath_errno.PZMath_SUCCESS;
                }
            }
            return PZMath_errno.PZMath_SUCCESS;
        }
コード例 #9
0
ファイル: Gamma.cs プロジェクト: Josep1984/pzmath
 public static int FactE(int n, ref SpecialFunctionResult result)
 {
     if (n < 18)
     {
         result.Val = fact_table[n]._f;
         result.Err = 0.0;
         return PZMath_errno.PZMath_SUCCESS;
     }
     else if (n <= GSL_SF_FACT_NMAX)
     {
         result.Val = fact_table[n]._f;
         result.Err = 2.0 * PZMath_machine.PZMath_DBL_EPSILON * System.Math.Abs(result.Val);
         return PZMath_errno.PZMath_SUCCESS;
     }
     else
     {
         PZMath_errno.OverFlowError(ref result);
     }
     return PZMath_errno.PZMath_SUCCESS;
 }
コード例 #10
0
ファイル: Gamma.cs プロジェクト: Josep1984/pzmath
        /* Lanczos method for real x > 0;
         * gamma=7, truncated at 1/(z+8)
         * [J. SIAM Numer. Anal, Ser. B, 1 (1964) 86]
         */
        public static int LnGammaLanczos(double x, ref SpecialFunctionResult result)
        {
            int k;
            double Ag;
            double term1, term2;

            x -= 1.0; /* Lanczos writes z! instead of Gamma(z) */

            Ag = lanczos_7_c[0];
            for (k = 1; k <= 8; k++) { Ag += lanczos_7_c[k] / (x + k); }

            /* (x+0.5)*System.Math.Log(x+7.5) - (x+7.5) + LogRootTwoPi_ + System.Math.Log(Ag(x)) */
            term1 = (x + 0.5) * System.Math.Log((x + 7.5) / PZMath.M_E);
            term2 = LogRootTwoPi_ + System.Math.Log(Ag);
            result.Val = term1 + (term2 - 7.0);
            result.Err = 2.0 * PZMath_machine.PZMath_DBL_EPSILON * (System.Math.Abs(term1) + System.Math.Abs(term2) + 7.0);
            result.Err += PZMath_machine.PZMath_DBL_EPSILON * System.Math.Abs(result.Val);

            return PZMath_errno.PZMath_SUCCESS;
        }
コード例 #11
0
ファイル: Gamma.cs プロジェクト: Josep1984/pzmath
        public static int LnGammaSgnE(double x, ref SpecialFunctionResult result_lg, ref double sgn)
        {
            if (System.Math.Abs(x - 1.0) < 0.01)
            {
                int stat = LnGamma1Pade(x - 1.0, ref result_lg);
                result_lg.Err *= 1.0 / (PZMath_machine.PZMath_DBL_EPSILON + System.Math.Abs(x - 1.0));
                sgn = 1.0;
                return stat;
            }
            else if (System.Math.Abs(x - 2.0) < 0.01)
            {
                int stat = LnGamma2Pade(x - 2.0, ref result_lg);
                result_lg.Err *= 1.0 / (PZMath_machine.PZMath_DBL_EPSILON + System.Math.Abs(x - 2.0));
                sgn = 1.0;
                return stat;
            }
            else if (x >= 0.5)
            {
                sgn = 1.0;
                return LnGammaLanczos(x, ref result_lg);
            }
            else if (x == 0.0)
            {
                sgn = 0.0;

                PZMath_errno.DomainError(ref result_lg);
            }
            else if (System.Math.Abs(x) < 0.02)
            {
                return LnGammaSgn0(x, ref result_lg, ref sgn);
            }
            else if (x > -0.5 / (PZMath_machine.PZMath_DBL_EPSILON * PZMath.M_PI))
            {
                /* Try to extract a fractional
                  * part from x.
                  */
                double z = 1.0 - x;
                double s = System.Math.Sin(PZMath.M_PI * x);
                double abss = System.Math.Abs(s);
                if (s == 0.0)
                {
                    sgn = 0.0;
                    PZMath_errno.DomainError(ref result_lg);
                }
                else if (abss < PZMath.M_PI * 0.015)
                {
                    /* x is near a negative integer, -N */
                    if (x < int.MinValue + 2.0)
                    {
                        result_lg.Val = 0.0;
                        result_lg.Err = 0.0;
                        sgn = 0.0;
                        PZMath_errno.ERROR("error", PZMath_errno.PZMath_EROUND);
                    }
                    else
                    {
                        int N = -(int)(x - 0.5);
                        double eps = x + N;
                        return LnGammaSgnSing(N, eps, ref result_lg, ref sgn);
                    }
                }
                else
                {
                    SpecialFunctionResult lg_z = new SpecialFunctionResult();
                    LnGammaLanczos(z, ref lg_z);
                    sgn = (s > 0.0 ? 1.0 : -1.0);
                    result_lg.Val = PZMath.M_LNPI - (System.Math.Log(abss) + lg_z.Val);
                    result_lg.Err = 2.0 * PZMath_machine.PZMath_DBL_EPSILON * System.Math.Abs(result_lg.Val) + lg_z.Err;
                    return PZMath_errno.PZMath_SUCCESS;
                }
            }
            else
            {
                /* |x| was too large to extract any fractional part */
                result_lg.Val = 0.0;
                result_lg.Err = 0.0;
                sgn = 0.0;
                PZMath_errno.ERROR("error", PZMath_errno.PZMath_EROUND);
            }
            return PZMath_errno.PZMath_SUCCESS;
        }
コード例 #12
0
ファイル: Zeta.cs プロジェクト: Josep1984/pzmath
 public static int Zetam1E(double s, ref SpecialFunctionResult result)
 {
     if (s <= 5.0)
     {
         int stat = ZetaE(s, ref result);
         result.Val = result.Val - 1.0;
         return stat;
     }
     else if (s < 15.0)
     {
         return RiemannZetaMinus1IntermediateS(s, ref result);
     }
     else
     {
         return RiemannZetaMinus1LargeS(s, ref result);
     }
 }
コード例 #13
0
ファイル: Zeta.cs プロジェクト: Josep1984/pzmath
 public static int Zetam1IntE(int n, ref SpecialFunctionResult result)
 {
     if (n < 0)
     {
         if (!PZMath.IsOdd(n))
         {
             result.Val = -1.0; /* at even negative integers zetam1 == -1 since zeta is exactly zero */
             result.Err = 0.0;
             return PZMath_errno.PZMath_SUCCESS;
         }
         else if (n > -ZETA_NEG_TABLE_NMAX)
         {
             result.Val = zeta_neg_int_table[-(n + 1) / 2] - 1.0;
             result.Err = 2.0 * PZMath_machine.PZMath_DBL_EPSILON * System.Math.Abs(result.Val);
             return PZMath_errno.PZMath_SUCCESS;
         }
         else
         {
             /* could use gsl_sf_zetam1_e here but subtracting 1 makes no difference
                for such large values, so go straight to the result */
             return ZetaE((double)n, ref result);
         }
     }
     else if (n == 1)
     {
         PZMath_errno.DomainError(ref result);
     }
     else if (n <= ZETA_POS_TABLE_NMAX)
     {
         result.Val = zetam1_pos_int_table[n];
         result.Err = 2.0 * PZMath_machine.PZMath_DBL_EPSILON * System.Math.Abs(result.Val);
         return PZMath_errno.PZMath_SUCCESS;
     }
     else
     {
         return Zetam1E(n, ref result);
     }
     return PZMath_errno.PZMath_SUCCESS;
 }
コード例 #14
0
ファイル: Zeta.cs プロジェクト: Josep1984/pzmath
        public static int ZetaIntE(int n, ref SpecialFunctionResult result)
        {
            if (n < 0)
            {
                if (!PZMath.IsOdd(n))
                {
                    result.Val = 0.0; /* exactly zero at even negative integers */
                    result.Err = 0.0;
                    return PZMath_errno.PZMath_SUCCESS;
                }
                else if (n > -ZETA_NEG_TABLE_NMAX)
                {
                    result.Val = zeta_neg_int_table[-(n + 1) / 2];
                    result.Err = 2.0 * PZMath_machine.PZMath_DBL_EPSILON * System.Math.Abs(result.Val);
                    return PZMath_errno.PZMath_SUCCESS;
                }
                else
                {
                    return ZetaE((double)n, ref result);
                }
            }
            else if (n == 1)
            {
                PZMath_errno.DomainError(ref result);
            }
            else if (n <= ZETA_POS_TABLE_NMAX)
            {
                result.Val = 1.0 + zetam1_pos_int_table[n];
                result.Err = 2.0 * PZMath_machine.PZMath_DBL_EPSILON * System.Math.Abs(result.Val);
                return PZMath_errno.PZMath_SUCCESS;
            }
            else
            {
                result.Val = 1.0;
                result.Err = PZMath_machine.PZMath_DBL_EPSILON;
                return PZMath_errno.PZMath_SUCCESS;
            }

            return PZMath_errno.PZMath_SUCCESS;
        }
コード例 #15
0
ファイル: Zeta.cs プロジェクト: Josep1984/pzmath
        public static int ZetaE(double s, ref SpecialFunctionResult result)
        {
            if (s == 1.0)
            {
                PZMath_errno.DomainError(ref result);
            }
            else if (s >= 0.0)
            {
                return RiemannZetaSgt0(s, ref result);
            }
            else
            {
                /* reflection formula, [Abramowitz+Stegun, 23.2.5] */

                SpecialFunctionResult zeta_one_minus_s = new SpecialFunctionResult();
                int stat_zoms = RiemannZeta1msSlt0(s, ref zeta_one_minus_s);
                double sin_term = (System.Math.IEEERemainder(s, 2.0) == 0.0) ? 0.0 : System.Math.Sin(0.5 * PZMath.M_PI * System.Math.IEEERemainder(s, 4.0)) / PZMath.M_PI;

                if (sin_term == 0.0)
                {
                    result.Val = 0.0;
                    result.Err = 0.0;
                    return PZMath_errno.PZMath_SUCCESS;
                }
                else if (s > -170)
                {
                    /* We have to be careful about losing digits
                     * in calculating System.Math.Pow(2 Pi, s). The gamma
                     * function is fine because we were careful
                     * with that implementation.
                     * We keep an array of (2 Pi)^(10 n).
                     */
                    double[] twopi_pow = { 1.0,
                                     9.589560061550901348e+007,
                                     9.195966217409212684e+015,
                                     8.818527036583869903e+023,
                                     8.456579467173150313e+031,
                                     8.109487671573504384e+039,
                                     7.776641909496069036e+047,
                                     7.457457466828644277e+055,
                                     7.151373628461452286e+063,
                                     6.857852693272229709e+071,
                                     6.576379029540265771e+079,
                                     6.306458169130020789e+087,
                                     6.047615938853066678e+095,
                                     5.799397627482402614e+103,
                                     5.561367186955830005e+111,
                                     5.333106466365131227e+119,
                                     5.114214477385391780e+127,
                                     4.904306689854036836e+135
                                    };
                    int n = (int)System.Math.Floor((-s) / 10.0);
                    double fs = s + 10.0 * n;
                    double p = System.Math.Pow(2.0 * PZMath.M_PI, fs) / twopi_pow[n];

                    SpecialFunctionResult g = new SpecialFunctionResult();
                    int stat_g = Gamma.GammaE(1.0 - s, ref g);
                    result.Val = p * g.Val * sin_term * zeta_one_minus_s.Val;
                    result.Err = System.Math.Abs(p * g.Val * sin_term) * zeta_one_minus_s.Err;
                    result.Err += System.Math.Abs(p * sin_term * zeta_one_minus_s.Val) * g.Err;
                    result.Err += PZMath_machine.PZMath_DBL_EPSILON * (System.Math.Abs(s) + 2.0) * System.Math.Abs(result.Val);
                    return PZMath_errno.ErrorSelect2(stat_g, stat_zoms);
                }
                else
                {
                    /* The actual zeta function may or may not
                     * overflow here. But we have no easy way
                     * to calculate it when the prefactor(s)
                     * overflow. Trying to use System.Math.Log's and exp
                     * is no good because we loose a couple
                     * digits to the exp error amplification.
                     * When we gather a little more patience,
                     * we can implement something here. Until
                     * then just give up.
                     */
                    PZMath_errno.OverFlowError(ref result);
                }
            }
            return PZMath_errno.PZMath_SUCCESS;
        }
コード例 #16
0
ファイル: Zeta.cs プロジェクト: Josep1984/pzmath
 /* assumes s >= 0 and s != 1.0 */
 public static int RiemannZetaSgt0(double s, ref SpecialFunctionResult result)
 {
     if (s < 1.0)
     {
         SpecialFunctionResult c = new SpecialFunctionResult();
         ChebyshevSeries.ChebEvalE(zeta_xlt1_cs, 2.0 * s - 1.0, ref c);
         result.Val = c.Val / (s - 1.0);
         result.Err = c.Err / System.Math.Abs(s - 1.0) + PZMath_machine.PZMath_DBL_EPSILON * System.Math.Abs(result.Val);
         return PZMath_errno.PZMath_SUCCESS;
     }
     else if (s <= 20.0)
     {
         double x = (2.0 * s - 21.0) / 19.0;
         SpecialFunctionResult c = new SpecialFunctionResult();
         ChebyshevSeries.ChebEvalE(zeta_xgt1_cs, x, ref c);
         result.Val = c.Val / (s - 1.0);
         result.Err = c.Err / (s - 1.0) + PZMath_machine.PZMath_DBL_EPSILON * System.Math.Abs(result.Val);
         return PZMath_errno.PZMath_SUCCESS;
     }
     else
     {
         double f2 = 1.0 - System.Math.Pow(2.0, -s);
         double f3 = 1.0 - System.Math.Pow(3.0, -s);
         double f5 = 1.0 - System.Math.Pow(5.0, -s);
         double f7 = 1.0 - System.Math.Pow(7.0, -s);
         result.Val = 1.0 / (f2 * f3 * f5 * f7);
         result.Err = 3.0 * PZMath_machine.PZMath_DBL_EPSILON * System.Math.Abs(result.Val);
         return PZMath_errno.PZMath_SUCCESS;
     }
 }
コード例 #17
0
ファイル: Zeta.cs プロジェクト: Josep1984/pzmath
 /* assumes s is large and positive
  * write: zeta(s) - 1 = zeta(s) * (1 - 1/zeta(s))
  * and expand a few terms of the product formula to evaluate 1 - 1/zeta(s)
  *
  * works well for s > 15
  */
 public static int RiemannZetaMinus1LargeS(double s, ref SpecialFunctionResult result)
 {
     double a = System.Math.Pow(2.0, -s);
     double b = System.Math.Pow(3.0, -s);
     double c = System.Math.Pow(5.0, -s);
     double d = System.Math.Pow(7.0, -s);
     double e = System.Math.Pow(11.0, -s);
     double f = System.Math.Pow(13.0, -s);
     double t1 = a + b + c + d + e + f;
     double t2 = a * (b + c + d + e + f) + b * (c + d + e + f) + c * (d + e + f) + d * (e + f) + e * f;
     /*
     double t3 = a*(b*(c+d+e+f) + c*(d+e+f) + d*(e+f) + e*f) +
                 b*(c*(d+e+f) + d*(e+f) + e*f) +
                 c*(d*(e+f) + e*f) +
                 d*e*f;
     double t4 = a*(b*(c*(d + e + f) + d*(e + f) + e*f) + c*(d*(e+f) + e*f) + d*e*f) +
                 b*(c*(d*(e+f) + e*f) + d*e*f) +
                 c*d*e*f;
     double t5 = b*c*d*e*f + a*c*d*e*f+ a*b*d*e*f+ a*b*c*e*f+ a*b*c*d*f+ a*b*c*d*e;
     double t6 = a*b*c*d*e*f;
     */
     double numt = t1 - t2 /* + t3 - t4 + t5 - t6 */;
     double zeta = 1.0 / ((1.0 - a) * (1.0 - b) * (1.0 - c) * (1.0 - d) * (1.0 - e) * (1.0 - f));
     result.Val = numt * zeta;
     result.Err = (15.0 / s + 1.0) * 6.0 * PZMath_machine.PZMath_DBL_EPSILON * result.Val;
     return PZMath_errno.PZMath_SUCCESS;
 }
コード例 #18
0
ファイル: Zeta.cs プロジェクト: Josep1984/pzmath
 /* works for 5 < s < 15*/
 public static int RiemannZetaMinus1IntermediateS(double s, ref SpecialFunctionResult result)
 {
     double t = (s - 10.0) / 5.0;
     SpecialFunctionResult c = new SpecialFunctionResult();
     ChebyshevSeries.ChebEvalE(zetam1_inter_cs, t, ref c);
     result.Val = System.Math.Exp(c.Val) + System.Math.Pow(2.0, -s);
     result.Err = (c.Err + 2.0 * PZMath_machine.PZMath_DBL_EPSILON) * result.Val;
     return PZMath_errno.PZMath_SUCCESS;
 }
コード例 #19
0
ファイル: Gamma.cs プロジェクト: Josep1984/pzmath
        /* x = eps near zero
         * gives double-precision for |eps| < 0.02
         */
        public static int LnGammaSgn0(double eps, ref SpecialFunctionResult lng, ref double sgn)
        {
            /* calculate series for g(eps) = Gamma(eps) eps - 1/(1+eps) - eps/2 */
            double c1 = -0.07721566490153286061;
            double c2 = -0.01094400467202744461;
            double c3 = 0.09252092391911371098;
            double c4 = -0.01827191316559981266;
            double c5 = 0.01800493109685479790;
            double c6 = -0.00685088537872380685;
            double c7 = 0.00399823955756846603;
            double c8 = -0.00189430621687107802;
            double c9 = 0.00097473237804513221;
            double c10 = -0.00048434392722255893;
            double g6 = c6 + eps * (c7 + eps * (c8 + eps * (c9 + eps * c10)));
            double g = eps * (c1 + eps * (c2 + eps * (c3 + eps * (c4 + eps * (c5 + eps * g6)))));

            /* calculate Gamma(eps) eps, a positive quantity */
            double gee = g + 1.0 / (1.0 + eps) + 0.5 * eps;

            lng.Val = System.Math.Log(gee / System.Math.Abs(eps));
            lng.Err = 4.0 * PZMath_machine.PZMath_DBL_EPSILON * System.Math.Abs(lng.Val);
            sgn = System.Math.Sign(eps);

            return PZMath_errno.PZMath_SUCCESS;
        }
コード例 #20
0
ファイル: Elementary.cs プロジェクト: Josep1984/pzmath
 public static int MultiplyErrE(double x, double dx, double y, double dy, ref SpecialFunctionResult result)
 {
     int status = MultiplyE(x, y, ref result);
     result.Err += System.Math.Abs(dx * y) + System.Math.Abs(dy * x);
     return status;
 }
コード例 #21
0
ファイル: Gamma.cs プロジェクト: Josep1984/pzmath
        /* x near a negative integer
         * Calculates sign as well as System.Math.Log(|gamma(x)|).
         * x = -N + eps
         * assumes N >= 1
         */
        public static int LnGammaSgnSing(int N, double eps, ref SpecialFunctionResult lng, ref double sgn)
        {
            if (eps == 0.0)
            {
                lng.Val = 0.0;
                lng.Err = 0.0;
                sgn = 0.0;
                PZMath_errno.ERROR("error", PZMath_errno.PZMath_EDOM);
            }
            else if (N == 1)
            {
                /* calculate series for
                 * g = eps gamma(-1+eps) + 1 + eps/2 (1+3eps)/(1-eps^2)
                 * double-precision for |eps| < 0.02
                 */
                double c0 = 0.07721566490153286061;
                double c1 = 0.08815966957356030521;
                double c2 = -0.00436125434555340577;
                double c3 = 0.01391065882004640689;
                double c4 = -0.00409427227680839100;
                double c5 = 0.00275661310191541584;
                double c6 = -0.00124162645565305019;
                double c7 = 0.00065267976121802783;
                double c8 = -0.00032205261682710437;
                double c9 = 0.00016229131039545456;
                double g5 = c5 + eps * (c6 + eps * (c7 + eps * (c8 + eps * c9)));
                double g = eps * (c0 + eps * (c1 + eps * (c2 + eps * (c3 + eps * (c4 + eps * g5)))));

                /* calculate eps gamma(-1+eps), a negative quantity */
                double gam_e = g - 1.0 - 0.5 * eps * (1.0 + 3.0 * eps) / (1.0 - eps * eps);

                lng.Val = System.Math.Log(System.Math.Abs(gam_e) / System.Math.Abs(eps));
                lng.Err = 2.0 * PZMath_machine.PZMath_DBL_EPSILON * System.Math.Abs(lng.Val);
                sgn = (eps > 0.0 ? -1.0 : 1.0);
                return PZMath_errno.PZMath_SUCCESS;
            }
            else
            {
                double g;

                /* series for System.Math.Sin(Pi(N+1-eps))/(Pi eps) modulo the sign
                 * double-precision for |eps| < 0.02
                 */
                double cs1 = -1.6449340668482264365;
                double cs2 = 0.8117424252833536436;
                double cs3 = -0.1907518241220842137;
                double cs4 = 0.0261478478176548005;
                double cs5 = -0.0023460810354558236;
                double e2 = eps * eps;
                double sin_ser = 1.0 + e2 * (cs1 + e2 * (cs2 + e2 * (cs3 + e2 * (cs4 + e2 * cs5))));

                /* calculate series for ln(gamma(1+N-eps))
                 * double-precision for |eps| < 0.02
                 */
                double aeps = System.Math.Abs(eps);
                double c1, c2, c3, c4, c5, c6, c7;
                double lng_ser;
                SpecialFunctionResult c0 = new SpecialFunctionResult();
                SpecialFunctionResult psi_0 = new SpecialFunctionResult();
                SpecialFunctionResult psi_1 = new SpecialFunctionResult();
                SpecialFunctionResult psi_2 = new SpecialFunctionResult();
                SpecialFunctionResult psi_3 = new SpecialFunctionResult();
                SpecialFunctionResult psi_4 = new SpecialFunctionResult();
                SpecialFunctionResult psi_5 = new SpecialFunctionResult();
                SpecialFunctionResult psi_6 = new SpecialFunctionResult();
                psi_2.Val = 0.0;
                psi_3.Val = 0.0;
                psi_4.Val = 0.0;
                psi_5.Val = 0.0;
                psi_6.Val = 0.0;
                LnFactE(N, ref c0);
                Psi.PsiIntE(N + 1, ref psi_0);
                Psi.Psi1IntE(N + 1, ref psi_1);
                if (aeps > 0.00001) Psi.PsiNE(2, N + 1.0, ref psi_2);
                if (aeps > 0.0002) Psi.PsiNE(3, N + 1.0, ref psi_3);
                if (aeps > 0.001) Psi.PsiNE(4, N + 1.0, ref psi_4);
                if (aeps > 0.005) Psi.PsiNE(5, N + 1.0, ref psi_5);
                if (aeps > 0.01) Psi.PsiNE(6, N + 1.0, ref psi_6);
                c1 = psi_0.Val;
                c2 = psi_1.Val / 2.0;
                c3 = psi_2.Val / 6.0;
                c4 = psi_3.Val / 24.0;
                c5 = psi_4.Val / 120.0;
                c6 = psi_5.Val / 720.0;
                c7 = psi_6.Val / 5040.0;
                lng_ser = c0.Val - eps * (c1 - eps * (c2 - eps * (c3 - eps * (c4 - eps * (c5 - eps * (c6 - eps * c7))))));

                /* calculate
                 * g = ln(|eps gamma(-N+eps)|)
                 *   = -ln(gamma(1+N-eps)) + ln(|eps Pi/System.Math.Sin(Pi(N+1+eps))|)
                 */
                g = -lng_ser - System.Math.Log(sin_ser);

                lng.Val = g - System.Math.Log(System.Math.Abs(eps));
                lng.Err = c0.Err + 2.0 * PZMath_machine.PZMath_DBL_EPSILON * (System.Math.Abs(g) + System.Math.Abs(lng.Val));

                sgn = (PZMath.IsOdd(N) ? -1.0 : 1.0) * (eps > 0.0 ? 1.0 : -1.0);

                return PZMath_errno.PZMath_SUCCESS;
            }
            return PZMath_errno.PZMath_SUCCESS;
        }
コード例 #22
0
ファイル: Gamma.cs プロジェクト: Josep1984/pzmath
        public static int LnChooseE(int n, int m, ref SpecialFunctionResult result)
        {
            /* CHECK_POINTER(result) */

            if (m > n)
            {
                PZMath_errno.DomainError(ref result);
            }
            else if (m == n || m == 0)
            {
                result.Val = 0.0;
                result.Err = 0.0;
                return PZMath_errno.PZMath_SUCCESS;
            }
            else
            {
                SpecialFunctionResult nf = new SpecialFunctionResult();
                SpecialFunctionResult mf = new SpecialFunctionResult();
                SpecialFunctionResult nmmf = new SpecialFunctionResult();
                if (m * 2 > n)
                    m = n - m;
                LnFactE(n, ref nf);
                LnFactE(m, ref mf);
                LnFactE(n - m, ref nmmf);
                result.Val = nf.Val - mf.Val - nmmf.Val;
                result.Err = nf.Err + mf.Err + nmmf.Err;
                result.Err += 2.0 * PZMath_machine.PZMath_DBL_EPSILON * System.Math.Abs(result.Val);
                return PZMath_errno.PZMath_SUCCESS;
            }
            return PZMath_errno.PZMath_SUCCESS;
        }
コード例 #23
0
ファイル: Gamma.cs プロジェクト: Josep1984/pzmath
        public static int ChooseE(int n, int m, ref SpecialFunctionResult result)
        {
            if (m > n)
            {
                PZMath_errno.DomainError(ref result);
            }
            else if (m == n || m == 0)
            {
                result.Val = 1.0;
                result.Err = 0.0;
                return PZMath_errno.PZMath_SUCCESS;
            }
            else if (n <= GSL_SF_FACT_NMAX)
            {
                result.Val = (fact_table[n]._f / fact_table[m]._f) / fact_table[n - m]._f;
                result.Err = 6.0 * PZMath_machine.PZMath_DBL_EPSILON * System.Math.Abs(result.Val);
                return PZMath_errno.PZMath_SUCCESS;
            }
            else
            {
                if (m * 2 < n)
                    m = n - m;

                if (n - m < 64)  /* compute product for a manageable number of terms */
                {
                    double prod = 1.0;
                    int k;

                    for (k = n; k >= m + 1; k--)
                    {
                        double tk = (double)k / (double)(k - m);
                        if (tk > PZMath_machine.PZMath_DBL_MAX / prod)
                        {
                            PZMath_errno.OverFlowError(ref result);
                        }
                        prod *= tk;
                    }
                    result.Val = prod;
                    result.Err = 2.0 * PZMath_machine.PZMath_DBL_EPSILON * prod * System.Math.Abs(n - m);
                    return PZMath_errno.PZMath_SUCCESS;
                }
                else
                {
                    SpecialFunctionResult lc = new SpecialFunctionResult();
                    int stat_lc = LnChooseE(n, m, ref lc);
                    int stat_e = Exp.ExpErrE(lc.Val, lc.Err, ref result);
                    return PZMath_errno.ErrorSelect2(stat_lc, stat_e);
                }
            }
            return PZMath_errno.PZMath_SUCCESS;
        }
コード例 #24
0
ファイル: Gamma.cs プロジェクト: Josep1984/pzmath
 public static int LnDoubleFactE(int n, ref SpecialFunctionResult result)
 {
     if (n <= GSL_SF_DOUBLEFACT_NMAX)
     {
         result.Val = System.Math.Log(doub_fact_table[n]._f);
         result.Err = 2.0 * PZMath_machine.PZMath_DBL_EPSILON * System.Math.Abs(result.Val);
         return PZMath_errno.PZMath_SUCCESS;
     }
     else if (PZMath.IsOdd(n))
     {
         SpecialFunctionResult lg = new SpecialFunctionResult();
         LnGammaE(0.5 * (n + 2.0), ref lg);
         result.Val = 0.5 * (n + 1.0) * PZMath.M_LN2 - 0.5 * PZMath.M_LNPI + lg.Val;
         result.Err = 2.0 * PZMath_machine.PZMath_DBL_EPSILON * System.Math.Abs(result.Val) + lg.Err;
         return PZMath_errno.PZMath_SUCCESS;
     }
     else
     {
         SpecialFunctionResult lg = new SpecialFunctionResult();
         LnGammaE(0.5 * n + 1.0, ref lg);
         result.Val = 0.5 * n * PZMath.M_LN2 + lg.Val;
         result.Err = 2.0 * PZMath_machine.PZMath_DBL_EPSILON * System.Math.Abs(result.Val) + lg.Err;
         return PZMath_errno.PZMath_SUCCESS;
     }
 }
コード例 #25
0
ファイル: Gamma.cs プロジェクト: Josep1984/pzmath
        public static int GammaE(double x, ref SpecialFunctionResult result)
        {
            if (x < 0.5)
            {
                int rint_x = (int)System.Math.Floor(x + 0.5);
                double f_x = x - rint_x;
                double sgn_gamma = (PZMath.IsEven(rint_x) ? 1.0 : -1.0);
                double sin_term = sgn_gamma * System.Math.Sin(PZMath.M_PI * f_x) / PZMath.M_PI;

                if (sin_term == 0.0)
                {
                    PZMath_errno.DomainError(ref result);
                }
                else if (x > -169.0)
                {
                    SpecialFunctionResult g = new SpecialFunctionResult();
                    GammaXGTHalf(1.0 - x, ref g);
                    if (System.Math.Abs(sin_term) * g.Val * PZMath_machine.PZMath_DBL_MIN < 1.0)
                    {
                        result.Val = 1.0 / (sin_term * g.Val);
                        result.Err = System.Math.Abs(g.Err / g.Val) * System.Math.Abs(result.Val);
                        result.Err += 2.0 * PZMath_machine.PZMath_DBL_EPSILON * System.Math.Abs(result.Val);
                        return PZMath_errno.PZMath_SUCCESS;
                    }
                    else
                    {
                        PZMath_errno.UnderFlowError(ref result);
                    }
                }
                else
                {
                    /* It is hard to control it here.
                     * We can only exponentiate the
                     * logarithm and eat the loss of
                     * precision.
                     */
                    SpecialFunctionResult lng = new SpecialFunctionResult();
                    double sgn = 0.0;
                    int stat_lng = LnGammaSgnE(x, ref lng, ref sgn);
                    int stat_e = Exp.ExpMultErrE(lng.Val, lng.Err, sgn, 0.0, ref result);
                    return PZMath_errno.ErrorSelect2(stat_e, stat_lng);
                }
            }
            else
            {
                return GammaXGTHalf(x, ref result);
            }
            return PZMath_errno.PZMath_SUCCESS;
        }
コード例 #26
0
ファイル: Gamma.cs プロジェクト: Josep1984/pzmath
        public static int LnFactE(int n, ref SpecialFunctionResult result)
        {
            /* CHECK_POINTER(result) */

            if (n <= GSL_SF_FACT_NMAX)
            {
                result.Val = System.Math.Log(fact_table[n]._f);
                result.Err = 2.0 * PZMath_machine.PZMath_DBL_EPSILON * System.Math.Abs(result.Val);
                return PZMath_errno.PZMath_SUCCESS;
            }
            else
            {
                LnGammaE(n + 1.0, ref result);
                return PZMath_errno.PZMath_SUCCESS;
            }
        }
コード例 #27
0
ファイル: Gamma.cs プロジェクト: Josep1984/pzmath
 public static int GammaStarE(double x, ref SpecialFunctionResult result)
 {
     if (x <= 0.0)
     {
         PZMath_errno.DomainError(ref result);
     }
     else if (x < 0.5)
     {
         SpecialFunctionResult lg = new SpecialFunctionResult();
         int stat_lg = LnGammaE(x, ref lg);
         double lx = System.Math.Log(x);
         double c = 0.5 * (PZMath.M_LN2 + PZMath.M_LNPI);
         double lnr_val = lg.Val - (x - 0.5) * lx + x - c;
         double lnr_err = lg.Err + 2.0 * PZMath_machine.PZMath_DBL_EPSILON * ((x + 0.5) * System.Math.Abs(lx) + c);
         int stat_e = Exp.ExpErrE(lnr_val, lnr_err, ref result);
         return PZMath_errno.ErrorSelect2(stat_lg, stat_e);
     }
     else if (x < 2.0)
     {
         double t = 4.0 / 3.0 * (x - 0.5) - 1.0;
         return ChebyshevSeries.ChebEvalE(gstar_a_cs, t, ref result);
     }
     else if (x < 10.0)
     {
         double t = 0.25 * (x - 2.0) - 1.0;
         SpecialFunctionResult c = new SpecialFunctionResult();
         ChebyshevSeries.ChebEvalE(gstar_b_cs, t, ref c);
         result.Val = c.Val / (x * x) + 1.0 + 1.0 / (12.0 * x);
         result.Err = c.Err / (x * x);
         result.Err += 2.0 * PZMath_machine.PZMath_DBL_EPSILON * System.Math.Abs(result.Val);
         return PZMath_errno.PZMath_SUCCESS;
     }
     else if (x < 1.0 / PZMath_machine.PZMath_ROOT4_DBL_EPSILON)
     {
         return GammaStarSer(x, ref result);
     }
     else if (x < 1.0 / PZMath_machine.PZMath_DBL_EPSILON)
     {
         /* Use Stirling formula for Gamma(x).
          */
         double xi = 1.0 / x;
         result.Val = 1.0 + xi / 12.0 * (1.0 + xi / 24.0 * (1.0 - xi * (139.0 / 180.0 + 571.0 / 8640.0 * xi)));
         result.Err = 2.0 * PZMath_machine.PZMath_DBL_EPSILON * System.Math.Abs(result.Val);
         return PZMath_errno.PZMath_SUCCESS;
     }
     else
     {
         result.Val = 1.0;
         result.Err = 1.0 / x;
         return PZMath_errno.PZMath_SUCCESS;
     }
     return PZMath_errno.PZMath_SUCCESS;
 }
コード例 #28
0
ファイル: Gamma.cs プロジェクト: Josep1984/pzmath
 /*-*-*-*-*-*-*-*-*-* Functions w/ Natural Prototypes *-*-*-*-*-*-*-*-*-*-*/
 public static double LnGamma(double x)
 {
     SpecialFunctionResult result = new SpecialFunctionResult();
     LnGammaE(x, ref result);
     return result.Val;
 }
コード例 #29
0
ファイル: Gamma.cs プロジェクト: Josep1984/pzmath
 /* gamma(x) for x >= 1/2
  * assumes x >= 1/2
  */
 public static int GammaXGTHalf(double x, ref SpecialFunctionResult result)
 {
     if (x == 0.5)
     {
         result.Val = 1.77245385090551602729817;
         result.Err = PZMath_machine.PZMath_DBL_EPSILON * result.Val;
         return PZMath_errno.PZMath_SUCCESS;
     }
     else if (x <= (GSL_SF_FACT_NMAX + 1.0) && x == System.Math.Floor(x))
     {
         int n = (int)System.Math.Floor(x);
         result.Val = fact_table[n - 1]._f;
         result.Err = PZMath_machine.PZMath_DBL_EPSILON * result.Val;
         return PZMath_errno.PZMath_SUCCESS;
     }
     else if (System.Math.Abs(x - 1.0) < 0.01)
     {
         /* Use series for Gamma[1+eps] - 1/(1+eps).
          */
         double eps = x - 1.0;
         double c1 = 0.4227843350984671394;
         double c2 = -0.01094400467202744461;
         double c3 = 0.09252092391911371098;
         double c4 = -0.018271913165599812664;
         double c5 = 0.018004931096854797895;
         double c6 = -0.006850885378723806846;
         double c7 = 0.003998239557568466030;
         result.Val = 1.0 / x + eps * (c1 + eps * (c2 + eps * (c3 + eps * (c4 + eps * (c5 + eps * (c6 + eps * c7))))));
         result.Err = PZMath_machine.PZMath_DBL_EPSILON;
         return PZMath_errno.PZMath_SUCCESS;
     }
     else if (System.Math.Abs(x - 2.0) < 0.01)
     {
         /* Use series for Gamma[1 + eps].
          */
         double eps = x - 2.0;
         double c1 = 0.4227843350984671394;
         double c2 = 0.4118403304264396948;
         double c3 = 0.08157691924708626638;
         double c4 = 0.07424901075351389832;
         double c5 = -0.00026698206874501476832;
         double c6 = 0.011154045718130991049;
         double c7 = -0.002852645821155340816;
         double c8 = 0.0021039333406973880085;
         result.Val = 1.0 + eps * (c1 + eps * (c2 + eps * (c3 + eps * (c4 + eps * (c5 + eps * (c6 + eps * (c7 + eps * c8)))))));
         result.Err = PZMath_machine.PZMath_DBL_EPSILON;
         return PZMath_errno.PZMath_SUCCESS;
     }
     else if (x < 5.0)
     {
         /* Exponentiating the logarithm is fine, as
          * long as the exponential is not so large
          * that it greatly amplifies the error.
          */
         SpecialFunctionResult lg = new SpecialFunctionResult();
         LnGammaLanczos(x, ref lg);
         result.Val = System.Math.Exp(lg.Val);
         result.Err = result.Val * (lg.Err + 2.0 * PZMath_machine.PZMath_DBL_EPSILON);
         return PZMath_errno.PZMath_SUCCESS;
     }
     else if (x < 10.0)
     {
         /* This is a sticky area. The logarithm
          * is too large and the gammastar series
          * is not good.
          */
         double gamma_8 = 5040.0;
         double t = (2.0 * x - 15.0) / 5.0;
         SpecialFunctionResult c = new SpecialFunctionResult();
         ChebyshevSeries.ChebEvalE(gamma_5_10_cs, t, ref c);
         result.Val = System.Math.Exp(c.Val) * gamma_8;
         result.Err = result.Val * c.Err;
         result.Err += 2.0 * PZMath_machine.PZMath_DBL_EPSILON * result.Val;
         return PZMath_errno.PZMath_SUCCESS;
     }
     else if (x < GSL_SF_GAMMA_XMAX)
     {
         /* We do not want to exponentiate the logarithm
          * if x is large because of the inevitable
          * inflation of the error. So we carefully
          * use System.Math.Pow() and System.Math.Exp() with exact quantities.
          */
         double p = System.Math.Pow(x, 0.5 * x);
         double e = System.Math.Exp(-x);
         double q = (p * e) * p;
         double pre = PZMath.M_SQRT2 * PZMath.M_SQRTPI * q / System.Math.Sqrt(x);
         SpecialFunctionResult gstar = new SpecialFunctionResult();
         int stat_gs = GammaStarSer(x, ref gstar);
         result.Val = pre * gstar.Val;
         result.Err = (x + 2.5) * PZMath_machine.PZMath_DBL_EPSILON * result.Val;
         return stat_gs;
     }
     else
     {
         PZMath_errno.OverFlowError(ref result);
     }
     return PZMath_errno.PZMath_SUCCESS;
 }
コード例 #30
0
ファイル: Gamma.cs プロジェクト: Josep1984/pzmath
 public static int LnGamma1Pade(double eps, ref SpecialFunctionResult result)
 {
     /* Use (2,2) Pade for Log[Gamma[1+eps]]/eps
      * plus a correction series.
      */
     double n1 = -1.0017419282349508699871138440;
     double n2 = 1.7364839209922879823280541733;
     double d1 = 1.2433006018858751556055436011;
     double d2 = 5.0456274100274010152489597514;
     double num = (eps + n1) * (eps + n2);
     double den = (eps + d1) * (eps + d2);
     double pade = 2.0816265188662692474880210318 * num / den;
     double c0 = 0.004785324257581753;
     double c1 = -0.01192457083645441;
     double c2 = 0.01931961413960498;
     double c3 = -0.02594027398725020;
     double c4 = 0.03141928755021455;
     double eps5 = eps * eps * eps * eps * eps;
     double corr = eps5 * (c0 + eps * (c1 + eps * (c2 + eps * (c3 + c4 * eps))));
     result.Val = eps * (pade + corr);
     result.Err = 2.0 * PZMath_machine.PZMath_DBL_EPSILON * System.Math.Abs(result.Val);
     return PZMath_errno.PZMath_SUCCESS;
 }