using System;
namespace Legalsoft.Truffer
{ /// <summary> /// Returns the derivative of function func at point x by Ridders' polynomial extrapolation method. /// Enter the value h as the initial step size of the estimate; it need not be small, but should be an increment in x at which func will /// change substantially. The error estimate derivative is returned as err. /// Returns the derivative of a function func at a point x by Ridders' method of polynomial extrap- /// olation. 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> public class Dfridr { public Dfridr() { }
public static double dfridr(UniVarRealValueFun func, double x, double h, ref double err)
{
const int ntab = 10;
const double con = 1.4;
const double con2 = (con * con);
const double big = double.MaxValue;
const double safe = 2.0;
double ans = 0.0;
double[,] a = new double[ntab, ntab];
//if (h == 0.0)
if (Math.Abs(h) <= float.Epsilon)
{
throw new Exception("h must be nonzero in dfridr.");
}
double hh = h;
a[0, 0] = (func.funk(x + hh) - func.funk(x - hh)) / (2.0 * hh);
err = big;
for (int i = 1; i < ntab; i++)
{
hh /= con;
a[0, i] = (func.funk(x + hh) - func.funk(x - hh)) / (2.0 * hh);
double fac = con2;
for (int j = 1; j <= i; j++)
{
a[j, i] = (a[j - 1, i] * fac - a[j - 1, i - 1]) / (fac - 1.0);
fac = con2 * fac;
double errt = Math.Max(Math.Abs(a[j, i] - a[j - 1, i]), Math.Abs(a[j, i] - a[j - 1, i - 1]));
if (errt <= err)
{
err = errt;
ans = a[j, i];
}
}
if (Math.Abs(a[i, i] - a[i - 1, i - 1]) >= safe * err)
{
break;
}
}
return ans;
}
}
}