/// <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));
        }