コード例 #1
0
 public void LogGammaSpecialValues()
 {
     Assert.IsTrue(Double.IsPositiveInfinity(AdvancedMath.LogGamma(0.0)));
     Assert.IsTrue(AdvancedMath.LogGamma(1.0) == 0.0);
     Assert.IsTrue(AdvancedMath.LogGamma(2.0) == 0.0);
     Assert.IsTrue(Double.IsPositiveInfinity(AdvancedMath.LogGamma(Double.PositiveInfinity)));
 }
コード例 #2
0
 public void EllipticFSpecialCases()
 {
     foreach (double phi in TestUtilities.GenerateUniformRealValues(-10.0, 10.0, 8))
     {
         Assert.IsTrue(TestUtilities.IsNearlyEqual(AdvancedMath.EllipticF(phi, 0.0), phi));
     }
 }
コード例 #3
0
        public void HypergeometricQuadraticTransforms()
        {
            foreach (double a in abcs)
            {
                foreach (double b in abcs)
                {
                    foreach (double x in xs)
                    {
                        if (!IsNonpositiveInteger(2.0 * b))
                        {
                            Assert.IsTrue(TestUtilities.IsNearlyEqual(
                                              AdvancedMath.Hypergeometric2F1(a, b, 2.0 * b, x),
                                              AdvancedMath.Hypergeometric2F1(0.5 * a, b - 0.5 * a, b + 0.5, x * x / (x - 1.0) / 4.0) / Math.Pow(1.0 - x, 0.5 * a),
                                              TestUtilities.TargetPrecision * 1000.0
                                              ));
                        }

                        // Wrong sign, but Mathematica agrees with values!

                        /*
                         * if (!IsNonpositiveInteger(a - b + 1.0)) {
                         *  Assert.IsTrue(TestUtilities.IsNearlyEqual(
                         *      AdvancedMath.Hypergeometric2F1(a, b, a - b + 1.0, x),
                         *      AdvancedMath.Hypergeometric2F1(0.5 * a, 0.5 * a - b + 0.5, a - b + 1.0, -4.0 * x / MoreMath.Sqr(1.0 - x)) / Math.Pow(1.0 - x, a)
                         *  ));
                         * }
                         */
                    }
                }
            }
        }
コード例 #4
0
 public void HypergeometricCubicTransforms()
 {
     foreach (double a in abcs)
     {
         foreach (double x in xs)
         {
             // DLMF 15.8.31
             //if ((a == 7.0) && (x == 0.8)) continue;
             if ((a == -3.0) && (x == 0.8))
             {
                 continue;
             }
             if ((a == 3.1) && (x == -5.0))
             {
                 continue;
             }
             if ((a == 4.5) && (x == -5.0))
             {
                 continue;
             }
             if ((a == 7.0) && (x == -5.0))
             {
                 continue;
             }
             if (x < 8.0 / 9.0)
             {
                 Assert.IsTrue(TestUtilities.IsNearlyEqual(
                                   AdvancedMath.Hypergeometric2F1(3.0 * a, 3.0 * a + 0.5, 4.0 * a + 2.0 / 3.0, x),
                                   AdvancedMath.Hypergeometric2F1(a, a + 0.5, 2.0 * a + 5.0 / 6.0, 27.0 * x * x * (x - 1.0) / MoreMath.Sqr(9.0 * x - 8.0)) * Math.Pow(1.0 - 9.0 / 8.0 * x, -2.0 * a)
                                   ));
             }
         }
     }
 }
コード例 #5
0
        public void ModifiedBesselGeneratingFunction()
        {
            // DLMF 10.35.1
            // e^{(z/2)(t + 1/t)} = \sum_{k=-\infty}^{+\infty} t^k I_k(z)

            foreach (double t in TestUtilities.GenerateRealValues(1.0E-1, 1.0E-1, 4))
            {
                foreach (double z in TestUtilities.GenerateRealValues(1.0E-2, 1.0E1, 4))
                {
                    double tn = 1.0;
                    double S  = AdvancedMath.ModifiedBesselI(0, z);

                    for (int n = 1; n < 100; n++)
                    {
                        double S_old = S;
                        tn *= t;
                        S  += tn * AdvancedMath.ModifiedBesselI(n, z) + AdvancedMath.ModifiedBesselI(-n, z) / tn;
                        if (S == S_old)
                        {
                            goto Test;
                        }
                    }
                    throw new NonconvergenceException();

Test:
                    Assert.IsTrue(TestUtilities.IsNearlyEqual(
                                      S, Math.Exp(z / 2.0 * (t + 1.0 / t))
                                      ));
                }
            }
        }
