/// <summary>
        /// Computes the Riemann zeta function for complex values.
        /// </summary>
        /// <param name="z">The argument.</param>
        /// <returns>The value of &#x3B6;(z).</returns>
        /// <remarks>
        /// <para>As the imaginary part of the argument increases, the computation of the zeta function becomes slower and more difficult.
        /// The computation time is approximately proprotional to the imaginary part of z. The result also slowly looses accuracy for arguments with
        /// very large imaginary parts; for arguments with z.Im of order 10^d, approximately the last d digits of the result are suspect.</para>
        /// <para>The image below shows the complex &#x393; function near the origin using domain coloring. You can see the first non-trivial
        /// zeros at (1/2, &#177;14.13...) as well as the trivial zeros along the negative real axis.</para>
        /// <img src="../images/ComplexRiemannZetaPlot.png" />
        /// </remarks>
        public static Complex RiemannZeta(Complex z)
        {
            // Use conjugation and reflection symmetry to move to the first quadrant.
            if (z.Im < 0.0)
            {
                return(RiemannZeta(z.Conjugate).Conjugate);
            }
            if (z.Re < 0.0)
            {
                Complex zp = Complex.One - z;
                return(2.0 * ComplexMath.Pow(Global.TwoPI, -zp) * ComplexMath.Cos(Global.HalfPI * zp) * AdvancedComplexMath.Gamma(zp) * RiemannZeta(zp));
            }

            // Close to pole, use Laurent series.
            Complex zm1 = z - Complex.One;

            if (ComplexMath.Abs(zm1) < 0.50)
            {
                return(RiemannZeta_LaurentSeries(zm1));
            }

            // Fall back to Euler-Maclaurin summation.
            int n = RiemannZeta_EulerMaclaurin_N(z.Re, z.Im);

            return(RiemannZeta_EulerMaclaurin(z, n));
        }
예제 #2
0
        public void Evaluate(double[] X, double[] P, double[] Y)
        {
            double x = X[0];

            if (_useFrequencyInsteadOmega)
            {
                x *= (2 * Math.PI);
            }

            Complex result = P[0] + P[1] / ComplexMath.Pow(1 + ComplexMath.Pow(Complex.I * x * P[2], P[3]), P[4]);

            Y[0] = result.Re;

            if (this._useFlowTerm)
            {
                if (this._isDielectricData)
                {
                    Y[1] = -result.Im + P[5] / (x * 8.854187817e-12);
                }
                else
                {
                    Y[1] = -result.Im + P[5] / (x);
                }
            }
            else
            {
                Y[1] = -result.Im;
            }
        }
예제 #3
0
    private static void CalcClx(string param, StreamWriter writer)
    {
        var x   = new Complex(param);
        var ans = ComplexMath.Pow(x, x) - x * x + 1;

        writer.WriteLine(ans.ToString());
    }
예제 #4
0
        public void Evaluate(double[] X, double[] P, double[] Y)
        {
            double x = X[0];

            if (_useFrequencyInsteadOmega)
            {
                x *= (2 * Math.PI);
            }

            Complex result = 1 / ComplexMath.Pow(1 + ComplexMath.Pow(Complex.I * x * P[2], P[3]), P[4]);

            result = P[1] + (P[0] - P[1]) * result;

            if (_useFlowTerm)
            {
                result = 1 / ((1 / result) - Complex.I * P[5] / x);
            }

            if (_logarithmizeResults)
            {
                Y[0] = Math.Log10(result.Re);
                Y[1] = Math.Log10(result.Im);
            }
            else
            {
                Y[0] = result.Re;
                Y[1] = result.Im;
            }
        }
예제 #5
0
        public void Evaluate(double[] X, double[] P, double[] Y)
        {
            double x = X[0];

            if (_useFrequencyInsteadOmega)
            {
                x *= (2 * Math.PI);
            }

            // Model this first as compliance
            Complex result = 1 / ComplexMath.Pow(1 + ComplexMath.Pow(Complex.I * x * P[2], P[3]), P[4]);

            result = (1 / P[1]) + ((1 / P[0]) - (1 / P[1])) * result;

            if (_useFlowTerm)
            {
                result -= Complex.I * P[5] / x;
            }

            result = 1 / result; // but now convert to modulus

            if (_logarithmizeResults)
            {
                Y[0] = Math.Log10(result.Re);
                Y[1] = Math.Log10(result.Im);
            }
            else
            {
                Y[0] = result.Re;
                Y[1] = result.Im;
            }
        }
예제 #6
0
        public static Complex Gamma(Complex z)
        {
            Complex t = z + LanczosGP;

            return(
                Global.SqrtTwoPI *
                ComplexMath.Pow(t / Math.E, z - 0.5) * LanczosExpG *
                Sum(z)
                );
        }
        // Euler-Maclaurin summation approximates a sum by an integral.
        //   \sum_{k=a}^{b} f(k) = \int_a^b \! f(x) \, dx  - B_1 \left[ f(b) + f(a) \right] +
        //     \sum_{j=0}^{\infty} \frac{B_{2j}}{(2j)!} \left[ f^{(2j-1)}(b) - f^{(2j-1)}(a) \right]

        private static Complex RiemannZeta_EulerMaclaurin(Complex z, int n)
        {
            Complex f = 0.0;

            // Sum terms up to (n-1)^{-z}
            for (int k = 1; k < n; k++)
            {
                f += ComplexMath.Pow(k, -z);
            }

            // Integral term
            Complex f_old = f;
            Complex zm1   = z - Complex.One;

            f += ComplexMath.Pow(n, -zm1) / zm1;
            if (f == f_old)
            {
                return(f);
            }

            // B_1 term
            f_old = f;
            Complex df = ComplexMath.Pow(n, -z) / 2.0;

            f += df;
            if (f == f_old)
            {
                return(f);
            }

            // B_2 term
            df *= z / n;
            f  += AdvancedIntegerMath.BernoulliNumber(2) * df;
            if (f == f_old)
            {
                return(f);
            }

            // Higher Bernoulli terms
            for (int k = 4; k < 2 * AdvancedIntegerMath.Bernoulli.Length; k += 2)
            {
                f_old = f;
                df   *= (z + (k - 2)) / n * (z + (k - 3)) / n / k / (k - 1);
                f    += AdvancedIntegerMath.Bernoulli[k / 2] * df;
                if (f == f_old)
                {
                    return(f);
                }
            }

            throw new NonconvergenceException();
        }
