Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
WrappedTF1.cxx
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 // implementation file for class WrappedTF1 and WrappedMultiTF1
12 
13 #include "Math/WrappedTF1.h"
14 #include "Math/WrappedMultiTF1.h"
15 #include "TClass.h" // needed to copy the TF1 pointer
16 
17 #include <cmath>
18 
19 
20 namespace ROOT {
21 
22  namespace Math {
23 
24  namespace Internal {
25  double DerivPrecision(double eps)
26  {
27  static double gEPs = 0.001; // static value for epsilon used in derivative calculations
28  if (eps > 0)
29  gEPs = eps;
30  return gEPs;
31  }
32 
33  TF1 *CopyTF1Ptr(const TF1 *funcToCopy)
34  {
35  TF1 *fnew = (TF1 *) funcToCopy->IsA()->New();
36  funcToCopy->Copy(*fnew);
37  return fnew;
38  }
39  }
40 
41  WrappedTF1::WrappedTF1(TF1 &f) :
42  fLinear(false),
43  fPolynomial(false),
44  fFunc(&f),
45  fX()
46  //fParams(f.GetParameters(),f.GetParameters()+f.GetNpar())
47  {
48  // constructor from a TF1 function pointer.
49 
50  // init the pointers for CINT
51  //if (fFunc->GetMethodCall() ) fFunc->InitArgs(fX, &fParams.front() );
52  if (fFunc->GetMethodCall()) fFunc->InitArgs(fX, 0);
53  // distinguish case of polynomial functions and linear functions
54  if (fFunc->GetNumber() >= 300 && fFunc->GetNumber() < 310) {
55  fLinear = true;
56  fPolynomial = true;
57  }
58  // check that in case function is linear the linear terms are not zero
59  if (fFunc->IsLinear()) {
60  int ip = 0;
61  fLinear = true;
62  while (fLinear && ip < fFunc->GetNpar()) {
63  fLinear &= (fFunc->GetLinearPart(ip) != 0) ;
64  ip++;
65  }
66  }
67  }
68 
69  WrappedTF1::WrappedTF1(const WrappedTF1 &rhs) :
70  BaseFunc(),
71  BaseGradFunc(),
72  IGrad(),
73  fLinear(rhs.fLinear),
74  fPolynomial(rhs.fPolynomial),
75  fFunc(rhs.fFunc),
76  fX()
77  //fParams(rhs.fParams)
78  {
79  // copy constructor
80  fFunc->InitArgs(fX, 0);
81  }
82 
83  WrappedTF1 &WrappedTF1::operator = (const WrappedTF1 &rhs)
84  {
85  // assignment operator
86  if (this == &rhs) return *this; // time saving self-test
87  fLinear = rhs.fLinear;
88  fPolynomial = rhs.fPolynomial;
89  fFunc = rhs.fFunc;
90  fFunc->InitArgs(fX, 0);
91  //fParams = rhs.fParams;
92  return *this;
93  }
94 
95  void WrappedTF1::ParameterGradient(double x, const double *par, double *grad) const
96  {
97  // evaluate the derivative of the function with respect to the parameters
98  if (!fLinear) {
99  // need to set parameter values
100  fFunc->SetParameters(par);
101  // no need to call InitArgs (it is called in TF1::GradientPar)
102  fFunc->GradientPar(&x, grad, GetDerivPrecision());
103  } else {
104  unsigned int np = NPar();
105  for (unsigned int i = 0; i < np; ++i)
106  grad[i] = DoParameterDerivative(x, par, i);
107  }
108  }
109 
110  double WrappedTF1::DoDerivative(double x) const
111  {
112  // return the function derivatives w.r.t. x
113 
114  // parameter are passed as non-const in Derivative
115  //double * p = (fParams.size() > 0) ? const_cast<double *>( &fParams.front()) : 0;
116  return fFunc->Derivative(x, (double *) 0, GetDerivPrecision());
117  }
118 
119  double WrappedTF1::DoParameterDerivative(double x, const double *p, unsigned int ipar) const
120  {
121  // evaluate the derivative of the function with respect to the parameters
122  //IMPORTANT NOTE: TF1::GradientPar returns 0 for fixed parameters to avoid computing useless derivatives
123  // BUT the TLinearFitter wants to have the derivatives also for fixed parameters.
124  // so in case of fLinear (or fPolynomial) a non-zero value will be returned for fixed parameters
125 
126  if (! fLinear) {
127  fFunc->SetParameters(p);
128  return fFunc->GradientPar(ipar, &x, GetDerivPrecision());
129  } else if (fPolynomial) {
130  // case of polynomial function (no parameter dependency)
131  return std::pow(x, static_cast<int>(ipar));
132  } else {
133  // case of general linear function (built in TFormula with ++ )
134  const TFormula *df = dynamic_cast<const TFormula *>(fFunc->GetLinearPart(ipar));
135  assert(df != 0);
136  fX[0] = x;
137  // hack since TFormula::EvalPar is not const
138  return (const_cast<TFormula *>(df))->Eval(x) ; // derivatives should not depend on parameters since func is linear
139  }
140  }
141 
142  void WrappedTF1::SetDerivPrecision(double eps)
143  {
144  ::ROOT::Math::Internal::DerivPrecision(eps);
145  }
146 
147  double WrappedTF1::GetDerivPrecision()
148  {
149  return ::ROOT::Math::Internal::DerivPrecision(-1);
150  }
151 
152  } // end namespace Math
153 
154 } // end namespace ROOT
155 
156