コード例 #6
0
        public void HypergeometricAtSpecialPoints()
        {
            // Documented at http://mathworld.wolfram.com/HypergeometricFunction.html

            Assert.IsTrue(TestUtilities.IsNearlyEqual(
                              AdvancedMath.Hypergeometric2F1(1.0 / 3.0, 2.0 / 3.0, 5.0 / 6.0, 27.0 / 32.0),
                              8.0 / 5.0
                              ));

            Assert.IsTrue(TestUtilities.IsNearlyEqual(
                              AdvancedMath.Hypergeometric2F1(0.25, 0.5, 0.75, 80.0 / 81.0),
                              9.0 / 5.0
                              ));

            Assert.IsTrue(TestUtilities.IsNearlyEqual(
                              AdvancedMath.Hypergeometric2F1(1.0 / 8.0, 3.0 / 8.0, 1.0 / 2.0, 2400.0 / 2401.0),
                              2.0 / 3.0 * Math.Sqrt(7.0)
                              ));

            Assert.IsTrue(TestUtilities.IsNearlyEqual(
                              AdvancedMath.Hypergeometric2F1(1.0 / 6.0, 1.0 / 3.0, 1.0 / 2.0, 25.0 / 27.0),
                              3.0 / 4.0 * Math.Sqrt(3.0)
                              ));

            Assert.IsTrue(TestUtilities.IsNearlyEqual(
                              AdvancedMath.Hypergeometric2F1(1.0 / 6.0, 1.0 / 2.0, 2.0 / 3.0, 125.0 / 128.0),
                              4.0 / 3.0 * Math.Pow(2.0, 1.0 / 6.0)
                              ));

            Assert.IsTrue(TestUtilities.IsNearlyEqual(
                              AdvancedMath.Hypergeometric2F1(1.0 / 12.0, 5.0 / 12.0, 1.0 / 2.0, 1323.0 / 1331.0),
                              3.0 / 4.0 * Math.Pow(11.0, 1.0 / 4.0)
                              ));
        }
コード例 #7
0
        public void HypergeometricAtOne()
        {
            // A&S 15.1.20
            foreach (double a in abcs)
            {
                foreach (double b in abcs)
                {
                    foreach (double c in abcs)
                    {
                        // Formula only hold for positive real c-a-b
                        if ((c - a - b) <= 0.0)
                        {
                            continue;
                        }

                        // Formula is still right for non-positive c, but to handle it we would need to deal with canceling infinite Gammas
                        if (IsNonpositiveInteger(c))
                        {
                            continue;
                        }

                        Assert.IsTrue(TestUtilities.IsNearlyEqual(
                                          AdvancedMath.Hypergeometric2F1(a, b, c, 1.0),
                                          AdvancedMath.Gamma(c) * AdvancedMath.Gamma(c - a - b) / AdvancedMath.Gamma(c - a) / AdvancedMath.Gamma(c - b)
                                          ));
                    }
                }
            }
        }
コード例 #8
0
        public void EllipticKIntegrals()
        {
            Interval i = Interval.FromEndpoints(0.0, 1.0);

            // http://mathworld.wolfram.com/CatalansConstant.html equation 37
            Assert.IsTrue(TestUtilities.IsNearlyEqual(
                              FunctionMath.Integrate(
                                  k => AdvancedMath.EllipticK(k),
                                  Interval.FromEndpoints(0.0, 1.0)),
                              2.0 * AdvancedMath.Catalan
                              ));

            Assert.IsTrue(TestUtilities.IsNearlyEqual(
                              FunctionMath.Integrate(
                                  k => AdvancedMath.EllipticK(k) * k,
                                  Interval.FromEndpoints(0.0, 1.0)),
                              1.0
                              ));

            Assert.IsTrue(TestUtilities.IsNearlyEqual(
                              FunctionMath.Integrate(
                                  k => AdvancedMath.EllipticK(k) / (1.0 + k),
                                  Interval.FromEndpoints(0.0, 1.0)),
                              Math.PI * Math.PI / 8.0
                              ));
        }
