CMS 3D CMS Logo

ClhepEvaluator.cc
Go to the documentation of this file.
1 #include <ext/alloc_traits.h>
2 #include <iostream>
3 #include <string>
4 #include <vector>
5 
6 #include "CLHEP/Evaluator/Evaluator.h"
10 
12  // enable standard mathematical funtions
13  evaluator_.setStdMath();
14 
15  // set Geant4 compatible units
16  evaluator_.setSystemOfUnits(1.e+3, 1. / 1.60217733e-25, 1.e+9, 1. / 1.60217733e-10, 1.0, 1.0, 1.0);
17 
18  // set some global vars, which are in fact known by Clhep::SystemOfUnits
19  // but are NOT set in CLHEP::Evaluator ...
20  evaluator_.setVariable("mum", "1.e-3*mm");
21  evaluator_.setVariable("fm", "1.e-15*meter");
22 }
23 
25 
26 void dd_exchange_value(std::vector<std::string>& vars,
27  std::vector<std::string>& vals,
28  const std::string& var,
29  const std::string& val) {
30  std::vector<std::string>::iterator it(vars.begin()), ed(vars.end());
32  for (; it != ed; ++it) {
33  if (*it == var) {
34  // a potential memory leak below! But CLHEP::Evaluator should take care about it!!
35  vals[count] = val;
36  break;
37  }
38  ++count;
39  }
40 }
41 
42 void ClhepEvaluator::set(const std::string& ns, const std::string& name, const std::string& exprValue) {
43  checkname(ns); // fancy characters in ns or name ??
44  checkname(name);
45  std::string newVar;
46  std::string newVal;
47  prepare(ns, name, exprValue, newVar, newVal);
48  evaluator_.setVariable(newVar.c_str(), newVal.c_str());
49  switch (evaluator_.status()) {
50  case HepTool::Evaluator::WARNING_EXISTING_VARIABLE:
51  dd_exchange_value(variables_, values_, newVar, newVal);
52  break;
54  case HepTool::Evaluator::WARNING_EXISTING_FUNCTION:
55  case HepTool::Evaluator::WARNING_BLANK_STRING:
56  variables_.emplace_back(newVar);
57  values_.emplace_back(newVal);
58  break;
59  default:
60  std::cout << "set-var: ns=" << ns << " nm=" << name << " val=" << exprValue << std::endl;
61  evaluator_.print_error();
62  throwex(ns, name, exprValue, "can't set parameter !");
63  }
64 }
65 
67  evaluator_.setVariable(n.c_str(), v.c_str());
68  switch (evaluator_.status()) {
69  case HepTool::Evaluator::WARNING_EXISTING_VARIABLE:
71  break;
73  case HepTool::Evaluator::WARNING_EXISTING_FUNCTION:
74  case HepTool::Evaluator::WARNING_BLANK_STRING:
75  variables_.emplace_back(n);
76  values_.emplace_back(v);
77  break;
78  default:
79  std::cout << "set-varname=" << n << " val=" << v << std::endl;
80  evaluator_.print_error();
81  throwex("", n, v, "can't set parameter !");
82  }
83 }
84 
85 double ClhepEvaluator::eval(const std::string& ns, const std::string& expr) {
86  // eval does not store std::strings in the values_!
87  // eval throws if it can't evaluate!
88  std::string pseudo("(evaluating)");
89  std::string prepared;
90 
91  prepare(ns, pseudo, expr, pseudo, prepared);
92 
93  double result = evaluator_.evaluate(prepared.c_str());
94  if (evaluator_.status() != HepTool::Evaluator::OK) {
95  std::cout << "expr: " << prepared << std::endl;
96  std::cout << "------";
97  for (int i = 0; i < evaluator_.error_position(); ++i)
98  std::cout << "-";
99  std::cout << "^" << std::endl;
100  evaluator_.print_error();
101  throwex(ns, prepared, expr, "can't evaluate: " + expr + std::string("!"));
102  }
103 
104  return result;
105 }
106 
107 double ClhepEvaluator::eval(const char* expression) {
108  double result = evaluator_.evaluate(expression);
109  if (evaluator_.status() != HepTool::Evaluator::OK) {
110  std::cout << "expr: " << expression << std::endl;
111  std::cout << "------";
112  for (int i = 0; i < evaluator_.error_position(); ++i)
113  std::cout << "-";
114  std::cout << "^" << std::endl;
115  evaluator_.print_error();
116  throwex("", expression, "", "can't evaluate: " + std::string(expression) + std::string("!"));
117  }
118  return result;
119 }
120 
121 bool ClhepEvaluator::isDefined(const std::string& ns, //< current namespace
122  const std::string& name //< name of the variable inside current namespace
123 ) {
124  std::string newVar;
125  std::string newVal;
126  prepare(ns, name, "0", newVar, newVal);
127  return evaluator_.findVariable(newVar.c_str());
128 }
129 
131  // clear the dictionary
132  evaluator_.clear();
133 
134  // clear the cache of values & variable-names
135  variables_.clear();
136  values_.clear();
137 }
138 
140  const std::string& name,
141  const std::string& exprValue,
142  std::string& nameResult,
143  std::string& valResult) const {
144  static const std::string sep("___"); // separator between ns and name
145  // SOME SPAGHETTI CODE ...
146  // break it down into some addional member functions ...
147 
148  // the name and namespaces are not checked for 'forbidden' symbols like [,],: ...
149  nameResult = ns + sep + name;
150 
151  // scan the expression std::string and remove [ ], and insert the current namespace if it's missing
153 
154  // 2 pass for simplicity (which is NOT efficient ...)
155  // pass 1: find variables without namespace, e.g. [abcd], and mark them
156  // pass 2: remove [ ] & ( exchange ':' with '_' | add the namespace at marked variables )
157 
158  std::string::size_type sz = exprValue.size();
160  bool insideBracket = false;
161  bool nsFound = false;
162  int varCount = 0; // count the variables from 1,2,3,...
163  std::vector<int> hasNs(1); // marked[i]=1 ... variable number i has a namespace attached with ':'
164 
165  while (idx < sz) {
166  switch (exprValue[idx]) {
167  case '[':
168  if (nsFound || insideBracket) { // oops, something went wrong. simply throw!
169  throwex(ns, name, exprValue, "found a ':' outside '[..]' , or too many '[' !", idx);
170  }
171  insideBracket = true;
172  ++varCount;
173  break;
174  case ']':
175  if (!insideBracket) {
176  throwex(ns, name, exprValue, "too many ']' !", idx);
177  }
178  insideBracket = false;
179  if (nsFound) {
180  nsFound = false; // reset
181  hasNs.emplace_back(1);
182  } else {
183  hasNs.emplace_back(0);
184  }
185  break;
186  case ':':
187  if ((!insideBracket) || nsFound) { // oops, a namespace outside [] or a 2nd ':' inside []! !
188  throwex(ns, name, exprValue, "found a ':' outside '[..]' , or multiple ':' inside '[..]'", idx);
189  }
190  nsFound = true;
191  break;
192  default:;
193  } // switch
194  ++idx;
195  } // while(sz)
196 
197  // status after pass 1 must be: every [ ] is closed and no ':'
198  if (insideBracket || nsFound) {
199  throwex(ns, name, exprValue, "'[..]' not closed , or ':' outside of '[..]'", idx);
200  }
201 
202  // Pass 2: now remove all '[' ']', replace ':' or add 'ns' + '_'
203  //sz = exprValue.size();
204  idx = 0;
205  varCount = 0;
206  //bool ommit = false;
207  while (idx < sz) {
208  switch (exprValue[idx]) {
209  case '[':
210  ++varCount;
211  if (!hasNs[varCount]) {
212  valResult = valResult + ns + sep;
213  }
214  break;
215  case ']':
216  break;
217  case ':':
218  valResult = valResult + sep;
219  break;
220  default:
221  valResult = valResult + exprValue[idx];
222  } // switch
223  ++idx;
224  } // while
225 }
226 
228  const std::string& ns, const std::string& name, const std::string& expr, const std::string& reason, int idx) const {
229  std::string er = std::string("ClhepEvaluator ERROR: ") + reason + std::string("\n") + std::string(" nmspace=") + ns +
230  std::string("\n varname=") + name + std::string("\n exp=") + expr + std::string("\n at=") +
231  expr.substr(0, idx);
232  throw cms::Exception("DDException") << er;
233 }
234 
236  // '[' ']' ' ' ':' are forbidden for names and namespaces of parameters
237  std::string::size_type sz = s.size();
238  while (sz) {
239  --sz;
240  //bool stop = false;
241  switch (s[sz]) {
242  case ']':
243  case '[':
244  case ' ':
245  case ':':
246  case '\n':
247  case '\t':
248  // case '.':
249  case '&':
250  case '*':
251  case '+':
252  case '-':
253  case '/':
254  case '^':
255  std::string e = std::string("ClhepEvaluator ERROR: forbidden character '") + s[sz] +
256  std::string("' found in '") + s + std::string("' !");
257  throw cms::Exception("DDException") << e;
258  break;
259  }
260  }
261 }
bool isDefined(const std::string &ns, const std::string &name)
std::vector< std::string > variables_
void prepare(const std::string &ns, const std::string &name, const std::string &exprValue, std::string &nameResult, std::string &valResult) const
void checkname(const std::string &name) const
std::vector< std::string > values_
uint16_t size_type
HepTool::Evaluator evaluator_
std::pair< int, edm::FunctionWithDict > OK
Definition: findMethod.cc:126
void throwex(const std::string &ns, const std::string &name, const std::string &expr, const std::string &reason, int idx=0) const
void set(const std::string &ns, const std::string &name, const std::string &exprValue)
double eval(const std::string &ns, const std::string &expr)
vars
Definition: DeepTauId.cc:166
void dd_exchange_value(std::vector< std::string > &vars, std::vector< std::string > &vals, const std::string &var, const std::string &val)