From 2e180aa8cce9bd980378f70c6a2611818c20c28f Mon Sep 17 00:00:00 2001 From: Xavier Valls <xaviervallspla@gmail.com> Date: Fri, 24 Feb 2017 11:57:29 +0100 Subject: [PATCH] Make derivative precission declarations static again For backwards compatibility --- hist/hist/inc/Math/WrappedMultiTF1.h | 24 +-- hist/hist/inc/Math/WrappedTF1.h | 255 ++++++++++++++------------- hist/hist/src/WrappedTF1.cxx | 24 ++- 3 files changed, 159 insertions(+), 144 deletions(-) diff --git a/hist/hist/inc/Math/WrappedMultiTF1.h b/hist/hist/inc/Math/WrappedMultiTF1.h index 515c774b62f..50b82674ad7 100644 --- a/hist/hist/inc/Math/WrappedMultiTF1.h +++ b/hist/hist/inc/Math/WrappedMultiTF1.h @@ -24,7 +24,9 @@ namespace ROOT { namespace Math { - + namespace Internal { + double DerivPrecision(double eps); + }; /** Class to Wrap a ROOT Function class (like TF1) in a IParamMultiFunction interface of multi-dimensions to be used in the ROOT::Math numerical algorithm. @@ -37,7 +39,7 @@ namespace ROOT { @ingroup CppFunctions */ -//LM note: are there any issues when cloning the class for the parameters that are not copied anymore ?? + //LM note: are there any issues when cloning the class for the parameters that are not copied anymore ?? template<class BackendType> class WrappedMultiTF1Templ: virtual public ROOT::Math::IParametricGradFunctionMultiDimTempl<BackendType> { @@ -117,10 +119,10 @@ namespace ROOT { /// precision value used for calculating the derivative step-size /// h = eps * |x|. The default is 0.001, give a smaller in case function changes rapidly - void SetDerivPrecision(double eps); + static void SetDerivPrecision(double eps); /// get precision value used for calculating the derivative step-size - double GetDerivPrecision(); + static double GetDerivPrecision(); /// method to retrieve the internal function pointer const TF1 *GetFunction() const @@ -166,7 +168,6 @@ namespace ROOT { unsigned int fDim; // cached value of dimension //std::vector<double> fParams; // cached vector with parameter values - double fEps; // epsilon used in derivative calculation h ~ eps |p| }; // impelmentations for WrappedMultiTF1Templ<BackendType> @@ -176,8 +177,7 @@ namespace ROOT { fPolynomial(false), fOwnFunc(false), fFunc(&f), - fDim(dim), - fEps(0.001) + fDim(dim) //fParams(f.GetParameters(),f.GetParameters()+f.GetNpar()) { // constructor of WrappedMultiTF1Templ<BackendType> @@ -243,7 +243,8 @@ namespace ROOT { // need to set parameter values fFunc->SetParameters(par); // no need to call InitArgs (it is called in TF1::GradientPar) - fFunc->GradientPar(x, grad, fEps); + double prec = this->GetDerivPrecision(); + fFunc->GradientPar(x, grad, prec); } else { // case of linear functions unsigned int np = NPar(); for (unsigned int i = 0; i < np; ++i) @@ -258,7 +259,8 @@ namespace ROOT { // see note above concerning the fixed parameters if (! fLinear) { fFunc->SetParameters(p); - return fFunc->GradientPar(ipar, x, fEps); + double prec = this->GetDerivPrecision(); + return fFunc->GradientPar(ipar, x, prec); } if (fPolynomial) { // case of polynomial function (no parameter dependency) (case for dim = 1) @@ -277,13 +279,13 @@ namespace ROOT { template<class BackendType> void WrappedMultiTF1Templ<BackendType>::SetDerivPrecision(double eps) { - fEps = eps; + ::ROOT::Math::Internal::DerivPrecision(eps); } template<class BackendType> double WrappedMultiTF1Templ<BackendType>::GetDerivPrecision() { - return fEps; + return ::ROOT::Math::Internal::DerivPrecision(-1); } template<class BackendType> diff --git a/hist/hist/inc/Math/WrappedTF1.h b/hist/hist/inc/Math/WrappedTF1.h index 1a7c73221ba..9fd313eddee 100644 --- a/hist/hist/inc/Math/WrappedTF1.h +++ b/hist/hist/inc/Math/WrappedTF1.h @@ -23,135 +23,142 @@ namespace ROOT { namespace Math { -/** - Class to Wrap a ROOT Function class (like TF1) in a IParamFunction interface - of one dimensions to be used in the ROOT::Math numerical algorithms - The wrapper does not own bby default the TF1 pointer, so it assumes it exists during the wrapper lifetime + /** + Class to Wrap a ROOT Function class (like TF1) in a IParamFunction interface + of one dimensions to be used in the ROOT::Math numerical algorithms + The wrapper does not own bby default the TF1 pointer, so it assumes it exists during the wrapper lifetime - The class from ROOT version 6.03 does not contain anymore a copy of the parameters. The parameters are - stored in the TF1 class. + The class from ROOT version 6.03 does not contain anymore a copy of the parameters. The parameters are + stored in the TF1 class. - @ingroup CppFunctions -*/ -class WrappedTF1 : public ROOT::Math::IParamGradFunction, public ROOT::Math::IGradientOneDim { + @ingroup CppFunctions + */ + class WrappedTF1 : public ROOT::Math::IParamGradFunction, public ROOT::Math::IGradientOneDim { -public: + public: - typedef ROOT::Math::IGradientOneDim IGrad; - typedef ROOT::Math::IParamGradFunction BaseGradFunc; - typedef ROOT::Math::IParamGradFunction::BaseFunc BaseFunc; - - - /** - constructor from a TF1 function pointer. - */ - WrappedTF1 ( TF1 & f ); - - /** - Destructor (no operations). TF1 Function pointer is not owned - */ - virtual ~WrappedTF1 () {} - - /** - Copy constructor - */ - WrappedTF1(const WrappedTF1 & rhs); - - /** - Assignment operator - */ - WrappedTF1 & operator = (const WrappedTF1 & rhs); - - /** @name interface inherited from IFunction */ - - /** - Clone the wrapper but not the original function - */ - ROOT::Math::IGenFunction * Clone() const { - return new WrappedTF1(*this); - } - - - /** @name interface inherited from IParamFunction */ - - /// get the parameter values (return values cachen inside, those inside TF1 might be different) - const double * Parameters() const { - //return (fParams.size() > 0) ? &fParams.front() : 0; - return fFunc->GetParameters(); - } - - /// set parameter values - /// need to call also SetParameters in TF1 in ace some other operations (re-normalizations) are needed - void SetParameters(const double * p) { - //std::copy(p,p+fParams.size(),fParams.begin()); - fFunc->SetParameters(p); - } - - /// return number of parameters - unsigned int NPar() const { - //return fParams.size(); - return fFunc->GetNpar(); - } - - /// return parameter name (this is stored in TF1) - std::string ParameterName(unsigned int i) const { - return std::string(fFunc->GetParName(i)); - } - - - using BaseGradFunc::operator(); - - /// evaluate the derivative of the function with respect to the parameters - void ParameterGradient(double x, const double * par, double * grad ) const; - - /// calculate function and derivative at same time (required by IGradient interface) - void FdF(double x, double & f, double & deriv) const { - f = DoEval(x); - deriv = DoDerivative(x); - } - - /// precision value used for calculating the derivative step-size - /// h = eps * |x|. The default is 0.001, give a smaller in case function changes rapidly - static void SetDerivPrecision(double eps); - - /// get precision value used for calculating the derivative step-size - static double GetDerivPrecision(); - -private: - - - /// evaluate function passing coordinates x and vector of parameters - double DoEvalPar (double x, const double * p ) const { - fX[0] = x; - if (fFunc->GetMethodCall() ) fFunc->InitArgs(fX,p); // needed for interpreted functions - return fFunc->EvalPar(fX,p); - } - - /// evaluate function using the cached parameter values (of TF1) - /// re-implement for better efficiency - double DoEval (double x) const { - // no need to call InitArg for interpreted functions (done in ctor) - // use EvalPar since it is much more efficient than Eval - fX[0] = x; - //const double * p = (fParams.size() > 0) ? &fParams.front() : 0; - return fFunc->EvalPar(fX, 0 ); - } - - /// return the function derivatives w.r.t. x - double DoDerivative( double x ) const; - - /// evaluate the derivative of the function with respect to the parameters - double DoParameterDerivative(double x, const double * p, unsigned int ipar ) const; - - bool fLinear; // flag for linear functions - bool fPolynomial; // flag for polynomial functions - TF1 * fFunc; // pointer to ROOT function - mutable double fX[1]; //! cached vector for x value (needed for TF1::EvalPar signature) - //std::vector<double> fParams; // cached vector with parameter values - - static double fgEps; // epsilon used in derivative calculation h ~ eps |x| -}; + typedef ROOT::Math::IGradientOneDim IGrad; + typedef ROOT::Math::IParamGradFunction BaseGradFunc; + typedef ROOT::Math::IParamGradFunction::BaseFunc BaseFunc; + + + /** + constructor from a TF1 function pointer. + */ + WrappedTF1(TF1 &f); + + /** + Destructor (no operations). TF1 Function pointer is not owned + */ + virtual ~WrappedTF1() {} + + /** + Copy constructor + */ + WrappedTF1(const WrappedTF1 &rhs); + + /** + Assignment operator + */ + WrappedTF1 &operator = (const WrappedTF1 &rhs); + + /** @name interface inherited from IFunction */ + + /** + Clone the wrapper but not the original function + */ + ROOT::Math::IGenFunction *Clone() const + { + return new WrappedTF1(*this); + } + + + /** @name interface inherited from IParamFunction */ + + /// get the parameter values (return values cachen inside, those inside TF1 might be different) + const double *Parameters() const + { + //return (fParams.size() > 0) ? &fParams.front() : 0; + return fFunc->GetParameters(); + } + + /// set parameter values + /// need to call also SetParameters in TF1 in ace some other operations (re-normalizations) are needed + void SetParameters(const double *p) + { + //std::copy(p,p+fParams.size(),fParams.begin()); + fFunc->SetParameters(p); + } + + /// return number of parameters + unsigned int NPar() const + { + //return fParams.size(); + return fFunc->GetNpar(); + } + + /// return parameter name (this is stored in TF1) + std::string ParameterName(unsigned int i) const + { + return std::string(fFunc->GetParName(i)); + } + + + using BaseGradFunc::operator(); + + /// evaluate the derivative of the function with respect to the parameters + void ParameterGradient(double x, const double *par, double *grad) const; + + /// calculate function and derivative at same time (required by IGradient interface) + void FdF(double x, double &f, double &deriv) const + { + f = DoEval(x); + deriv = DoDerivative(x); + } + + /// precision value used for calculating the derivative step-size + /// h = eps * |x|. The default is 0.001, give a smaller in case function changes rapidly + static void SetDerivPrecision(double eps); + + /// get precision value used for calculating the derivative step-size + static double GetDerivPrecision(); + + private: + + + /// evaluate function passing coordinates x and vector of parameters + double DoEvalPar(double x, const double *p) const + { + fX[0] = x; + if (fFunc->GetMethodCall()) fFunc->InitArgs(fX, p); // needed for interpreted functions + return fFunc->EvalPar(fX, p); + } + + /// evaluate function using the cached parameter values (of TF1) + /// re-implement for better efficiency + double DoEval(double x) const + { + // no need to call InitArg for interpreted functions (done in ctor) + // use EvalPar since it is much more efficient than Eval + fX[0] = x; + //const double * p = (fParams.size() > 0) ? &fParams.front() : 0; + return fFunc->EvalPar(fX, 0); + } + + /// return the function derivatives w.r.t. x + double DoDerivative(double x) const; + + /// evaluate the derivative of the function with respect to the parameters + double DoParameterDerivative(double x, const double *p, unsigned int ipar) const; + + bool fLinear; // flag for linear functions + bool fPolynomial; // flag for polynomial functions + TF1 *fFunc; // pointer to ROOT function + mutable double fX[1]; //! cached vector for x value (needed for TF1::EvalPar signature) + //std::vector<double> fParams; // cached vector with parameter values + + }; } // end namespace Fit diff --git a/hist/hist/src/WrappedTF1.cxx b/hist/hist/src/WrappedTF1.cxx index 7e0577dcb01..1e581aa6230 100644 --- a/hist/hist/src/WrappedTF1.cxx +++ b/hist/hist/src/WrappedTF1.cxx @@ -21,9 +21,16 @@ namespace ROOT { namespace Math { -// static value for epsilon used in derivative calculations - double WrappedTF1::fgEps = 0.001; + namespace Internal { + double DerivPrecision(double eps) + { + static double gEPs = 0.001; // static value for epsilon used in derivative calculations + if (eps > 0) + gEPs = eps; + return gEPs; + } + } WrappedTF1::WrappedTF1(TF1 &f) : fLinear(false), @@ -86,7 +93,7 @@ namespace ROOT { // need to set parameter values fFunc->SetParameters(par); // no need to call InitArgs (it is called in TF1::GradientPar) - fFunc->GradientPar(&x, grad, fgEps); + fFunc->GradientPar(&x, grad, GetDerivPrecision()); } else { unsigned int np = NPar(); for (unsigned int i = 0; i < np; ++i) @@ -100,7 +107,7 @@ namespace ROOT { // parameter are passed as non-const in Derivative //double * p = (fParams.size() > 0) ? const_cast<double *>( &fParams.front()) : 0; - return fFunc->Derivative(x, (double *) 0, fgEps); + return fFunc->Derivative(x, (double *) 0, GetDerivPrecision()); } double WrappedTF1::DoParameterDerivative(double x, const double *p, unsigned int ipar) const @@ -112,7 +119,7 @@ namespace ROOT { if (! fLinear) { fFunc->SetParameters(p); - return fFunc->GradientPar(ipar, &x, fgEps); + return fFunc->GradientPar(ipar, &x, GetDerivPrecision()); } else if (fPolynomial) { // case of polynomial function (no parameter dependency) return std::pow(x, static_cast<int>(ipar)); @@ -128,16 +135,15 @@ namespace ROOT { void WrappedTF1::SetDerivPrecision(double eps) { - fgEps = eps; + ::ROOT::Math::Internal::DerivPrecision(eps); } double WrappedTF1::GetDerivPrecision() { - return fgEps; + return ::ROOT::Math::Internal::DerivPrecision(-1); } - - } // end namespace Fit + } // end namespace Math } // end namespace ROOT -- GitLab