5#include "CLHEP/GenericFunctions/FunctionNumDeriv.hh"
20 _arg1(right._arg1->clone()),
21 _wrtIndex(right._wrtIndex)
35#define ROBUST_DERIVATIVES
36#ifdef ROBUST_DERIVATIVES
38double FunctionNumDeriv::f_x (
double x)
const {
43double FunctionNumDeriv::f_Arg (
double x)
const {
44 _xArg [_wrtIndex] = x;
45 return (*_arg1)(_xArg);
51 assert (_wrtIndex==0);
52 return numericalDerivative ( &FunctionNumDeriv::f_x, x );
59 double xx = x[_wrtIndex];
60 return numericalDerivative ( &FunctionNumDeriv::f_Arg, xx );
64double FunctionNumDeriv::numericalDerivative
67 const double h0 = 5 * std::pow(2.0, -17);
69 const double maxErrorA = .0012;
70 const double maxErrorB = .0000026;
72 const double maxErrorC = .0003;
76 const int nItersMax = 6;
78 double bestError = 1.0E30;
81 const double valFactor = std::pow(2.0, -16);
83 const double w = 5.0/8;
84 const double wi2 = 64.0/25.0;
85 const double wi4 = wi2*wi2;
87 double size = fabs((this->*f)(x));
88 if (size==0) size = std::pow(2.0, -53);
90 const double adjustmentFactor[nItersMax] = {
98 for ( nIters = 0; nIters < nItersMax; ++nIters ) {
100 double h = h0 * adjustmentFactor[nIters];
104 double A1 = ((this->*
f)(x+h) - (this->*
f)(x-h))/(2.0*h);
106 if (fabs(A1) > size) size = fabs(A1);
109 double A2 = ((this->*
f)(x+hh) - (this->*
f)(x-hh))/(2.0*hh);
111 if (fabs(A2) > size) size = fabs(A2);
114 double A3 = ((this->*
f)(x+hh) - (this->*
f)(x-hh))/(2.0*hh);
116 if (fabs(A3) > size) size = fabs(A3);
118 if ( (fabs(A1-A2)/size > maxErrorA) || (fabs(A1-A3)/size > maxErrorA) ) {
124 double B1 = ( A2 * wi2 - A1 ) / ( wi2 - 1 );
125 double B2 = ( A3 * wi2 - A2 ) / ( wi2 - 1 );
126 if ( fabs(B1-B2)/size > maxErrorB ) {
132 double ans = ( B2 * wi4 - B1 ) / ( wi4 - 1 );
133 double err = fabs ( ans - B1 );
134 if ( err < bestError ) {
142 double val = ((this->*
f)(x+hh) - (this->*
f)(x-hh))/(2.0*hh);
143 if ( fabs(val-ans)/size > maxErrorC ) {
158#ifdef SIMPLER_DERIVATIVES
161 assert (_wrtIndex==0);
162 const double h=1.0E-6;
163 return ((*_arg1)(x+h) - (*_arg1)(x-h))/(2.0*h);
168 assert (_wrtIndex<x.dimension());
169 const double h=1.0E-6;
173 return ((*_arg1)(x1) - (*_arg1)(x0))/(2.0*h);
#define FUNCTION_OBJECT_IMP(classname)
virtual unsigned int dimensionality() const
unsigned int dimension() const
virtual unsigned int dimensionality() const override
virtual double operator()(double argument) const override
virtual ~FunctionNumDeriv()
FunctionNumDeriv(const AbsFunction *arg1, unsigned int index=0)