Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-16 10:29:36

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 // design is inspired by the Loki Functor
0013 
0014 #ifndef ROOT_Math_ParamFunctor
0015 #define ROOT_Math_ParamFunctor
0016 
0017 // #ifndef ROOT_Math_IFunction
0018 // #include "Math/IFunction.h"
0019 // #endif
0020 
0021 // #ifndef Root_Math_StaticCheck
0022 // #include "Math/StaticCheck.h"
0023 // #endif
0024 
0025 //#include <memory>
0026 
0027 #include "RtypesCore.h"
0028 #include <functional>
0029 #include <iostream>
0030 
0031 namespace ROOT {
0032 
0033 namespace Math {
0034 
0035 /**
0036  * \defgroup ParamFunctor_int N-D parametric functions
0037  * \brief Multi-dimensional parametric functions
0038  */
0039 
0040 /** class defining the signature for multi-dim parametric functions
0041 
0042    @ingroup  ParamFunctor_int
0043  */
0044 template<class T>
0045 class ParamFunctionBase {
0046   public:
0047    virtual ~ParamFunctionBase() {}
0048    virtual T operator() (const T * x, const double *p) = 0;
0049    virtual T operator() (T * x, double *p) = 0;
0050    virtual ParamFunctionBase * Clone() const = 0;
0051 };
0052 
0053 
0054 
0055 /**
0056    ParamFunctor Handler class is responsible for wrapping any other functor and pointer to
0057    free C functions.
0058    It can be created from any function implementing the correct signature
0059    corresponding to the requested type
0060 
0061    @ingroup  ParamFunctor_int
0062 
0063 */
0064 
0065 template<class ParentFunctor, class Func >
0066 class ParamFunctorHandler : public ParentFunctor::Impl {
0067 
0068    typedef typename ParentFunctor::EvalType EvalType;
0069    typedef typename ParentFunctor::Impl     Base;
0070 
0071 public:
0072 
0073    // constructor
0074    ParamFunctorHandler(const Func & fun) : fFunc(fun) {}
0075 
0076 
0077    virtual ~ParamFunctorHandler() {}
0078 
0079 
0080    // for 1D functions
0081    inline EvalType operator() (EvalType x, double *p)  {
0082       return fFunc(x,p);
0083    }
0084 //    inline double operator() (double x, const double *p) const {
0085 //       return fFunc(x,p);
0086 //    }
0087    // for multi-dimensional functions
0088 //    inline double operator() (const double * x, const double *p) const {
0089 //       return fFunc(x,p);
0090 //    }
0091    inline EvalType operator() (EvalType * x, double *p) override {
0092       return FuncEvaluator<Func, EvalType>::Eval(fFunc,x,p);
0093    }
0094 
0095    inline EvalType operator() (const EvalType * x, const double *p) override {
0096       return FuncEvaluator<Func, EvalType>::EvalConst(fFunc,x,p);
0097    }
0098 
0099    // clone (use same pointer)
0100    ParamFunctorHandler  * Clone() const override {
0101       return new ParamFunctorHandler(fFunc);
0102    }
0103 
0104 
0105 private :
0106 
0107    Func fFunc;
0108 
0109    // structure to distinguish pointer types
0110    template <typename F,typename  T> struct FuncEvaluator {
0111       inline static T Eval( F & f, T *x, double * p) {
0112          return f(x, p);
0113       }
0114 
0115       inline static T EvalConst( F & f, const T *x, const double * p) {
0116          return f((T*)x, (double*)p);
0117       }
0118    };
0119 
0120    template <typename F, typename T> struct FuncEvaluator<F*, T> {
0121       inline static T Eval( F * f, T *x, double * p) {
0122          return (*f)(x, p);
0123       }
0124 
0125       inline static T EvalConst( F * f, const T *x, const double * p) {
0126          return (*f)((T*)x, (double*)p);
0127 
0128       }
0129    };
0130 
0131    template <typename F,typename  T> struct FuncEvaluator<F* const, T> {
0132       inline static T Eval( const F * f, T *x, double * p) {
0133          return (*f)(x, p);
0134       }
0135 
0136       inline static T EvalConst( const F * f, const T *x, const double * p) {
0137          return (*f)((T*)x, (double*)p);
0138       }
0139    };
0140 
0141    // need maybe also volatile ?
0142 };
0143 
0144 
0145 #if defined(__MAKECINT__) || defined(G__DICTIONARY)
0146 // needed since CINT initialize it with TRootIOCtor
0147 //class TRootIOCtor;
0148 template<class ParentFunctor>
0149 class ParamFunctorHandler<ParentFunctor,TRootIOCtor *> : public ParentFunctor::Impl
0150 {
0151 public:
0152 
0153    ParamFunctorHandler(TRootIOCtor  *) {}
0154 
0155    double operator() (double *, double * )  { return 0; }
0156 
0157    double operator() (const double *, const double * )  { return 0; }
0158    // clone (use same pointer)
0159    ParamFunctorHandler  * Clone() const {
0160       return 0;
0161    }
0162 
0163 };
0164 #endif
0165 
0166 
0167 /**
0168    ParamFunctor Handler to Wrap pointers to member functions
0169 
0170    @ingroup  ParamFunctor_int
0171 */
0172 template <class ParentFunctor, typename PointerToObj,
0173           typename PointerToMemFn>
0174 class ParamMemFunHandler : public ParentFunctor::Impl
0175 {
0176    typedef typename ParentFunctor::Impl Base;
0177 
0178 
0179 public:
0180 
0181    /// constructor from a pointer to the class and a pointer to the function
0182    ParamMemFunHandler(const PointerToObj& pObj, PointerToMemFn pMemFn)
0183       : fObj(pObj), fMemFn(pMemFn)
0184    {}
0185 
0186    virtual ~ParamMemFunHandler() {}
0187 
0188 //    inline double operator() (double x, const double * p) const {
0189 //       return ((*fObj).*fMemFn)(x,p);
0190 //    }
0191 
0192    inline double operator() (double x, double * p)  {
0193       return ((*fObj).*fMemFn)(x,p);
0194    }
0195 
0196 //    inline double operator() (const double * x, const double * p) const {
0197 //       return ((*fObj).*fMemFn)(x,p);
0198 //    }
0199 
0200    inline double operator() (double * x, double * p) override {
0201       return MemFuncEvaluator<PointerToObj,PointerToMemFn, double>::Eval(fObj,fMemFn,x,p);
0202    }
0203 
0204    inline double operator() (const double * x, const double * p) override {
0205       return MemFuncEvaluator<PointerToObj,PointerToMemFn, double>::EvalConst(fObj,fMemFn,x,p);
0206    }
0207 
0208    // clone (use same pointer)
0209    ParamMemFunHandler  * Clone() const override {
0210       return new ParamMemFunHandler(fObj, fMemFn);
0211    }
0212 
0213 private:
0214 
0215    // structure to distinguish pointer types
0216    template <typename PObj, typename F,typename  T> struct MemFuncEvaluator {
0217       inline static T Eval(PObj & pobj, F &  f, T *x, double * p) {
0218          return ((*pobj).*f)(x, p);
0219       }
0220 
0221       inline static T EvalConst(PObj & pobj, F & f, const T *x, const double * p) {
0222          return ((*pobj).*f)((T*)x, (double*)p);
0223       }
0224    };
0225 
0226 
0227    // // these are needed ??
0228    // template <typename PObj, typename F, typename T> struct MemFuncEvaluator<PObj,F*, T> {
0229    //    inline static T Eval(PObj & pobj,  F * f, T *x, double * p) {
0230    //       return ((*pobj).*f)f(x, p);
0231    //    }
0232 
0233    //    inline static T EvalConst(PObj & pobj,  F * f, const T *x, const double * p) {
0234    //       return ((*pobj).*f)((T*)x, (double*)p);
0235 
0236    //    }
0237    // };
0238 
0239    // template <typename PObj, typename F,typename  T> struct FuncEvaluator<PObj,F* const, T> {
0240    //    inline static T Eval(PObj &, const F * f, T *x, double * p) {
0241    //       return ((*pobj).*f)f(x, p);
0242    //    }
0243 
0244    //    inline static T EvalConst(PObj & pobj, const F * f, const T *x, const double * p) {
0245    //       return ((*pobj).*f)((T*)x, (double*)p);
0246    //    }
0247    // };
0248 
0249 private :
0250    ParamMemFunHandler(const ParamMemFunHandler&) = delete; // Not implemented
0251    ParamMemFunHandler& operator=(const ParamMemFunHandler&) = delete; // Not implemented
0252 
0253    PointerToObj fObj;
0254    PointerToMemFn fMemFn;
0255 
0256 };
0257 
0258 
0259 
0260 
0261 /**
0262    Param Functor class for Multidimensional functions.
0263    It is used to wrap in a very simple and convenient way
0264    any other C++ callable object (implementation double operator( const double *, const double * ) )
0265    or a member function with the correct signature,
0266    like Foo::EvalPar(const double *, const double *)
0267 
0268    @ingroup  ParamFunc
0269 
0270  */
0271 
0272 
0273 template<class T>
0274 class ParamFunctorTempl   {
0275 
0276 
0277 public:
0278 
0279    typedef  T                    EvalType;
0280    typedef  ParamFunctionBase<T> Impl;
0281 
0282 
0283    /**
0284       Default constructor
0285    */
0286    ParamFunctorTempl ()  : fImpl(nullptr) {}
0287 
0288 
0289    /**
0290        construct from a pointer to member function (multi-dim type)
0291     */
0292    template <class PtrObj, typename MemFn>
0293    ParamFunctorTempl(const PtrObj& p, MemFn memFn)
0294       : fImpl(new ParamMemFunHandler<ParamFunctorTempl<T>, PtrObj, MemFn>(p, memFn))
0295    {}
0296 
0297 
0298 
0299    /**
0300       construct from another generic Functor of multi-dimension
0301     */
0302    template <typename Func>
0303    explicit ParamFunctorTempl( const Func & f) :
0304       fImpl(new ParamFunctorHandler<ParamFunctorTempl<T>,Func>(f) )
0305    {}
0306 
0307 
0308 
0309    // specialization used in TF1
0310    typedef T (* FreeFunc ) (T * , double *);
0311    ParamFunctorTempl(FreeFunc f) :
0312       fImpl(new ParamFunctorHandler<ParamFunctorTempl<T>,FreeFunc>(f) )
0313    {
0314    }
0315 
0316    // specialization used in TF1
0317    ParamFunctorTempl(const std::function<T(const T *f, const Double_t *param)> &func) :
0318       fImpl(new ParamFunctorHandler<ParamFunctorTempl<T>, const std::function<T(const T *f, const Double_t *param)>>(func))
0319    {
0320    }
0321 
0322    /**
0323       Destructor (no operations)
0324    */
0325    virtual ~ParamFunctorTempl ()  {
0326       if (fImpl) delete fImpl;
0327    }
0328 
0329    /**
0330       Copy constructor
0331    */
0332    ParamFunctorTempl(const ParamFunctorTempl & rhs) :
0333       fImpl(nullptr)
0334    {
0335 //       if (rhs.fImpl.get() != 0)
0336 //          fImpl = std::unique_ptr<Impl>( (rhs.fImpl)->Clone() );
0337       if (rhs.fImpl)  fImpl = rhs.fImpl->Clone();
0338    }
0339 
0340    /**
0341       Assignment operator
0342    */
0343    ParamFunctorTempl & operator = (const ParamFunctorTempl & rhs)  {
0344 //      ParamFunctor copy(rhs);
0345       // swap unique_ptr by hand
0346 //       Impl * p = fImpl.release();
0347 //       fImpl.reset(copy.fImpl.release());
0348 //       copy.fImpl.reset(p);
0349 
0350       if(this != &rhs) {
0351          if (fImpl) delete fImpl;
0352          fImpl = nullptr;
0353          if (rhs.fImpl)
0354             fImpl = rhs.fImpl->Clone();
0355       }
0356       return *this;
0357    }
0358 
0359    void * GetImpl() { return (void *) fImpl; }
0360 
0361 
0362    T operator() ( T * x, double * p)  {
0363       return (*fImpl)(x,p);
0364    }
0365 
0366    T operator() (const T * x, const double * p)  {
0367       return (*fImpl)(x,p);
0368    }
0369 
0370 
0371    bool Empty() const { return !fImpl; }
0372 
0373 
0374    void SetFunction(Impl * f) {
0375       fImpl = f;
0376    }
0377 
0378 private :
0379 
0380 
0381    //std::unique_ptr<Impl> fImpl;
0382    Impl * fImpl;
0383 
0384 
0385 };
0386 
0387 
0388 using ParamFunctor = ParamFunctorTempl<double>;
0389 
0390    } // end namespace Math
0391 
0392 } // end namespace ROOT
0393 
0394 
0395 #endif /* ROOT_Math_ParamFunctor */