コード例 #9
0
 public void HypergeometricIncompleteBeta()
 {
     foreach (double a in abcs)
     {
         if (a <= 0.0)
         {
             continue;
         }
         foreach (double b in abcs)
         {
             if (b <= 0.0)
             {
                 continue;
             }
             foreach (double x in xs)
             {
                 if ((x < 0.0) || (x > 1.0))
                 {
                     continue;
                 }
                 Assert.IsTrue(TestUtilities.IsNearlyEqual(
                                   Math.Pow(x, a) * Math.Pow(1.0 - x, b) * AdvancedMath.Hypergeometric2F1(a + b, 1.0, a + 1.0, x) / a,
                                   AdvancedMath.Beta(a, b, x)
                                   ));
             }
         }
     }
 }
コード例 #10
0
        public void HypergeometricIntegral()
        {
            // A&S 15.3.1

            // F(a, b, c, x) = \frac{\Gamma(c)}{\Gamma(b) \Gamma(c - b)}
            // \int_{0}^{1} \! dt \, t^{b-1} (1 - t)^{c - b - 1} (1 - x t)^{-a}

            // Choose limits on a, b, c so that singularities of integrand are numerically integrable.

            foreach (double a in TestUtilities.GenerateRealValues(1.0, 10.0, 2))
            {
                foreach (double b in TestUtilities.GenerateRealValues(0.6, 10.0, 2))
                {
                    foreach (double c in TestUtilities.GenerateRealValues(b + 0.6, 10.0, 2))
                    {
                        foreach (double x in xs)
                        {
                            double I = FunctionMath.Integrate(
                                t => Math.Pow(t, b - 1.0) * Math.Pow(1.0 - t, c - b - 1.0) * Math.Pow(1.0 - x * t, -a),
                                Interval.FromEndpoints(0.0, 1.0)
                                );

                            double B = AdvancedMath.Beta(b, c - b);

                            Assert.IsTrue(TestUtilities.IsNearlyEqual(AdvancedMath.Hypergeometric2F1(a, b, c, x), I / B));
                        }
                    }
                }
            }
        }
コード例 #11
0
 /// <summary>
 /// Initializes a new &#x3B2; distribution.
 /// </summary>
 /// <param name="alpha">The left shape parameter, which controls the form of the distribution near x=0.</param>
 /// <param name="beta">The right shape parameter, which controls the form of the distribution near x=1.</param>
 /// <remarks>
 /// <para>The <paramref name="alpha"/> shape parameter controls the form of the distribution near x=0. The
 /// <paramref name="beta"/> shape parameter controls the form of the distribution near z=1. If a shape parameter
 /// is less than one, the PDF diverges on the side of the distribution it controls. If a shape parameter
 /// is greater than one, the PDF goes to zero on the side of the distribution it controls. If the left and right
 /// shape parameters are equal, the distribution is symmetric about x=1/2.</para>
 /// </remarks>
 /// <exception cref="ArgumentOutOfRangeException"><paramref name="alpha"/> or <paramref name="beta"/> is non-positive.</exception>
 public BetaDistribution(double alpha, double beta)
 {
     if (alpha <= 0.0)
     {
         throw new ArgumentOutOfRangeException(nameof(alpha));
     }
     if (beta <= 0.0)
     {
         throw new ArgumentOutOfRangeException(nameof(beta));
     }
     this.a = alpha;
     this.b = beta;
     // cache value of B(alpha, beta) to avoid having to re-calculate it whenever needed
     this.bigB = AdvancedMath.Beta(alpha, beta);
     // get a beta generator
     if (alpha < 0.75 && beta < 0.75)
     {
         this.betaRng = new JoehnkBetaGenerator(alpha, beta);
     }
     else if (alpha > 1.0 && beta > 1.0)
     {
         this.betaRng = new ChengBetaGenerator(alpha, beta);
     }
     else
     {
         this.betaRng = DeviateGeneratorFactory.GetBetaGenerator(alpha, beta);
     }
     // get a beta inverter
     this.betaInverter = new BetaInverter(alpha, beta);
 }
