// @(#)root/mathcore:$Id$
// Authors: David Gonzalez Maline    01/2008

/**********************************************************************
 *                                                                    *
 * Copyright (c) 2006 , LCG ROOT MathLib Team                         *
 *                                                                    *
 *                                                                    *
 **********************************************************************/

// Header file for RichardsonDerivator
//
// Created by: David Gonzalez Maline  : Mon Feb 4 2008
//

#ifndef ROOT_Math_RichardsonDerivator
#define ROOT_Math_RichardsonDerivator

#include <Math/IFunction.h>

namespace ROOT {
namespace Math {

//___________________________________________________________________________________________
/**
   User class for calculating the derivatives of a function. It can calculate first (method Derivative1),
   second (method Derivative2) and third (method Derivative3) of a function.

   It uses the Richardson extrapolation method for function derivation in a given interval.
   The method use 2 derivative estimates (one computed with step h and one computed with step h/2)
   to compute a third, more accurate estimation. It is equivalent to the
   <a href = http://en.wikipedia.org/wiki/Five-point_stencil>5-point method</a>,
   which can be obtained with a Taylor expansion.
   A step size should be given, depending on x and f(x).
   An optimal step size value minimizes the truncation error of the expansion and the rounding
   error in evaluating x+h and f(x+h). A too small h will yield a too large rounding error while a too large
   h will give a large truncation error in the derivative approximation.
   A good discussion can be found in discussed in
   <a href=http://www.nrbook.com/a/bookcpdf/c5-7.pdf>Chapter 5.7</a>  of Numerical Recipes in C.
   By default a value of 0.001 is uses, acceptable in many cases.

   This class is implemented using code previosuly in  TF1::Derivate{,2,3}(). Now TF1 uses this class.

   @ingroup Deriv

 */

class RichardsonDerivator {
public:

   /** Destructor: Removes function if needed. */
   ~RichardsonDerivator();

   /** Default Constructor.
       Give optionally the step size for derivation. By default is 0.001, which is fine for x ~ 1
       Increase if x is in averga larger or decrease if x is smaller
    */
   RichardsonDerivator(double h = 0.001);

   /** Construct from function and step size
    */
   RichardsonDerivator(const ROOT::Math::IGenFunction & f, double h = 0.001, bool copyFunc = false);

   /**
      Copy constructor
    */
   RichardsonDerivator(const RichardsonDerivator & rhs);

   /**
      Assignment operator
    */
   RichardsonDerivator & operator= ( const RichardsonDerivator & rhs);


   /** Returns the estimate of the absolute Error of the last derivative calculation. */
   double Error () const {  return fLastError; }


   /**
      Returns the first derivative of the function at point x,
      computed by Richardson's extrapolation method (use 2 derivative estimates
      to compute a third, more accurate estimation)
      first, derivatives with steps h and h/2 are computed by central difference formulas
     Begin_Latex
      D(h) = #frac{f(x+h) - f(x-h)}{2h}
     End_Latex
      the final estimate Begin_Latex D = #frac{4D(h/2) - D(h)}{3} End_Latex
       "Numerical Methods for Scientists and Engineers", H.M.Antia, 2nd edition"

      the argument eps may be specified to control the step size (precision).
      the step size is taken as eps*(xmax-xmin).
      the default value (0.001) should be good enough for the vast majority
      of functions. Give a smaller value if your function has many changes
      of the second derivative in the function range.

      Getting the error via TF1::DerivativeError:
        (total error = roundoff error + interpolation error)
      the estimate of the roundoff error is taken as follows:
     Begin_Latex
         err = k#sqrt{f(x)^{2} + x^{2}deriv^{2}}#sqrt{#sum ai^{2}},
     End_Latex
      where k is the double precision, ai are coefficients used in
      central difference formulas
      interpolation error is decreased by making the step size h smaller.
   */
   double Derivative1 (double x);
   double operator() (double x) { return Derivative1(x); }

   /**
      First Derivative calculation passing function and step-size
    */
   double Derivative1(const IGenFunction & f, double x, double h) {
      fFunction = &f;
      fStepSize = h;
      return Derivative1(x);
   }

