Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-16 09:08:10

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           @note ROOT::Math::Functor is the recommended way to use one's own function with the fitting framework.
0058 
0059           @ingroup  GenFunc
0060       */
0061 
0062       template<class T>
0063       class IBaseFunctionMultiDimTempl {
0064 
0065       public:
0066 
0067          typedef T BackendType;
0068          typedef  IBaseFunctionMultiDimTempl<T> BaseFunc;
0069 
0070          virtual ~IBaseFunctionMultiDimTempl() = default;
0071 
0072          /// Clone a function.
0073          /// Each derived class must implement their version of the Clone method.
0074          virtual IBaseFunctionMultiDimTempl<T> *Clone() const = 0;
0075 
0076          /// Retrieve the dimension of the function.
0077          virtual unsigned int NDim() const = 0;
0078 
0079          /// Evaluate the function at a point x[].
0080          /// Use the pure virtual private method DoEval which must be implemented by the sub-classes.
0081          T operator()(const T *x) const { return DoEval(x); }
0082 
0083 #ifdef LATER
0084          /// Template method to evaluate the function using the begin of an iterator.
0085          /// User is responsible to provide correct size for the iterator.
0086          template <class Iterator>
0087          T operator()(const Iterator it) const { return DoEval(&(*it)); }
0088 #endif
0089 
0090          // Indicate whether this class supports gradient calculations, i.e.,
0091          // if it inherits from ROOT::Math::IGradientFunctionMultiDim.
0092          virtual bool HasGradient() const { return false; }
0093 
0094       private:
0095 
0096          /// Implementation of the evaluation function. Must be implemented by derived classes.
0097          virtual T DoEval(const T *x) const = 0;
0098       };
0099 
0100 
0101 //___________________________________________________________________________________
0102       /**
0103           Interface (abstract class) for generic functions objects of one-dimension
0104           Provides a method to evaluate the function given a value (simple double)
0105           by implementing operator() (const double ).
0106           In addition it defines the interface for copying functions via the pure virtual method Clone().
0107           Derived classes must implement the pure virtual private method DoEval(double ) for the
0108           function evaluation in addition to  Clone().
0109           An interface for evaluating the function passing a vector (like for multidim functions) is also
0110           provided
0111 
0112           @ingroup  GenFunc
0113       */
0114       class IBaseFunctionOneDim {
0115 
0116       public:
0117 
0118          typedef  IBaseFunctionOneDim BaseFunc;
0119 
0120          virtual ~IBaseFunctionOneDim() = default;
0121 
0122          /// Clone a function.
0123          /// Each derived class will implement their version of the private DoClone method.
0124          virtual IBaseFunctionOneDim *Clone() const = 0;
0125 
0126          /// Evaluate the function at a point x.
0127          /// Use the a pure virtual private method DoEval which must be implemented by sub-classes.
0128          double operator()(double x) const { return DoEval(x); }
0129 
0130          /// Evaluate the function at a point x[].
0131          /// Compatible method with multi-dimensional functions.
0132          double operator()(const double *x) const { return DoEval(*x); }
0133 
0134          // Indicate whether this class supports gradient calculations, i.e.,
0135          // if it inherits from ROOT::Math::IGradientFunctionOneDim.
0136          virtual bool HasGradient() const { return false; }
0137 
0138       private:
0139 
0140          /// implementation of the evaluation function. Must be implemented by derived classes
0141          virtual double DoEval(double x) const = 0;
0142       };
0143 
0144 
0145 //-------- GRAD  functions---------------------------
0146 
0147 
0148 
0149 //___________________________________________________________________________________
0150       /**
0151          Interface (abstract class) for multi-dimensional functions providing a gradient calculation.
0152          The method ROOT::Math::IFunction::Gradient calculates the full gradient vector,
0153          ROOT::Math::IFunction::Derivative calculates the partial derivative for each coordinate and
0154          ROOT::Math::Fdf calculates the gradient and the function value at the same time.
0155          The pure private virtual method DoDerivative() must be implemented by the derived classes, while
0156          Gradient and FdF are by default implemented using DoDerivative, butthey  can be overloaded by the
0157          derived classes to improve the efficiency in the derivative calculation.
0158 
0159          Gradient interface (abstract class) defining the signature for calculating the gradient of a
0160          multi-dimensional function.
0161          Three methods are provided:
0162          - Gradient(const double *x, double * grad) evaluate the full gradient vector at the vector value x
0163          - Derivative(const double * x, int icoord) evaluate the partial derivative for the icoord coordinate
0164          - FdF(const double *x, double &f, double * g) evaluate at the same time gradient and function/
0165 
0166          @ingroup  GenFunc
0167       */
0168 
0169       template <class T>
0170       class IGradientFunctionMultiDimTempl : virtual public IBaseFunctionMultiDimTempl<T> {
0171 
0172       public:
0173          typedef IBaseFunctionMultiDimTempl<T> BaseFunc;
0174          typedef IGradientFunctionMultiDimTempl<T> BaseGrad;
0175 
0176 
0177          /// Evaluate all the vector of function derivatives (gradient)  at a point x.
0178          /// Derived classes must re-implement it if more efficient than evaluating one at a time
0179          virtual void Gradient(const T *x, T *grad) const
0180          {
0181             unsigned int ndim = NDim();
0182             for (unsigned int icoord  = 0; icoord < ndim; ++icoord) {
0183                grad[icoord] = Derivative(x, icoord);
0184             }
0185          }
0186 
0187          /// In some cases, the gradient algorithm will use information from the previous step, these can be passed
0188          /// in with this overload. The `previous_*` arrays can also be used to return second derivative and step size
0189          /// so that these can be passed forward again as well at the call site, if necessary.
0190          virtual void GradientWithPrevResult(const T *x, T *grad, T *previous_grad, T *previous_g2, T *previous_gstep) const
0191          {
0192             unsigned int ndim = NDim();
0193             for (unsigned int icoord  = 0; icoord < ndim; ++icoord) {
0194                grad[icoord] = Derivative(x, icoord, previous_grad, previous_g2, previous_gstep);
0195             }
0196          }
0197 
0198          using BaseFunc::NDim;
0199 
0200          /// Optimized method to evaluate at the same time the function value and derivative at a point x.
0201          /// Often both value and derivatives are needed and it is often more efficient to compute them at the same time.
0202          /// Derived class should implement this method if performances play an important role and if it is faster to
0203          /// evaluate value and derivative at the same time
0204          virtual void FdF(const T *x, T &f, T *df) const
0205          {
0206             f = BaseFunc::operator()(x);
0207             Gradient(x, df);
0208          }
0209 
0210          /// Return the partial derivative with respect to the passed coordinate.
0211          T Derivative(const T *x, unsigned int icoord = 0) const { return DoDerivative(x, icoord); }
0212 
0213          /// In some cases, the derivative algorithm will use information from the previous step, these can be passed
0214          /// in with this overload. The `previous_*` arrays can also be used to return second derivative and step size
0215          /// so that these can be passed forward again as well at the call site, if necessary.
0216          T Derivative(const T *x, unsigned int icoord, T *previous_grad, T *previous_g2,
0217                       T *previous_gstep) const
0218          {
0219             return DoDerivativeWithPrevResult(x, icoord, previous_grad, previous_g2, previous_gstep);
0220          }
0221 
0222          bool HasGradient() const { return true; }
0223 
0224          virtual bool returnsInMinuit2ParameterSpace() const { return false; }
0225 
0226       private:
0227          /// Function to evaluate the derivative with respect each coordinate. To be implemented by the derived class.
0228          virtual T DoDerivative(const T *x, unsigned int icoord) const = 0;
0229 
0230          /// In some cases, the derivative algorithm will use information from the previous step, these can be passed
0231          /// in with this overload. The `previous_*` arrays can also be used to return second derivative and step size
0232          /// so that these can be passed forward again as well at the call site, if necessary.
0233          virtual T DoDerivativeWithPrevResult(const T *x, unsigned int icoord, T * /*previous_grad*/,
0234                                               T * /*previous_g2*/, T * /*previous_gstep*/) const
0235          {
0236             return DoDerivative(x, icoord);
0237          }
0238       };
0239 
0240 
0241 //___________________________________________________________________________________
0242       /**
0243          Interface (abstract class) for one-dimensional functions providing a gradient calculation.
0244          The method  ROOT::Math::IFunction::Derivative calculates the derivative  and
0245          ROOT::Math::Fdf calculates the derivative and the function values at the same time.
0246          The pure private virtual method DoDerivative() must be implemented by the derived classes, while
0247          FdF is by default implemented using DoDerivative, but it can be overloaded by the
0248          derived classes to improve the efficiency in the derivative calculation.
0249 
0250          Specialized Gradient interface(abstract class)  for one dimensional functions
0251          It provides a method to evaluate the derivative of the function, Derivative and a
0252          method to evaluate at the same time the function and the derivative FdF
0253 
0254          @ingroup  GenFunc
0255       */
0256       class IGradientFunctionOneDim : virtual public IBaseFunctionOneDim {
0257 
0258       public:
0259 
0260          typedef IBaseFunctionOneDim BaseFunc;
0261          typedef IGradientFunctionOneDim BaseGrad;
0262 
0263          /// Return the derivative of the function at a point x
0264          /// Use the private method DoDerivative
0265          double Derivative(double x) const { return DoDerivative(x); }
0266 
0267          /// Compatibility method with multi-dimensional interface for partial derivative.
0268          double Derivative(const double *x) const { return DoDerivative(*x); }
0269 
0270          /// Compatibility method with multi-dimensional interface for Gradient.
0271          void Gradient(const double *x, double *g) const { g[0] = DoDerivative(*x); }
0272 
0273          /// Optimized method to evaluate at the same time the function value and derivative at a point x.
0274          /// Often both value and derivatives are needed and it is often more efficient to compute them at the same time.
0275          /// Derived class should implement this method if performances play an important role and if it is faster to
0276          /// evaluate value and derivative at the same time.
0277          virtual void FdF(double x, double &f, double &df) const
0278          {
0279             f = operator()(x);
0280             df = Derivative(x);
0281          }
0282 
0283          /// Compatibility method with multi-dimensional interface for Gradient and function evaluation.
0284          void FdF(const double *x, double &f, double *df) const { FdF(*x, f, *df); }
0285 
0286          bool HasGradient() const override { return true; }
0287 
0288       private:
0289 
0290          /// Function to evaluate the derivative with respect each coordinate. To be implemented by the derived class.
0291          virtual  double  DoDerivative(double x) const = 0;
0292       };
0293 
0294 
0295 
0296    } // namespace Math
0297 } // namespace ROOT
0298 
0299 #endif /* ROOT_Math_IFunction */