예제 #8
0
        public void Evaluate(double[] X, double[] P, double[] Y)
        {
            double x = X[0];

            if (_useFrequencyInsteadOmega)
            {
                x *= (2 * Math.PI);
            }

            Complex result = P[0];
            int     i, j;

            for (i = 0, j = 1; i < _numberOfTerms; ++i, j += 4)
            {
                result += P[j] / ComplexMath.Pow(1 + ComplexMath.Pow(Complex.I * x * P[1 + j], P[2 + j]), P[3 + j]);
            }

            // note: because it is a susceptiblity, the imaginary part is still negative

            if (_useFlowTerm)
            {
                if (_isDielectricData)
                {
                    result.Im -= P[j] / (x * 8.854187817e-12);
                }
                else if (_invertViscosity)
                {
                    result.Im -= P[j] / (x);
                }
                else
                {
                    result.Im -= 1 / (P[j] * x);
                }
            }

            if (_invertResult)
            {
                result = 1 / result; // if we invert, i.e. we calculate the modulus, the imaginary part is now positive
            }
            else
            {
                result.Im = -result.Im; // else if we don't invert, i.e. we calculate susceptibility, we negate the imaginary part to make it positive
            }
            if (_logarithmizeResults)
            {
                result.Re = Math.Log10(result.Re);
                result.Im = Math.Log10(result.Im);
            }

            Y[0] = result.Re;
            Y[1] = result.Im;
        }
예제 #9
0
        public static Complex Riemann_Euler(Complex z)
        {
            Complex f = 1.0;

            for (int k = 0; k < primes.Length; k++)
            {
                Complex f_old = f;
                Complex fk    = 1.0 - ComplexMath.Pow(primes[k], -z);
                f = f * fk;
                if (f == f_old)
                {
                    return(1.0 / f);
                }
            }
            throw new NonconvergenceException();
        }
예제 #10
0
        public static Complex AiryAi_Asymptotic(Complex z)
        {
            Debug.Assert(ComplexMath.Abs(z) >= 9.0);

            if (z.Re >= 0.0)
            {
                Complex xi = 2.0 / 3.0 * ComplexMath.Pow(z, 3.0 / 2.0);
                Airy_Asymptotic_Subseries(xi, out Complex u0, out Complex v0, out Complex u1, out Complex v1);
                Complex e = ComplexMath.Exp(xi);
                Complex q = ComplexMath.Pow(z, 1.0 / 4.0);
                return(0.5 / Global.SqrtPI / q / e * u1);
            }
            else
            {
                z = -z;
                Complex xi = 2.0 / 3.0 * ComplexMath.Pow(z, 3.0 / 2.0);
                Airy_Asymptotic_Subseries(xi, out Complex u0, out Complex v0, out Complex u1, out Complex v1);
                Complex c = ComplexMath.Cos(xi);
                Complex s = ComplexMath.Sin(xi);

                throw new NotImplementedException();
            }
        }
예제 #11
0
        public void EvaluateGradient(double[] X, double[] P, double[][] DY)
        {
            double x = X[0];

            if (_useFrequencyInsteadOmega)
            {
                x *= (2 * Math.PI);
            }

            DY[0][0] = 1;
            DY[1][0] = 0;

            Complex OneByDenom = 1 / ComplexMath.Pow(1 + ComplexMath.Pow(Complex.I * x * P[2], P[3]), P[4]);

            DY[0][1] = OneByDenom.Re;
            DY[1][1] = -OneByDenom.Im;
            Complex IXP2      = Complex.I * x * P[2];
            Complex IXP2PowP3 = ComplexMath.Pow(IXP2, P[3]);
            Complex der2      = OneByDenom * -P[1] * P[2] * P[4] * IXP2PowP3 / (P[2] * (1 + IXP2PowP3));

            DY[0][2] = der2.Re;
            DY[1][2] = -der2.Im;
            Complex der3 = OneByDenom * -P[1] * P[4] * IXP2PowP3 *ComplexMath.Log(IXP2) / (1 + IXP2PowP3);

            DY[0][3] = der3.Re;
            DY[1][3] = -der3.Im;
            Complex der4 = OneByDenom * -P[1] * ComplexMath.Log(1 + IXP2PowP3);

            DY[0][4] = der4.Re;
            DY[1][4] = -der4.Im;

            if (_useFlowTerm)
            {
                DY[0][5] = 0;
                DY[1][5] = _isDielectricData ?  1 / (x * 8.854187817e-12) : 1 / x;
            }
        }