WrappedTF1.cxx

Go to the documentation of this file.
00001 // @(#)root/mathmore:$Id: WrappedTF1.cxx 31764 2009-12-10 10:41:33Z moneta $
00002 // Author: L. Moneta Wed Sep  6 09:52:26 2006
00003 
00004 /**********************************************************************
00005  *                                                                    *
00006  * Copyright (c) 2006  LCG ROOT Math Team, CERN/PH-SFT                *
00007  *                                                                    *
00008  *                                                                    *
00009  **********************************************************************/
00010 
00011 // implementation file for class WrappedTF1 and WrappedMultiTF1
00012 
00013 #include "Math/WrappedTF1.h"
00014 #include "Math/WrappedMultiTF1.h"
00015 
00016 #include <cmath>
00017 
00018 
00019 namespace ROOT { 
00020    
00021 namespace Math { 
00022 
00023 // static value for epsilon used in derivative calculations
00024 double WrappedTF1::fgEps      = 0.001; 
00025 double WrappedMultiTF1::fgEps = 0.001; 
00026 
00027 
00028 WrappedTF1::WrappedTF1 ( TF1 & f  )  : 
00029    fLinear(false), 
00030    fPolynomial(false),
00031    fFunc(&f), 
00032    fX (), 
00033    fParams(f.GetParameters(),f.GetParameters()+f.GetNpar())
00034 {
00035    // constructor from a TF1 function pointer.
00036    
00037    // init the pointers for CINT
00038    if (fFunc->GetMethodCall() )  fFunc->InitArgs(fX, &fParams.front() );
00039    // distinguish case of polynomial functions and linear functions
00040    if (fFunc->GetNumber() >= 300 && fFunc->GetNumber() < 310) { 
00041       fLinear = true; 
00042       fPolynomial = true; 
00043    }
00044    // check that in case function is linear the linear terms are not zero
00045    if (fFunc->IsLinear() ) { 
00046       unsigned int ip = 0; 
00047       fLinear = true;
00048       while (fLinear && ip < fParams.size() )  { 
00049          fLinear &= (fFunc->GetLinearPart(ip) != 0) ; 
00050          ip++;
00051       }
00052    }      
00053 }
00054 
00055 WrappedTF1::WrappedTF1(const WrappedTF1 & rhs) :
00056    BaseFunc(),
00057    BaseGradFunc(),
00058    IGrad(), 
00059    fLinear(rhs.fLinear), 
00060    fPolynomial(rhs.fPolynomial),
00061    fFunc(rhs.fFunc), 
00062    fX(),
00063    fParams(rhs.fParams)
00064 {
00065    // copy constructor
00066    fFunc->InitArgs(fX,&fParams.front()  );
00067 }
00068    
00069 WrappedTF1 & WrappedTF1::operator = (const WrappedTF1 & rhs) { 
00070    // assignment operator 
00071    if (this == &rhs) return *this;  // time saving self-test
00072    fLinear = rhs.fLinear;  
00073    fPolynomial = rhs.fPolynomial; 
00074    fFunc = rhs.fFunc; 
00075    fFunc->InitArgs(fX, &fParams.front() );
00076    fParams = rhs.fParams;
00077    return *this;
00078 } 
00079 
00080 void  WrappedTF1::ParameterGradient(double x, const double * par, double * grad ) const {
00081    // evaluate the derivative of the function with respect to the parameters 
00082    if (!fLinear) { 
00083       // need to set parameter values
00084       fFunc->SetParameters( par );
00085       // no need to call InitArgs (it is called in TF1::GradientPar)
00086       fFunc->GradientPar(&x,grad,fgEps);
00087    }
00088    else { 
00089       unsigned int np = NPar();
00090       for (unsigned int i = 0; i < np; ++i) 
00091          grad[i] = DoParameterDerivative(x, par, i);
00092    }
00093 }
00094 
00095 double WrappedTF1::DoDerivative( double  x  ) const { 
00096    // return the function derivatives w.r.t. x 
00097 
00098    // parameter are passed as non-const in Derivative
00099    double * p =  (fParams.size() > 0) ? const_cast<double *>( &fParams.front()) : 0;
00100    return  fFunc->Derivative(x,p,fgEps); 
00101 }
00102    
00103 double WrappedTF1::DoParameterDerivative(double x, const double * p, unsigned int ipar ) const { 
00104    // evaluate the derivative of the function with respect to the parameters
00105 
00106    if (! fLinear ) {  
00107       fFunc->SetParameters( p );
00108       return fFunc->GradientPar(ipar, &x,fgEps);
00109    }
00110    else if (fPolynomial) { 
00111       // case of polynomial function (no parameter dependency)  
00112       return std::pow(x, static_cast<int>(ipar) );  
00113    }
00114    else { 
00115       // case of general linear function (built in TFormula with ++ )
00116       const TFormula * df = dynamic_cast<const TFormula*>( fFunc->GetLinearPart(ipar) );
00117       assert(df != 0); 
00118       fX[0] = x; 
00119       // hack since TFormula::EvalPar is not const
00120       return (const_cast<TFormula*> ( df) )->EvalPar( fX ) ; // derivatives should not depend on parameters since func is linear 
00121    }
00122 }
00123 
00124 void WrappedTF1::SetDerivPrecision(double eps) { fgEps = eps; }
00125 
00126 double WrappedTF1::GetDerivPrecision( ) { return fgEps; }
00127 
00128 
00129 
00130 // impelmentations for WrappedMultiTF1
00131 
00132 
00133 WrappedMultiTF1::WrappedMultiTF1 (TF1 & f, unsigned int dim  )  : 
00134    fLinear(false), 
00135    fFunc(&f),
00136    fDim(dim),
00137    fParams(f.GetParameters(),f.GetParameters()+f.GetNpar())
00138 { 
00139    // constructor of WrappedMultiTF1 
00140    // pass a dimension if dimension specified in TF1 does not correspond to real dimension
00141    // for example in case of multi-dimensional TF1 objects defined as TF1 (i.e. for functions with dims > 3 )
00142    if (fDim == 0) fDim = fFunc->GetNdim(); 
00143 
00144    // check that in case function is linear the linear terms are not zero
00145    // function is linear when is a TFormula created with "++" 
00146    // hyperplane are not yet existing in TFormula
00147    if (fFunc->IsLinear() ) { 
00148       unsigned int ip = 0; 
00149       fLinear = true;
00150       while (fLinear && ip < fParams.size() )  { 
00151          fLinear &= (fFunc->GetLinearPart(ip) != 0) ; 
00152          ip++;
00153       }
00154    }      
00155 }
00156 
00157 
00158 WrappedMultiTF1::WrappedMultiTF1(const WrappedMultiTF1 & rhs) :
00159    BaseFunc(),
00160    BaseParamFunc(),
00161    fLinear(rhs.fLinear), 
00162    fFunc(rhs.fFunc),
00163    fDim(rhs.fDim),
00164    fParams(rhs.fParams) 
00165 {
00166    // copy constructor 
00167 }
00168 
00169 
00170 WrappedMultiTF1 & WrappedMultiTF1::operator= (const WrappedMultiTF1 & rhs) { 
00171    // Assignment operator
00172    if (this == &rhs) return *this;  // time saving self-test
00173    fLinear = rhs.fLinear;  
00174    fFunc = rhs.fFunc; 
00175    fDim = rhs.fDim;
00176    fParams = rhs.fParams;
00177    return *this;
00178 } 
00179 
00180 
00181 void  WrappedMultiTF1::ParameterGradient(const double * x, const double * par, double * grad ) const {
00182    // evaluate the gradient of the function with respect to the parameters 
00183    if (!fLinear) { 
00184       // need to set parameter values
00185       fFunc->SetParameters( par );
00186       // no need to call InitArgs (it is called in TF1::GradientPar)
00187       fFunc->GradientPar(x,grad,fgEps);
00188    }
00189    else {  // case of linear functions
00190       unsigned int np = NPar();
00191       for (unsigned int i = 0; i < np; ++i) 
00192          grad[i] = DoParameterDerivative(x, par, i);
00193    }
00194 }
00195 
00196 double WrappedMultiTF1::DoParameterDerivative(const double * x, const double * p, unsigned int ipar ) const { 
00197    // evaluate the derivative of the function with respect to parameter ipar
00198    if (! fLinear ) {  
00199       fFunc->SetParameters( p );
00200       return fFunc->GradientPar(ipar, x,fgEps);
00201    }
00202    else { 
00203       // case of general linear function (built in TFormula with ++ )
00204       const TFormula * df = dynamic_cast<const TFormula*>( fFunc->GetLinearPart(ipar) );
00205       assert(df != 0); 
00206       // hack since TFormula::EvalPar is not const
00207       return (const_cast<TFormula*> ( df) )->EvalPar( x ) ; // derivatives should not depend on parameters since func is linear 
00208    }
00209 }
00210 
00211 void WrappedMultiTF1::SetDerivPrecision(double eps) { fgEps = eps; }
00212 
00213 double WrappedMultiTF1::GetDerivPrecision( ) { return fgEps; }
00214 
00215 
00216 } // end namespace Fit
00217 
00218 } // end namespace ROOT
00219 
00220 

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