00001 // @(#)root/mathcore:$Id: RichardsonDerivator.cxx 24403 2008-06-20 08:31:10Z moneta $ 00002 // Authors: David Gonzalez Maline 01/2008 00003 00004 /********************************************************************** 00005 * * 00006 * Copyright (c) 2006 , LCG ROOT MathLib Team * 00007 * * 00008 * * 00009 **********************************************************************/ 00010 00011 #include "Math/RichardsonDerivator.h" 00012 #include <cmath> 00013 #include <limits> 00014 00015 #ifndef ROOT_Math_Error 00016 #include "Math/Error.h" 00017 #endif 00018 00019 namespace ROOT { 00020 namespace Math { 00021 00022 RichardsonDerivator::RichardsonDerivator(double h) : 00023 fFunctionCopied(false), 00024 fStepSize(h), 00025 fLastError(0), 00026 fFunction(0) 00027 { 00028 // Default Constructor. 00029 } 00030 RichardsonDerivator::RichardsonDerivator(const ROOT::Math::IGenFunction & f, double h, bool copyFunc) : 00031 fFunctionCopied(false), 00032 fStepSize(h), 00033 fLastError(0), 00034 fFunction(0) 00035 { 00036 // Constructor from a function and step size 00037 if (copyFunc) fFunction = f.Clone(); 00038 else fFunction = &f; 00039 } 00040 00041 RichardsonDerivator::~RichardsonDerivator() 00042 { 00043 // destructor 00044 if ( fFunction != 0 && fFunctionCopied ) 00045 delete fFunction; 00046 } 00047 00048 RichardsonDerivator::RichardsonDerivator(const RichardsonDerivator & rhs) 00049 { 00050 // copy constructor 00051 *this = rhs; 00052 } 00053 00054 RichardsonDerivator & RichardsonDerivator::operator= ( const RichardsonDerivator & rhs) 00055 { 00056 // Assignment operator 00057 fFunctionCopied = rhs.fFunctionCopied; 00058 fStepSize = rhs.fStepSize; 00059 fLastError = rhs.fLastError; 00060 fFunction = rhs.fFunction; 00061 if (fFunctionCopied && fFunction != 0) 00062 fFunction = fFunction->Clone(); 00063 return *this; 00064 } 00065 00066 double RichardsonDerivator::Derivative1 (double x) 00067 { 00068 const double kC1 = 1.E-15; 00069 00070 double h = fStepSize; 00071 00072 double xx[1]; 00073 xx[0] = x+h; double f1 = (*fFunction)(xx); 00074 //xx[0] = x; double fx = (*fFunction)(xx); // not needed 00075 xx[0] = x-h; double f2 = (*fFunction)(xx); 00076 00077 xx[0] = x+h/2; double g1 = (*fFunction)(xx); 00078 xx[0] = x-h/2; double g2 = (*fFunction)(xx); 00079 00080 //compute the central differences 00081 double h2 = 1/(2.*h); 00082 double d0 = f1 - f2; 00083 double d2 = g1 - g2; 00084 double deriv = h2*(8*d2 - d0)/3.; 00085 // compute the error ( to be improved ) this is just a simple truncation error 00086 fLastError = kC1*h2*0.5*(f1+f2); //compute the error 00087 00088 return deriv; 00089 } 00090 00091 double RichardsonDerivator::Derivative2 (double x) 00092 { 00093 const double kC1 = 2*1e-15; 00094 00095 double h = fStepSize; 00096 00097 double xx[1]; 00098 xx[0] = x+h; double f1 = (*fFunction)(xx); 00099 xx[0] = x; double f2 = (*fFunction)(xx); 00100 xx[0] = x-h; double f3 = (*fFunction)(xx); 00101 00102 xx[0] = x+h/2; double g1 = (*fFunction)(xx); 00103 xx[0] = x-h/2; double g3 = (*fFunction)(xx); 00104 00105 //compute the central differences 00106 double hh = 1/(h*h); 00107 double d0 = f3 - 2*f2 + f1; 00108 double d2 = 4*g3 - 8*f2 +4*g1; 00109 fLastError = kC1*hh*f2; //compute the error 00110 double deriv = hh*(4*d2 - d0)/3.; 00111 return deriv; 00112 } 00113 00114 double RichardsonDerivator::Derivative3 (double x) 00115 { 00116 const double kC1 = 1e-15; 00117 00118 double h = fStepSize; 00119 00120 double xx[1]; 00121 xx[0] = x+2*h; double f1 = (*fFunction)(xx); 00122 xx[0] = x+h; double f2 = (*fFunction)(xx); 00123 xx[0] = x-h; double f3 = (*fFunction)(xx); 00124 xx[0] = x-2*h; double f4 = (*fFunction)(xx); 00125 xx[0] = x; double fx = (*fFunction)(xx); 00126 xx[0] = x+h/2; double g2 = (*fFunction)(xx); 00127 xx[0] = x-h/2; double g3 = (*fFunction)(xx); 00128 00129 //compute the central differences 00130 double hhh = 1/(h*h*h); 00131 double d0 = 0.5*f1 - f2 +f3 - 0.5*f4; 00132 double d2 = 4*f2 - 8*g2 +8*g3 - 4*f3; 00133 fLastError = kC1*hhh*fx; //compute the error 00134 double deriv = hhh*(4*d2 - d0)/3.; 00135 return deriv; 00136 } 00137 00138 } // end namespace Math 00139 00140 } // end namespace ROOT