Logo ROOT   6.10/09
Reference Guide
RichardsonDerivator.cxx
Go to the documentation of this file.
1 // @(#)root/mathcore:$Id$
2 // Authors: David Gonzalez Maline 01/2008
3 
4 /**********************************************************************
5  * *
6  * Copyright (c) 2006 , LCG ROOT MathLib Team *
7  * *
8  * *
9  **********************************************************************/
10 
12 #include "Math/IFunctionfwd.h"
13 #include <cmath>
14 #include <limits>
15 
16 #include "Math/Error.h"
17 
18 namespace ROOT {
19 namespace Math {
20 
22  fFunctionCopied(false),
23  fStepSize(h),
24  fLastError(0),
25  fFunction(0)
26 {
27  // Default Constructor.
28 }
30  fFunctionCopied(copyFunc),
31  fStepSize(h),
32  fLastError(0),
33  fFunction(0)
34 {
35  // Constructor from a function and step size
36  if (copyFunc) fFunction = f.Clone();
37  else fFunction = &f;
38 }
39 
40 
42 {
43  // destructor
44  if ( fFunction != 0 && fFunctionCopied )
45  delete fFunction;
46 }
47 
49 {
50  // copy constructor
51  // copy constructor (deep copy or not depending on fFunctionCopied)
52  fStepSize = rhs.fStepSize;
53  fLastError = rhs.fLastError;
55  SetFunction(*rhs.fFunction);
56  }
57 
59 {
60  // Assignment operator
61  if (&rhs == this) return *this;
63  fStepSize = rhs.fStepSize;
64  fLastError = rhs.fLastError;
65  SetFunction(*rhs.fFunction);
66  return *this;
67 }
68 
70 {
71  // set function
72  if (fFunctionCopied) {
73  if (fFunction) delete fFunction;
74  fFunction = f.Clone();
75  }
76  else fFunction = &f;
77 }
78 
79 double RichardsonDerivator::Derivative1 (const IGenFunction & function, double x, double h)
80 {
81  const double keps = std::numeric_limits<double>::epsilon();
82 
83 
84  double xx;
85  xx = x+h; double f1 = (function)(xx);
86 
87  xx = x-h; double f2 = (function)(xx);
88 
89  xx = x+h/2; double g1 = (function)(xx);
90  xx = x-h/2; double g2 = (function)(xx);
91 
92  //compute the central differences
93  double h2 = 1/(2.*h);
94  double d0 = f1 - f2;
95  double d2 = g1 - g2;
96  double deriv = h2*(8*d2 - d0)/3.;
97  // // compute the error ( to be improved ) this is just a simple truncation error
98  // fLastError = kC1*h2*0.5*(f1+f2); //compute the error
99 
100  // compute the error ( from GSL deriv implementation)
101 
102  double e0 = (std::abs( f1) + std::abs(f2)) * keps;
103  double e2 = 2* (std::abs( g1) + std::abs(g2)) * keps + e0;
104  double delta = std::max( std::abs( h2*d0), std::abs( deriv) ) * std::abs( x)/h * keps;
105 
106  // estimate the truncation error from d2-d0 which is O(h^2)
107  double err_trunc = std::abs( deriv - h2*d0 );
108  // rounding error due to cancellation
109  double err_round = std::abs( e2/h) + delta;
110 
111  fLastError = err_trunc + err_round;
112  return deriv;
113 }
114 
115 double RichardsonDerivator::DerivativeForward (const IGenFunction & function, double x, double h)
116 {
117  const double keps = std::numeric_limits<double>::epsilon();
118 
119 
120  double xx;
121  xx = x+h/4.0; double f1 = (function)(xx);
122  xx = x+h/2.0; double f2 = (function)(xx);
123 
124  xx = x+(3.0/4.0)*h; double f3 = (function)(xx);
125  xx = x+h; double f4 = (function)(xx);
126 
127  //compute the forward differences
128 
129  double r2 = 2.0*(f4 - f2);
130  double r4 = (22.0 / 3.0) * (f4 - f3) - (62.0 / 3.0) * (f3 - f2) +
131  (52.0 / 3.0) * (f2 - f1);
132 
133  // Estimate the rounding error for r4
134 
135  double e4 = 2 * 20.67 * (fabs (f4) + fabs (f3) + fabs (f2) + fabs (f1)) * keps;
136 
137  // The next term is due to finite precision in x+h = O (eps * x)
138 
139  double dy = std::max (fabs (r2 / h), fabs (r4 / h)) * fabs (x / h) * keps;
140 
141  // The truncation error in the r4 approximation itself is O(h^3).
142  // However, for safety, we estimate the error from r4-r2, which is
143  // O(h). By scaling h we will minimise this estimated error, not
144  // the actual truncation error in r4.
145 
146  double result = r4 / h;
147  double abserr_trunc = fabs ((r4 - r2) / h); // Estimated truncation error O(h)
148  double abserr_round = fabs (e4 / h) + dy;
149 
150  fLastError = abserr_trunc + abserr_round;
151 
152  return result;
153 }
154 
155 
156  double RichardsonDerivator::Derivative2 (const IGenFunction & function, double x, double h)
157 {
158  const double kC1 = 4*std::numeric_limits<double>::epsilon();
159 
160  double xx;
161  xx = x+h; double f1 = (function)(xx);
162  xx = x; double f2 = (function)(xx);
163  xx = x-h; double f3 = (function)(xx);
164 
165  xx = x+h/2; double g1 = (function)(xx);
166  xx = x-h/2; double g3 = (function)(xx);
167 
168  //compute the central differences
169  double hh = 1/(h*h);
170  double d0 = f3 - 2*f2 + f1;
171  double d2 = 4*g3 - 8*f2 +4*g1;
172  fLastError = kC1*hh*f2; //compute the error
173  double deriv = hh*(4*d2 - d0)/3.;
174  return deriv;
175 }
176 
177 double RichardsonDerivator::Derivative3 (const IGenFunction & function, double x, double h)
178 {
179  const double kC1 = 4*std::numeric_limits<double>::epsilon();
180 
181  double xx;
182  xx = x+2*h; double f1 = (function)(xx);
183  xx = x+h; double f2 = (function)(xx);
184  xx = x-h; double f3 = (function)(xx);
185  xx = x-2*h; double f4 = (function)(xx);
186  xx = x; double fx = (function)(xx);
187  xx = x+h/2; double g2 = (function)(xx);
188  xx = x-h/2; double g3 = (function)(xx);
189 
190  //compute the central differences
191  double hhh = 1/(h*h*h);
192  double d0 = 0.5*f1 - f2 +f3 - 0.5*f4;
193  double d2 = 4*f2 - 8*g2 +8*g3 - 4*f3;
194  fLastError = kC1*hhh*fx; //compute the error
195  double deriv = hhh*(4*d2 - d0)/3.;
196  return deriv;
197 }
198 
199 } // end namespace Math
200 
201 } // end namespace ROOT
double Derivative3(double x)
Returns the third derivative of the function at point x, computed by Richardson&#39;s extrapolation metho...
Interface (abstract class) for generic functions objects of one-dimension Provides a method to evalua...
Definition: IFunction.h:134
Namespace for new ROOT classes and functions.
Definition: StringConv.hxx:21
double DerivativeForward(double x)
Computation of the first derivative using a forward formula.
TH1 * h
Definition: legend2.C:5
double Derivative2(double x)
Returns the second derivative of the function at point x, computed by Richardson&#39;s extrapolation meth...
Float_t delta
Double_t x[n]
Definition: legend1.C:17
void SetFunction(const IGenFunction &f)
Set function for derivative calculation (copy the function if option has been enabled in the construc...
double Derivative1(double x)
Returns the first derivative of the function at point x, computed by Richardson&#39;s extrapolation metho...
VecExpr< UnaryOp< Fabs< T >, VecExpr< A, T, D >, T >, T, D > fabs(const VecExpr< A, T, D > &rhs)
~RichardsonDerivator()
Destructor: Removes function if needed.
REAL epsilon
Definition: triangle.c:617
RichardsonDerivator(double h=0.001)
Default Constructor.
double f(double x)
Namespace for new Math classes and functions.
RichardsonDerivator & operator=(const RichardsonDerivator &rhs)
Assignment operator.
double f2(const double *x)
TF1 * f1
Definition: legend1.C:11
virtual IBaseFunctionOneDim * Clone() const =0
Clone a function.
double result[121]
User class for calculating the derivatives of a function.
unsigned int r2[N_CITIES]
Definition: simanTSP.cxx:322