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