コード例 #12
0
 public void SphericalBesselSpecialCase()
 {
     Assert.IsTrue(AdvancedMath.SphericalBesselJ(0, 0.0) == 1.0);
     Assert.IsTrue(AdvancedMath.SphericalBesselJ(1, 0.0) == 0.0);
     Assert.IsTrue(AdvancedMath.SphericalBesselY(0, 0.0) == Double.NegativeInfinity);
     Assert.IsTrue(AdvancedMath.SphericalBesselY(1, 0.0) == Double.NegativeInfinity);
 }
コード例 #13
0
        /// <summary>
        /// Initializes a new instance of a Gamma distribution with the given parameters.
        /// </summary>
        /// <param name="shape">The shape parameter, which must be positive.</param>
        /// <param name="scale">The scale parameter, which must be positive.</param>
        public GammaDistribution(double shape, double scale)
        {
            if (shape <= 0.0)
            {
                throw new ArgumentOutOfRangeException(nameof(shape));
            }
            if (scale <= 0.0)
            {
                throw new ArgumentOutOfRangeException(nameof(scale));
            }
            a = shape;
            s = scale;

            // depending on size of a, store Gamma(a) or -Ln(Gamma(a)) for future use
            if (a < 64.0)
            {
                ga = AdvancedMath.Gamma(a);
            }
            else
            {
                ga = -AdvancedMath.LogGamma(a);
            }

            gammaRng = DeviateGeneratorFactory.GetGammaGenerator(a);
        }
コード例 #14
0
ファイル: RootsTest.cs プロジェクト: wolflion521/metanumerics
        public void RootOfPsi()
        {
            double x = FunctionMath.FindZero(AdvancedMath.Psi, 1.5);

            Assert.IsTrue(TestUtilities.IsNearlyEqual(x, 1.46163214496836234126));
            Assert.IsTrue(AdvancedMath.Psi(x) < TestUtilities.TargetPrecision);
        }
コード例 #15
0
        public void HypergeometrticRecurrenceA()
        {
            // A&S 15.2.10

            foreach (double a in abcs)
            {
                foreach (double b in abcs)
                {
                    foreach (double c in abcs)
                    {
                        foreach (double x in xs)
                        {
                            double FM = AdvancedMath.Hypergeometric2F1(a - 1.0, b, c, x);
                            double F0 = AdvancedMath.Hypergeometric2F1(a, b, c, x);
                            double FP = AdvancedMath.Hypergeometric2F1(a + 1.0, b, c, x);

                            if ((c == a) && Double.IsNaN(FM))
                            {
                                continue;
                            }

                            Assert.IsTrue(TestUtilities.IsSumNearlyEqual(
                                              new double[] { (c - a) * FM, (2.0 * a - c - a * x + b * x) * F0 },
                                              -a * (x - 1.0) * FP,
                                              new EvaluationSettings()
                            {
                                RelativePrecision = 1.0E-12, AbsolutePrecision = 1.0E-15
                            }
                                              ));
                        }
                    }
                }
            }
        }
コード例 #16
0
        public void EllipticNomeAgreement()
        {
            foreach (double k in TestUtilities.GenerateRealValues(1.0E-2, 1.0, 4))
            {
                double K = AdvancedMath.EllipticK(k);

                double k1 = Math.Sqrt((1.0 - k) * (1.0 + k));
                double K1 = AdvancedMath.EllipticK(k1);

                double q = AdvancedMath.EllipticNome(k);

                // For k << 1, this test fails if formulated as q = e^{\pi K' / K}.
                // Problem is that computation of k' looses some digits to cancellation,
                // then K' is near singularity so error is amplified, then
                // exp function amplifies error some more. Investigation indicates
                // that q agrees with Mathematica to nearly all digits, so problem
                // isn't in nome function. Run test in log space and don't let k get
                // extremely small.

                Assert.IsTrue(TestUtilities.IsNearlyEqual(
                                  Math.Log(q),
                                  -Math.PI * K1 / K
                                  ));
            }
        }
