Logo ROOT  
Reference Guide
WrappedMultiTF1.h
Go to the documentation of this file.
1// @(#)root/mathmore:$Id$
2// Author: L. Moneta Wed Sep 6 09:52:26 2006
3
4/**********************************************************************
5 * *
6 * Copyright (c) 2006 LCG ROOT Math Team, CERN/PH-SFT *
7 * *
8 * *
9 **********************************************************************/
10
11// Header file for class WrappedTFunction
12
13#ifndef ROOT_Math_WrappedMultiTF1
14#define ROOT_Math_WrappedMultiTF1
15
16
17#include "Math/IParamFunction.h"
18
19#include "TF1.h"
20#include <string>
21#include <vector>
22
23namespace ROOT {
24
25 namespace Math {
26
27 namespace Internal {
28 double DerivPrecision(double eps);
29 TF1 *CopyTF1Ptr(const TF1 *funcToCopy);
30 };
31
32 /**
33 Class to Wrap a ROOT Function class (like TF1) in a IParamMultiFunction interface
34 of multi-dimensions to be used in the ROOT::Math numerical algorithm.
35 This wrapper class does not own the TF1 pointer, so it assumes it exists during the wrapper lifetime.
36 The class copy the TF1 pointer only when it owns it.
37
38 The class from ROOT version 6.03 does not contain anymore a copy of the parameters. The parameters are
39 stored in the TF1 class.
40
41 @ingroup CppFunctions
42 */
43
44 //LM note: are there any issues when cloning the class for the parameters that are not copied anymore ??
45
46 template<class T>
48
49 public:
50
53
54 /**
55 constructor from a function pointer to a TF1
56 If dim = 0 dimension is taken from TF1::GetNdim().
57 In case of multi-dimensional function created using directly TF1 object the dimension
58 returned by TF1::GetNdim is always 1. The user must then pass the correct value of dim
59 */
60 WrappedMultiTF1Templ(TF1 &f, unsigned int dim = 0);
61
62 /**
63 Destructor (no operations). Function pointer is not owned
64 */
66 {
67 if (fOwnFunc && fFunc) delete fFunc;
68 }
69
70 /**
71 Copy constructor
72 */
74
75 /**
76 Assignment operator
77 */
79
80 /** @name interface inherited from IParamFunction */
81
82 /**
83 Clone the wrapper but not the original function
84 */
86 {
87 return new WrappedMultiTF1Templ<T>(*this);
88 }
89
90 /**
91 Retrieve the dimension of the function
92 */
93 unsigned int NDim() const override
94 {
95 return fDim;
96 }
97
98 /// get the parameter values (return values from TF1)
99 const double *Parameters() const override
100 {
101 //return (fParams.size() > 0) ? &fParams.front() : 0;
102 return fFunc->GetParameters();
103 }
104
105 /// set parameter values (only the cached one in this class,leave unchanges those of TF1)
106 void SetParameters(const double *p) override
107 {
108 //std::copy(p,p+fParams.size(),fParams.begin());
110 }
111
112 /// return number of parameters
113 unsigned int NPar() const override
114 {
115 // return fParams.size();
116 return fFunc->GetNpar();
117 }
118
119 /// return parameter name (from TF1)
120 std::string ParameterName(unsigned int i) const override {
121 return std::string(fFunc->GetParName(i));
122 }
123
124 // evaluate the derivative of the function with respect to the parameters
125 void ParameterGradient(const T *x, const double *par, T *grad) const override;
126
127 /// precision value used for calculating the derivative step-size
128 /// h = eps * |x|. The default is 0.001, give a smaller in case function changes rapidly
129 static void SetDerivPrecision(double eps);
130
131 /// get precision value used for calculating the derivative step-size
132 static double GetDerivPrecision();
133
134 /// method to retrieve the internal function pointer
135 const TF1 *GetFunction() const
136 {
137 return fFunc;
138 }
139
140 /// method to set a new function pointer and copy it inside.
141 /// By calling this method the class manages now the passed TF1 pointer
142 void SetAndCopyFunction(const TF1 *f = 0);
143
144 private:
145 /// evaluate function passing coordinates x and vector of parameters
146 T DoEvalPar(const T *x, const double *p) const override
147 {
148 return fFunc->EvalPar(x, p);
149 }
150
151 /// evaluate function using the cached parameter values (of TF1)
152 /// re-implement for better efficiency
153 T DoEvalVec(const T *x) const
154 {
155 return fFunc->EvalPar(x, 0);
156 }
157
158 /// evaluate function using the cached parameter values (of TF1)
159 /// re-implement for better efficiency
160 T DoEval(const T *x) const override
161 {
162 // no need to call InitArg for interpreted functions (done in ctor)
163
164 //const double * p = (fParams.size() > 0) ? &fParams.front() : 0;
165 return fFunc->EvalPar(x, 0);
166 }
167
168 /// evaluate the partial derivative with respect to the parameter
169 T DoParameterDerivative(const T *x, const double *p, unsigned int ipar) const override;
170
171 bool fLinear; // flag for linear functions
172 bool fPolynomial; // flag for polynomial functions
173 bool fOwnFunc; // flag to indicate we own the TF1 function pointer
174 TF1 *fFunc; // pointer to ROOT function
175 unsigned int fDim; // cached value of dimension
176 //std::vector<double> fParams; // cached vector with parameter values
177
178 };
179
180 /**
181 * Auxiliar class to bypass the (provisional) lack of vectorization in TFormula::EvalPar.
182 *
183 * WrappedMultiTF1Templ::DoParameterDerivation calls TFormula::EvalPar in the case of a general linear function
184 * built with TFormula using ++; as EvalPar is not vectorized, in order to generalize DoParameterDerivative with
185 * a general type T, we use this auxiliar class to branch the code in compile time with the double
186 * specialization (that can call EvalPar) and the general implementation (that throws an error in the case of
187 * general linear function).
188 */
189 template <class T>
191 static T DoParameterDerivative(const WrappedMultiTF1Templ<T> *, const T *, unsigned int)
192 {
193 Error("DoParameterDerivative", "The vectorized implementation of DoParameterDerivative does not support"
194 "general linear functions built in TFormula with ++");
195
196 return TMath::SignalingNaN();
197 }
198 };
199
200 template <>
202 static double
203 DoParameterDerivative(const WrappedMultiTF1Templ<double> *wrappedFunc, const double *x, unsigned int ipar)
204 {
205 const TFormula *df = dynamic_cast<const TFormula *>(wrappedFunc->GetFunction()->GetLinearPart(ipar));
206 assert(df != 0);
207 return (const_cast<TFormula *>(df))->EvalPar(x); // derivatives should not depend on parameters since
208 // function is linear
209 }
210 };
211
212 // implementations for WrappedMultiTF1Templ<T>
213 template<class T>
215 fLinear(false),
216 fPolynomial(false),
217 fOwnFunc(false),
218 fFunc(&f),
219 fDim(dim)
220 //fParams(f.GetParameters(),f.GetParameters()+f.GetNpar())
221 {
222 // constructor of WrappedMultiTF1Templ<T>
223 // pass a dimension if dimension specified in TF1 does not correspond to real dimension
224 // for example in case of multi-dimensional TF1 objects defined as TF1 (i.e. for functions with dims > 3 )
225 if (fDim == 0) fDim = fFunc->GetNdim();
226
227 // check that in case function is linear the linear terms are not zero
228 // function is linear when is a TFormula created with "++"
229 // hyperplane are not yet existing in TFormula
230 if (fFunc->IsLinear()) {
231 int ip = 0;
232 fLinear = true;
233 while (fLinear && ip < fFunc->GetNpar()) {
234 fLinear &= (fFunc->GetLinearPart(ip) != 0) ;
235 ip++;
236 }
237 }
238 // distinguish case of polynomial functions and linear functions
239 if (fDim == 1 && fFunc->GetNumber() >= 300 && fFunc->GetNumber() < 310) {
240 fLinear = true;
241 fPolynomial = true;
242 }
243 }
244
245 template<class T>
247 BaseParamFunc(rhs),
248 fLinear(rhs.fLinear),
249 fPolynomial(rhs.fPolynomial),
250 fOwnFunc(rhs.fOwnFunc),
251 fFunc(rhs.fFunc),
252 fDim(rhs.fDim)
253 //fParams(rhs.fParams)
254 {
255 // copy constructor
257 }
258
259 template<class T>
261 {
262 // Assignment operator
263 if (this == &rhs) return *this; // time saving self-test
264 fLinear = rhs.fLinear;
265 fPolynomial = rhs.fPolynomial;
266 fOwnFunc = rhs.fOwnFunc;
267 fDim = rhs.fDim;
268 //fParams = rhs.fParams;
269 return *this;
270 }
271
272 template <class T>
273 void WrappedMultiTF1Templ<T>::ParameterGradient(const T *x, const double *par, T *grad) const
274 {
275 // evaluate the gradient of the function with respect to the parameters
276 //IMPORTANT NOTE: TF1::GradientPar returns 0 for fixed parameters to avoid computing useless derivatives
277 // BUT the TLinearFitter wants to have the derivatives also for fixed parameters.
278 // so in case of fLinear (or fPolynomial) a non-zero value will be returned for fixed parameters
279
280 if (!fLinear) {
281 // need to set parameter values
282 fFunc->SetParameters(par);
283 // no need to call InitArgs (it is called in TF1::GradientPar)
284 double prec = this->GetDerivPrecision();
285 fFunc->GradientPar(x, grad, prec);
286 } else { // case of linear functions
287 unsigned int np = NPar();
288 for (unsigned int i = 0; i < np; ++i)
289 grad[i] = DoParameterDerivative(x, par, i);
290 }
291 }
292
293 template <class T>
294 T WrappedMultiTF1Templ<T>::DoParameterDerivative(const T *x, const double *p, unsigned int ipar) const
295 {
296 // evaluate the derivative of the function with respect to parameter ipar
297 // see note above concerning the fixed parameters
298 if (!fLinear) {
299 fFunc->SetParameters(p);
300 double prec = this->GetDerivPrecision();
301 return fFunc->GradientPar(ipar, x, prec);
302 }
303 if (fPolynomial) {
304 // case of polynomial function (no parameter dependency) (case for dim = 1)
305 assert(fDim == 1);
306 if (ipar == 0) return 1.0;
307#ifdef R__HAS_VECCORE
308 return vecCore::math::Pow(x[0], static_cast<T>(ipar));
309#else
310 return std::pow(x[0], static_cast<int>(ipar));
311#endif
312 } else {
313 // case of general linear function (built in TFormula with ++ )
315 }
316 }
317 template<class T>
319 {
321 }
322
323 template<class T>
325 {
327 }
328
329 template<class T>
331 {
332 const TF1 *funcToCopy = (f) ? f : fFunc;
333 fFunc = ::ROOT::Math::Internal::CopyTF1Ptr(funcToCopy);
334 fOwnFunc = true;
335 }
336
338
339 } // end namespace Math
340
341} // end namespace ROOT
342
343
344#endif /* ROOT_Fit_WrappedMultiTF1 */
#define f(i)
Definition: RSha256.hxx:104
void Error(const char *location, const char *msgfmt,...)
Use this function in case an error occurred.
Definition: TError.cxx:187
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t np
Documentation for the abstract class IBaseFunctionMultiDim.
Definition: IFunction.h:62
Interface (abstract class) for parametric gradient multi-dimensional functions providing in addition ...
Class to Wrap a ROOT Function class (like TF1) in a IParamMultiFunction interface of multi-dimensions...
T DoParameterDerivative(const T *x, const double *p, unsigned int ipar) const override
evaluate the partial derivative with respect to the parameter
~WrappedMultiTF1Templ() override
Destructor (no operations).
void SetAndCopyFunction(const TF1 *f=0)
method to set a new function pointer and copy it inside.
const double * Parameters() const override
get the parameter values (return values from TF1)
T DoEval(const T *x) const override
evaluate function using the cached parameter values (of TF1) re-implement for better efficiency
static void SetDerivPrecision(double eps)
precision value used for calculating the derivative step-size h = eps * |x|.
static double GetDerivPrecision()
get precision value used for calculating the derivative step-size
ROOT::Math::IParametricGradFunctionMultiDimTempl< T > BaseParamFunc
WrappedMultiTF1Templ & operator=(const WrappedMultiTF1Templ< T > &rhs)
Assignment operator.
std::string ParameterName(unsigned int i) const override
return parameter name (from TF1)
const TF1 * GetFunction() const
method to retrieve the internal function pointer
unsigned int NDim() const override
Retrieve the dimension of the function.
unsigned int NPar() const override
return number of parameters
IMultiGenFunctionTempl< T > * Clone() const override
Clone the wrapper but not the original function.
void SetParameters(const double *p) override
set parameter values (only the cached one in this class,leave unchanges those of TF1)
void ParameterGradient(const T *x, const double *par, T *grad) const override
Evaluate the all the derivatives (gradient vector) of the function with respect to the parameters at ...
ROOT::Math::IParametricFunctionMultiDimTempl< T >::BaseFunc BaseFunc
T DoEvalVec(const T *x) const
evaluate function using the cached parameter values (of TF1) re-implement for better efficiency
T DoEvalPar(const T *x, const double *p) const override
evaluate function passing coordinates x and vector of parameters
WrappedMultiTF1Templ(TF1 &f, unsigned int dim=0)
constructor from a function pointer to a TF1 If dim = 0 dimension is taken from TF1::GetNdim().
1-Dim function class
Definition: TF1.h:213
virtual Int_t GetNumber() const
Definition: TF1.h:503
virtual Int_t GetNpar() const
Definition: TF1.h:486
virtual Double_t * GetParameters() const
Definition: TF1.h:525
virtual Double_t EvalPar(const Double_t *x, const Double_t *params=0)
Evaluate function with given coordinates and parameters.
Definition: TF1.cxx:1483
virtual const char * GetParName(Int_t ipar) const
Definition: TF1.h:534
virtual Bool_t IsLinear() const
Definition: TF1.h:607
virtual void SetParameters(const Double_t *params)
Definition: TF1.h:649
virtual Int_t GetNdim() const
Definition: TF1.h:490
virtual const TObject * GetLinearPart(Int_t i) const
Definition: TF1.h:470
The Formula class.
Definition: TFormula.h:87
RVec< PromoteTypes< T0, T1 > > pow(const T0 &x, const RVec< T1 > &v)
Definition: RVec.hxx:1753
Double_t x[n]
Definition: legend1.C:17
Namespace for new Math classes and functions.
double T(double x)
Definition: ChebyshevPol.h:34
double DerivPrecision(double eps)
Definition: WrappedTF1.cxx:25
TF1 * CopyTF1Ptr(const TF1 *funcToCopy)
Definition: WrappedTF1.cxx:33
This file contains a specialised ROOT message handler to test for diagnostic in unit tests.
Double_t SignalingNaN()
Returns a signaling NaN as defined by IEEE 754](http://en.wikipedia.org/wiki/NaN#Signaling_NaN).
Definition: TMath.h:907
static double DoParameterDerivative(const WrappedMultiTF1Templ< double > *wrappedFunc, const double *x, unsigned int ipar)
Auxiliar class to bypass the (provisional) lack of vectorization in TFormula::EvalPar.
static T DoParameterDerivative(const WrappedMultiTF1Templ< T > *, const T *, unsigned int)