package hep.aida.ref.pdf; /** * * @author The FreeHEP team @ SLAC * */ public abstract class FunctionDerivative { /** * Computes the derivative of a function with respect to one argument. * Adapted from Numerical Recipes in FORTRAN dfridr, pp. 182-183. * @param f a JAIDA IFunction * @param x a double[] with the point where the derivative is evaluated * @param ind the index of the argument of f we differentiate wrto * @param h a typical step size for x[ind] * @return the value of df/dx[ind] at x[] */ public static double derivative(Function f, Variable x, double h) { final double BIG = Double.MAX_VALUE; final double CON = 1.4; final double CON2 = CON*CON; final double SAFE = 2.; final int NTAB = 10; double[][] a = new double[NTAB][NTAB]; double res = Double.NaN; double err = BIG; a[0][0] = evaluateMatrixElement(f,x,h); for (int i=1; i<NTAB; i++) { h /= CON; a[0][i] = evaluateMatrixElement(f,x,h); 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.); fac *= CON2; 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; res = a[j][i]; } } if (Math.abs(a[i][i]-a[i-1][i-1]) >= SAFE*err) { return res; } } return res; } private static double evaluateMatrixElement(Function f, Variable x, double increment) { double xVal = x.value(); double result = 0; double xPlus = xVal + increment; double xMinus = xVal - increment; x.setValue(xPlus); result += f.value(); x.setValue(xMinus); result -= f.value(); result /= 2*increment; // Set the dependents back to its original value x.setValue(xVal); return result; } }