ATLAS Offline Software
Loading...
Searching...
No Matches
ExpressionEvaluator.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
3*/
4
7
8#include <cstdlib>
9#include <cctype>
10#include <cstring>
11#include <iostream>
12#include <sstream>
13#include <algorithm>
14
15using namespace AGDD;
16
18{
19 m_calc.clear();
20 m_calc.setStdMath(); // set standard constants and functions
21 // Set Geant4 system of units
22 m_calc.setSystemOfUnits(1.e+3, 1./1.60217733e-25, 1.e+9, 1./1.60217733e-10,1.0, 1.0, 1.0);
24}
25
27{
28 m_CTable.clear();
29 m_PCTable.clear();
30 m_calc.clear();
31}
32
33bool ExpressionEvaluator::RegisterConstant( std::string& c, double v )
34{
35 double value = v;
36
37 if( m_calc.status() != HepTool::Evaluator::OK )
38 {
39 std::cerr << "Expression evaluator:: Error registering constant " << c << std::endl;
40 m_calc.print_error();
41 std::cout << std::endl;
42 return false;
43 }
44
45 RegisterVariable( c, value );
46 return true;
47}
48bool ExpressionEvaluator::RegisterArray( std::string& c, const std::vector<double>& v)
49{
50 for(unsigned int i=0; i<v.size(); i++)
51 {
52 double value = v[i];
53 std::stringstream ss;
54 std::string index;
55 ss << i;
56 ss >> index;
57 std::string name = c+"_"+index+"_";
58 RegisterVariable( name, value );
59 }
60 return true;
61}
62
63bool ExpressionEvaluator::RegisterVariable( const std::string& var_name, double value)
64{
65 m_real_vars.push_back(var_name);
66 m_calc.setVariable( var_name.c_str(), value );
67 return true;
68}
69
70bool ExpressionEvaluator::is_real_variable(const std::string& var_name)
71{
72
73 std::vector<std::string>::iterator start = m_real_vars.begin();
74 std::vector<std::string>::iterator end = m_real_vars.end();
75 std::vector<std::string>::iterator iter;
76
77 iter = find(start, end, var_name);
78
79 if (iter == end)
80 {
81 return false;
82 }
83 else
84 {
85 return true;
86 }
87}
88
90{
91 if(strchr(" ()|&=!><+-%*/^", c) || c==9 || c==0 || c=='\r' || c=='\n' || c=='\t' || c=='\0' || isspace(c)) return true;
92 else return false;
93}
94
95double ExpressionEvaluator::EvaluateString(const std::string& str)
96{
97 std::string str_mod = str;
98 const char* c_str_mod = str.c_str(); //string to be modified with file namespace!
99 std::vector<int> variable_ends; //variable names to be changed
100 int cur_variable_end = 0;
101 while(*c_str_mod)
102 {
103 if(is_delimiter(*c_str_mod) || isdigit(*c_str_mod))
104 {
105 c_str_mod++;
106 cur_variable_end++;
107 }
108 else if(isalpha(*c_str_mod))
109 {
110 char variable[80];
111 char* token;
112 token = variable;
113 *token = '\0';
114 while(!is_delimiter(*c_str_mod))
115 {
116 *token=*c_str_mod;
117 token++;
118 c_str_mod++;
119 cur_variable_end++;
120 }
121 *token = '\0';
122 std::string variable_to_check = variable;
123 if(is_real_variable(variable_to_check))
124 {
125 variable_ends.push_back(cur_variable_end);
126 }
127 }
128 else
129 {
130 c_str_mod++;
131 cur_variable_end++;
132 }
133 std::string::size_type shift = 0;
134 std::string::size_type ns_length = m_fileCurrentlyParsed.size();
135 for(unsigned int i=0; i<variable_ends.size(); i++)
136 {
137 str_mod.insert(shift+variable_ends[i],m_fileCurrentlyParsed);
138 shift += ns_length;
139 }
140 }
141 double result = m_calc.evaluate( str_mod.c_str() );
142 return result;
143}
144/*********************************************************************************************************/
145/*********************************************************************************************************/
146/*********************************************************************************************************/
147/*********************************************************************************************************/
148
149
150bool ExpressionEvaluator::RegisterPhysConstant( std::string& c, const std::string& value, const std::string& unit )
151{
152 std::string expr = value;
153 expr += "*(";
154 expr += unit;
155 expr += ")";
156
157 double dvalue = EvaluateString( expr );
158
159 if( m_calc.status() != HepTool::Evaluator::OK )
160 {
161 std::cerr << "Expression evaluator:: Error registering quantity "
162 << c << std::endl;
163 m_calc.print_error();
164 std::cout << std::endl;
165 return false;
166 }
167
168 RegisterVariable( c, dvalue );
169 return true;
170}
171
172bool ExpressionEvaluator::RegisterExpression( std::string& name, const std::string& text )
173{
174 std::string expr = "(";
175 expr += text;
176 expr += ")";
177 double value = EvaluateString( expr );
178
179 if( m_calc.status() != HepTool::Evaluator::OK )
180 {
181 std::cerr << "Expression evaluator:: Error registering expression " << name << std::endl;
182 m_calc.print_error();
183 std::cout << std::endl;
184 return false;
185 }
186
187 RegisterVariable( name, value );
188 return true;
189}
190
191double ExpressionEvaluator::Eval( const std::string& expr )
192{
193 return Eval( expr.c_str() );
194}
195
196double ExpressionEvaluator::Eval( const char* expr_mod )
197{
198
199 std::string expr = expr_mod;
200 std::string::size_type start_index = 0;
201 std::string::size_type end_index = 0;
202 while(true)
203 {
204 start_index = expr.find('[', start_index);
205 if(start_index == std::string::npos) break;
206 std::string::size_type boundary_index = expr.find(']', start_index);
207 expr.replace(start_index,1,1,'_');
208 end_index = expr.find(',', start_index);
209 if(end_index != std::string::npos && end_index < boundary_index)
210 {
211 start_index++;
212 std::string var1 = expr.substr(start_index, end_index-start_index);
213 double eval1 = EvaluateString( var1 );
214 std::stringstream ss1;
215 std::string str1;
216 ss1 << eval1;
217 ss1 >> str1;
218 expr.replace(start_index, end_index-start_index, str1, 0, str1.size());
219 }
220 else
221 {
222 end_index = boundary_index;
223 if(end_index != std::string::npos)
224 {
225 start_index++;
226 std::string var1 = expr.substr(start_index, end_index-start_index);
227 double eval1 = EvaluateString( var1 );
228 std::stringstream ss1;
229 std::string str1;
230 ss1 << eval1;
231 ss1 >> str1;
232 expr.replace(start_index, end_index-start_index, str1, 0, str1.size());
233 }
234 }
235 }
236 start_index = 0;
237 end_index = 0;
238 while(true)
239 {
240 start_index = expr.find(',', start_index);
241 if(start_index == std::string::npos) break;
242 expr.replace(start_index,1,1,'_');
243 end_index = expr.find(']', start_index);
244 start_index++;
245 std::string var2 = expr.substr(start_index, end_index-start_index);
246 double eval2 = EvaluateString( var2 );
247 std::stringstream ss2;
248 std::string str2;
249 ss2 << eval2;
250 ss2 >> str2;
251 expr.replace(start_index, end_index-start_index, str2, 0, str2.size());
252 }
253 start_index = 0;
254 end_index = 0;
255 while(true)
256 {
257 start_index = expr.find(']', start_index);
258 if(start_index == std::string::npos) break;
259 expr.replace(start_index,1,1,'_');
260 }
261 double result = EvaluateString( expr );
262 if( m_calc.status() != HepTool::Evaluator::OK )
263 {
264 std::cerr << expr << std::endl;
265 for (int i=0; i<m_calc.error_position(); i++)
266 {
267 std::cerr << "-";
268 }
269 std::cerr << "^\a" << std::endl;
270 m_calc.print_error();
271 std::cerr << std::endl;
272 }
273 return result;
274}
275
276std::string ExpressionEvaluator::trim (const std::string& s)
277//-------------------------------------------------------------
278{
279 if (s.size () == 0) return (s);
280 std::string temp = s;
281 std::string::size_type i;
282 i = temp.find_first_not_of (' ');
283 if (i == std::string::npos) return std::string();
284// There is at least 1 non blank character in s.
285 if (i > 0)
286 {
287 temp = temp.substr (i);
288 }
289 i = temp.find_last_not_of (' ');
290 if (i < temp.size ())
291 {
292 temp.resize (i + 1);
293 }
294 return (temp);
295}
296
297std::vector<std::string> ExpressionEvaluator::tokenize(const std::string& sep,const std::string& expr)
298{
299 std::vector<std::string> tempvect;
300 AGDDTokenizer aa(sep,expr);
301 for (unsigned int i=0;i<aa.size();i++) tempvect.push_back(trim(aa[i]));
302 return tempvect;
303}
const PlainObject unit() const
This is a plugin that makes Eigen look like CLHEP & defines some convenience methods.
static Double_t ss
double EvaluateString(const std::string &str)
std::vector< std::string > m_real_vars
double Eval(const std::string &expr)
PhysicalConstantsTable m_PCTable
static std::vector< std::string > tokenize(const std::string &, const std::string &)
bool is_real_variable(const std::string &var_name)
bool RegisterVariable(const std::string &var_name, double value)
static std::string trim(const std::string &)
bool RegisterPhysConstant(std::string &, const std::string &, const std::string &)
bool RegisterArray(std::string &c, const std::vector< double > &v)
bool RegisterConstant(std::string &c, double v)
bool RegisterExpression(std::string &c, const std::string &v)
std::string find(const std::string &s)
return a remapped string
Definition hcg.cxx:138
Definition index.py:1