Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 10:22:05

0001 // @(#)root/mathcore:$Id$
0002 // Authors: L. Moneta    11/2006
0003 
0004 /**********************************************************************
0005  *                                                                    *
0006  * Copyright (c) 2006 , LCG ROOT MathLib Team                         *
0007  *                                                                    *
0008  *                                                                    *
0009  **********************************************************************/
0010 
0011 // Header file for function interfaces
0012 //
0013 // Generic Interfaces for one or  multi-dimensional functions
0014 //
0015 // Created by: Lorenzo Moneta  : Wed Nov 13 2006
0016 //
0017 //
0018 #ifndef ROOT_Math_IFunction
0019 #define ROOT_Math_IFunction
0020 
0021 /**
0022 @defgroup CppFunctions Function Classes and Interfaces
0023 
0024  Interfaces (abstract classes) and Base classes used in MathCore and MathMore numerical methods
0025  for describing function classes. They define function and gradient evaluation and as well the
0026  functionality for dealing with parameters in the case of parametric functions which are used for
0027  fitting and data modeling.
0028  Included are also adapter classes, such as  functors, to wrap generic callable C++ objects
0029  in the desired interface.
0030 
0031 @ingroup MathCore
0032 */
0033 
0034 #include "Math/IFunctionfwd.h"
0035 
0036 
0037 namespace ROOT {
0038    namespace Math {
0039 
0040       /**
0041          @defgroup GenFunc Generic Function Evaluation Interfaces
0042          Interface classes for evaluation of function object classes in one or multi-dimensions.
0043          @ingroup CppFunctions
0044       */
0045 
0046 //___________________________________________________________________________________
0047       /**
0048           Documentation for the abstract class IBaseFunctionMultiDim.
0049           Interface (abstract class) for generic functions objects of multi-dimension
0050           Provides a method to evaluate the function given a vector of coordinate values,
0051           by implementing operator() (const double *).
0052           In addition it defines the interface for copying functions via the pure virtual method Clone()
0053           and the interface for getting the function dimension via the NDim() method.
0054           Derived classes must implement the pure private virtual method DoEval(const double *) for the
0055           function evaluation in addition to NDim() and Clone().
0056 
0057           @ingroup  GenFunc
0058       */
0059 
0060       template<class T>
0061       class IBaseFunctionMultiDimTempl {
0062 
0063       public:
0064 
0065          typedef T BackendType;
0066          typedef  IBaseFunctionMultiDimTempl<T> BaseFunc;
0067 
0068          virtual ~IBaseFunctionMultiDimTempl() = default;
0069 
0070          /// Clone a function.
0071          /// Each derived class must implement their version of the Clone method.
0072          virtual IBaseFunctionMultiDimTempl<T> *Clone() const = 0;
0073 
0074          /// Retrieve the dimension of the function.
0075          virtual unsigned int NDim() const = 0;
0076 
0077          /// Evaluate the function at a point x[].
0078          /// Use the pure virtual private method DoEval which must be implemented by the sub-classes.
0079          T operator()(const T *x) const { return DoEval(x); }
0080 
0081 #ifdef LATER
0082          /// Template method to evaluate the function using the begin of an iterator.
0083          /// User is responsible to provide correct size for the iterator.
0084          template <class Iterator>
0085          T operator()(const Iterator it) const { return DoEval(&(*it)); }
0086 #endif
0087 
0088          // Indicate whether this class supports gradient calculations, i.e.,
0089          // if it inherits from ROOT::Math::IGradientFunctionMultiDim.
0090          virtual bool HasGradient() const { return false; }
0091 
0092       private:
0093 
0094          /// Implementation of the evaluation function. Must be implemented by derived classes.
0095          virtual T DoEval(const T *x) const = 0;
0096       };
0097 
0098 
0099 //___________________________________________________________________________________
0100       /**
0101           Interface (abstract class) for generic functions objects of one-dimension
0102           Provides a method to evaluate the function given a value (simple double)
0103           by implementing operator() (const double ).
0104           In addition it defines the interface for copying functions via the pure virtual method Clone().
0105           Derived classes must implement the pure virtual private method DoEval(double ) for the
0106           function evaluation in addition to  Clone().
0107           An interface for evaluating the function passing a vector (like for multidim functions) is also
0108           provided
0109 
0110           @ingroup  GenFunc
0111       */
0112       class IBaseFunctionOneDim {
0113 
0114       public:
0115 
0116          typedef  IBaseFunctionOneDim BaseFunc;
0117 
0118          virtual ~IBaseFunctionOneDim() = default;
0119 
0120          /// Clone a function.
0121          /// Each derived class will implement their version of the private DoClone method.
0122          virtual IBaseFunctionOneDim *Clone() const = 0;
0123 
0124          /// Evaluate the function at a point x.
0125          /// Use the a pure virtual private method DoEval which must be implemented by sub-classes.
0126          double operator()(double x) const { return DoEval(x); }
0127 
0128          /// Evaluate the function at a point x[].
0129          /// Compatible method with multi-dimensional functions.
0130          double operator()(const double *x) const { return DoEval(*x); }
0131 
0132          // Indicate whether this class supports gradient calculations, i.e.,
0133          // if it inherits from ROOT::Math::IGradientFunctionOneDim.
0134          virtual bool HasGradient() const { return false; }
0135 
0136       private:
0137 
0138          /// implementation of the evaluation function. Must be implemented by derived classes
0139          virtual double DoEval(double x) const = 0;
0140       };
0141 
0142 
0143 //-------- GRAD  functions---------------------------
0144 
0145 
0146 
0147 //___________________________________________________________________________________
0148       /**
0149          Interface (abstract class) for multi-dimensional functions providing a gradient calculation.
0150          The method ROOT::Math::IFunction::Gradient calculates the full gradient vector,
0151          ROOT::Math::IFunction::Derivative calculates the partial derivative for each coordinate and
0152          ROOT::Math::Fdf calculates the gradient and the function value at the same time.
0153          The pure private virtual method DoDerivative() must be implemented by the derived classes, while
0154          Gradient and FdF are by default implemented using DoDerivative, butthey  can be overloaded by the
0155          derived classes to improve the efficiency in the derivative calculation.
0156 
0157          Gradient interface (abstract class) defining the signature for calculating the gradient of a
0158          multi-dimensional function.
0159          Three methods are provided:
0160          - Gradient(const double *x, double * grad) evaluate the full gradient vector at the vector value x
0161          - Derivative(const double * x, int icoord) evaluate the partial derivative for the icoord coordinate
0162          - FdF(const double *x, double &f, double * g) evaluate at the same time gradient and function/
0163 
0164          @ingroup  GenFunc
0165       */
0166 
0167       template <class T>
0168       class IGradientFunctionMultiDimTempl : virtual public IBaseFunctionMultiDimTempl<T> {
0169 
0170       public:
0171          typedef IBaseFunctionMultiDimTempl<T> BaseFunc;
0172          typedef IGradientFunctionMultiDimTempl<T> BaseGrad;
0173 
0174 
0175          /// Evaluate all the vector of function derivatives (gradient)  at a point x.
0176          /// Derived classes must re-implement it if more efficient than evaluating one at a time
0177          virtual void Gradient(const T *x, T *grad) const
0178          {
0179             unsigned int ndim = NDim();
0180             for (unsigned int icoord  = 0; icoord < ndim; ++icoord) {
0181                grad[icoord] = Derivative(x, icoord);
0182             }
0183          }
0184 
0185          /// In some cases, the gradient algorithm will use information from the previous step, these can be passed
0186          /// in with this overload. The `previous_*` arrays can also be used to return second derivative and step size
0187          /// so that these can be passed forward again as well at the call site, if necessary.
0188          virtual void GradientWithPrevResult(const T *x, T *grad, T *previous_grad, T *previous_g2, T *previous_gstep) const
0189          {
0190             unsigned int ndim = NDim();
0191             for (unsigned int icoord  = 0; icoord < ndim; ++icoord) {
0192                grad[icoord] = Derivative(x, icoord, previous_grad, previous_g2, previous_gstep);
0193             }
0194          }
0195 
0196          using BaseFunc::NDim;
0197 
0198          /// Optimized method to evaluate at the same time the function value and derivative at a point x.
0199          /// Often both value and derivatives are needed and it is often more efficient to compute them at the same time.
0200          /// Derived class should implement this method if performances play an important role and if it is faster to
0201          /// evaluate value and derivative at the same time
0202          virtual void FdF(const T *x, T &f, T *df) const
0203          {
0204             f = BaseFunc::operator()(x);
0205             Gradient(x, df);
0206          }
0207 
0208          /// Return the partial derivative with respect to the passed coordinate.
0209          T Derivative(const T *x, unsigned int icoord = 0) const { return DoDerivative(x, icoord); }
0210 
0211          /// In some cases, the derivative algorithm will use information from the previous step, these can be passed
0212          /// in with this overload. The `previous_*` arrays can also be used to return second derivative and step size
0213          /// so that these can be passed forward again as well at the call site, if necessary.
0214          T Derivative(const T *x, unsigned int icoord, T *previous_grad, T *previous_g2,
0215                       T *previous_gstep) const
0216          {
0217             return DoDerivativeWithPrevResult(x, icoord, previous_grad, previous_g2, previous_gstep);
0218          }
0219 
0220          bool HasGradient() const { return true; }
0221 
0222          virtual bool returnsInMinuit2ParameterSpace() const { return false; }
0223 
0224       private:
0225          /// Function to evaluate the derivative with respect each coordinate. To be implemented by the derived class.
0226          virtual T DoDerivative(const T *x, unsigned int icoord) const = 0;
0227 
0228          /// In some cases, the derivative algorithm will use information from the previous step, these can be passed
0229          /// in with this overload. The `previous_*` arrays can also be used to return second derivative and step size
0230          /// so that these can be passed forward again as well at the call site, if necessary.
0231          virtual T DoDerivativeWithPrevResult(const T *x, unsigned int icoord, T * /*previous_grad*/,
0232                                               T * /*previous_g2*/, T * /*previous_gstep*/) const
0233          {
0234             return DoDerivative(x, icoord);
0235          }
0236       };
0237 
0238 
0239 //___________________________________________________________________________________
0240       /**
0241          Interface (abstract class) for one-dimensional functions providing a gradient calculation.
0242          The method  ROOT::Math::IFunction::Derivative calculates the derivative  and
0243          ROOT::Math::Fdf calculates the derivative and the function values at the same time.
0244          The pure private virtual method DoDerivative() must be implemented by the derived classes, while
0245          FdF is by default implemented using DoDerivative, but it can be overloaded by the
0246          derived classes to improve the efficiency in the derivative calculation.
0247 
0248          Specialized Gradient interface(abstract class)  for one dimensional functions
0249          It provides a method to evaluate the derivative of the function, Derivative and a
0250          method to evaluate at the same time the function and the derivative FdF
0251 
0252          @ingroup  GenFunc
0253       */
0254       class IGradientFunctionOneDim : virtual public IBaseFunctionOneDim {
0255 
0256       public:
0257 
0258          typedef IBaseFunctionOneDim BaseFunc;
0259          typedef IGradientFunctionOneDim BaseGrad;
0260 
0261          /// Return the derivative of the function at a point x
0262          /// Use the private method DoDerivative
0263          double Derivative(double x) const { return DoDerivative(x); }
0264 
0265          /// Compatibility method with multi-dimensional interface for partial derivative.
0266          double Derivative(const double *x) const { return DoDerivative(*x); }
0267 
0268          /// Compatibility method with multi-dimensional interface for Gradient.
0269          void Gradient(const double *x, double *g) const { g[0] = DoDerivative(*x); }
0270 
0271          /// Optimized method to evaluate at the same time the function value and derivative at a point x.
0272          /// Often both value and derivatives are needed and it is often more efficient to compute them at the same time.
0273          /// Derived class should implement this method if performances play an important role and if it is faster to
0274          /// evaluate value and derivative at the same time.
0275          virtual void FdF(double x, double &f, double &df) const
0276          {
0277             f = operator()(x);
0278             df = Derivative(x);
0279          }
0280 
0281          /// Compatibility method with multi-dimensional interface for Gradient and function evaluation.
0282          void FdF(const double *x, double &f, double *df) const { FdF(*x, f, *df); }
0283 
0284          bool HasGradient() const override { return true; }
0285 
0286       private:
0287 
0288          /// Function to evaluate the derivative with respect each coordinate. To be implemented by the derived class.
0289          virtual  double  DoDerivative(double x) const = 0;
0290       };
0291 
0292 
0293 
0294    } // namespace Math
0295 } // namespace ROOT
0296 
0297 #endif /* ROOT_Math_IFunction */