   /**
      Returns the second derivative of the function at point x,
      computed by Richardson's extrapolation method (use 2 derivative estimates
      to compute a third, more accurate estimation)
      first, derivatives with steps h and h/2 are computed by central difference formulas
     Begin_Latex
         D(h) = #frac{f(x+h) - 2f(x) + f(x-h)}{h^{2}}
     End_Latex
      the final estimate Begin_Latex D = #frac{4D(h/2) - D(h)}{3} End_Latex
       "Numerical Methods for Scientists and Engineers", H.M.Antia, 2nd edition"

      the argument eps may be specified to control the step size (precision).
      the step size is taken as eps*(xmax-xmin).
      the default value (0.001) should be good enough for the vast majority
      of functions. Give a smaller value if your function has many changes
      of the second derivative in the function range.

      Getting the error via TF1::DerivativeError:
        (total error = roundoff error + interpolation error)
      the estimate of the roundoff error is taken as follows:
     Begin_Latex
         err = k#sqrt{f(x)^{2} + x^{2}deriv^{2}}#sqrt{#sum ai^{2}},
     End_Latex
      where k is the double precision, ai are coefficients used in
      central difference formulas
      interpolation error is decreased by making the step size h smaller.
   */
   double Derivative2 (double x);

   /**
      Second Derivative calculation passing function and step-size
    */
   double Derivative2(const IGenFunction & f, double x, double h) {
      fFunction = &f;
      fStepSize = h;
      return Derivative2(x);
   }

   /**
      Returns the third derivative of the function at point x,
      computed by Richardson's extrapolation method (use 2 derivative estimates
      to compute a third, more accurate estimation)
      first, derivatives with steps h and h/2 are computed by central difference formulas
     Begin_Latex
         D(h) = #frac{f(x+2h) - 2f(x+h) + 2f(x-h) - f(x-2h)}{2h^{3}}
     End_Latex
      the final estimate Begin_Latex D = #frac{4D(h/2) - D(h)}{3} End_Latex
       "Numerical Methods for Scientists and Engineers", H.M.Antia, 2nd edition"

      the argument eps may be specified to control the step size (precision).
      the step size is taken as eps*(xmax-xmin).
      the default value (0.001) should be good enough for the vast majority
      of functions. Give a smaller value if your function has many changes
      of the second derivative in the function range.

      Getting the error via TF1::DerivativeError:
        (total error = roundoff error + interpolation error)
      the estimate of the roundoff error is taken as follows:
     Begin_Latex
         err = k#sqrt{f(x)^{2} + x^{2}deriv^{2}}#sqrt{#sum ai^{2}},
     End_Latex
      where k is the double precision, ai are coefficients used in
      central difference formulas
      interpolation error is decreased by making the step size h smaller.
   */
   double Derivative3 (double x);

   /**
      Third Derivative calculation passing function and step-size
    */
   double Derivative3(const IGenFunction & f, double x, double h) {
      fFunction = &f;
      fStepSize = h;
      return Derivative3(x);
   }

   /** Set function for derivative calculation (copy the function if option has been enabled in the constructor)

       \@param f Function to be differentiated
   */
   void SetFunction (const IGenFunction & f);

   /** Set step size for derivative calculation

       \@param h step size for calculation
   */
   void SetStepSize (double h) { fStepSize = h; }

protected:

   bool fFunctionCopied;     // flag to control if function is copied in the class
   double fStepSize;         // step size used for derivative calculation
   double fLastError;        //  error estimate of last derivative calculation
   const IGenFunction* fFunction;  // pointer to function

};

} // end namespace Math

} // end namespace ROOT

