Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
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
94 {
95 return fDim;
96 }
97
98 /// get the parameter values (return values from TF1)
99 const double *Parameters() const
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)
107 {
108 //std::copy(p,p+fParams.size(),fParams.begin());
110 }
111
112 /// return number of parameters
113 unsigned int NPar() const
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 {
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;
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
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
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;
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 {
326 return ::ROOT::Math::Internal::DerivPrecision(-1);
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 */
double
#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
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...
void SetParameters(const double *p)
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
Evaluate the all the derivatives (gradient vector) of the function with respect to the parameters at ...
unsigned int NDim() const
Retrieve the dimension of the function.
T DoParameterDerivative(const T *x, const double *p, unsigned int ipar) const
evaluate the partial derivative with respect to the parameter
void SetAndCopyFunction(const TF1 *f=0)
method to set a new function pointer and copy it inside.
unsigned int NPar() const
return number of parameters
static void SetDerivPrecision(double eps)
precision value used for calculating the derivative step-size h = eps * |x|.
const double * Parameters() const
get the parameter values (return values from TF1)
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.
T DoEval(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
evaluate function passing coordinates x and vector of parameters
std::string ParameterName(unsigned int i) const
return parameter name (from TF1)
const TF1 * GetFunction() const
method to retrieve the internal function pointer
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
WrappedMultiTF1Templ(TF1 &f, unsigned int dim=0)
constructor from a function pointer to a TF1 If dim = 0 dimension is taken from TF1::GetNdim().
IMultiGenFunctionTempl< T > * Clone() const
Clone the wrapper but not the original function.
~WrappedMultiTF1Templ()
Destructor (no operations).
1-Dim function class
Definition TF1.h:213
virtual Int_t GetNumber() const
Definition TF1.h:498
virtual Int_t GetNpar() const
Definition TF1.h:481
virtual Double_t * GetParameters() const
Definition TF1.h:520
virtual Double_t EvalPar(const Double_t *x, const Double_t *params=0)
Evaluate function with given coordinates and parameters.
Definition TF1.cxx:1463
virtual const char * GetParName(Int_t ipar) const
Definition TF1.h:529
virtual Bool_t IsLinear() const
Definition TF1.h:602
virtual void SetParameters(const Double_t *params)
Definition TF1.h:644
virtual Int_t GetNdim() const
Definition TF1.h:485
virtual const TObject * GetLinearPart(Int_t i) const
Definition TF1.h:465
The Formula class.
Definition TFormula.h:87
Double_t x[n]
Definition legend1.C:17
Namespace for new Math classes and functions.
double DerivPrecision(double eps)
TF1 * CopyTF1Ptr(const TF1 *funcToCopy)
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...
Double_t SignalingNaN()
Returns a signaling NaN as defined by IEEE 754](http://en.wikipedia.org/wiki/NaN#Signaling_NaN)
Definition TMath.h:908
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)