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