#endif /* ROOT_Math_RichardsonDerivator */

 RichardsonDerivator.h:1
 RichardsonDerivator.h:2
 RichardsonDerivator.h:3
 RichardsonDerivator.h:4
 RichardsonDerivator.h:5
 RichardsonDerivator.h:6
 RichardsonDerivator.h:7
 RichardsonDerivator.h:8
 RichardsonDerivator.h:9
 RichardsonDerivator.h:10
 RichardsonDerivator.h:11
 RichardsonDerivator.h:12
 RichardsonDerivator.h:13
 RichardsonDerivator.h:14
 RichardsonDerivator.h:15
 RichardsonDerivator.h:16
 RichardsonDerivator.h:17
 RichardsonDerivator.h:18
 RichardsonDerivator.h:19
 RichardsonDerivator.h:20
 RichardsonDerivator.h:21
 RichardsonDerivator.h:22
 RichardsonDerivator.h:23
 RichardsonDerivator.h:24
 RichardsonDerivator.h:25
 RichardsonDerivator.h:26
 RichardsonDerivator.h:27
 RichardsonDerivator.h:28
 RichardsonDerivator.h:29
 RichardsonDerivator.h:30
 RichardsonDerivator.h:31
 RichardsonDerivator.h:32
 RichardsonDerivator.h:33
 RichardsonDerivator.h:34
 RichardsonDerivator.h:35
 RichardsonDerivator.h:36
 RichardsonDerivator.h:37
 RichardsonDerivator.h:38
 RichardsonDerivator.h:39
 RichardsonDerivator.h:40
 RichardsonDerivator.h:41
 RichardsonDerivator.h:42
 RichardsonDerivator.h:43
 RichardsonDerivator.h:44
 RichardsonDerivator.h:45
 RichardsonDerivator.h:46
 RichardsonDerivator.h:47
 RichardsonDerivator.h:48
 RichardsonDerivator.h:49
 RichardsonDerivator.h:50
 RichardsonDerivator.h:51
 RichardsonDerivator.h:52
 RichardsonDerivator.h:53
 RichardsonDerivator.h:54
 RichardsonDerivator.h:55
 RichardsonDerivator.h:56
 RichardsonDerivator.h:57
 RichardsonDerivator.h:58
 RichardsonDerivator.h:59
 RichardsonDerivator.h:60
 RichardsonDerivator.h:61
 RichardsonDerivator.h:62
 RichardsonDerivator.h:63
 RichardsonDerivator.h:64
 RichardsonDerivator.h:65
 RichardsonDerivator.h:66
 RichardsonDerivator.h:67
 RichardsonDerivator.h:68
 RichardsonDerivator.h:69
 RichardsonDerivator.h:70
 RichardsonDerivator.h:71
 RichardsonDerivator.h:72
 RichardsonDerivator.h:73
 RichardsonDerivator.h:74
 RichardsonDerivator.h:75
 RichardsonDerivator.h:76
 RichardsonDerivator.h:77
 RichardsonDerivator.h:78
 RichardsonDerivator.h:79
 RichardsonDerivator.h:80
 RichardsonDerivator.h:81
 RichardsonDerivator.h:82
 RichardsonDerivator.h:83
 RichardsonDerivator.h:84
 RichardsonDerivator.h:85
 RichardsonDerivator.h:86
 RichardsonDerivator.h:87
 RichardsonDerivator.h:88
 RichardsonDerivator.h:89
 RichardsonDerivator.h:90
 RichardsonDerivator.h:91
 RichardsonDerivator.h:92
 RichardsonDerivator.h:93
 RichardsonDerivator.h:94
 RichardsonDerivator.h:95
 RichardsonDerivator.h:96
 RichardsonDerivator.h:97
 RichardsonDerivator.h:98
 RichardsonDerivator.h:99
 RichardsonDerivator.h:100
 RichardsonDerivator.h:101
 RichardsonDerivator.h:102
 RichardsonDerivator.h:103
 RichardsonDerivator.h:104
 RichardsonDerivator.h:105
 RichardsonDerivator.h:106
 RichardsonDerivator.h:107
 RichardsonDerivator.h:108
 RichardsonDerivator.h:109
 RichardsonDerivator.h:110
 RichardsonDerivator.h:111
 RichardsonDerivator.h:112
 RichardsonDerivator.h:113
 RichardsonDerivator.h:114
 RichardsonDerivator.h:115
 RichardsonDerivator.h:116
 RichardsonDerivator.h:117
 RichardsonDerivator.h:118
 RichardsonDerivator.h:119
 RichardsonDerivator.h:120
 RichardsonDerivator.h:121
 RichardsonDerivator.h:122
 RichardsonDerivator.h:123
 RichardsonDerivator.h:124
 RichardsonDerivator.h:125
 RichardsonDerivator.h:126
 RichardsonDerivator.h:127
 RichardsonDerivator.h:128
 RichardsonDerivator.h:129
 RichardsonDerivator.h:130
 RichardsonDerivator.h:131
 RichardsonDerivator.h:132
 RichardsonDerivator.h:133
 RichardsonDerivator.h:134
 RichardsonDerivator.h:135
 RichardsonDerivator.h:136
 RichardsonDerivator.h:137
 RichardsonDerivator.h:138
 RichardsonDerivator.h:139
 RichardsonDerivator.h:140
 RichardsonDerivator.h:141
 RichardsonDerivator.h:142
 RichardsonDerivator.h:143
 RichardsonDerivator.h:144
 RichardsonDerivator.h:145
 RichardsonDerivator.h:146
 RichardsonDerivator.h:147
 RichardsonDerivator.h:148
 RichardsonDerivator.h:149
 RichardsonDerivator.h:150
 RichardsonDerivator.h:151
 RichardsonDerivator.h:152
 RichardsonDerivator.h:153
 RichardsonDerivator.h:154
 RichardsonDerivator.h:155
 RichardsonDerivator.h:156
 RichardsonDerivator.h:157
 RichardsonDerivator.h:158
 RichardsonDerivator.h:159
 RichardsonDerivator.h:160
 RichardsonDerivator.h:161
 RichardsonDerivator.h:162
 RichardsonDerivator.h:163
 RichardsonDerivator.h:164
 RichardsonDerivator.h:165
 RichardsonDerivator.h:166
 RichardsonDerivator.h:167
 RichardsonDerivator.h:168
 RichardsonDerivator.h:169
 RichardsonDerivator.h:170
 RichardsonDerivator.h:171
 RichardsonDerivator.h:172
 RichardsonDerivator.h:173
 RichardsonDerivator.h:174
 RichardsonDerivator.h:175
 RichardsonDerivator.h:176
 RichardsonDerivator.h:177
 RichardsonDerivator.h:178
 RichardsonDerivator.h:179
 RichardsonDerivator.h:180
 RichardsonDerivator.h:181
 RichardsonDerivator.h:182
 RichardsonDerivator.h:183
 RichardsonDerivator.h:184
 RichardsonDerivator.h:185
 RichardsonDerivator.h:186
 RichardsonDerivator.h:187
 RichardsonDerivator.h:188
 RichardsonDerivator.h:189
 RichardsonDerivator.h:190
 RichardsonDerivator.h:191
 RichardsonDerivator.h:192
 RichardsonDerivator.h:193
 RichardsonDerivator.h:194
 RichardsonDerivator.h:195
 RichardsonDerivator.h:196
 RichardsonDerivator.h:197
 RichardsonDerivator.h:198
 RichardsonDerivator.h:199
 RichardsonDerivator.h:200
 RichardsonDerivator.h:201
 RichardsonDerivator.h:202
 RichardsonDerivator.h:203
 RichardsonDerivator.h:204
 RichardsonDerivator.h:205
 RichardsonDerivator.h:206
 RichardsonDerivator.h:207
 RichardsonDerivator.h:208
 RichardsonDerivator.h:209
 RichardsonDerivator.h:210
 RichardsonDerivator.h:211
 RichardsonDerivator.h:212
 RichardsonDerivator.h:213
 RichardsonDerivator.h:214
 RichardsonDerivator.h:215
 RichardsonDerivator.h:216
 RichardsonDerivator.h:217
 RichardsonDerivator.h:218
 RichardsonDerivator.h:219
 RichardsonDerivator.h:220