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