コード例 #17
0
        public void HypergeometricAtMinusOne()
        {
            foreach (double a in abcs)
            {
                if ((a <= 0.0) && (Math.Round(a) == a))
                {
                    continue;
                }

                Assert.IsTrue(TestUtilities.IsNearlyEqual(
                                  AdvancedMath.Hypergeometric2F1(1.0, a, a + 1.0, -1.0),
                                  a / 2.0 * (AdvancedMath.Psi((a + 1.0) / 2.0) - AdvancedMath.Psi(a / 2.0))
                                  ));

                foreach (double b in abcs)
                {
                    double c = a - b + 1.0;
                    if ((c <= 0.0) && (Math.Round(c) == c))
                    {
                        continue;
                    }

                    // If result vanishes, returned value may just be very small.
                    double R = AdvancedMath.Gamma(a - b + 1.0) * AdvancedMath.Gamma(a / 2.0 + 1.0) / AdvancedMath.Gamma(a + 1.0) / AdvancedMath.Gamma(a / 2.0 - b + 1.0);
                    if (R == 0.0)
                    {
                        Assert.IsTrue(Math.Abs(AdvancedMath.Hypergeometric2F1(a, b, a - b + 1.0, -1.0)) <= 1.0E-14);
                    }
                    else
                    {
                        Assert.IsTrue(TestUtilities.IsNearlyEqual(AdvancedMath.Hypergeometric2F1(a, b, a - b + 1.0, -1.0), R));
                    }
                }
            }
        }
コード例 #18
0
 public void ModifiedBesselAtZero()
 {
     Assert.IsTrue(AdvancedMath.ModifiedBesselI(0, 0.0) == 1.0);
     Assert.IsTrue(AdvancedMath.ModifiedBesselI(1, 0.0) == 0.0);
     Assert.IsTrue(AdvancedMath.ModifiedBesselK(0, 0.0) == Double.PositiveInfinity);
     Assert.IsTrue(AdvancedMath.ModifiedBesselK(1, 0.0) == Double.PositiveInfinity);
 }
コード例 #19
0
        public void EllipticLandenTransform()
        {
            foreach (double k in TestUtilities.GenerateUniformRealValues(0.0, 1.0, 8))
            {
                double kp = Math.Sqrt(1.0 - k * k);
                double k1 = (1.0 - kp) / (1.0 + kp);

                // For complete 1st kind
                Assert.IsTrue(TestUtilities.IsNearlyEqual(
                                  AdvancedMath.EllipticK(k),
                                  (1.0 + k1) * AdvancedMath.EllipticK(k1)
                                  ));

                // For complete 2nd kind
                Assert.IsTrue(TestUtilities.IsNearlyEqual(
                                  AdvancedMath.EllipticE(k) + kp * AdvancedMath.EllipticK(k),
                                  (1.0 + kp) * AdvancedMath.EllipticE(k1)
                                  ));

                /*
                 * foreach (double t in TestUtilities.GenerateUniformRealValues(0.0, Math.PI / 2.0, 4)) {
                 *
                 *  double s = Math.Sin(t);
                 *  double t1 = Math.Asin((1.0 + kp) * s * Math.Sqrt(1.0 - s * s) / Math.Sqrt(1.0 - k * k * s * s));
                 *
                 *  // Since t1 can be > pi/2, we need to handle a larger range of angles before we can test the incomplete cases
                 *
                 *
                 * }
                 *
                 */
            }
        }
コード例 #20
0
ファイル: RootsTest.cs プロジェクト: wolflion521/metanumerics
        public void RootOfEi()
        {
            double x = FunctionMath.FindZero(AdvancedMath.IntegralEi, Interval.FromEndpoints(0.1, 1.0));

            Assert.IsTrue(TestUtilities.IsNearlyEqual(x, 0.37250741078136663446));
            Assert.IsTrue(Math.Abs(AdvancedMath.IntegralEi(x)) < TestUtilities.TargetPrecision);
        }
