Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TFormula.h
Go to the documentation of this file.
1 // @(#)root/hist:$Id$
2 // Author: Maciej Zimnoch 30/09/2013
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2013, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 // ---------------------------------- TFormula.h
12 #ifndef ROOT_TFormula
13 #define ROOT_TFormula
14 
15 
16 #include "TNamed.h"
17  #include "TBits.h"
18 #include "TObjArray.h"
19 #include "TMethodCall.h"
20 #include "TInterpreter.h"
21 #include <vector>
22 #include <list>
23 #include <map>
24 #include <Math/Types.h>
25 
26 class TFormulaFunction
27 {
28 public:
29  TString fName;
30  TString fBody;
31  Int_t fNargs;
32  Bool_t fFound;
33  Bool_t fFuncCall;
34  const char * GetName() const { return fName.Data(); }
35  const char * GetBody() const { return fBody.Data(); }
36  Int_t GetNargs() const { return fNargs;}
37  Bool_t IsFuncCall() const { return fFuncCall;}
38  TFormulaFunction(){}
39  TFormulaFunction(const TString &name, const TString &body, int numArgs)
40  : fName(name),fBody(body),fNargs(numArgs),fFound(false),fFuncCall(true) {}
41  TFormulaFunction(const TString& name)
42  : fName(name),fBody(""),fNargs(0),fFound(false),fFuncCall(false){}
43  Bool_t operator<(const TFormulaFunction &rhv) const
44  {
45  // order by length - first the longer ones to avoid replacing wrong functions
46  if ( fName.Length() < rhv.fName.Length() )
47  return true;
48  else if ( fName.Length() > rhv.fName.Length() )
49  return false;
50  // case of equal length
51  return fName < rhv.fName && fBody < rhv.fBody;
52  }
53  Bool_t operator==(const TFormulaFunction &rhv) const
54  {
55  return fName == rhv.fName && fBody == rhv.fBody && fNargs == rhv.fNargs;
56  }
57 };
58 
59 class TFormulaVariable
60 {
61 public:
62  TString fName;
63  Double_t fValue;
64  Int_t fArrayPos;
65  Bool_t fFound;
66  const char * GetName() const { return fName.Data(); }
67  Double_t GetInitialValue() const { return fValue; }
68  Int_t GetArrayPos() const { return fArrayPos; }
69  TFormulaVariable():fName(""),fValue(-1),fArrayPos(-1),fFound(false){}
70  TFormulaVariable(const TString &name, Double_t value, Int_t pos)
71  : fName(name), fValue(value), fArrayPos(pos),fFound(false) {}
72  Bool_t operator<(const TFormulaVariable &rhv) const
73  {
74  return fName < rhv.fName;
75  }
76 };
77 
78 struct TFormulaParamOrder {
79  bool operator() (const TString& a, const TString& b) const;
80 };
81 
82 
83 class TFormula : public TNamed
84 {
85 private:
86 
87  // All data members are transient apart from the string defining the formula and the parameter values
88 
89  TString fClingInput; //! input function passed to Cling
90  std::vector<Double_t> fClingVariables; //! cached variables
91  std::vector<Double_t> fClingParameters; // parameter values
92  Bool_t fReadyToExecute; //! trasient to force initialization
93  Bool_t fClingInitialized; //! transient to force re-initialization
94  Bool_t fAllParametersSetted; // flag to control if all parameters are setted
95  Bool_t fLazyInitialization = kFALSE; //! transient flag to control lazy initialization (needed for reading from files)
96  TMethodCall *fMethod; //! pointer to methodcall
97  std::unique_ptr<TMethodCall> fGradMethod; //! pointer to a methodcall
98  TString fClingName; //! unique name passed to Cling to define the function ( double clingName(double*x, double*p) )
99  std::string fSavedInputFormula; //! unique name used to defined the function and used in the global map (need to be saved in case of lazy initialization)
100 
101  using CallFuncSignature = TInterpreter::CallFuncIFacePtr_t::Generic_t;
102  std::string fGradGenerationInput; //! input query to clad to generate a gradient
103  CallFuncSignature fFuncPtr = nullptr; //! function pointer, owned by the JIT.
104  CallFuncSignature fGradFuncPtr = nullptr; //! function pointer, owned by the JIT.
105  void * fLambdaPtr = nullptr; //! pointer to the lambda function
106  static bool fIsCladRuntimeIncluded;
107 
108  void InputFormulaIntoCling();
109  Bool_t PrepareEvalMethod();
110  void FillDefaults();
111  void HandlePolN(TString &formula);
112  void HandleParametrizedFunctions(TString &formula);
113  void HandleParamRanges(TString &formula);
114  void HandleFunctionArguments(TString &formula);
115  void HandleExponentiation(TString &formula);
116  void HandleLinear(TString &formula);
117  Bool_t InitLambdaExpression(const char * formula);
118  static Bool_t IsDefaultVariableName(const TString &name);
119  void ReplaceAllNames(TString &formula, std::map<TString, TString> &substitutions);
120  void FillParametrizedFunctions(std::map<std::pair<TString, Int_t>, std::pair<TString, TString>> &functions);
121  void FillVecFunctionsShurtCuts();
122  void ReInitializeEvalMethod();
123  std::string GetGradientFuncName() const {
124  assert(fClingName.Length() && "TFormula is not initialized yet!");
125  return std::string(fClingName.Data()) + "_grad";
126  }
127  bool HasGradientGenerationFailed() const {
128  return !fGradMethod && !fGradGenerationInput.empty();
129  }
130 
131 protected:
132 
133  std::list<TFormulaFunction> fFuncs; //!
134  std::map<TString,TFormulaVariable> fVars; //! list of variable names
135  std::map<TString,Int_t,TFormulaParamOrder> fParams; //|| list of parameter names
136  std::map<TString,Double_t> fConsts; //!
137  std::map<TString,TString> fFunctionsShortcuts; //!
138  TString fFormula; // string representing the formula expression
139  Int_t fNdim; // Dimension - needed for lambda expressions
140  Int_t fNpar; //! Number of parameter (transient since we save the vector)
141  Int_t fNumber; //!
142  std::vector<TObject*> fLinearParts; // vector of linear functions
143  Bool_t fVectorized = false; // whether we should use vectorized or regular variables
144  // (we default to false since a lot of functions still cannot be expressed in vectorized form)
145 
146  static Bool_t IsOperator(const char c);
147  static Bool_t IsBracket(const char c);
148  static Bool_t IsFunctionNameChar(const char c);
149  static Bool_t IsScientificNotation(const TString & formula, int ipos);
150  static Bool_t IsHexadecimal(const TString & formula, int ipos);
151  static Bool_t IsAParameterName(const TString & formula, int ipos);
152  void ExtractFunctors(TString &formula);
153  void PreProcessFormula(TString &formula);
154  void ProcessFormula(TString &formula);
155  Bool_t PrepareFormula(TString &formula);
156  void ReplaceParamName(TString &formula, const TString & oldname, const TString & name);
157  void DoAddParameter(const TString &name, Double_t value, bool processFormula);
158  void DoSetParameters(const Double_t * p, Int_t size);
159  void SetPredefinedParamNames();
160 
161  Double_t DoEval(const Double_t * x, const Double_t * p = nullptr) const;
162 #ifdef R__HAS_VECCORE
163  ROOT::Double_v DoEvalVec(const ROOT::Double_v *x, const Double_t *p = nullptr) const;
164 #endif
165 
166 public:
167 
168  enum EStatusBits {
169  kNotGlobal = BIT(10), // don't store in gROOT->GetListOfFunction (it should be protected)
170  kNormalized = BIT(14), // set to true if the TFormula (ex gausn) is normalized
171  kLinear = BIT(16), //set to true if the TFormula is for linear fitting
172  kLambda = BIT(17) // set to true if TFormula has been build with a lambda
173  };
174  using GradientStorage = std::vector<Double_t>;
175 
176  TFormula();
177  virtual ~TFormula();
178  TFormula& operator=(const TFormula &rhs);
179  TFormula(const char *name, const char * formula = "", bool addToGlobList = true, bool vectorize = false);
180  TFormula(const char *name, const char * formula, int ndim, int npar, bool addToGlobList = true);
181  TFormula(const TFormula &formula);
182  // TFormula(const char *name, Int_t nparams, Int_t ndims);
183 
184  void AddParameter(const TString &name, Double_t value = 0) { DoAddParameter(name,value,true); }
185  void AddVariable(const TString &name, Double_t value = 0);
186  void AddVariables(const TString *vars, const Int_t size);
187  Int_t Compile(const char *expression="");
188  virtual void Copy(TObject &f1) const;
189  virtual void Clear(Option_t * option="");
190  Double_t Eval(Double_t x) const;
191  Double_t Eval(Double_t x, Double_t y) const;
192  Double_t Eval(Double_t x, Double_t y , Double_t z) const;
193  Double_t Eval(Double_t x, Double_t y , Double_t z , Double_t t ) const;
194  Double_t EvalPar(const Double_t *x, const Double_t *params=0) const;
195 
196  /// Generate gradient computation routine with respect to the parameters.
197  /// \returns true if a gradient was generated and GradientPar can be called.
198  bool GenerateGradientPar();
199 
200  /// Compute the gradient employing automatic differentiation.
201  ///
202  /// \param[in] x - The given variables, if nullptr the already stored
203  /// variables are used.
204  /// \param[out] result - The result of the computation wrt each direction.
205  void GradientPar(const Double_t *x, TFormula::GradientStorage& result);
206 
207  void GradientPar(const Double_t *x, Double_t *result);
208 
209  // template <class T>
210  // T Eval(T x, T y = 0, T z = 0, T t = 0) const;
211  template <class T>
212  T EvalPar(const T *x, const Double_t *params = 0) const {
213  return EvalParVec(x, params);
214  }
215 #ifdef R__HAS_VECCORE
216  ROOT::Double_v EvalParVec(const ROOT::Double_v *x, const Double_t *params = 0) const;
217 #endif
218  TString GetExpFormula(Option_t *option="") const;
219  TString GetGradientFormula() const;
220  const TObject *GetLinearPart(Int_t i) const;
221  Int_t GetNdim() const {return fNdim;}
222  Int_t GetNpar() const {return fNpar;}
223  Int_t GetNumber() const { return fNumber; }
224  const char * GetParName(Int_t ipar) const;
225  Int_t GetParNumber(const char * name) const;
226  Double_t GetParameter(const char * name) const;
227  Double_t GetParameter(Int_t param) const;
228  Double_t* GetParameters() const;
229  void GetParameters(Double_t *params) const;
230  Double_t GetVariable(const char *name) const;
231  Int_t GetVarNumber(const char *name) const;
232  TString GetVarName(Int_t ivar) const;
233  Bool_t IsValid() const { return fReadyToExecute && fClingInitialized; }
234  Bool_t IsVectorized() const { return fVectorized; }
235  Bool_t IsLinear() const { return TestBit(kLinear); }
236  void Print(Option_t *option = "") const;
237  void SetName(const char* name);
238  void SetParameter(const char* name, Double_t value);
239  void SetParameter(Int_t param, Double_t value);
240  void SetParameters(const Double_t *params);
241  //void SetParameters(const pair<TString,Double_t> *params, const Int_t size);
242  void SetParameters(Double_t p0,Double_t p1,Double_t p2=0,Double_t p3=0,Double_t p4=0,
243  Double_t p5=0,Double_t p6=0,Double_t p7=0,Double_t p8=0,
244  Double_t p9=0,Double_t p10=0); // *MENU*
245  void SetParName(Int_t ipar, const char *name);
246  void SetParNames(const char *name0="p0",const char *name1="p1",const char
247  *name2="p2",const char *name3="p3",const char
248  *name4="p4", const char *name5="p5",const char *name6="p6",const char *name7="p7",const char
249  *name8="p8",const char *name9="p9",const char *name10="p10"); // *MENU*
250  void SetVariable(const TString &name, Double_t value);
251  void SetVariables(const std::pair<TString,Double_t> *vars, const Int_t size);
252  void SetVectorized(Bool_t vectorized);
253 
254  ClassDef(TFormula,12)
255 };
256 #endif