Beispiel #1
0
        /// <summary>
        /// Returns the derivative of a complex function at a point x by Ridders' method of polynomial
        /// extrapolation. The value h is input as an estimated initial stepsize; it need not be small, but
        /// rather should be an increment in x over which func changes substantially. An estimate of the
        /// error in the derivative is returned as err.
        /// </summary>
        /// <param name="function">A target complex function.</param>
        /// <param name="difference">A complex function represents the difference quotient.</param>
        /// <param name="x">A point at which the derivative is calculated.</param>
        /// <param name="h">An estimated initial stepsize.</param>
        /// <param name="err">An estimate of the error.</param>
        /// <returns>Numerical approximation of the value of the derivative of function at point x.</returns>
        private static Complex RidersDerivation(Func <Complex, Complex> function, DifferenceQuotient difference, Complex x, double h, out double err)
        {
            if (Complex.IsNaN(function(x)) || Complex.IsInfinity(function(x)))
            {
                err = double.MaxValue;
                return(double.NaN);
            }

            int     i, j;
            double  errt, fac, hh;
            Complex ans = Complex.Zero;

            if (h == 0.0)
            {
                throw new ArgumentException("h must be nonzero.");
            }

            hh      = h;
            a[0, 0] = difference(function, x, hh);
            err     = big;

            for (i = 1; i < ntab; i++)
            {
                // Successive columns in the Neville tableau will go to smaller stepsizes and higher orders of
                // extrapolation.

                hh     /= con;
                a[0, i] = difference(function, x, hh);      // Try new, smaller stepsize.
                fac     = con2;

                // Compute extrapolations of various orders, requiring no new function evaluations.
                for (j = 1; j <= i; j++)
                {
                    a[j, i] = (a[j - 1, i] * fac - a[j - 1, i - 1]) / (fac - 1.0);
                    fac     = con2 * fac;
                    errt    = Math.Max(Complex.Abs(a[j, i] - a[j - 1, i]), Complex.Abs(a[j, i] - a[j - 1, i - 1]));

                    // The error strategy is to compare each new extrapolation to one order lower, both
                    // at the present stepsize and the previous one.

                    // If error is decreased, save the improved answer.
                    if (errt <= err)
                    {
                        err = errt;
                        ans = a[j, i];
                    }
                }

                // If higher order is worse by a significant factor SAFE, then quit early.
                if (Complex.Abs(a[i, i] - a[i - 1, i - 1]) >= safe * err && err <= _tol * Complex.Abs(ans))
                {
                    return(ans);
                }
            }

            throw new NotConvergenceException("Calculation does not converge to a solution.");
        }
        /// <summary>
        /// Returns the derivative of a complex function at a point x by Ridders' method of polynomial
        /// extrapolation. The value h is input as an estimated initial stepsize; it need not be small, but
        /// rather should be an increment in x over which func changes substantially. An estimate of the
        /// error in the derivative is returned as err.
        /// </summary>
        /// <param name="function">A target complex function.</param>
        /// <param name="difference">A complex function represents the difference quotient.</param>
        /// <param name="x">A point at which the derivative is calculated.</param>
        /// <param name="h">An estimated initial stepsize.</param>
        /// <param name="err">An estimate of the error.</param>
        /// <returns>Numerical approximation of the value of the derivative of function at point x.</returns>
        private static Complex RidersDerivation(Func<Complex, Complex> function, DifferenceQuotient difference, Complex x, double h, out double err)
        {
            if (Complex.IsNaN(function(x)) || Complex.IsInfinity(function(x)))
            {
                err = double.MaxValue;
                return double.NaN;
            }

            int i, j;
            double errt, fac, hh;
            Complex ans = Complex.Zero;

            if (h == 0.0)
                throw new ArgumentException("h must be nonzero.");

            hh = h;
            a[0, 0] = difference(function, x, hh);
            err = big;

            for (i = 1; i < ntab; i++)
            {
                // Successive columns in the Neville tableau will go to smaller stepsizes and higher orders of
                // extrapolation.

                hh /= con;
                a[0, i] = difference(function, x, hh);      // Try new, smaller stepsize.
                fac = con2;

                // Compute extrapolations of various orders, requiring no new function evaluations.
                for (j = 1; j <= i; j++)
                {
                    a[j, i] = (a[j - 1, i] * fac - a[j - 1, i - 1]) / (fac - 1.0);
                    fac = con2 * fac;
                    errt = Math.Max(Complex.Abs(a[j, i] - a[j - 1, i]), Complex.Abs(a[j, i] - a[j - 1, i - 1]));

                    // The error strategy is to compare each new extrapolation to one order lower, both
                    // at the present stepsize and the previous one.

                    // If error is decreased, save the improved answer.
                    if (errt <= err)
                    {
                        err = errt;
                        ans = a[j, i];
                    }
                }

                // If higher order is worse by a significant factor SAFE, then quit early.
                if (Complex.Abs(a[i, i] - a[i - 1, i - 1]) >= safe * err && err <= _tol * Complex.Abs(ans))
                {
                    return ans;
                }
            }

            throw new NotConvergenceException("Calculation does not converge to a solution.");
        }