Back to home page

EIC code displayed by LXR

 
 

    


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

0001 // @(#)root/mathmore:$Id: OneDimFunctionAdapter.h 20063 2007-09-24 13:16:14Z moneta $
0002 // Author: L. Moneta Wed Dec  6 11:45:55 2006
0003 
0004 /**********************************************************************
0005  *                                                                    *
0006  * Copyright (c) 2006  LCG ROOT Math Team, CERN/PH-SFT                *
0007  *                                                                    *
0008  *                                                                    *
0009  **********************************************************************/
0010 
0011 // Header file for class OneDimMultiFunctionAdapter
0012 
0013 #ifndef ROOT_Math_OneDimFunctionAdapter
0014 #define ROOT_Math_OneDimFunctionAdapter
0015 
0016 #include "Math/IFunction.h"
0017 #include "Math/IParamFunction.h"
0018 
0019 #include <cassert>
0020 
0021 namespace ROOT {
0022 
0023 namespace Math {
0024 
0025 
0026 
0027 // struct using for evaluating the function
0028 template<class MultiFuncType>
0029 struct EvaluatorOneDim {
0030    // evaluate function (in general case no param)
0031    static double F (MultiFuncType f, const double * x, const double *  = nullptr ) {
0032       return f( x );
0033    }
0034 };
0035 // specialized for param functions
0036 template<>
0037 struct EvaluatorOneDim< const ROOT::Math::IParamMultiFunction &> {
0038    static double F ( const ROOT::Math::IParamMultiFunction &  f, const double * x, const double * p = nullptr ) {
0039       return f( x, p );
0040    }
0041 };
0042 
0043 
0044 /**
0045    OneDimMultiFunctionAdapter class to wrap a multidimensional function in
0046    one dimensional one.
0047    Given a f(x1,x2,x3,....xn) transforms in a f( x_i) given the coordinate intex i and the vector x[]
0048    of the coordinates.
0049    It provides the possibility to copy and own the data array of the coordinates or to maintain internally a pointer to an external array
0050    for being more efficient. In this last case the user must guarantee the life of the given passed pointer
0051 
0052    @ingroup  GenFunc
0053 
0054 */
0055 template <class MultiFuncType = const ROOT::Math::IMultiGenFunction &>
0056 class OneDimMultiFunctionAdapter : public ROOT::Math::IGenFunction  {
0057 
0058 public:
0059 
0060 
0061    /**
0062       Constructor from the function object , pointer to an external array of x values
0063       and coordinate we want to adapt
0064    */
0065    OneDimMultiFunctionAdapter (MultiFuncType f, const double * x, unsigned int icoord = 0, const double * p = nullptr ) :
0066       fFunc(f),
0067       fX( const_cast<double *>(x) ), // we need to modify x but then we restore it as before
0068       fParams(p),
0069       fCoord(icoord),
0070       fDim(0),
0071       fOwn(false)
0072    {
0073       assert(fX != nullptr);
0074    }
0075    /**
0076       Constructor from the function object , dimension of the function and
0077       and coordinate we want to adapt.
0078       The coordinate cached vector is created inside and eventually the values must be passed
0079       later with the SetX which will copy them
0080    */
0081    OneDimMultiFunctionAdapter (MultiFuncType f, unsigned int dim = 1, unsigned int icoord = 0, const double *p = nullptr) :
0082       fFunc(f),
0083       fX(nullptr),
0084       fParams(p),
0085       fCoord(icoord),
0086       fDim(dim),
0087       fOwn(true)
0088    {
0089       fX = new double[dim];
0090    }
0091 
0092    /**
0093       Destructor (no operations)
0094    */
0095    ~OneDimMultiFunctionAdapter () override  { if (fOwn && fX) delete [] fX; }
0096 
0097    /**
0098       clone
0099    */
0100    OneDimMultiFunctionAdapter * Clone( ) const override {
0101       if (fOwn) {
0102          OneDimMultiFunctionAdapter * f =  new OneDimMultiFunctionAdapter( fFunc, fDim, fCoord, fParams);
0103          std::copy(fX, fX+fDim, f->fX);
0104          return f;
0105       }
0106       else
0107          return new OneDimMultiFunctionAdapter( fFunc, fX, fCoord, fParams);
0108    }
0109 
0110 public:
0111 
0112    /**
0113        Set X values in case vector is own, iterator size must match previous
0114        set dimension
0115    */
0116    template<class Iterator>
0117    void SetX(Iterator begin, Iterator end) {
0118       if (fOwn) std::copy(begin, end, fX);
0119    }
0120 
0121 
0122    /**
0123       set pointer without copying the values
0124     */
0125    void SetX(double * x) {
0126       if (!fOwn) fX = x;
0127    }
0128 
0129    /**
0130        set values
0131    */
0132    void SetX(const double * x) {
0133       if (fOwn) std::copy(x, x+fDim, fX);
0134       else
0135          SetX( const_cast<double *>(x) ); // we need to modify x but then we restore it as before
0136    }
0137 
0138 
0139    void SetCoord(int icoord) { fCoord=icoord;}
0140 
0141    // copy constructor
0142    OneDimMultiFunctionAdapter( const OneDimMultiFunctionAdapter & rhs) :
0143       fFunc(rhs.fFunc),
0144       fParams(rhs.fParams),
0145       fCoord(rhs.fCoord),
0146       fDim(rhs.fDim),
0147       fOwn(rhs.fOwn)
0148    {
0149       if (fOwn) {
0150          fX = new double[fDim];
0151          std::copy( rhs.fX, rhs.fX+fDim, fX);
0152       }
0153       else fX = rhs.fX;
0154    }
0155 
0156 
0157 private:
0158 
0159    // dummy assignment (should never be called and clone must be used)
0160    OneDimMultiFunctionAdapter & operator= ( const OneDimMultiFunctionAdapter & rhs) {
0161       if (this == &rhs)  return *this;
0162       assert(false);
0163    }
0164 
0165    /**
0166       evaluate function at the  values x[] given in the constructor and
0167       as function of  the coordinate fCoord.
0168    */
0169    double DoEval(double x) const override {
0170       if (fOwn) {
0171          fX[fCoord] = x;
0172          return EvaluatorOneDim<MultiFuncType>::F( fFunc, fX, fParams );
0173       }
0174       else {
0175 
0176          // case vector fX represents useful values needed later
0177          // need to modify fX and restore afterwards the original values
0178          double xprev = fX[fCoord]; // keep original value to restore in fX
0179          fX[fCoord] = x;
0180          double y = EvaluatorOneDim<MultiFuncType>::F( fFunc, fX, fParams );
0181          // restore original values
0182          fX[fCoord] = xprev;
0183          return y;
0184       }
0185    }
0186 
0187 
0188 private:
0189 
0190    MultiFuncType fFunc;
0191    mutable double * fX;
0192    const double   * fParams;
0193    unsigned int fCoord;
0194    unsigned int fDim;
0195    bool fOwn;
0196 
0197 };
0198 
0199 
0200 /**
0201    OneDimParamFunctionAdapter class to wrap a multi-dim parametric function in
0202    one dimensional one.
0203    Given a f(x[],p1,...pn) transforms in a f( p_i) given the param index i and the vectors x[] and p[]
0204    of the coordinates and parameters
0205    It has to be used carefully, since for efficiency reason it does not copy the parameter object
0206    but re-uses the given pointer for  the p[] vector.
0207    The ParamFuncType reference by default is not const because the operator()(x,p) is not a const method
0208 
0209    @ingroup  GenFunc
0210 
0211 */
0212 template <class ParamFuncType = ROOT::Math::IParamMultiFunction &>
0213 class OneDimParamFunctionAdapter :  public ROOT::Math::IGenFunction {
0214 
0215 public:
0216 
0217 
0218    /**
0219       Constructor from the function object , x value and coordinate we want to adapt
0220    */
0221    OneDimParamFunctionAdapter (ParamFuncType f, const double * x, const double * p, unsigned int ipar =0 ) :
0222       fFunc(f),
0223       fX(x ),
0224       fParams(p),
0225       fIpar(ipar)
0226    {
0227       assert(fX != nullptr);
0228       assert(fParams != nullptr);
0229    }
0230 
0231    /**
0232       Destructor (no operations)
0233    */
0234    ~OneDimParamFunctionAdapter () override  {}
0235 
0236    /**
0237       clone
0238    */
0239    OneDimParamFunctionAdapter * Clone( ) const override {
0240       return new OneDimParamFunctionAdapter(fFunc, fX, fParams, fIpar);
0241    }
0242 
0243    // can use default copy constructor
0244 
0245 private:
0246 
0247    /**
0248       evaluate function at the  values x[] given in the constructor and
0249       as function of  the coordinate fCoord.
0250    */
0251    double DoEval(double x) const override {
0252       // HACK: use const_cast to modify the function values x[] and restore afterwards the original ones
0253       double * p = const_cast<double *>(fParams);
0254       double pprev = fParams[fIpar]; // keep original value to restore in fX
0255       p[fIpar] = x;
0256       double y =  fFunc( fX, p );
0257       p[fIpar] = pprev;
0258       return y;
0259    }
0260 
0261 
0262 private:
0263 
0264    ParamFuncType fFunc;
0265    const double * fX;
0266    const double * fParams;
0267    unsigned int fIpar;
0268 
0269 };
0270 
0271 
0272 } // end namespace Math
0273 
0274 } // end namespace ROOT
0275 
0276 
0277 #endif /* ROOT_Math_OneDimFunctionAdapter */