コード例 #21
0
 public void GammaAtNegativeIntegers()
 {
     Assert.IsTrue(Double.IsInfinity(AdvancedMath.Gamma(0.0)));
     foreach (int n in TestUtilities.GenerateIntegerValues(1, 100, 4))
     {
         Assert.IsTrue(Double.IsInfinity(AdvancedMath.Gamma(-n)));
     }
 }
コード例 #22
0
ファイル: Functions.cs プロジェクト: YburnContributors/Yburn
 public static double WoodsSaxonPotentialNormalizingConstant3D(
     double nuclearRadius,
     double diffuseness
     )
 {
     return(-8.0 * Math.PI * diffuseness * diffuseness * diffuseness
            * AdvancedMath.PolyLog(3, -Math.Exp(nuclearRadius / diffuseness)));
 }
コード例 #23
0
 public void GammaRecurrsion()
 {
     // Limit x to avoid overflow.
     foreach (double x in TestUtilities.GenerateRealValues(1.0E-4, 1.0E2, 16))
     {
         Assert.IsTrue(TestUtilities.IsNearlyEqual(AdvancedMath.Gamma(x + 1.0), x * AdvancedMath.Gamma(x)));
     }
 }
コード例 #24
0
        public void CarlsonNormalization()
        {
            // All Carlson integrals are normalized so that they are 1 when all arguments are 1.

            Assert.IsTrue(AdvancedMath.CarlsonF(1.0, 1.0, 1.0) == 1.0);
            Assert.IsTrue(AdvancedMath.CarlsonG(1.0, 1.0, 1.0) == 1.0);
            Assert.IsTrue(AdvancedMath.CarlsonD(1.0, 1.0, 1.0) == 1.0);
        }
コード例 #25
0
 public void ComplexDiLogAgreement () {
     // use negative arguments b/c positive real DiLog function complex for x > 1
     foreach (double x in TestUtilities.GenerateRealValues(1.0E-2, 1.0E2, 10)) {
         Assert.IsTrue(TestUtilities.IsNearlyEqual(
             AdvancedMath.DiLog(-x), AdvancedComplexMath.DiLog(-x)
         ));
     }
 }
コード例 #26
0
 public void InverseErfTest()
 {
     foreach (double P in TestUtilities.GenerateRealValues(1.0E-8, 1.0, 16))
     {
         Assert.IsTrue(TestUtilities.IsNearlyEqual(AdvancedMath.Erf(AdvancedMath.InverseErf(P)), P));
         Assert.IsTrue(TestUtilities.IsNearlyEqual(AdvancedMath.Erfc(AdvancedMath.InverseErfc(P)), P));
     }
 }
コード例 #27
0
        public void InverseErfSpecialValues()
        {
            Assert.IsTrue(AdvancedMath.InverseErf(-1.0) == Double.NegativeInfinity);
            Assert.IsTrue(AdvancedMath.InverseErf(0.0) == 0.0);
            Assert.IsTrue(AdvancedMath.InverseErf(1.0) == Double.PositiveInfinity);

            //Assert.IsTrue(Double.IsNaN(AdvancedMath.InverseErf(Double.NaN)));
        }
コード例 #28
0
 public void IntegralE0()
 {
     // A & S 5.1.24
     foreach (double x in TestUtilities.GenerateRealValues(1.0E-4, 1.0E3, 8))
     {
         Assert.IsTrue(TestUtilities.IsNearlyEqual(AdvancedMath.IntegralE(0, x), Math.Exp(-x) / x));
     }
 }
コード例 #29
0
 public void IntegralEAtZero()
 {
     // A & S 5.1.23
     foreach (int n in TestUtilities.GenerateIntegerValues(2, 100, 8))
     {
         Assert.IsTrue(AdvancedMath.IntegralE(n, 0.0) == 1.0 / (n - 1.0));
     }
 }
コード例 #30
0
 public void IntegralE1Integral()
 {
     // A & S 5.1.33
     Assert.IsTrue(TestUtilities.IsNearlyEqual(
                       FunctionMath.Integrate(t => MoreMath.Sqr(AdvancedMath.IntegralE(1, t)), 0.0, Double.PositiveInfinity),
                       2.0 * Math.Log(2.0)
                       ));
 }