OneDimFunctionAdapter.h

Go to the documentation of this file.
00001 // @(#)root/mathmore:$Id: OneDimFunctionAdapter.h 20063 2007-09-24 13:16:14Z moneta $
00002 // Author: L. Moneta Wed Dec  6 11:45:55 2006
00003 
00004 /**********************************************************************
00005  *                                                                    *
00006  * Copyright (c) 2006  LCG ROOT Math Team, CERN/PH-SFT                *
00007  *                                                                    *
00008  *                                                                    *
00009  **********************************************************************/
00010 
00011 // Header file for class OneDimMultiFunctionAdapter
00012 
00013 #ifndef ROOT_Math_OneDimFunctionAdapter
00014 #define ROOT_Math_OneDimFunctionAdapter
00015 
00016 #ifndef ROOT_Math_IFunction
00017 #include "Math/IFunction.h"
00018 #endif
00019 #ifndef ROOT_Math_IParamFunction
00020 #include "Math/IParamFunction.h"
00021 #endif
00022 
00023 #include <cassert> 
00024 
00025 namespace ROOT { 
00026 
00027 namespace Math { 
00028 
00029 
00030 
00031 // struct using for evaluating the function 
00032 template<class MultiFuncType>
00033 struct EvaluatorOneDim { 
00034    // evaluate function (in general case no param) 
00035    static double F (MultiFuncType f, const double * x, const double *  = 0 ) { 
00036       return f( x );
00037    }
00038 };
00039 // specialized for param functions
00040 template<>
00041 struct EvaluatorOneDim< const ROOT::Math::IParamMultiFunction &> { 
00042    static double F ( const ROOT::Math::IParamMultiFunction &  f, const double * x, const double * p = 0 ) { 
00043       return f( x, p );
00044    }
00045 };
00046 
00047 
00048 /** 
00049    OneDimMultiFunctionAdapter class to wrap a multidimensional function in 
00050    one dimensional one. 
00051    Given a f(x1,x2,x3,....xn) transforms in a f( x_i) given the coordinate intex i and the vector x[]
00052    of the coordinates. 
00053    It provides the possibility to copy and own the data array of the coordinates or to maintain internally a pointer to an external array 
00054    for being more efficient. In this last case the user must garantee the life of the given passed pointer 
00055 
00056    @ingroup  GenFunc
00057    
00058 */ 
00059 template <class MultiFuncType = const ROOT::Math::IMultiGenFunction &> 
00060 class OneDimMultiFunctionAdapter : public ROOT::Math::IGenFunction  {
00061 
00062 public: 
00063 
00064   
00065    /** 
00066       Constructor from the function object , pointer to an external array of x values 
00067       and coordinate we want to adapt
00068    */ 
00069    OneDimMultiFunctionAdapter (MultiFuncType f, const double * x, unsigned int icoord =0, const double * p = 0 ) : 
00070       fFunc(f), 
00071       fX( const_cast<double *>(x) ), // wee need to modify x but then we restore it as before 
00072       fParams(p),
00073       fCoord(icoord), 
00074       fDim(0), 
00075       fOwn(false)
00076    {
00077       assert(fX != 0); 
00078    }  
00079    /** 
00080       Constructor from the function object , dimension of the function and  
00081       and coordinate we want to adapt. 
00082       The coordinate cached vector is created inside and eventually the values must be passed 
00083       later with the SetX which will copy them
00084    */ 
00085    OneDimMultiFunctionAdapter (MultiFuncType f, unsigned int dim = 1, unsigned int icoord =0, const double * p = 0 ) : 
00086       fFunc(f), 
00087       fX(0 ), 
00088       fParams(p),
00089       fCoord(icoord), 
00090       fDim(dim),
00091       fOwn(true)
00092    {
00093       fX = new double[dim]; 
00094    }  
00095 
00096    /** 
00097       Destructor (no operations)
00098    */ 
00099    virtual ~OneDimMultiFunctionAdapter ()  { if (fOwn && fX) delete [] fX; }  
00100 
00101    /**
00102       clone
00103    */
00104    virtual OneDimMultiFunctionAdapter * Clone( ) const { 
00105       if (fOwn) 
00106          return new OneDimMultiFunctionAdapter( fFunc, fDim, fCoord, fParams); 
00107       else 
00108          return new OneDimMultiFunctionAdapter( fFunc, fX, fCoord, fParams); 
00109    }
00110 
00111 public: 
00112 
00113    /** 
00114        Set X values in case vector is own, iterator size must match previous 
00115        set dimension
00116    */ 
00117    template<class Iterator>
00118    void SetX(Iterator begin, Iterator end) { 
00119       if (fOwn) std::copy(begin, end, fX);
00120    }
00121 
00122 
00123    /**
00124       set pointer without copying the values
00125     */
00126    void SetX(double * x) { 
00127       if (!fOwn) fX = x; 
00128    }
00129 
00130    /** 
00131        set values 
00132    */
00133    void SetX(const double * x) { 
00134       if (fOwn) std::copy(x, x+fDim, fX);
00135       else 
00136          SetX( const_cast<double *>(x) ); // wee need to modify x but then we restore it as before
00137    }
00138 
00139 
00140    void SetCoord(int icoord) { fCoord=icoord;}
00141 
00142    // copy constructor
00143    OneDimMultiFunctionAdapter( const OneDimMultiFunctionAdapter & rhs) : 
00144       fFunc(rhs.fFunc), 
00145       fParams(rhs.fParams),
00146       fCoord(rhs.fCoord),
00147       fDim(rhs.fDim), 
00148       fOwn(rhs.fOwn)
00149    { 
00150       if (fOwn) { 
00151          fX = new double[fDim]; 
00152          std::copy( rhs.fX, rhs.fX+fDim, fX);
00153       }         
00154       else fX = rhs.fX; 
00155    }
00156 
00157 
00158 private: 
00159 
00160    // dummy assignment (should never be called and clone must be used) 
00161    OneDimMultiFunctionAdapter & operator= ( const OneDimMultiFunctionAdapter & rhs) { 
00162       if (this == &rhs)  return *this;
00163       assert(false); 
00164    }
00165 
00166    /**
00167       evaluate function at the  values x[] given in the constructor and  
00168       as function of  the coordinate fCoord. 
00169    */
00170    double DoEval(double x) const {
00171       if (fOwn) { 
00172          fX[fCoord] = x; 
00173          return EvaluatorOneDim<MultiFuncType>::F( fFunc, fX, fParams );
00174       }
00175       else { 
00176 
00177          // case vector fX represents useful values needed later
00178          // need to modify fX and restore afterwards the original values
00179          double xprev = fX[fCoord]; // keep original value to restore in fX
00180          fX[fCoord] = x; 
00181          double y = EvaluatorOneDim<MultiFuncType>::F( fFunc, fX, fParams );
00182          // restore original values
00183          fX[fCoord] = xprev; 
00184          return y; 
00185       }
00186    }
00187 
00188 
00189 private: 
00190 
00191    MultiFuncType fFunc; 
00192    mutable double * fX;
00193    const double   * fParams;
00194    unsigned int fCoord;
00195    unsigned int fDim; 
00196    bool fOwn;
00197 
00198 }; 
00199 
00200 
00201 /** 
00202    OneDimParamFunctionAdapter class to wrap a multi-dim parameteric function in 
00203    one dimensional one. 
00204    Given a f(x[],p1,...pn) transforms in a f( p_i) given the param index i and the vectors x[] and p[]
00205    of the coordinates and parameters
00206    It has to be used carefully, since for efficiency reason it does not copy the parameter object 
00207    but re-uses the given pointer for  the p[] vector. 
00208    The ParamFuncType reference by default is not const because the operator()(x,p) is not a const method
00209 
00210    @ingroup  GenFunc
00211    
00212 */ 
00213 template <class ParamFuncType = ROOT::Math::IParamMultiFunction &> 
00214 class OneDimParamFunctionAdapter :  public ROOT::Math::IGenFunction {
00215 
00216 public: 
00217 
00218   
00219    /** 
00220       Constructor from the function object , x value and coordinate we want to adapt
00221    */ 
00222    OneDimParamFunctionAdapter (ParamFuncType f, const double * x, const double * p, unsigned int ipar =0 ) : 
00223       fFunc(f), 
00224       fX(x ), 
00225       fParams(p), 
00226       fIpar(ipar)
00227    {
00228       assert(fX != 0); 
00229       assert(fParams != 0); 
00230    }  
00231 
00232    /** 
00233       Destructor (no operations)
00234    */ 
00235    ~OneDimParamFunctionAdapter ()  {}  
00236 
00237    /**
00238       clone
00239    */
00240    virtual OneDimParamFunctionAdapter * Clone( ) const { 
00241       return new OneDimParamFunctionAdapter(fFunc, fX, fParams, fIpar);
00242    }
00243 
00244    // can use default copy constructor
00245 
00246 private: 
00247 
00248    /**
00249       evaluate function at the  values x[] given in the constructor and  
00250       as function of  the coordinate fCoord. 
00251    */
00252    double DoEval(double x) const {
00253       // HACK: use const_cast to modify the function values x[] and restore afterwards the original ones
00254       double * p = const_cast<double *>(fParams); 
00255       double pprev = fParams[fIpar]; // keep original value to restore in fX
00256       p[fIpar] = x; 
00257       double y =  fFunc( fX, p );
00258       p[fIpar] = pprev; 
00259       return y; 
00260    }
00261 
00262 
00263 private: 
00264 
00265    ParamFuncType fFunc; 
00266    const double * fX; 
00267    const double * fParams; 
00268    unsigned int fIpar;
00269 
00270 }; 
00271 
00272 
00273 
00274 
00275 } // end namespace Math
00276 
00277 } // end namespace ROOT
00278 
00279 
00280 #endif /* ROOT_Math_OneDimFunctionAdapter */

Generated on Tue Jul 5 14:25:36 2011 for ROOT_528-00b_version by  doxygen 1.5.1