Esempio n. 1
0
        /// <summary>
        /// The Faddeeva function or Kramp function is a scaled complex complementary error function.
        /// </summary>
        /// <param name="z">The argument z.</param>
        /// <returns>The evaluated value.</returns>
        public static ScalarValue Faddeeva(ScalarValue z)
        {
            if (z.Im < 0.0)
            {
                return(2.0 * (-z * z).Exp() - Faddeeva(-z));
            }

            if (z.Re < 0.0)
            {
                return(Faddeeva(-z.Conjugate()).Conjugate());
            }

            var r = z.Abs();

            if (r < 2.0)
            {
                return((-z * z).Exp() * (1.0 - Erf_Series(-ScalarValue.I * z)));
            }
            else if ((z.Im < 0.1) && (z.Re < 30.0))
            {
                return(Taylor(new ScalarValue(z.Re), Math.Exp(-z.Re * z.Re) + 2.0 * Dawson.DawsonIntegral(z.Re) / Helpers.SqrtPI * ScalarValue.I, new ScalarValue(0.0, z.Im)));
            }
            else if (r > 7.0)
            {
                return(ContinuedFraction(z));
            }

            return(Weideman(z));
        }
Esempio n. 2
0
        static ScalarValue LambertW(ScalarValue x)
        {
            var EI = 1.0 / Math.E;

            // use an initial approximation
            var W   = ScalarValue.Zero;
            var abs = x.Abs();

            if (abs < EI / 2.0)
            {
                W = SeriesSmall(x);

                if ((x + EI).Abs() < 1e-6)
                {
                    return(W);
                }
            }
            else if (abs < EI)
            {
                W = SeriesZero(x);
            }
            else if (abs > Math.E)
            {
                W = SeriesLarge(x);
            }
            else
            {
                W = new ScalarValue(0.5);
            }

            return(Halley(x, W));
        }
Esempio n. 3
0
        /// <summary>
        /// Computes the complex Riemann Zeta function.
        /// </summary>
        /// <param name="s">The complex argument.</param>
        /// <returns>The (in general complex) value.</returns>
        public static ScalarValue RiemannZeta(ScalarValue s)
        {
            if (s == 1.0)
            {
                return(new ScalarValue(Double.PositiveInfinity));
            }
            else if (s.Re >= 0.0)
            {
                return(RiemannZetaGt0(s));
            }

            //See real zeta function for more information
            var zeta_one_minus_s = RiemannZeta1msLt0(s);
            var sin_term         = (0.5 * Math.PI * s).Sin() / Math.PI;
            var sabs             = s.Abs();

            if (sin_term == 0.0)
            {
                return(ScalarValue.Zero);
            }
            else if (sabs < 170)
            {
                //See below
                int n = (int)Math.Floor(sabs / 10.0);
                var p = new ScalarValue(2.0 * Math.PI).Pow(s + 10.0 * n) / Helpers.TwoPIpow[n];
                var g = Gamma.LinearGamma(1.0 - s);
                return(p * g * sin_term * zeta_one_minus_s);
            }

            throw new YAMPNumericOverflowException("Zeta");
        }
Esempio n. 4
0
        public static ScalarValue Gegenbauer(Int32 n, Double alpha, ScalarValue x)
        {
            if (n < 0)
                throw new YAMPArgumentRangeException("n");

            if (alpha <= 0)
                throw new YAMPArgumentRangeException("alpha", 0);

            if (x.Abs() > 1.0)
                throw new YAMPArgumentRangeException("x", -1, 1);

            var C0 = ScalarValue.One;

            if (n == 0)
            {
                return C0;
            }

            var C1 = 2.0 * alpha * x;

            if (n == 1)
            {
                return C1;
            }

            for (var k = 2; k <= n; k++)
            {
                var Ck = (2 * x * (k + alpha - 1) * C1 - (k + 2 * alpha - 2) * C0) / k;
                C0 = C1;
                C1 = Ck;
            }

            return C1;
        }
