CMS 3D CMS Logo

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