Geant4 9.6.0
Toolkit for the simulation of the passage of particles through matter
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
Evaluator.cc
Go to the documentation of this file.
1// -*- C++ -*-
2// $Id:$
3// ---------------------------------------------------------------------------
4
6
7#include <iostream>
8#include <sstream>
9#include <cmath> // for std::pow()
10#include "CLHEP/Evaluator/stack.icc"
11#include "CLHEP/Evaluator/string.icc"
12#include "CLHEP/Evaluator/hash_map.icc"
13#include <string.h>
14#include <ctype.h>
15#include <errno.h>
16#include <stdlib.h> // for strtod()
17
18//---------------------------------------------------------------------------
19// Fix non ISO C++ compliant cast from pointer to function
20// to void*, which is a pointer to an object
21typedef void (*voidfuncptr)();
22struct Item {
24 double variable;
25 string expression;
26 // Fix non ISO C++ compliant cast from pointer to function
27 // to void*, which is a pointer to an object
28 //void *function;
30
32 Item(double x) : what(VARIABLE), variable(x),expression(), function(0) {}
35};
36
37typedef char * pchar;
38typedef hash_map<string,Item> dic_type;
39
40struct Struct {
45 double theResult;
46};
47
48//---------------------------------------------------------------------------
49#define EVAL HepTool::Evaluator
50
51#define REMOVE_BLANKS \
52for(pointer=name;;pointer++) if (!isspace(*pointer)) break; \
53for(n=strlen(pointer);n>0;n--) if (!isspace(*(pointer+n-1))) break
54
55#define SKIP_BLANKS \
56for(;;pointer++) { \
57 c = (pointer > end) ? '\0' : *pointer; \
58 if (!isspace(c)) break; \
59}
60
61#define EVAL_EXIT(STATUS,POSITION) endp = POSITION; return STATUS
62#define MAX_N_PAR 5
63
64static const char sss[MAX_N_PAR+2] = "012345";
65
66enum { ENDL, LBRA, OR, AND, EQ, NE, GE, GT, LE, LT,
68
69static int engine(pchar, pchar, double &, pchar &, const dic_type &);
70
71static int variable(const string & name, double & result,
72 const dic_type & dictionary)
73/***********************************************************************
74 * *
75 * Name: variable Date: 03.10.00 *
76 * Author: Evgeni Chernyaev Revised: *
77 * *
78 * Function: Finds value of the variable. *
79 * This function is used by operand(). *
80 * *
81 * Parameters: *
82 * name - name of the variable. *
83 * result - value of the variable. *
84 * dictionary - dictionary of available variables and functions. *
85 * *
86 ***********************************************************************/
87{
88 dic_type::const_iterator iter = dictionary.find(name);
89 if (iter == dictionary.end())
90 return EVAL::ERROR_UNKNOWN_VARIABLE;
91 Item item = iter->second;
92 switch (item.what) {
93 case Item::VARIABLE:
94 result = item.variable;
95 return EVAL::OK;
96 case Item::EXPRESSION: {
97 pchar exp_begin = (char *)(item.expression.c_str());
98 pchar exp_end = exp_begin + strlen(exp_begin) - 1;
99 if (engine(exp_begin, exp_end, result, exp_end, dictionary) == EVAL::OK)
100 return EVAL::OK;
101 }
102 default:
103 return EVAL::ERROR_CALCULATION_ERROR;
104 }
105}
106
107static int function(const string & name, stack<double> & par,
108 double & result, const dic_type & dictionary)
109/***********************************************************************
110 * *
111 * Name: function Date: 03.10.00 *
112 * Author: Evgeni Chernyaev Revised: *
113 * *
114 * Function: Finds value of the function. *
115 * This function is used by operand(). *
116 * *
117 * Parameters: *
118 * name - name of the function. *
119 * par - stack of parameters. *
120 * result - value of the function. *
121 * dictionary - dictionary of available variables and functions. *
122 * *
123 ***********************************************************************/
124{
125 int npar = par.size();
126 if (npar > MAX_N_PAR) return EVAL::ERROR_UNKNOWN_FUNCTION;
127
128 dic_type::const_iterator iter = dictionary.find(sss[npar]+name);
129 if (iter == dictionary.end()) return EVAL::ERROR_UNKNOWN_FUNCTION;
130 Item item = iter->second;
131
132 double pp[MAX_N_PAR];
133 for(int i=0; i<npar; i++) { pp[i] = par.top(); par.pop(); }
134 errno = 0;
135 if (item.function == 0) return EVAL::ERROR_CALCULATION_ERROR;
136 switch (npar) {
137 case 0:
138 result = ((double (*)())item.function)();
139 break;
140 case 1:
141 result = ((double (*)(double))item.function)(pp[0]);
142 break;
143 case 2:
144 result = ((double (*)(double,double))item.function)(pp[1], pp[0]);
145 break;
146 case 3:
147 result = ((double (*)(double,double,double))item.function)
148 (pp[2],pp[1],pp[0]);
149 break;
150 case 4:
151 result = ((double (*)(double,double,double,double))item.function)
152 (pp[3],pp[2],pp[1],pp[0]);
153 break;
154 case 5:
155 result = ((double (*)(double,double,double,double,double))item.function)
156 (pp[4],pp[3],pp[2],pp[1],pp[0]);
157 break;
158 }
159 return (errno == 0) ? EVAL::OK : EVAL::ERROR_CALCULATION_ERROR;
160}
161
162static int operand(pchar begin, pchar end, double & result,
163 pchar & endp, const dic_type & dictionary)
164/***********************************************************************
165 * *
166 * Name: operand Date: 03.10.00 *
167 * Author: Evgeni Chernyaev Revised: *
168 * *
169 * Function: Finds value of the operand. The operand can be either *
170 * a number or a variable or a function. *
171 * This function is used by engine(). *
172 * *
173 * Parameters: *
174 * begin - pointer to the first character of the operand. *
175 * end - pointer to the last character of the character string. *
176 * result - value of the operand. *
177 * endp - pointer to the character where the evaluation stoped. *
178 * dictionary - dictionary of available variables and functions. *
179 * *
180 ***********************************************************************/
181{
182 pchar pointer = begin;
183 int EVAL_STATUS;
184 char c;
185
186 // G E T N U M B E R
187
188 if (!isalpha(*pointer)) {
189 errno = 0;
190 result = strtod(pointer, (char **)(&pointer));
191 if (errno == 0) {
192 EVAL_EXIT( EVAL::OK, --pointer );
193 }else{
194 EVAL_EXIT( EVAL::ERROR_CALCULATION_ERROR, begin );
195 }
196 }
197
198 // G E T N A M E
199
200 while(pointer <= end) {
201 c = *pointer;
202 if (c != '_' && !isalnum(c)) break;
203 pointer++;
204 }
205 c = *pointer;
206 *pointer = '\0';
207 string name(begin);
208 *pointer = c;
209
210 // G E T V A R I A B L E
211
212 result = 0.0;
214 if (c != '(') {
215 EVAL_STATUS = variable(name, result, dictionary);
216 EVAL_EXIT( EVAL_STATUS, (EVAL_STATUS == EVAL::OK) ? --pointer : begin);
217 }
218
219 // G E T F U N C T I O N
220
221 stack<pchar> pos; // position stack
222 stack<double> par; // parameter stack
223 double value;
224 pchar par_begin = pointer+1, par_end;
225
226 for(;;pointer++) {
227 c = (pointer > end) ? '\0' : *pointer;
228 switch (c) {
229 case '\0':
230 EVAL_EXIT( EVAL::ERROR_UNPAIRED_PARENTHESIS, pos.top() );
231 case '(':
232 pos.push(pointer); break;
233 case ',':
234 if (pos.size() == 1) {
235 par_end = pointer-1;
236 EVAL_STATUS = engine(par_begin, par_end, value, par_end, dictionary);
237 if (EVAL_STATUS == EVAL::WARNING_BLANK_STRING)
238 { EVAL_EXIT( EVAL::ERROR_EMPTY_PARAMETER, --par_end ); }
239 if (EVAL_STATUS != EVAL::OK)
240 { EVAL_EXIT( EVAL_STATUS, par_end ); }
241 par.push(value);
242 par_begin = pointer + 1;
243 }
244 break;
245 case ')':
246 if (pos.size() > 1) {
247 pos.pop();
248 break;
249 }else{
250 par_end = pointer-1;
251 EVAL_STATUS = engine(par_begin, par_end, value, par_end, dictionary);
252 switch (EVAL_STATUS) {
253 case EVAL::OK:
254 par.push(value);
255 break;
256 case EVAL::WARNING_BLANK_STRING:
257 if (par.size() != 0)
258 { EVAL_EXIT( EVAL::ERROR_EMPTY_PARAMETER, --par_end ); }
259 break;
260 default:
261 EVAL_EXIT( EVAL_STATUS, par_end );
262 }
263 EVAL_STATUS = function(name, par, result, dictionary);
264 EVAL_EXIT( EVAL_STATUS, (EVAL_STATUS == EVAL::OK) ? pointer : begin);
265 }
266 }
267 }
268}
269
270/***********************************************************************
271 * *
272 * Name: maker Date: 28.09.00 *
273 * Author: Evgeni Chernyaev Revised: *
274 * *
275 * Function: Executes basic arithmetic operations on values in the top *
276 * of the stack. Result is placed back into the stack. *
277 * This function is used by engine(). *
278 * *
279 * Parameters: *
280 * op - code of the operation. *
281 * val - stack of values. *
282 * *
283 ***********************************************************************/
284static int maker(int op, stack<double> & val)
285{
286 if (val.size() < 2) return EVAL::ERROR_SYNTAX_ERROR;
287 double val2 = val.top(); val.pop();
288 double val1 = val.top();
289 switch (op) {
290 case OR: // operator ||
291 val.top() = (val1 || val2) ? 1. : 0.;
292 return EVAL::OK;
293 case AND: // operator &&
294 val.top() = (val1 && val2) ? 1. : 0.;
295 return EVAL::OK;
296 case EQ: // operator ==
297 val.top() = (val1 == val2) ? 1. : 0.;
298 return EVAL::OK;
299 case NE: // operator !=
300 val.top() = (val1 != val2) ? 1. : 0.;
301 return EVAL::OK;
302 case GE: // operator >=
303 val.top() = (val1 >= val2) ? 1. : 0.;
304 return EVAL::OK;
305 case GT: // operator >
306 val.top() = (val1 > val2) ? 1. : 0.;
307 return EVAL::OK;
308 case LE: // operator <=
309 val.top() = (val1 <= val2) ? 1. : 0.;
310 return EVAL::OK;
311 case LT: // operator <
312 val.top() = (val1 < val2) ? 1. : 0.;
313 return EVAL::OK;
314 case PLUS: // operator '+'
315 val.top() = val1 + val2;
316 return EVAL::OK;
317 case MINUS: // operator '-'
318 val.top() = val1 - val2;
319 return EVAL::OK;
320 case MULT: // operator '*'
321 val.top() = val1 * val2;
322 return EVAL::OK;
323 case DIV: // operator '/'
324 if (val2 == 0.0) return EVAL::ERROR_CALCULATION_ERROR;
325 val.top() = val1 / val2;
326 return EVAL::OK;
327 case POW: // operator '^' (or '**')
328 errno = 0;
329 val.top() = std::pow(val1,val2);
330 if (errno == 0) return EVAL::OK;
331 case UNARY_PLUS: // unary operator '+'
332 val.top() = val1 + val2; // val1 is zero
333 return EVAL::OK;
334 case UNARY_MINUS: // unary operator '-'
335 val.top() = val1 - val2; // val1 is zero
336 return EVAL::OK;
337 default:
338 return EVAL::ERROR_CALCULATION_ERROR;
339 }
340}
341
342/***********************************************************************
343 * *
344 * Name: engine Date: 28.09.00 *
345 * Author: Evgeni Chernyaev Revised: *
346 * *
347 * Function: Evaluates arithmetic expression. *
348 * *
349 * Parameters: *
350 * begin - pointer to the character string with expression. *
351 * end - pointer to the end of the character string (it is needed *
352 * for recursive call of engine(), when there is no '\0'). *
353 * result - result of the evaluation. *
354 * endp - pointer to the character where the evaluation stoped. *
355 * dictionary - dictionary of available variables and functions. *
356 * *
357 ***********************************************************************/
358static int engine(pchar begin, pchar end, double & result,
359 pchar & endp, const dic_type & dictionary)
360{
361 enum SyntaxTableEntry {
362 SyntaxError = 0,
363 NumberVariableOrFunction = 1,
364 UnaryPlusOrMinus = 2,
365 AnyOperator = 3
366 };
367 static const int SyntaxTable[19][19] = {
368 //E ( || && == != >= > <= < + - u+ u- * / ^ ) V - current token
369 { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 }, // E - previous
370 { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 }, // ( token
371 { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 }, // ||
372 { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 }, // &&
373 { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 }, // ==
374 { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 }, // !=
375 { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 }, // >=
376 { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 }, // >
377 { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 }, // <=
378 { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 }, // <
379 { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 }, // +
380 { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 }, // -
381 { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 }, // unary +
382 { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 }, // unary -
383 { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 }, // *
384 { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 }, // /
385 { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 }, // ^
386 { 3, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0 }, // )
387 { 3, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0 } // V = {.,N,C}
388 };
389 enum ActionTableEntry {
390 UnbalancedParentheses = -1,
391 ExpressionCompleted = 0,
392 HigherPrecedenceOperator = 1,
393 SamePrecedenceOperator = 2,
394 CloseProcessedParenthesesOrExpression = 3,
395 LowerPrecedenceOperator = 4
396 };
397 static const int ActionTable[17][18] = {
398 //E ( || && == != >= > <= < + - u+ u- * / ^ ) - current operator
399 { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,-1 }, // E - top operator
400 {-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3 }, // ( in stack
401 { 4, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4 }, // ||
402 { 4, 1, 4, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4 }, // &&
403 { 4, 1, 4, 4, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4 }, // ==
404 { 4, 1, 4, 4, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4 }, // !=
405 { 4, 1, 4, 4, 4, 4, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 4 }, // >=
406 { 4, 1, 4, 4, 4, 4, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 4 }, // >
407 { 4, 1, 4, 4, 4, 4, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 4 }, // <=
408 { 4, 1, 4, 4, 4, 4, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 4 }, // <
409 { 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 1, 1, 1, 1, 1, 4 }, // +
410 { 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 1, 1, 1, 1, 1, 4 }, // -
411 { 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1, 4, 4, 1, 4 }, // unary +
412 { 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1, 4, 4, 1, 4 }, // unary -
413 { 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1, 2, 2, 1, 4 }, // *
414 { 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1, 2, 2, 1, 4 }, // /
415 { 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1, 4, 4, 4, 4 } // ^
416 };
417
418 stack<int> op; // operator stack
419 stack<pchar> pos; // position stack
420 stack<double> val; // value stack
421 double value;
422 pchar pointer = begin;
423 int iWhat, iCur, iPrev = 0, iTop, EVAL_STATUS;
424 char c;
425
426 op.push(0); pos.push(pointer); // push EOL to the stack
428 if (c == '\0') { EVAL_EXIT( EVAL::WARNING_BLANK_STRING, begin ); }
429 for(;;pointer++) {
430
431 // N E X T T O K E N
432
433 c = (pointer > end) ? '\0' : *pointer;
434 if (isspace(c)) continue; // skip space, tab etc.
435 switch (c) {
436 case '\0': iCur = ENDL; break;
437 case '(': iCur = LBRA; break;
438 case '|':
439 if (*(pointer+1) == '|') {
440 pointer++; iCur = OR; break;
441 }else{
442 EVAL_EXIT( EVAL::ERROR_UNEXPECTED_SYMBOL, pointer );
443 }
444 case '&':
445 if (*(pointer+1) == '&') {
446 pointer++; iCur = AND; break;
447 }else{
448 EVAL_EXIT( EVAL::ERROR_UNEXPECTED_SYMBOL, pointer );
449 }
450 case '=':
451 if (*(pointer+1) == '=') {
452 pointer++; iCur = EQ; break;
453 }else{
454 EVAL_EXIT( EVAL::ERROR_UNEXPECTED_SYMBOL, pointer );
455 }
456 case '!':
457 if (*(pointer+1) == '=') {
458 pointer++; iCur = NE; break;
459 }else{
460 EVAL_EXIT( EVAL::ERROR_UNEXPECTED_SYMBOL, pointer );
461 }
462 case '>':
463 if (*(pointer+1) == '=') { pointer++; iCur = GE; } else { iCur = GT; }
464 break;
465 case '<':
466 if (*(pointer+1) == '=') { pointer++; iCur = LE; } else { iCur = LT; }
467 break;
468 case '+': iCur = PLUS; break;
469 case '-': iCur = MINUS; break;
470 case '*':
471 if (*(pointer+1) == '*') { pointer++; iCur = POW; }else{ iCur = MULT; }
472 break;
473 case '/': iCur = DIV; break;
474 case '^': iCur = POW; break;
475 case ')': iCur = RBRA; break;
476 default:
477 if (c == '.' || isalnum(c)) {
478 iCur = VALUE; break;
479 }else{
480 EVAL_EXIT( EVAL::ERROR_UNEXPECTED_SYMBOL, pointer );
481 }
482 }
483
484 // S Y N T A X A N A L I S Y S
485
486 iWhat = SyntaxTable[iPrev][iCur];
487 iPrev = iCur;
488 switch (iWhat) {
489 case 0: // syntax error
490 EVAL_EXIT( EVAL::ERROR_SYNTAX_ERROR, pointer );
491 case 1: // operand: number, variable, function
492 EVAL_STATUS = operand(pointer, end, value, pointer, dictionary);
493 if (EVAL_STATUS != EVAL::OK) { EVAL_EXIT( EVAL_STATUS, pointer ); }
494 val.push(value);
495 continue;
496 case 2: // unary + or unary -
497 val.push(0.0);
498 if (iCur == PLUS) iCur = UNARY_PLUS;
499 if (iCur == MINUS) iCur = UNARY_MINUS;
500 // Note that for syntax purposes, ordinary + or - are fine.
501 // Thus iPrev need not change when we encounter a unary minus or plus.
502 case 3: default: // next operator
503 break;
504 }
505
506 // N E X T O P E R A T O R
507
508 for(;;) {
509 if (op.size() == 0) { EVAL_EXIT( EVAL::ERROR_SYNTAX_ERROR, pointer ); }
510 iTop = op.top();
511 switch (ActionTable[iTop][iCur]) {
512 case -1: // syntax error
513 if (op.size() > 1) pointer = pos.top();
514 EVAL_EXIT( EVAL::ERROR_UNPAIRED_PARENTHESIS, pointer );
515 case 0: // last operation (assignment)
516 if (val.size() == 1) {
517 result = val.top();
518 EVAL_EXIT( EVAL::OK, pointer );
519 }else{
520 EVAL_EXIT( EVAL::ERROR_SYNTAX_ERROR, pointer );
521 }
522 case 1: // push current operator in stack
523 op.push(iCur); pos.push(pointer);
524 break;
525 case 2: // execute top operator
526 EVAL_STATUS = maker(iTop, val); // put current operator in stack
527 if (EVAL_STATUS != EVAL::OK) {
528 EVAL_EXIT( EVAL_STATUS, pos.top() );
529 }
530 op.top() = iCur; pos.top() = pointer;
531 break;
532 case 3: // delete '(' from stack
533 op.pop(); pos.pop();
534 break;
535 case 4: default: // execute top operator and
536 EVAL_STATUS = maker(iTop, val); // delete it from stack
537 if (EVAL_STATUS != EVAL::OK) { // repete with the same iCur
538 EVAL_EXIT( EVAL_STATUS, pos.top() );
539 }
540 op.pop(); pos.pop();
541 continue;
542 }
543 break;
544 }
545 }
546}
547
548//---------------------------------------------------------------------------
549static void setItem(const char * prefix, const char * name,
550 const Item & item, Struct * s) {
551
552 if (name == 0 || *name == '\0') {
553 s->theStatus = EVAL::ERROR_NOT_A_NAME;
554 return;
555 }
556
557 // R E M O V E L E A D I N G A N D T R A I L I N G S P A C E S
558
559 const char * pointer; int n; REMOVE_BLANKS;
560
561 // C H E C K N A M E
562
563 if (n == 0) {
564 s->theStatus = EVAL::ERROR_NOT_A_NAME;
565 return;
566 }
567 for(int i=0; i<n; i++) {
568 char c = *(pointer+i);
569 if (c != '_' && !isalnum(c)) {
570 s->theStatus = EVAL::ERROR_NOT_A_NAME;
571 return;
572 }
573 }
574
575 // A D D I T E M T O T H E D I C T I O N A R Y
576
577 string item_name = prefix + string(pointer,n);
578 dic_type::iterator iter = (s->theDictionary).find(item_name);
579 if (iter != (s->theDictionary).end()) {
580 iter->second = item;
581 if (item_name == name) {
582 s->theStatus = EVAL::WARNING_EXISTING_VARIABLE;
583 }else{
584 s->theStatus = EVAL::WARNING_EXISTING_FUNCTION;
585 }
586 }else{
587 (s->theDictionary)[item_name] = item;
588 s->theStatus = EVAL::OK;
589 }
590}
591
592//---------------------------------------------------------------------------
593namespace HepTool {
594
595//---------------------------------------------------------------------------
597 Struct * s = new Struct();
598 p = (void *) s;
599 s->theExpression = 0;
600 s->thePosition = 0;
601 s->theStatus = OK;
602 s->theResult = 0.0;
603}
604
605//---------------------------------------------------------------------------
607 delete (Struct *)(p);
608}
609
610//---------------------------------------------------------------------------
611double Evaluator::evaluate(const char * expression) {
612 Struct * s = (Struct *)(p);
613 if (s->theExpression != 0) { delete[] s->theExpression; }
614 s->theExpression = 0;
615 s->thePosition = 0;
617 s->theResult = 0.0;
618 if (expression != 0) {
619 s->theExpression = new char[strlen(expression)+1];
620 strcpy(s->theExpression, expression);
621 s->theStatus = engine(s->theExpression,
622 s->theExpression+strlen(expression)-1,
623 s->theResult,
624 s->thePosition,
625 s->theDictionary);
626 }
627 return s->theResult;
628}
629
630//---------------------------------------------------------------------------
631int Evaluator::status() const {
632 return ((Struct *)(p))->theStatus;
633}
634
635//---------------------------------------------------------------------------
637 return ((Struct *)(p))->thePosition - ((Struct *)(p))->theExpression;
638}
639
640//---------------------------------------------------------------------------
642 Struct * s = (Struct *) p;
643 if(s->theStatus != OK) {
644 std::cerr << error_name() << std::endl;
645 }
646 return;
647}
648
649//---------------------------------------------------------------------------
650std::string Evaluator::error_name() const
651{
652 char prefix[] = "Evaluator : ";
653 std::ostringstream errn;
654 Struct * s = (Struct *) p;
655 switch (s->theStatus) {
656 case ERROR_NOT_A_NAME:
657 errn << prefix << "invalid name";
658 break;
660 errn << prefix << "syntax error";
661 break;
663 errn << prefix << "unpaired parenthesis";
664 break;
666 errn << prefix << "unexpected symbol";
667 break;
669 errn << prefix << "unknown variable";
670 break;
672 errn << prefix << "unknown function";
673 break;
675 errn << prefix << "empty parameter in function call";
676 break;
678 errn << prefix << "calculation error";
679 break;
680 default:
681 errn << " ";
682 }
683 return errn.str();
684}
685
686//---------------------------------------------------------------------------
687void Evaluator::setVariable(const char * name, double value)
688{ setItem("", name, Item(value), (Struct *)p); }
689
690void Evaluator::setVariable(const char * name, const char * expression)
691{ setItem("", name, Item(expression), (Struct *)p); }
692
693//---------------------------------------------------------------------------
694// Fix non ISO C++ compliant cast from pointer to function
695// to void*, which is a pointer to an object
696void Evaluator::setFunction(const char * name,
697 double (*fun)())
698{ setItem("0", name, Item(reinterpret_cast<voidfuncptr>(fun)), (Struct *)p); }
699
700void Evaluator::setFunction(const char * name,
701 double (*fun)(double))
702{ setItem("1", name, Item(reinterpret_cast<voidfuncptr>(fun)), (Struct *)p); }
703
704void Evaluator::setFunction(const char * name,
705 double (*fun)(double,double))
706{ setItem("2", name, Item(reinterpret_cast<voidfuncptr>(fun)), (Struct *)p); }
707
708void Evaluator::setFunction(const char * name,
709 double (*fun)(double,double,double))
710{ setItem("3", name, Item(reinterpret_cast<voidfuncptr>(fun)), (Struct *)p); }
711
712void Evaluator::setFunction(const char * name,
713 double (*fun)(double,double,double,double))
714{ setItem("4", name, Item(reinterpret_cast<voidfuncptr>(fun)), (Struct *)p); }
715
716void Evaluator::setFunction(const char * name,
717 double (*fun)(double,double,double,double,double))
718{ setItem("5", name, Item(reinterpret_cast<voidfuncptr>(fun)), (Struct *)p); }
719
720//---------------------------------------------------------------------------
721bool Evaluator::findVariable(const char * name) const {
722 if (name == 0 || *name == '\0') return false;
723 const char * pointer; int n; REMOVE_BLANKS;
724 if (n == 0) return false;
725 Struct * s = (Struct *)(p);
726 return
727 ((s->theDictionary).find(string(pointer,n)) == (s->theDictionary).end()) ?
728 false : true;
729}
730
731//---------------------------------------------------------------------------
732bool Evaluator::findFunction(const char * name, int npar) const {
733 if (name == 0 || *name == '\0') return false;
734 if (npar < 0 || npar > MAX_N_PAR) return false;
735 const char * pointer; int n; REMOVE_BLANKS;
736 if (n == 0) return false;
737 Struct * s = (Struct *)(p);
738 return ((s->theDictionary).find(sss[npar]+string(pointer,n)) ==
739 (s->theDictionary).end()) ? false : true;
740}
741
742//---------------------------------------------------------------------------
743void Evaluator::removeVariable(const char * name) {
744 if (name == 0 || *name == '\0') return;
745 const char * pointer; int n; REMOVE_BLANKS;
746 if (n == 0) return;
747 Struct * s = (Struct *)(p);
748 (s->theDictionary).erase(string(pointer,n));
749}
750
751//---------------------------------------------------------------------------
752void Evaluator::removeFunction(const char * name, int npar) {
753 if (name == 0 || *name == '\0') return;
754 if (npar < 0 || npar > MAX_N_PAR) return;
755 const char * pointer; int n; REMOVE_BLANKS;
756 if (n == 0) return;
757 Struct * s = (Struct *)(p);
758 (s->theDictionary).erase(sss[npar]+string(pointer,n));
759}
760
761//---------------------------------------------------------------------------
763 Struct * s = (Struct *) p;
764 s->theDictionary.clear();
765 s->theExpression = 0;
766 s->thePosition = 0;
767 s->theStatus = OK;
768 s->theResult = 0.0;
769}
770
771//---------------------------------------------------------------------------
772} // namespace HepTool
#define EVAL_EXIT(STATUS, POSITION)
Definition: Evaluator.cc:61
#define MAX_N_PAR
Definition: Evaluator.cc:62
#define REMOVE_BLANKS
Definition: Evaluator.cc:51
hash_map< string, Item > dic_type
Definition: Evaluator.cc:38
char * pchar
Definition: Evaluator.cc:37
#define SKIP_BLANKS
Definition: Evaluator.cc:55
void(* voidfuncptr)()
Definition: Evaluator.cc:21
@ RBRA
Definition: Evaluator.cc:67
@ LBRA
Definition: Evaluator.cc:66
@ GT
Definition: Evaluator.cc:66
@ MULT
Definition: Evaluator.cc:67
@ ENDL
Definition: Evaluator.cc:66
@ POW
Definition: Evaluator.cc:67
@ UNARY_MINUS
Definition: Evaluator.cc:67
@ LT
Definition: Evaluator.cc:66
@ NE
Definition: Evaluator.cc:66
@ GE
Definition: Evaluator.cc:66
@ UNARY_PLUS
Definition: Evaluator.cc:67
@ LE
Definition: Evaluator.cc:66
@ DIV
Definition: Evaluator.cc:67
@ AND
Definition: Evaluator.cc:66
@ PLUS
Definition: Evaluator.cc:67
@ OR
Definition: Evaluator.cc:66
@ EQ
Definition: Evaluator.cc:66
@ VALUE
Definition: Evaluator.cc:67
@ MINUS
Definition: Evaluator.cc:67
G4double(* function)(G4double)
int error_position() const
Definition: Evaluator.cc:636
bool findFunction(const char *name, int npar) const
Definition: Evaluator.cc:732
void print_error() const
Definition: Evaluator.cc:641
double evaluate(const char *expression)
Definition: Evaluator.cc:611
std::string error_name() const
Definition: Evaluator.cc:650
void removeVariable(const char *name)
Definition: Evaluator.cc:743
void removeFunction(const char *name, int npar)
Definition: Evaluator.cc:752
void setFunction(const char *name, double(*fun)())
Definition: Evaluator.cc:696
void setVariable(const char *name, double value)
Definition: Evaluator.cc:687
int status() const
Definition: Evaluator.cc:631
bool findVariable(const char *name) const
Definition: Evaluator.cc:721
@ ERROR_UNPAIRED_PARENTHESIS
Definition: Evaluator.h:46
Item()
Definition: Evaluator.cc:31
Item(double x)
Definition: Evaluator.cc:32
voidfuncptr function
Definition: Evaluator.cc:29
string expression
Definition: Evaluator.cc:25
Item(string x)
Definition: Evaluator.cc:33
Item(voidfuncptr x)
Definition: Evaluator.cc:34
double variable
Definition: Evaluator.cc:24
@ VARIABLE
Definition: Evaluator.cc:23
@ EXPRESSION
Definition: Evaluator.cc:23
@ UNKNOWN
Definition: Evaluator.cc:23
@ FUNCTION
Definition: Evaluator.cc:23
enum Item::@12 what
pchar thePosition
Definition: Evaluator.cc:43
pchar theExpression
Definition: Evaluator.cc:42
int theStatus
Definition: Evaluator.cc:44
dic_type theDictionary
Definition: Evaluator.cc:41
double theResult
Definition: Evaluator.cc:45