Esempio n. 5
0
        static ScalarValue LambertW(ScalarValue x)
        {
            var EI = 1.0 / Math.E;

            // use an initial approximation
            var W = ScalarValue.Zero;
            var abs = x.Abs();

            if (abs < EI / 2.0)
            {
                W = SeriesSmall(x);

                if ((x + EI).Abs() < 1e-6)
                {
                    return W;
                }
            }
            else if (abs < EI)
            {
                W = SeriesZero(x);
            }
            else if (abs > Math.E)
            {
                W = SeriesLarge(x);
            }
            else
            {
                W = new ScalarValue(0.5);
            }

            return Halley(x, W);
        }
Esempio n. 6
0
        /// <summary>
        /// Computes the complex error function erf(z).
        /// </summary>
        /// <param name="z">The complex argument.</param>
        /// <returns>The value of erf(z).</returns>
        public static ScalarValue Erf(ScalarValue z)
        {
            if (z.Abs() < 4.0)
            {
                return(Erf_Series(z));
            }
            else if (z.Re < 0.0)
            {
                return((-z * z).Exp() * Faddeeva(-ScalarValue.I * z) - 1.0);
            }

            return(1.0 - (-z * z).Exp() * Faddeeva(ScalarValue.I * z));
        }
Esempio n. 7
0
        /// <summary>
        /// Computes the complex (log) gamma function.
        /// </summary>
        /// <param name="z">The complex argument.</param>
        /// <returns>The evaluated value.</returns>
        public static ScalarValue LogGamma(ScalarValue z)
        {
            if (z.Re < 0.0)
            {
                return(new ScalarValue(double.PositiveInfinity));
            }

            if (z.Abs() > 15.0)
            {
                return(LogGamma_Stirling(z));
            }

            return(LanczosLogGamma(z));
        }
Esempio n. 8
0
        public static ScalarValue Gegenbauer(Int32 n, Double alpha, ScalarValue x)
        {
            if (n < 0)
            {
                throw new YAMPArgumentRangeException("n");
            }

            if (alpha <= 0)
            {
                throw new YAMPArgumentRangeException("alpha", 0);
            }

            if (x.Abs() > 1.0)
            {
                throw new YAMPArgumentRangeException("x", -1, 1);
            }

            var C0 = ScalarValue.One;

            if (n == 0)
            {
                return(C0);
            }

            var C1 = 2.0 * alpha * x;

            if (n == 1)
            {
                return(C1);
            }

            for (var k = 2; k <= n; k++)
            {
                var Ck = (2 * x * (k + alpha - 1) * C1 - (k + 2 * alpha - 2) * C0) / k;
                C0 = C1;
                C1 = Ck;
            }

            return(C1);
        }
Esempio n. 9
0
        /// <summary>
        /// Computes the complex dilogarithm function, also called Spence's function.
        /// </summary>
        /// <param name="z">The complex argument.</param>
        /// <returns>The value Li<sub>2</sub>(z).</returns>
        public static ScalarValue DiLog(ScalarValue z)
        {
            ScalarValue f;
            double      a0 = z.Abs();

            if (a0 > 1.0)
            {
                // outside the unit disk, reflect into the unit disk
                var ln = (-z).Ln();
                f = -Math.PI * Math.PI / 6.0 - ln * ln / 2.0 - DiLog(1.0 / z);
            }
            else
            {
                // inside the unit disk...
                if (a0 < 0.75)
                {
                    f = DiLog0(z);
                }
                else if (z.Re < 0.0)
                {
                    f = DiLog(z * z) / 2.0 - DiLog(-z);
                }
                else
                {
                    var e = 1.0 - z;
                    f = e.Abs() < 0.5 ? DiLog1(e) : DiLog_Log_Series(z);
                }
            }

            if ((z.Re > 1.0) && (Math.Sign(f.Im) != Math.Sign(z.Im)))
            {
                f = f.Conjugate();
            }

            return(f);
        }
