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