Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:10:16

0001 // @(#)root/mathcore:$Id$
0002 // Author: L. Moneta Mon Nov 13 15:58:13 2006
0003 
0004 /**********************************************************************
0005  *                                                                    *
0006  * Copyright (c) 2006  LCG ROOT Math Team, CERN/PH-SFT                *
0007  *                                                                    *
0008  *                                                                    *
0009  **********************************************************************/
0010 
0011 // Header file for Functor classes.
0012 // designed is inspired by the Loki Functor
0013 
0014 #ifndef ROOT_Math_Functor
0015 #define ROOT_Math_Functor
0016 
0017 #include "Math/IFunction.h"
0018 
0019 // #ifndef Root_Math_StaticCheck
0020 // #include "Math/StaticCheck.h"
0021 // #endif
0022 
0023 #include <memory>
0024 #include <functional>
0025 #include <vector>
0026 
0027 namespace ROOT {
0028 
0029 namespace Math {
0030 
0031 /**
0032    Documentation for class Functor class.
0033    It is used to wrap in a very simple and convenient way multi-dimensional function objects.
0034    It can wrap all the following types:
0035    <ul>
0036    <li> any C++ callable object implementation double operator()( const double *  )
0037    <li> a free C function of type double ()(const double * )
0038    <li> an std::function of type std::function<double (double const *)>
0039    <li> a member function with the correct signature like Foo::Eval(const double * ).
0040        In this case one pass the object pointer and a pointer to the member function (&Foo::Eval)
0041    </ul>
0042    The function dimension is required when constructing the functor.
0043 
0044    @ingroup  GenFunc
0045 
0046  */
0047 class Functor : public IBaseFunctionMultiDim  {
0048 
0049 public:
0050 
0051    /// Default constructor.
0052    Functor ()  {}
0053 
0054    /// Construct from a pointer to member function (multi-dim type).
0055    template <class PtrObj, typename MemFn>
0056    Functor(const PtrObj& p, MemFn memFn, unsigned int dim )
0057       : fDim{dim}, fFunc{std::bind(memFn, p, std::placeholders::_1)}
0058    {}
0059 
0060    /// Construct from a callable object of multi-dimension
0061    /// with the right signature (implementing `double operator()(const double *x)`).
0062    Functor(std::function<double(double const *)> const& f, unsigned int dim ) : fDim{dim}, fFunc{f} {}
0063 
0064    // clone of the function handler (use copy-ctor)
0065    Functor * Clone() const override { return new Functor(*this); }
0066 
0067    // for multi-dimensional functions
0068    unsigned int NDim() const override { return fDim; }
0069 
0070 private :
0071 
0072    inline double DoEval (const double * x) const override {
0073       return fFunc(x);
0074    }
0075 
0076    unsigned int fDim;
0077    std::function<double(double const *)> fFunc;
0078 };
0079 
0080 /**
0081    Functor1D class for one-dimensional functions.
0082    It is used to wrap in a very simple and convenient way:
0083    <ul>
0084    <li> any C++ callable object implementation double operator()( double  )
0085    <li> a free C function of type double ()(double )
0086    <li> a member function with the correct signature like Foo::Eval(double ).
0087        In this case one pass the object pointer and a pointer to the member function (&Foo::Eval)
0088    </ul>
0089 
0090 
0091    @ingroup  GenFunc
0092 
0093  */
0094 
0095 class Functor1D : public IBaseFunctionOneDim  {
0096 
0097 public:
0098 
0099    /// Default constructor.
0100    Functor1D() = default;
0101 
0102    /// Construct from a callable object with the right signature
0103    /// implementing `double operator() (double x)`.
0104    Functor1D(std::function<double(double)> const& f) : fFunc{f} {}
0105 
0106    // Construct from a pointer to member function (1D type).
0107    template <class PtrObj, typename MemFn>
0108    Functor1D(const PtrObj& p, MemFn memFn) : fFunc{std::bind(memFn, p, std::placeholders::_1)} {}
0109 
0110    // Clone of the function handler (use copy-ctor).
0111    Functor1D * Clone() const override { return new Functor1D(*this); }
0112 
0113 private :
0114 
0115    inline double DoEval (double x) const override {
0116       return fFunc(x);
0117    }
0118 
0119    std::function<double(double)> fFunc;
0120 };
0121 
0122 /**
0123    GradFunctor class for Multidimensional gradient functions.
0124    It is used to wrap in a very C++ callable object to make gradient functions.
0125    It can be constructed in three different way:
0126    <ol>
0127    <li> from an object implementing both
0128         double operator()( const double * ) for the function evaluation  and
0129         double Derivative(const double *, int icoord) for the partial derivatives
0130     <li>from an object implementing any member function like Foo::XXX(const double *) for the function evaluation
0131         and any member function like Foo::XXX(const double *, int icoord) for the partial derivatives
0132     <li>from two function objects implementing
0133         double operator()( const double * ) for the function evaluation and another function object implementing
0134         double operator() (const double *, int icoord) for the partial derivatives
0135     <li>from two function objects
0136    </ol>
0137    The function dimension is required when constructing the functor.
0138 
0139    @ingroup  GenFunc
0140 
0141  */
0142 class GradFunctor : public IGradientFunctionMultiDim  {
0143 
0144 
0145 public:
0146 
0147    /// Default constructor.
0148    GradFunctor() = default;
0149 
0150    /**
0151       construct from a callable object of multi-dimension
0152       implementing operator()(const double *x) and
0153       Derivative(const double * x,icoord)
0154     */
0155    template <typename Func>
0156    GradFunctor( const Func & f, unsigned int dim ) :
0157       fDim{dim}, fFunc{f}, fDerivFunc{std::bind(&Func::Derivative, f, std::placeholders::_1, std::placeholders::_2)}
0158    {}
0159 
0160    /// Construct from a pointer to member function and member function types for function and derivative evaluations.
0161    template <class PtrObj, typename MemFn, typename DerivMemFn,
0162              std::enable_if_t<std::is_floating_point<decltype((std::declval<std::remove_pointer_t<PtrObj>>().*
0163                                                                std::declval<DerivMemFn>())(
0164                                  std::declval<const double *>(), std::declval<int>()))>::value,
0165                               bool> = true>
0166    GradFunctor(const PtrObj &p, MemFn memFn, DerivMemFn gradFn, unsigned int dim)
0167       : fDim{dim},
0168         fFunc{std::bind(memFn, p, std::placeholders::_1)},
0169         fDerivFunc{std::bind(gradFn, p, std::placeholders::_1, std::placeholders::_2)}
0170    {}
0171 
0172    /// Construct from a pointer to member function and member function, types for function and full derivative
0173    /// evaluations.
0174    template <
0175       class PtrObj, typename MemFn, typename GradMemFn,
0176       std::enable_if_t<std::is_void<decltype((std::declval<std::remove_pointer_t<PtrObj>>().*std::declval<GradMemFn>())(
0177                           std::declval<const double *>(), std::declval<double *>()))>::value,
0178                        bool> = true>
0179    GradFunctor(const PtrObj &p, MemFn memFn, GradMemFn gradFn, unsigned int dim)
0180       : fDim{dim},
0181         fFunc{std::bind(memFn, p, std::placeholders::_1)},
0182         fGradFunc{std::bind(gradFn, p, std::placeholders::_1, std::placeholders::_2)}
0183    {
0184    }
0185 
0186    /// Construct for Gradient Functions of multi-dimension Func gives the
0187    /// function evaluation, GradFunc the partial derivatives The function
0188    /// dimension is required.
0189    GradFunctor(std::function<double(double const *)> const& f,
0190                std::function<double(double const *, unsigned int)> const& g, unsigned int dim)
0191       : fDim{dim}, fFunc{f}, fDerivFunc{g}
0192    {}
0193 
0194    /**
0195     * @brief Construct a new GradFunctor object using 2 std::function,
0196     *        one for the function evaluation and one for the Gradient
0197     *        Note the difference with the constructor above where partial derivative function
0198     *        is used as input
0199     *
0200     * @param f  : function object computing the function value
0201     * @param dim : number of function dimension
0202     * @param g   : function object computing the function gradient
0203     */
0204    GradFunctor(std::function<double(double const *)> const&f, unsigned int dim,
0205                std::function<void(double const *, double *)> const& g)
0206       : fDim{dim}, fFunc{f}, fGradFunc{g}
0207    {}
0208 
0209    // Clone of the function handler (use copy-ctor).
0210    GradFunctor * Clone() const override { return new GradFunctor(*this); }
0211 
0212    // for multi-dimensional functions
0213    unsigned int NDim() const override { return fDim; }
0214 
0215    void Gradient(const double *x, double *g) const override {
0216       // Fall back to base implementation if no gradient function is provided
0217       // (it will fill the gradient calling DoDerivative() for each component).
0218       if(!fGradFunc) {
0219          IGradientFunctionMultiDim::Gradient(x, g);
0220          return;
0221       }
0222       fGradFunc(x, g);
0223    }
0224 
0225 private :
0226 
0227    inline double DoEval (const double * x) const override {
0228       return fFunc(x);
0229    }
0230 
0231    inline double DoDerivative (const double * x, unsigned int icoord  ) const override {
0232       if(fDerivFunc) {
0233          return fDerivFunc(x, icoord);
0234       }
0235       // Get the component from the gradient if not derivative function is
0236       // specified.
0237       std::vector<double> gradBuffer(fDim);
0238       std::fill(gradBuffer.begin(), gradBuffer.end(), 0.0);
0239       fGradFunc(x, gradBuffer.data());
0240       return gradBuffer[icoord];
0241    }
0242 
0243    unsigned int fDim;
0244    std::function<double(const double *)> fFunc;
0245    std::function<double(double const *, unsigned int)> fDerivFunc;
0246    std::function<void(const double *, double*)> fGradFunc;
0247 };
0248 
0249 
0250 //_______________________________________________________________________________________________
0251 /**
0252    GradFunctor1D class for one-dimensional gradient functions.
0253    It is used to wrap in a very C++ callable object to make a 1D gradient functions.
0254    It can be constructed in three different way:
0255    <ol>
0256    <li> from an object implementing both
0257         double operator()( double  ) for the function evaluation  and
0258         double Derivative(double ) for the partial derivatives
0259     <li>from an object implementing any member function like Foo::XXX(double ) for the function evaluation
0260         and any other member function like Foo::YYY(double ) for the derivative.
0261     <li>from an 2 function objects implementing
0262         double operator()( double ) . One object provides the function evaluation, the other the derivative.
0263    </ol>
0264 
0265    @ingroup  GenFunc
0266 
0267  */
0268 
0269 class GradFunctor1D : public IGradientFunctionOneDim  {
0270 
0271 public:
0272 
0273    /// Default constructor.
0274    GradFunctor1D() = default;
0275 
0276    /// Construct from an object with the right signature,
0277    /// implementing both `operator() (double x)` and `Derivative(double x)`.
0278    template <typename Func>
0279    GradFunctor1D(const Func & f) : fFunc{f}, fDerivFunc{std::bind(&Func::Derivative, f, std::placeholders::_1)} {}
0280 
0281    /**
0282        construct from a pointer to class and two pointers to member functions, one for
0283        the function evaluation and the other for the derivative.
0284        The member functions must take a double as argument and return a double
0285     */
0286    template <class PtrObj, typename MemFn, typename GradMemFn>
0287    GradFunctor1D(const PtrObj& p, MemFn memFn, GradMemFn gradFn)
0288       : fFunc{std::bind(memFn, p, std::placeholders::_1)}, fDerivFunc{std::bind(gradFn, p, std::placeholders::_1)}
0289    {}
0290 
0291 
0292    /// Specialized constructor from 2 function objects implementing double
0293    /// operator()(double x). The first one for the function evaluation and the
0294    /// second one implementing the function derivative.
0295    GradFunctor1D(std::function<double(double)> const& f, std::function<double(double)> const& g)
0296       : fFunc{f}, fDerivFunc{g}
0297    {}
0298 
0299    // clone of the function handler (use copy-ctor)
0300    GradFunctor1D * Clone() const override { return new GradFunctor1D(*this); }
0301 
0302 private :
0303 
0304    inline double DoEval (double x) const override { return fFunc(x); }
0305    inline double DoDerivative (double x) const override { return fDerivFunc(x); }
0306 
0307    std::function<double(double)> fFunc;
0308    std::function<double(double)> fDerivFunc;
0309 };
0310 
0311 
0312 } // end namespace Math
0313 
0314 } // end namespace ROOT
0315 
0316 
0317 #endif /* ROOT_Math_Functor */