Esempio n. 10
0
        /// <summary>
        /// Computes the complex dilogarithm function, also called Spence's function.
        /// </summary>
        /// <param name="z">The complex argument.</param>
        /// <returns>The value Li<sub>2</sub>(z).</returns>
        public static ScalarValue DiLog(ScalarValue z)
        {
            var f = default(ScalarValue);
            var a0 = z.Abs();

            if (a0 > 1.0)
            {
                // outside the unit disk, reflect into the unit disk
                var ln = (-z).Ln();
                f = -Math.PI * Math.PI / 6.0 - ln * ln / 2.0 - DiLog(1.0 / z);
            }
            else
            {
                // inside the unit disk...
                if (a0 < 0.75)
                {
                    f = DiLog0(z);
                }
                else if (z.Re < 0.0)
                {
                    f = DiLog(z * z) / 2.0 - DiLog(-z);
                }
                else
                {
                    var e = 1.0 - z;
                    f = e.Abs() < 0.5 ? DiLog1(e) : DiLog_Log_Series(z);
                }
            }

            if ((z.Re > 1.0) && (Math.Sign(f.Im) != Math.Sign(z.Im)))
            {
                f = f.Conjugate();
            }

            return f;
        }
Esempio n. 11
0
        /// <summary>
        /// Computes the complex Riemann Zeta function.
        /// </summary>
        /// <param name="s">The complex argument.</param>
        /// <returns>The (in general complex) value.</returns>
        public static ScalarValue RiemannZeta(ScalarValue s)
        {
            if (s == 1.0)
            {
                return new ScalarValue(Double.PositiveInfinity);
            }
            else if (s.Re >= 0.0)
            {
                return RiemannZetaGt0(s);
            }

            //See real zeta function for more information
            var zeta_one_minus_s = RiemannZeta1msLt0(s);
            var sin_term = (0.5 * Math.PI * s).Sin() / Math.PI;
            var sabs = s.Abs();

            if (sin_term == 0.0)
            {
                return ScalarValue.Zero;
            }
            else if (sabs < 170)
            {
                //See below
                int n = (int)Math.Floor(sabs / 10.0);
                var p = new ScalarValue(2.0 * Math.PI).Pow(s + 10.0 * n) / Helpers.TwoPIpow[n];
                var g = Gamma.LinearGamma(1.0 - s);
                return p * g * sin_term * zeta_one_minus_s;
            }

            throw new YAMPNumericOverflowException("Zeta");
        }
Esempio n. 12
0
        public static ScalarValue HurwitzZeta(ScalarValue s, ScalarValue q)
        {
            if (s.Re <= 1.0)
            {
                throw new YAMPArgumentRangeException("s", 1.0);
            }

            if (q.Re <= 0.0)
            {
                throw new YAMPArgumentRangeException("q", 0.0);
            }

            var max_bits = 54.0;
            var ln_term0 = -s *q.Log();

            var qabs = q.Abs();
            var sabs = s.Abs();
            var ss   = s;

            if ((sabs > max_bits && qabs < 1.0) || (sabs > 0.5 * max_bits && qabs < 0.25))
            {
                return(q.Pow(-ss));
            }
            else if (sabs > 0.5 * max_bits && qabs < 1.0)
            {
                var p1 = q.Pow(-ss);
                var p2 = (q / (1.0 + q)).Pow(ss);
                var p3 = (q / (2.0 + q)).Pow(ss);
                return(p1 * (1.0 + p2 + p3));
            }

            /* Euler-Maclaurin summation formula
             * [Moshier, p. 400, with several typo corrections]
             */
            const int jmax = 12;
            const int kmax = 10;

            var pmax = (kmax + q).Pow(-ss);
            var scp  = s;
            var pcp  = pmax / (kmax + q);
            var ans  = pmax * ((kmax + q) / (s - 1.0) + 0.5);

            for (var k = 0; k < kmax; k++)
            {
                ans += (k + q).Pow(-ss);
            }

            for (var j = 0; j <= jmax; j++)
            {
                var delta = COEFFICIENTS[j + 1] * scp * pcp;
                ans += delta;

                if ((delta / ans).Abs() < 0.5 * Double.Epsilon)
                {
                    break;
                }

                scp *= (s + 2 * j + 1) * (s + 2 * j + 2);
                pcp /= (kmax + q) * (kmax + q);
            }

            return(ans);
        }
