00001 // @(#)root/mathcore:$Id: IFunction.h 24482 2008-06-23 15:33:08Z moneta $ 00002 // Authors: L. Moneta 11/2006 00003 00004 /********************************************************************** 00005 * * 00006 * Copyright (c) 2006 , LCG ROOT MathLib Team * 00007 * * 00008 * * 00009 **********************************************************************/ 00010 00011 // Header file for function interfaces 00012 // 00013 // Generic Interfaces for one or multi-dimensional functions 00014 // 00015 // Created by: Lorenzo Moneta : Wed Nov 13 2006 00016 // 00017 // 00018 #ifndef ROOT_Math_IFunction 00019 #define ROOT_Math_IFunction 00020 00021 /** 00022 @defgroup CppFunctions Function Classes and Interfaces 00023 00024 Interfaces (abstract classes) and Base classes used in MathCore and MathMore numerical methods 00025 for describing function classes. They define function and gradient evaluation and as well the 00026 functionality for dealing with parameters in the case of parametric functions which are used for 00027 fitting and data modeling. 00028 Included are also adapter classes, such as functors, to wrap generic callable C++ objects 00029 in the desired interface. 00030 */ 00031 00032 //typedefs and tags definitions 00033 #ifndef ROOT_Math_IFunctionfwd 00034 #include "Math/IFunctionfwd.h" 00035 #endif 00036 00037 00038 namespace ROOT { 00039 namespace Math { 00040 00041 /** 00042 @defgroup GenFunc Interfaces for generic function evaluation 00043 @ingroup CppFunctions 00044 */ 00045 00046 //___________________________________________________________________________________ 00047 /** 00048 Documentation for the abstract class IBaseFunctionMultiDim. 00049 Interface (abstract class) for generic functions objects of multi-dimension 00050 Provides a method to evaluate the function given a vector of coordinate values, 00051 by implementing operator() (const double *). 00052 In addition it defines the interface for copying functions via the pure virtual method Clone() 00053 and the interface for getting the function dimension via the NDim() method. 00054 Derived classes must implement the pure private virtual method DoEval(const double *) for the 00055 function evaluation in addition to NDim() and Clone(). 00056 00057 @ingroup GenFunc 00058 */ 00059 00060 class IBaseFunctionMultiDim { 00061 00062 public: 00063 00064 typedef IBaseFunctionMultiDim BaseFunc; 00065 00066 00067 IBaseFunctionMultiDim() {} 00068 00069 /** 00070 virtual destructor 00071 */ 00072 virtual ~IBaseFunctionMultiDim() {} 00073 00074 /** 00075 Clone a function. 00076 Each derived class must implement his version of the Clone method 00077 */ 00078 virtual IBaseFunctionMultiDim * Clone() const = 0; 00079 00080 /** 00081 Retrieve the dimension of the function 00082 */ 00083 virtual unsigned int NDim() const = 0; 00084 00085 /** 00086 Evaluate the function at a point x[]. 00087 Use the pure virtual private method DoEval which must be implemented by the sub-classes 00088 */ 00089 double operator() (const double* x) const { 00090 return DoEval(x); 00091 } 00092 00093 #ifdef LATER 00094 /** 00095 Template method to eveluate the function using the begin of an iterator 00096 User is responsible to provide correct size for the iterator 00097 */ 00098 template <class Iterator> 00099 double operator() (const Iterator it ) const { 00100 return DoEval( &(*it) ); 00101 } 00102 #endif 00103 00104 00105 private: 00106 00107 00108 /** 00109 Implementation of the evaluation function. Must be implemented by derived classes 00110 */ 00111 virtual double DoEval(const double * x) const = 0; 00112 00113 00114 }; 00115 00116 00117 //___________________________________________________________________________________ 00118 /** 00119 Interface (abstract class) for generic functions objects of one-dimension 00120 Provides a method to evaluate the function given a value (simple double) 00121 by implementing operator() (const double ). 00122 In addition it defines the interface for copying functions via the pure virtual method Clone(). 00123 Derived classes must implement the pure virtual private method DoEval(double ) for the 00124 function evaluation in addition to Clone(). 00125 An interface for evaluating the function passing a vector (like for multidim functions) is also 00126 provided 00127 00128 @ingroup GenFunc 00129 */ 00130 class IBaseFunctionOneDim { 00131 00132 public: 00133 00134 typedef IBaseFunctionOneDim BaseFunc; 00135 00136 IBaseFunctionOneDim() {} 00137 00138 /** 00139 virtual destructor 00140 */ 00141 virtual ~IBaseFunctionOneDim() {} 00142 00143 /** 00144 Clone a function. 00145 Each derived class will implement his version of the provate DoClone method 00146 */ 00147 virtual IBaseFunctionOneDim * Clone() const = 0; 00148 00149 /** 00150 Evaluate the function at a point x 00151 Use the a pure virtual private method DoEval which must be implemented by sub-classes 00152 */ 00153 double operator() (double x) const { 00154 return DoEval(x); 00155 } 00156 00157 /** 00158 Evaluate the function at a point x[]. 00159 Compatible method with multi-dimensional functions 00160 */ 00161 double operator() (const double * x) const { 00162 return DoEval(*x); 00163 } 00164 00165 00166 00167 private: 00168 00169 // use private virtual inheritance 00170 00171 /// implementation of the evaluation function. Must be implemented by derived classes 00172 virtual double DoEval(double x) const = 0; 00173 00174 }; 00175 00176 00177 //-------- GRAD functions--------------------------- 00178 00179 //___________________________________________________________________________________ 00180 /** 00181 Gradient interface (abstract class) defining the signature for calculating the gradient of a 00182 multi-dimensional function. 00183 Three methods are provided: 00184 - Gradient(const double *x, double * grad) evaluate the full gradient vector at the vector value x 00185 - Derivative(const double * x, int icoord) evaluate the partial derivative for the icoord coordinate 00186 - FdF(const double *x, double &f, double * g) evaluate at the same time gradient and function/ 00187 00188 Concrete classes should derive from ROOT::Math::IGradientFunctionMultiDim and not from this class. 00189 00190 @ingroup GenFunc 00191 */ 00192 00193 class IGradientMultiDim { 00194 00195 public: 00196 00197 /// virual destructor 00198 virtual ~IGradientMultiDim() {} 00199 00200 /** 00201 Evaluate all the vector of function derivatives (gradient) at a point x. 00202 Derived classes must re-implement if it is more efficient than evaluting one at a time 00203 */ 00204 virtual void Gradient(const double *x, double * grad) const = 0; 00205 00206 /** 00207 Return the partial derivative with respect to the passed coordinate 00208 */ 00209 double Derivative(const double * x, unsigned int icoord = 0) const { 00210 return DoDerivative(x, icoord); 00211 } 00212 00213 00214 /** 00215 Optimized method to evaluate at the same time the function value and derivative at a point x. 00216 Often both value and derivatives are needed and it is often more efficient to compute them at the same time. 00217 Derived class should implement this method if performances play an important role and if it is faster to 00218 evaluate value and derivative at the same time 00219 00220 */ 00221 virtual void FdF (const double * x, double & f, double * df) const = 0; 00222 00223 00224 private: 00225 00226 00227 /** 00228 function to evaluate the derivative with respect each coordinate. To be implemented by the derived class 00229 */ 00230 virtual double DoDerivative(const double * x, unsigned int icoord ) const = 0; 00231 00232 }; 00233 00234 //___________________________________________________________________________________ 00235 /** 00236 Specialized Gradient interface(abstract class) for one dimensional functions 00237 It provides a method to evaluate the derivative of the function, Derivative and a 00238 method to evaluate at the same time the function and the derivative FdF 00239 00240 Concrete classes should derive from ROOT::Math::IGradientFunctionOneDim and not from this class. 00241 00242 @ingroup GenFunc 00243 */ 00244 class IGradientOneDim { 00245 00246 public: 00247 00248 /// virtual destructor 00249 virtual ~IGradientOneDim() {} 00250 00251 /** 00252 Return the derivative of the function at a point x 00253 Use the private method DoDerivative 00254 */ 00255 double Derivative(double x ) const { 00256 return DoDerivative(x ); 00257 } 00258 00259 00260 /** 00261 Optimized method to evaluate at the same time the function value and derivative at a point x. 00262 Often both value and derivatives are needed and it is often more efficient to compute them at the same time. 00263 Derived class should implement this method if performances play an important role and if it is faster to 00264 evaluate value and derivative at the same time 00265 00266 */ 00267 virtual void FdF (double x, double & f, double & df) const = 0; 00268 00269 00270 /** 00271 Compatibility method with multi-dimensional interface for partial derivative 00272 */ 00273 double Derivative(const double * x) const { 00274 return DoDerivative( *x); 00275 } 00276 00277 /** 00278 Compatibility method with multi-dimensional interface for Gradient 00279 */ 00280 void Gradient(const double * x, double *g) const { 00281 g[0] = DoDerivative( *x); 00282 } 00283 00284 /** 00285 Compatibility method with multi-dimensional interface for Gradient and function evaluation 00286 */ 00287 void FdF(const double * x, double & f, double * df) const { 00288 FdF(*x, f, *df); 00289 } 00290 00291 00292 00293 private: 00294 00295 00296 /** 00297 function to evaluate the derivative with respect each coordinate. To be implemented by the derived class 00298 */ 00299 virtual double DoDerivative(double x ) const = 0; 00300 00301 }; 00302 00303 //___________________________________________________________________________________ 00304 /** 00305 Interface (abstract class) for multi-dimensional functions providing a gradient calculation. 00306 It implements both the ROOT::Math::IBaseFunctionMultiDim and 00307 ROOT::Math::IGradientMultiDim interfaces. 00308 The method ROOT::Math::IFunction::Gradient calculates the full gradient vector, 00309 ROOT::Math::IFunction::Derivative calculates the partial derivative for each coordinate and 00310 ROOT::Math::Fdf calculates the gradient and the function value at the same time. 00311 The pure private virtual method DoDerivative() must be implemented by the derived classes, while 00312 Gradient and FdF are by default implemented using DoDerivative, butthey can be overloaded by the 00313 derived classes to improve the efficiency in the derivative calculation. 00314 00315 @ingroup GenFunc 00316 */ 00317 00318 class IGradientFunctionMultiDim : 00319 virtual public IBaseFunctionMultiDim , 00320 public IGradientMultiDim { 00321 00322 00323 public: 00324 00325 typedef IBaseFunctionMultiDim BaseFunc; 00326 typedef IGradientMultiDim BaseGrad; 00327 00328 00329 /** 00330 Virtual Destructor (no operations) 00331 */ 00332 virtual ~IGradientFunctionMultiDim () {} 00333 00334 /** 00335 Evaluate all the vector of function derivatives (gradient) at a point x. 00336 Derived classes must re-implement it if more efficient than evaluting one at a time 00337 */ 00338 virtual void Gradient(const double *x, double * grad) const { 00339 unsigned int ndim = NDim(); 00340 for (unsigned int icoord = 0; icoord < ndim; ++icoord) 00341 grad[icoord] = BaseGrad::Derivative(x,icoord); 00342 } 00343 00344 using BaseFunc::NDim; 00345 00346 00347 /** 00348 Optimized method to evaluate at the same time the function value and derivative at a point x. 00349 Often both value and derivatives are needed and it is often more efficient to compute them at the same time. 00350 Derived class should implement this method if performances play an important role and if it is faster to 00351 evaluate value and derivative at the same time 00352 00353 */ 00354 virtual void FdF (const double * x, double & f, double * df) const { 00355 f = BaseFunc::operator()(x); 00356 Gradient(x,df); 00357 } 00358 00359 00360 }; 00361 00362 00363 //___________________________________________________________________________________ 00364 /** 00365 Interface (abstract class) for one-dimensional functions providing a gradient calculation. 00366 It implements both the ROOT::Math::IBaseFunctionOneDim and 00367 ROOT::Math::IGradientOneDim interfaces. 00368 The method ROOT::Math::IFunction::Derivative calculates the derivative and 00369 ROOT::Math::Fdf calculates the derivative and the function values at the same time. 00370 The pure private virtual method DoDerivative() must be implemented by the derived classes, while 00371 FdF is by default implemented using DoDerivative, but it can be overloaded by the 00372 derived classes to improve the efficiency in the derivative calculation. 00373 00374 00375 @ingroup GenFunc 00376 */ 00377 //template <> 00378 class IGradientFunctionOneDim : 00379 virtual public IBaseFunctionOneDim , 00380 public IGradientOneDim { 00381 00382 00383 public: 00384 00385 typedef IBaseFunctionOneDim BaseFunc; 00386 typedef IGradientOneDim BaseGrad; 00387 00388 00389 /** 00390 Virtual Destructor (no operations) 00391 */ 00392 virtual ~IGradientFunctionOneDim () {} 00393 00394 00395 /** 00396 Optimized method to evaluate at the same time the function value and derivative at a point x. 00397 Often both value and derivatives are needed and it is often more efficient to compute them at the same time. 00398 Derived class should implement this method if performances play an important role and if it is faster to 00399 evaluate value and derivative at the same time 00400 00401 */ 00402 virtual void FdF (double x, double & f, double & df) const { 00403 f = operator()(x); 00404 df = Derivative(x); 00405 } 00406 00407 00408 00409 }; 00410 00411 00412 00413 00414 00415 } // namespace Math 00416 } // namespace ROOT 00417 00418 #endif /* ROOT_Math_IGenFunction */