Back to home page

EIC code displayed by LXR

 
 

    


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

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