Back to home page

EIC code displayed by LXR

 
 

    


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

0001 // @(#)root/mathcore:$Id$
0002 // Author: L. Moneta Thu Nov 23 10:38:32 2006
0003 
0004  /**********************************************************************
0005   *                                                                    *
0006   * Copyright (c) 2006  CERN                                           *
0007   * All rights reserved.                                               *
0008   *                                                                    *
0009   * For the licensing terms see $ROOTSYS/LICENSE.                      *
0010   * For the list of contributors see $ROOTSYS/README/CREDITS.          *
0011   *                                                                    *
0012   **********************************************************************/
0013 
0014 // Header file for class WrappedParamFunction
0015 
0016 #ifndef ROOT_Math_WrappedParamFunction
0017 #define ROOT_Math_WrappedParamFunction
0018 
0019 #include "Math/IParamFunction.h"
0020 
0021 //#include <iostream>
0022 //#include <iterator>
0023 
0024 #include <vector>
0025 
0026 
0027 namespace ROOT {
0028 
0029    namespace Math {
0030 
0031 
0032 typedef double( * FreeParamMultiFunctionPtr ) (const double *, const double * );
0033 
0034 /**
0035    WrappedParamFunction class to wrap any multi-dimensional function object
0036    implementing the operator()(const double * x, const double * p)
0037    in an interface-like IParamFunction with a vector storing and caching internally the
0038    parameter values
0039 
0040    @ingroup  ParamFunc
0041 
0042 */
0043 template< typename FuncPtr =  FreeParamMultiFunctionPtr   >
0044 class WrappedParamFunction : public IParamMultiFunction {
0045 
0046 public:
0047 
0048    /**
0049       Constructor a wrapped function from a pointer to a callable object, the function dimension and number of parameters
0050       which are set to zero by default
0051    */
0052    WrappedParamFunction (FuncPtr  func, unsigned int dim = 1, unsigned int npar = 0, double * par = nullptr) :
0053       fFunc(func),
0054       fDim(dim),
0055       fParams(std::vector<double>(npar) )
0056    {
0057       if (par) std::copy(par, par+npar, fParams.begin());
0058    }
0059 
0060 //    /**
0061 //       Constructor a wrapped function from a non-const pointer to a callable object, the function dimension and number of parameters
0062 //       which are set to zero by default
0063 //       This constructor is needed in the case FuncPtr is a std::unique_ptr which has a copy ctor taking non const objects
0064 //    */
0065 //    WrappedParamFunction (FuncPtr & func, unsigned int dim = 1, unsigned int npar = 0, double * par = 0) :
0066 //       fFunc(func),
0067 //       fDim(dim),
0068 //       fParams(std::vector<double>(npar) )
0069 //    {
0070 //       if (par != 0) std::copy(par,par+npar,fParams.begin() );
0071 //    }
0072 
0073    /**
0074       Constructor a wrapped function from a pointer to a callable object, the function dimension and an iterator specifying begin and end
0075       of parameters
0076    */
0077    template<class Iterator>
0078    WrappedParamFunction (FuncPtr func, unsigned int dim, Iterator begin, Iterator end) :
0079       fFunc(func),
0080       fDim(dim),
0081       fParams(std::vector<double>(begin,end) )
0082    {}
0083 
0084 //    /**
0085 //       Constructor a wrapped function from a non - const pointer to a callable object, the function dimension and an iterator specifying begin and end of parameters.
0086 //       This constructor is needed in the case FuncPtr is a std::unique_ptr which has a copy ctor taking non const objects
0087 //    */
0088 //    template<class Iterator>
0089 //    WrappedParamFunction (FuncPtr func, unsigned int dim, Iterator begin, Iterator end) :
0090 //       fFunc(func),
0091 //       fDim(dim),
0092 //       fParams(std::vector<double>(begin,end) )
0093 //    {}
0094 
0095    /// clone the function
0096    IMultiGenFunction * Clone() const override {
0097       return new WrappedParamFunction(fFunc, fDim, fParams.begin(), fParams.end());
0098    }
0099 
0100    const double * Parameters() const override {
0101       return fParams.empty() ? nullptr : &fParams.front();
0102    }
0103 
0104    void SetParameters(const double * p) override  {
0105       std::copy(p, p+NPar(), fParams.begin() );
0106    }
0107 
0108    unsigned int NPar() const override { return fParams.size(); }
0109 
0110    unsigned int NDim() const override { return fDim; }
0111 
0112 
0113 private:
0114 
0115    /// evaluate the function given values and parameters (requested interface)
0116    double DoEvalPar(const double * x, const double * p) const override {
0117       return (*fFunc)( x, p );
0118    }
0119 
0120 
0121    FuncPtr fFunc;
0122    unsigned int fDim;
0123    std::vector<double> fParams;
0124 
0125 
0126 
0127 };
0128 
0129 
0130 typedef double( * FreeMultiFunctionPtr ) (const double *);
0131 
0132 /**
0133    WrappedParamGenFunction class to wrap any multi-dimensional function
0134    implementing the operator()(const double * )
0135    in an interface-like IParamFunction, by fixing some of the variables and define them as
0136    parameters.
0137    i.e. transform any multi-dim function in a parametric function
0138 
0139    @ingroup  ParamFunc
0140 
0141 */
0142 template< typename FuncPtr =  FreeMultiFunctionPtr   >
0143 class WrappedParamFunctionGen : public IParamMultiFunction {
0144 
0145 public:
0146 
0147    /**
0148       Constructor a wrapped function from a pointer to a generic callable object implementation operator()(const double *), the new function dimension, the number of parameters (number of fixed variables) and an array specifying the index of the fixed variables which became
0149       parameters in the new API
0150    */
0151 
0152    WrappedParamFunctionGen (const FuncPtr & func, unsigned int dim, unsigned int npar, const double * par, const unsigned int * idx) :
0153       fFunc(func),
0154       fDim(dim),
0155       fParams(std::vector<double>(par,par+npar) ),
0156       fParIndices(std::vector<unsigned int>(idx, idx + npar) ),
0157       fX(std::vector<double>(npar+dim) )  // cached vector
0158    {
0159       DoInit();
0160    }
0161 
0162    /**
0163       Constructor as before but taking now a non - const pointer to a callable object.
0164       This constructor is needed in the case FuncPtr is a std::unique_ptr which has a copy ctor taking non const objects
0165    */
0166    WrappedParamFunctionGen (FuncPtr & func, unsigned int dim, unsigned int npar, const double * par, const unsigned int * idx) :
0167       fFunc(func),
0168       fDim(dim),
0169       fParams(std::vector<double>(par,par+npar) ),
0170       fParIndices(std::vector<unsigned int>(idx, idx + npar) ),
0171       fX(std::vector<double>(npar+dim) ) // cached vector
0172    {
0173       DoInit();
0174    }
0175 
0176    /// clone the function
0177    IMultiGenFunction * Clone() const override {
0178       return new WrappedParamFunctionGen(fFunc, fDim, fParams.size(), fParams.empty() ? nullptr : &fParams.front(), fParIndices.empty() ? nullptr : &fParIndices.front());
0179    }
0180 
0181 private:
0182    // copy ctor
0183    WrappedParamFunctionGen(const  WrappedParamFunctionGen &) = delete;   // not implemented
0184    WrappedParamFunctionGen & operator=(const  WrappedParamFunctionGen &) = delete; // not implemented
0185 
0186 public:
0187 
0188    const double * Parameters() const override {
0189       return fParams.empty() ? nullptr : &fParams.front();
0190    }
0191 
0192    void SetParameters(const double * p) override  {
0193       unsigned int npar = NPar();
0194       std::copy(p, p+ npar, fParams.begin() );
0195       SetParValues(npar, p);
0196    }
0197 
0198    unsigned int NPar() const override { return fParams.size(); }
0199 
0200    unsigned int NDim() const override { return fDim; }
0201 
0202 //    // re-implement this since is more efficient
0203 //    double operator() (const double * x, const double * p) {
0204 //       unsigned int n = fX.size();
0205 //       unsigned int npar = fParams.size();
0206 //       unsigned j = 0;
0207 //       return (*fFunc)( fX);
0208 //    }
0209 
0210 private:
0211 
0212    /// evaluate the function (re-implement for being more efficient)
0213    double DoEval(const double * x) const override {
0214 
0215 //       std::cout << this << fDim << " x : ";
0216 //       std::ostream_iterator<double> oix(std::cout," ,  ");
0217 //       std::copy(x, x+fDim, oix);
0218 //       std::cout << std::endl;
0219 //       std::cout << "npar " << npar << std::endl;
0220 //       std::cout <<  fVarIndices.size() << std::endl;
0221 //       assert ( fVarIndices.size() == fDim);  // otherwise something is wrong
0222 
0223       for (unsigned int i = 0; i < fDim; ++i) {
0224          unsigned int j = fVarIndices[i];
0225          assert ( j  < NPar() + fDim);
0226          fX[ j ] = x[i];
0227       }
0228 //       std::cout << "X : (";
0229 //       std::ostream_iterator<double> oi(std::cout," ,  ");
0230 //       std::copy(fX.begin(), fX.end(), oi);
0231 //       std::cout << std::endl;
0232 
0233       return (*fFunc)( fX.empty() ? nullptr : &fX.front() );
0234    }
0235 
0236 
0237    /**
0238        implement the required IParamFunction interface
0239    */
0240    double DoEvalPar(const double * x, const double * p ) const override {
0241       SetParValues(NPar(), p);
0242       return DoEval(x);
0243    }
0244 
0245 
0246    void DoInit() {
0247       // calculate variable indices and set in X the parameter values
0248       fVarIndices.reserve(fDim);
0249       unsigned int npar = NPar();
0250       for (unsigned int i = 0; i < npar + fDim; ++i) {
0251          bool isVar = true;
0252          for (unsigned int j = 0; j < npar; ++j) {
0253             if (fParIndices[j] == i) {
0254                isVar = false;
0255                break;
0256             }
0257          }
0258          if (isVar) fVarIndices.push_back(i);
0259       }
0260       assert ( fVarIndices.size() == fDim);  // otherwise something is wrong
0261 
0262 //       std::cout << "n variables " << fVarIndices.size() << std::endl;
0263 //       std::ostream_iterator<int> oi(std::cout,"  ");
0264 //       std::copy(fVarIndices.begin(), fVarIndices.end(), oi);
0265 //       std::cout << std::endl;
0266 //       assert( fVarIndices.size() == fDim);
0267 //       std::cout << this << std::endl;
0268 
0269       // set parameter values in fX
0270       SetParValues(npar, fParams.empty() ? nullptr : &fParams.front());
0271       for (unsigned int i = 0; i < npar; ++i) {
0272          unsigned int j = fParIndices[i];
0273          assert ( j  < npar + fDim);
0274          fX[j] = fParams[i];
0275       }
0276 
0277    }
0278 
0279    // set the parameter values in the cached fX vector
0280    // make const because it might be called from const methods
0281    void SetParValues(unsigned int npar, const double * p) const {
0282       for (unsigned int i = 0; i < npar; ++i) {
0283          unsigned int j = fParIndices[i];
0284          assert ( j  < npar + fDim);
0285          fX[j] = p[i];
0286       }
0287    }
0288 
0289 
0290    mutable FuncPtr fFunc;
0291    unsigned int fDim;
0292    std::vector<double> fParams;
0293    std::vector<unsigned int> fVarIndices;
0294    std::vector<unsigned int> fParIndices;
0295    mutable std::vector<double> fX;
0296 
0297 
0298 
0299 };
0300 
0301 
0302    } // end namespace Math
0303 
0304 } // end namespace ROOT
0305 
0306 
0307 #endif /* ROOT_Math_WrappedParamFunction */