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