Geant4 9.6.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
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