00001
00002
00003
00004
00005 #include "TNumDeriv.h"
00006
00007 #ifndef __CINT__
00008 #include <stdio.h>
00009 #include <stdlib.h>
00010 #include <assert.h>
00011
00012 Double_t TNumDeriv::fgTiny=0;
00013 Double_t TNumDeriv::fgEpsilon=0;
00014
00015
00016
00017 ClassImp(TNumDeriv)
00018 ClassImp(TNumDeriv1Test)
00019
00020 Double_t TNumDeriv::DFcn(Double_t add )
00021 {
00022 double dfdx,delta=fStep,rerr=0;
00023 dfdx = numericalDerivative( add ,delta,rerr);
00024 fStep=delta;
00025 return dfdx;
00026 }
00027
00028
00029
00030 Double_t TNumDeriv::Tiny()
00031 {
00032 if (fgTiny) return fgTiny;
00033 for (double d = 1; d ; d/=2) { fgTiny=d;}
00034 return fgTiny;
00035 }
00036
00037
00038 Double_t TNumDeriv::Epsilon()
00039 {
00040 if (fgEpsilon) return fgEpsilon;
00041 for (double d = 1; (d+1.)>1. ; d/=2) { fgEpsilon=d;}
00042 return fgEpsilon;
00043 }
00044
00045 double TNumDeriv::numericalDerivative( double x, double &delta, double &error )
00046 {
00047
00048
00049 double h0 = delta;
00050 if(!h0) h0 = 5 * pow(2.0, -17);
00051
00052 const double maxErrorA = .0012;
00053 const double maxErrorB = .0000026;
00054
00055 const double maxErrorC = .0003;
00056
00057
00058
00059 static const int nItersMax = 6;
00060 int nIters;
00061 double bestError = 1.0E30;
00062 double bestAns = 0;
00063 double bestDelta = 0;
00064
00065 static const double valFactor = pow(2.0, -16);
00066 static const double zero = 1e-10;
00067
00068 static const double w = 5.0/8;
00069 static const double wi2 = 64.0/25.0;
00070 static const double wi4 = wi2*wi2;
00071
00072 double F0,Fl,Fr;
00073 F0 = Fcn(x);
00074 if (!finite(F0)) return 0;
00075 double size0 = fabs(F0);
00076 if (size0==0) size0 = pow(2.0, -53);
00077
00078 static const double adjustmentFactor[nItersMax] = {
00079 1.0,
00080 pow(2.0, -17),
00081 pow(2.0, +17),
00082 pow(2.0, -34),
00083 pow(2.0, +34),
00084 pow(2.0, -51) };
00085
00086 for ( nIters = 0; nIters < nItersMax; ++nIters ) {
00087 fOutLim=0;
00088 double size = size0;
00089
00090 double h = h0 * adjustmentFactor[nIters];
00091
00092
00093
00094 Fr = Fcn(x+h);
00095 if (!finite(Fr) || fOutLim) continue;
00096 Fl = Fcn(x-h);
00097 if (!finite(Fl) || fOutLim) continue;
00098
00099 double A1 = (Fr - Fl)/(2.0*h);
00100 if (!finite(A1) || fabs(A1) < zero) continue;
00101
00102 if (fabs(A1) > size) size = fabs(A1);
00103
00104 double hh = w*h;
00105 Fr = Fcn(x+hh);
00106 if (!finite(Fr) || fOutLim) continue;
00107 Fl = Fcn(x-hh);
00108 if (!finite(Fl) || fOutLim) continue;
00109 double A2 = (Fr-Fl)/(2.0*hh);
00110 if (!finite(A2) || fabs(A2) < zero) continue;
00111
00112 if (fabs(A2) > size) size = fabs(A2);
00113
00114 hh *= w;
00115 Fr = Fcn(x+hh);
00116 if (!finite(Fr) || fOutLim) continue;
00117 Fl = Fcn(x-hh);
00118 if (!finite(Fl) || fOutLim) continue;
00119 double A3 = (Fr-Fl)/(2.0*hh);
00120
00121 if (!finite(A3)|| fabs(A3) < zero) continue;
00122 if (fabs(A3) > size) size = fabs(A3);
00123
00124 if ( (fabs(A1-A2)/size > maxErrorA) || (fabs(A1-A3)/size > maxErrorA) ) {
00125 continue;
00126 }
00127
00128
00129
00130 double B1 = ( A2 * wi2 - A1 ) / ( wi2 - 1 );
00131 if (!finite(B1)) continue;
00132 double B2 = ( A3 * wi2 - A2 ) / ( wi2 - 1 );
00133 if (!finite(B2)) continue;
00134 if ( fabs(B1-B2)/size > maxErrorB ) {
00135 continue;
00136 }
00137
00138
00139
00140 double ans = ( B2 * wi4 - B1 ) / ( wi4 - 1 );
00141 if (!finite(ans)) continue;
00142 double err = fabs ( ans - B1 );
00143 if ( err < bestError ) {
00144 bestError = err;
00145 bestAns = ans;
00146 bestDelta = h;
00147 }
00148
00149
00150
00151 hh = h * valFactor;
00152 double val = (Fcn(x+hh) - Fcn(x-hh))/(2.0*hh);
00153 if (!finite(val) || fOutLim) continue;
00154 if ( fabs(val-ans)/size > maxErrorC ) {
00155 continue;
00156 }
00157
00158
00159 break;
00160 }
00161 delta = bestDelta;
00162 error = bestError;
00163 return bestAns;
00164
00165 }
00166
00167 #endif