Esempio n. 13
0
        /// <summary>
        /// The Faddeeva function or Kramp function is a scaled complex complementary error function.
        /// </summary>
        /// <param name="z">The argument z.</param>
        /// <returns>The evaluated value.</returns>
        public static ScalarValue Faddeeva(ScalarValue z)
        {
            if (z.Im < 0.0)
                return 2.0 * (-z * z).Exp() - Faddeeva(-z);

            if (z.Re < 0.0)
                return Faddeeva(-z.Conjugate()).Conjugate();

            var r = z.Abs();

            if (r < 2.0)
                return (-z * z).Exp() * (1.0 - Erf_Series(-ScalarValue.I * z));
            else if ((z.Im < 0.1) && (z.Re < 30.0))
                return Taylor(new ScalarValue(z.Re), Math.Exp(-z.Re * z.Re) + 2.0 * Dawson.DawsonIntegral(z.Re) / Helpers.SqrtPI * ScalarValue.I, new ScalarValue(0.0, z.Im));
            else if (r > 7.0)
                return ContinuedFraction(z);

            return Weideman(z);
        }
Esempio n. 14
0
        static ScalarValue Zernike(int n, int m, ScalarValue rho)
        {
            if (n < 0)
            {
                throw new YAMPArgumentRangeException("n");
            }

            if ((m < 0) || (m > n))
            {
                throw new YAMPArgumentRangeException("m", "n >= m >= 0");
            }

            // n and m have the same parity
            if ((n - m) % 2 != 0)
            {
                return(ScalarValue.Zero);
            }

            // R00
            if (n == 0)
            {
                return(ScalarValue.One);
            }

            var absrho = rho.Abs();

            if ((absrho < 0.0) || (absrho > 1.0))
            {
                throw new YAMPNotConvergedException("zernike");
            }

            // R^{m}_m
            var r2 = rho.Pow(new ScalarValue(m));

            if (n == m)
            {
                return(r2);
            }

            // R^{m+1}_{m+1}
            var k  = m;
            var r1 = r2 * rho;

            while (true)
            {
                k += 2;

                // *
                //  \
                //   * recurrence involving two lesser m's
                //  /
                // *
                // 2n R^{m+1}_{n-1} = (n+m) R^{m}_{n-2} + (n-m) R^{m}_{n}

                var r0 = ((2 * k) * rho * r1 - (k + m) * r2) / (k - m);

                if (k == n)
                {
                    return(r0);
                }

                //   *
                //  /
                // * recurrence involving two greater m's
                //  \
                //   *
                //

                var rp = (2 * (k + 1) * rho * r0 - (k - m) * r1) / (k + m + 2);

                r2 = r0;
                r1 = rp;
            }
        }
Esempio n. 15
0
        /// <summary>
        /// Computes the complex (log) gamma function.
        /// </summary>
        /// <param name="z">The complex argument.</param>
        /// <returns>The evaluated value.</returns>
        public static ScalarValue LogGamma(ScalarValue z)
        {
            if (z.Re < 0.0)
                return new ScalarValue(double.PositiveInfinity);

            if (z.Abs() > 15.0)
                return LogGamma_Stirling(z);

            return LanczosLogGamma(z);
        }
