Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-15 10:28:18

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