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