Esempio n. 16
0
        static ScalarValue Zernike(int n, int m, ScalarValue rho)
        {
            if (n < 0)
                throw new YAMPArgumentRangeException("n");

            if ((m < 0) || (m > n))
                throw new YAMPArgumentRangeException("m", "n >= m >= 0");

            // n and m have the same parity
            if ((n - m) % 2 != 0)
            {
                return ScalarValue.Zero;
            }

            // R00
            if (n == 0)
            {
                return ScalarValue.One;
            }

            var absrho = rho.Abs();

            if ((absrho < 0.0) || (absrho > 1.0))
                throw new YAMPNotConvergedException("zernike");

            // R^{m}_m
            var r2 = rho.Pow(new ScalarValue(m));

            if (n == m)
            {
                return r2;
            }

            // R^{m+1}_{m+1}
            var k = m;
            var r1 = r2 * rho;

            while (true)
            {
                k += 2;

                // *
                //  \
                //   * recurrence involving two lesser m's
                //  /
                // *
                // 2n R^{m+1}_{n-1} = (n+m) R^{m}_{n-2} + (n-m) R^{m}_{n}

                var r0 = ((2 * k) * rho * r1 - (k + m) * r2) / (k - m);

                if (k == n)
                {
                    return r0;
                }

                //   *
                //  /
                // * recurrence involving two greater m's
                //  \
                //   *
                //

                var rp = (2 * (k + 1) * rho * r0 - (k - m) * r1) / (k + m + 2);

                r2 = r0;
                r1 = rp;
            }
        }
Esempio n. 17
0
        public static ScalarValue HurwitzZeta(ScalarValue s, ScalarValue q)
        {
            if (s.Re <= 1.0)
                throw new YAMPArgumentRangeException("s", 1.0);

            if (q.Re <= 0.0)
                throw new YAMPArgumentRangeException("q", 0.0);

            var max_bits = 54.0;
            var ln_term0 = -s * q.Log();
            var qabs = q.Abs();
            var sabs = s.Abs();
            var ss = s;

            if ((sabs > max_bits && qabs < 1.0) || (sabs > 0.5 * max_bits && qabs < 0.25))
            {
                return q.Pow(-ss);
            }
            else if (sabs > 0.5 * max_bits && qabs < 1.0)
            {
                var p1 = q.Pow(-ss);
                var p2 = (q / (1.0 + q)).Pow(ss);
                var p3 = (q / (2.0 + q)).Pow(ss);
                return p1 * (1.0 + p2 + p3);
            }

            /* Euler-Maclaurin summation formula
             * [Moshier, p. 400, with several typo corrections]
             */
            const int jmax = 12;
            const int kmax = 10;

            var pmax = (kmax + q).Pow(-ss);
            var scp = s;
            var pcp = pmax / (kmax + q);
            var ans = pmax * ((kmax + q) / (s - 1.0) + 0.5);

            for (var k = 0; k < kmax; k++)
            {
                ans += (k + q).Pow(-ss);
            }

            for (var j = 0; j <= jmax; j++)
            {
                var delta = COEFFICIENTS[j + 1] * scp * pcp;
                ans += delta;

                if ((delta / ans).Abs() < 0.5 * Double.Epsilon)
                {
                    break;
                }

                scp *= (s + 2 * j + 1) * (s + 2 * j + 2);
                pcp /= (kmax + q) * (kmax + q);
            }

            return ans;
        }
Esempio n. 18
0
        /// <summary>
        /// Computes the complex error function erf(z).
        /// </summary>
        /// <param name="z">The complex argument.</param>
        /// <returns>The value of erf(z).</returns>
        public static ScalarValue Erf(ScalarValue z)
        {
            if (z.Abs() < 4.0)
                return Erf_Series(z);
            else if (z.Re < 0.0)
                return (-z * z).Exp() * Faddeeva(-ScalarValue.I * z) - 1.0;

            return 1.0 - (-z * z).Exp() * Faddeeva(ScalarValue.I * z);
        }