File indexing completed on 2025-01-18 09:14:33
0001
0002
0003
0004
0005 #include "Evaluator/Evaluator.h"
0006 #include "Evaluator/detail/Evaluator.h"
0007
0008 #include <iostream>
0009 #include <cmath> // for pow()
0010 #include <sstream>
0011 #include <mutex>
0012 #include <condition_variable>
0013 #include <cctype>
0014 #include <cerrno>
0015 #include <cstring>
0016 #include <cstdlib> // for strtod()
0017 #include <stack>
0018 #include <string>
0019 #include <unordered_map>
0020
0021
0022 #if defined(__GNUC__) && !defined(__APPLE__) && !defined(__llvm__)
0023
0024
0025
0026
0027
0028
0029 #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
0030 #endif
0031
0032
0033 #if defined __has_cpp_attribute
0034 #if __has_cpp_attribute(fallthrough)
0035 #define ATTR_FALLTHROUGH [[fallthrough]]
0036 #else
0037 #define ATTR_FALLTHROUGH
0038 #endif
0039 #else
0040 #define ATTR_FALLTHROUGH
0041 #endif
0042
0043
0044 #define EVAL dd4hep::tools::Evaluator
0045
0046 namespace {
0047
0048
0049 struct Item {
0050 enum { UNKNOWN, VARIABLE, EXPRESSION, FUNCTION, STRING } what;
0051 double variable;
0052 std::string expression;
0053 void *function;
0054
0055 explicit Item() : what(UNKNOWN), variable(0),expression(), function(0) {}
0056 explicit Item(double x) : what(VARIABLE), variable(x),expression(), function(0) {}
0057 explicit Item(std::string x) : what(EXPRESSION),variable(0),expression(std::move(x)),function(0) {}
0058 explicit Item(void *x) : what(FUNCTION), variable(0),expression(), function(x) {}
0059 };
0060
0061
0062 union FCN {
0063 void* ptr;
0064 double (*f0)();
0065 double (*f1)(double);
0066 double (*f2)(double,double);
0067 double (*f3)(double,double,double);
0068 double (*f4)(double,double,double,double);
0069 double (*f5)(double,double,double,double,double);
0070 FCN(void* p) { ptr = p; }
0071 FCN(double (*f)()) { f0 = f; }
0072 FCN(double (*f)(double)) { f1 = f; }
0073 FCN(double (*f)(double,double)) { f2 = f; }
0074 FCN(double (*f)(double,double,double)) { f3 = f; }
0075 FCN(double (*f)(double,double,double,double)) { f4 = f; }
0076 FCN(double (*f)(double,double,double,double,double)) { f5 = f; }
0077 };
0078 }
0079
0080
0081 typedef std::unordered_map<std::string,Item> dic_type;
0082
0083
0084 struct EVAL::Object::Struct {
0085
0086 struct ReadLock {
0087 ReadLock(Struct* s): theStruct(s), theLg(s->theLock) {
0088 while(theStruct->theWriterWaiting)
0089 theStruct->theCond.wait(theLg);
0090 ++theStruct->theReadersWaiting;
0091 }
0092
0093 ReadLock(const ReadLock&) = delete;
0094 ~ReadLock() {
0095 --theStruct->theReadersWaiting;
0096 while(theStruct->theReadersWaiting > 0)
0097 theStruct->theCond.wait(theLg);
0098 theStruct->theCond.notify_one();
0099 }
0100 Struct* theStruct;
0101 std::unique_lock<std::mutex> theLg;
0102
0103 };
0104 struct WriteLock {
0105 WriteLock(Struct* s): theStruct(s), theLg(s->theLock) {
0106 while(theStruct->theWriterWaiting)
0107 theStruct->theCond.wait(theLg);
0108 }
0109 WriteLock(const WriteLock&) = delete;
0110 ~WriteLock() {
0111 theStruct->theWriterWaiting = true;
0112 while(theStruct->theReadersWaiting > 0)
0113 theStruct->theCond.wait(theLg);
0114 theStruct->theWriterWaiting = false;
0115 theStruct->theCond.notify_all();
0116 }
0117 Struct* theStruct;
0118 std::unique_lock<std::mutex> theLg;
0119 };
0120
0121 dic_type theDictionary;
0122 int theReadersWaiting = 0;
0123 bool theWriterWaiting = false;
0124 std::condition_variable theCond;
0125 std::mutex theLock;
0126 };
0127
0128
0129 #define REMOVE_BLANKS \
0130 for(pointer=name;;pointer++) if (!isspace(*pointer)) break; \
0131 for(n=strlen(pointer);n>0;n--) if (!isspace(*(pointer+n-1))) break
0132
0133 #define SKIP_BLANKS \
0134 for(;;pointer++) { \
0135 c = (pointer > end) ? '\0' : *pointer; \
0136 if (!isspace(c)) break; \
0137 }
0138
0139 #define EVAL_EXIT(STATUS,POSITION) endp = POSITION; return STATUS
0140 #define MAX_N_PAR 5
0141
0142 static constexpr char sss[MAX_N_PAR+2] = "012345";
0143
0144 enum { ENDL, LBRA, OR, AND, EQ, NE, GE, GT, LE, LT,
0145 PLUS, MINUS, MULT, DIV, POW, RBRA, VALUE };
0146
0147 static int engine(char const*, char const*, double &, char const* &, const dic_type &);
0148
0149 static int variable(const std::string & name, double & result,
0150 const dic_type & dictionary)
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165 {
0166 dic_type::const_iterator iter = dictionary.find(name);
0167 if (iter == dictionary.end())
0168 return EVAL::ERROR_UNKNOWN_VARIABLE;
0169
0170 Item const& item = iter->second;
0171 switch (item.what) {
0172 case Item::VARIABLE:
0173 result = item.variable;
0174 return EVAL::OK;
0175 case Item::EXPRESSION: {
0176 char const* exp_begin = (item.expression.c_str());
0177 char const* exp_end = exp_begin + strlen(exp_begin) - 1;
0178 if (engine(exp_begin, exp_end, result, exp_end, dictionary) == EVAL::OK)
0179 return EVAL::OK;
0180 return EVAL::ERROR_CALCULATION_ERROR;
0181 }
0182 default:
0183 return EVAL::ERROR_CALCULATION_ERROR;
0184 }
0185 }
0186
0187 static int execute_function(const std::string & name, std::stack<double> & par,
0188 double & result, const dic_type & dictionary)
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204 {
0205 int npar = par.size();
0206 if (npar > MAX_N_PAR) return EVAL::ERROR_UNKNOWN_FUNCTION;
0207
0208 dic_type::const_iterator iter = dictionary.find(sss[npar]+name);
0209 if (iter == dictionary.end()) return EVAL::ERROR_UNKNOWN_FUNCTION;
0210
0211 Item const& item = iter->second;
0212
0213 double pp[MAX_N_PAR];
0214 for(int i=0; i<npar; i++) { pp[i] = par.top(); par.pop(); }
0215 errno = 0;
0216 if (item.function == 0) return EVAL::ERROR_CALCULATION_ERROR;
0217 FCN fcn(item.function);
0218 switch (npar) {
0219 case 0:
0220 result = (*fcn.f0)();
0221 break;
0222 case 1:
0223 result = (*fcn.f1)(pp[0]);
0224 break;
0225 case 2:
0226 result = (*fcn.f2)(pp[1], pp[0]);
0227 break;
0228 case 3:
0229 result = (*fcn.f3)(pp[2],pp[1],pp[0]);
0230 break;
0231 case 4:
0232 result = (*fcn.f4)(pp[3],pp[2],pp[1],pp[0]);
0233 break;
0234 case 5:
0235 result = (*fcn.f5)(pp[4],pp[3],pp[2],pp[1],pp[0]);
0236 break;
0237 }
0238 return (errno == 0) ? EVAL::OK : EVAL::ERROR_CALCULATION_ERROR;
0239 }
0240
0241 static int operand(char const* begin, char const* end, double & result,
0242 char const* & endp, const dic_type & dictionary)
0243
0244
0245
0246
0247
0248
0249
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259
0260 {
0261 char const* pointer = begin;
0262 int EVAL_STATUS;
0263 char c;
0264
0265
0266
0267 if (!isalpha(*pointer)) {
0268 errno = 0;
0269 #ifdef _WIN32
0270 if ( pointer[0] == '0' && pointer < end && (pointer[1] == 'x' || pointer[1] == 'X') )
0271 result = strtol(pointer, (char **)(&pointer), 0);
0272 else
0273 #endif
0274 result = strtod(pointer, (char **)(&pointer));
0275 if (errno == 0) {
0276 EVAL_EXIT( EVAL::OK, --pointer );
0277 }else{
0278 EVAL_EXIT( EVAL::ERROR_CALCULATION_ERROR, begin );
0279 }
0280 }
0281
0282
0283
0284 while(pointer <= end) {
0285 c = *pointer;
0286 if ( !(c == '_' || c == ':') && !isalnum(c)) break;
0287 pointer++;
0288 }
0289 std::string name(begin, pointer-begin);
0290
0291
0292
0293 result = 0.0;
0294 SKIP_BLANKS;
0295 if (c != '(') {
0296 EVAL_STATUS = variable(name, result, dictionary);
0297 EVAL_EXIT( EVAL_STATUS, (EVAL_STATUS == EVAL::OK) ? --pointer : begin);
0298 }
0299
0300
0301
0302 std::stack<char const*> pos;
0303 std::stack<double> par;
0304 double value;
0305 char const* par_begin = pointer+1;
0306 char const* par_end;
0307
0308 for(;;pointer++) {
0309 c = (pointer > end) ? '\0' : *pointer;
0310 switch (c) {
0311 case '\0':
0312 EVAL_EXIT( EVAL::ERROR_UNPAIRED_PARENTHESIS, pos.top() );
0313 case '(':
0314 pos.push(pointer); break;
0315 case ',':
0316 if (pos.size() == 1) {
0317 par_end = pointer-1;
0318 EVAL_STATUS = engine(par_begin, par_end, value, par_end, dictionary);
0319 if (EVAL_STATUS == EVAL::WARNING_BLANK_STRING)
0320 { EVAL_EXIT( EVAL::ERROR_EMPTY_PARAMETER, --par_end ); }
0321 if (EVAL_STATUS != EVAL::OK)
0322 { EVAL_EXIT( EVAL_STATUS, par_end ); }
0323 par.push(value);
0324 par_begin = pointer + 1;
0325 }
0326 break;
0327 case ')':
0328 if (pos.size() > 1) {
0329 pos.pop();
0330 break;
0331 }else{
0332 par_end = pointer-1;
0333 EVAL_STATUS = engine(par_begin, par_end, value, par_end, dictionary);
0334 switch (EVAL_STATUS) {
0335 case EVAL::OK:
0336 par.push(value);
0337 break;
0338 case EVAL::WARNING_BLANK_STRING:
0339 if (par.size() != 0)
0340 { EVAL_EXIT( EVAL::ERROR_EMPTY_PARAMETER, --par_end ); }
0341 break;
0342 default:
0343 EVAL_EXIT( EVAL_STATUS, par_end );
0344 }
0345 EVAL_STATUS = execute_function(name, par, result, dictionary);
0346 EVAL_EXIT( EVAL_STATUS, (EVAL_STATUS == EVAL::OK) ? pointer : begin);
0347 }
0348 }
0349 }
0350 }
0351
0352
0353
0354
0355
0356
0357
0358
0359
0360
0361
0362
0363
0364
0365
0366 static int maker(int op, std::stack<double> & val)
0367 {
0368 if (val.size() < 2) return EVAL::ERROR_SYNTAX_ERROR;
0369 double val2 = val.top(); val.pop();
0370 double val1 = val.top();
0371 switch (op) {
0372 case OR:
0373 val.top() = (val1 || val2) ? 1. : 0.;
0374 return EVAL::OK;
0375 case AND:
0376 val.top() = (val1 && val2) ? 1. : 0.;
0377 return EVAL::OK;
0378 case EQ:
0379 val.top() = (val1 == val2) ? 1. : 0.;
0380 return EVAL::OK;
0381 case NE:
0382 val.top() = (val1 != val2) ? 1. : 0.;
0383 return EVAL::OK;
0384 case GE:
0385 val.top() = (val1 >= val2) ? 1. : 0.;
0386 return EVAL::OK;
0387 case GT:
0388 val.top() = (val1 > val2) ? 1. : 0.;
0389 return EVAL::OK;
0390 case LE:
0391 val.top() = (val1 <= val2) ? 1. : 0.;
0392 return EVAL::OK;
0393 case LT:
0394 val.top() = (val1 < val2) ? 1. : 0.;
0395 return EVAL::OK;
0396 case PLUS:
0397 val.top() = val1 + val2;
0398 return EVAL::OK;
0399 case MINUS:
0400 val.top() = val1 - val2;
0401 return EVAL::OK;
0402 case MULT:
0403 val.top() = val1 * val2;
0404 return EVAL::OK;
0405 case DIV:
0406 if (val2 == 0.0) return EVAL::ERROR_CALCULATION_ERROR;
0407 val.top() = val1 / val2;
0408 return EVAL::OK;
0409 case POW:
0410 errno = 0;
0411 val.top() = pow(val1,val2);
0412 if (errno == 0) return EVAL::OK;
0413 ATTR_FALLTHROUGH;
0414 default:
0415 return EVAL::ERROR_CALCULATION_ERROR;
0416 }
0417 }
0418
0419
0420
0421
0422
0423
0424
0425
0426
0427
0428
0429
0430
0431
0432
0433
0434
0435 static int engine(char const* begin, char const* end, double & result,
0436 char const*& endp, const dic_type & dictionary)
0437 {
0438 static constexpr int SyntaxTable[17][17] = {
0439
0440 { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 1 },
0441 { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 1 },
0442 { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
0443 { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
0444 { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
0445 { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
0446 { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
0447 { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
0448 { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
0449 { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
0450 { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
0451 { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
0452 { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
0453 { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
0454 { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
0455 { 3, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0 },
0456 { 3, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0 }
0457 };
0458 static constexpr int ActionTable[15][16] = {
0459
0460 { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,-1 },
0461 {-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3 },
0462 { 4, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4 },
0463 { 4, 1, 4, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4 },
0464 { 4, 1, 4, 4, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4 },
0465 { 4, 1, 4, 4, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4 },
0466 { 4, 1, 4, 4, 4, 4, 2, 2, 2, 2, 1, 1, 1, 1, 1, 4 },
0467 { 4, 1, 4, 4, 4, 4, 2, 2, 2, 2, 1, 1, 1, 1, 1, 4 },
0468 { 4, 1, 4, 4, 4, 4, 2, 2, 2, 2, 1, 1, 1, 1, 1, 4 },
0469 { 4, 1, 4, 4, 4, 4, 2, 2, 2, 2, 1, 1, 1, 1, 1, 4 },
0470 { 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 1, 1, 1, 4 },
0471 { 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 1, 1, 1, 4 },
0472 { 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 1, 4 },
0473 { 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 1, 4 },
0474 { 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 }
0475 };
0476
0477 std::stack<int> op;
0478 std::stack<char const*> pos;
0479 std::stack<double> val;
0480 double value;
0481 char const* pointer = begin;
0482 int iWhat, iCur, iPrev = 0, iTop, EVAL_STATUS;
0483 char c;
0484
0485 op.push(0); pos.push(pointer);
0486 SKIP_BLANKS;
0487 if (c == '\0') { EVAL_EXIT( EVAL::WARNING_BLANK_STRING, begin ); }
0488 for(;;pointer++) {
0489
0490
0491
0492 c = (pointer > end) ? '\0' : *pointer;
0493 if (isspace(c)) continue;
0494 switch (c) {
0495 case '\0': iCur = ENDL; break;
0496 case '(': iCur = LBRA; break;
0497 case '|':
0498 if (*(pointer+1) == '|') {
0499 pointer++; iCur = OR; break;
0500 }else{
0501 EVAL_EXIT( EVAL::ERROR_UNEXPECTED_SYMBOL, pointer );
0502 }
0503 case '&':
0504 if (*(pointer+1) == '&') {
0505 pointer++; iCur = AND; break;
0506 }else{
0507 EVAL_EXIT( EVAL::ERROR_UNEXPECTED_SYMBOL, pointer );
0508 }
0509 case '=':
0510 if (*(pointer+1) == '=') {
0511 pointer++; iCur = EQ; break;
0512 }else{
0513 EVAL_EXIT( EVAL::ERROR_UNEXPECTED_SYMBOL, pointer );
0514 }
0515 case '!':
0516 if (*(pointer+1) == '=') {
0517 pointer++; iCur = NE; break;
0518 }else{
0519 EVAL_EXIT( EVAL::ERROR_UNEXPECTED_SYMBOL, pointer );
0520 }
0521 case '>':
0522 if (*(pointer+1) == '=') { pointer++; iCur = GE; } else { iCur = GT; }
0523 break;
0524 case '<':
0525 if (*(pointer+1) == '=') { pointer++; iCur = LE; } else { iCur = LT; }
0526 break;
0527 case '+': iCur = PLUS; break;
0528 case '-': iCur = MINUS; break;
0529 case '*':
0530 if (*(pointer+1) == '*') { pointer++; iCur = POW; }else{ iCur = MULT; }
0531 break;
0532 case '/': iCur = DIV; break;
0533 case '^': iCur = POW; break;
0534 case ')': iCur = RBRA; break;
0535 default:
0536 if (c == '.' || isalnum(c)) {
0537 iCur = VALUE; break;
0538 }else{
0539 EVAL_EXIT( EVAL::ERROR_UNEXPECTED_SYMBOL, pointer );
0540 }
0541 }
0542
0543
0544
0545 iWhat = SyntaxTable[iPrev][iCur];
0546 iPrev = iCur;
0547 switch (iWhat) {
0548 case 0:
0549 EVAL_EXIT( EVAL::ERROR_SYNTAX_ERROR, pointer );
0550 case 1:
0551 EVAL_STATUS = operand(pointer, end, value, pointer, dictionary);
0552 if (EVAL_STATUS != EVAL::OK) { EVAL_EXIT( EVAL_STATUS, pointer ); }
0553 val.push(value);
0554 continue;
0555 case 2:
0556 val.push(0.0);
0557 case 3: default:
0558 break;
0559 }
0560
0561
0562
0563 for(;;) {
0564 if (op.size() == 0) { EVAL_EXIT( EVAL::ERROR_SYNTAX_ERROR, pointer ); }
0565 iTop = op.top();
0566 switch (ActionTable[iTop][iCur]) {
0567 case -1:
0568 if (op.size() > 1) pointer = pos.top();
0569 EVAL_EXIT( EVAL::ERROR_UNPAIRED_PARENTHESIS, pointer );
0570 case 0:
0571 if (val.size() == 1) {
0572 result = val.top();
0573 EVAL_EXIT( EVAL::OK, pointer );
0574 }else{
0575 EVAL_EXIT( EVAL::ERROR_SYNTAX_ERROR, pointer );
0576 }
0577 case 1:
0578 op.push(iCur); pos.push(pointer);
0579 break;
0580 case 2:
0581 EVAL_STATUS = maker(iTop, val);
0582 if (EVAL_STATUS != EVAL::OK) {
0583 EVAL_EXIT( EVAL_STATUS, pos.top() );
0584 }
0585 op.top() = iCur; pos.top() = pointer;
0586 break;
0587 case 3:
0588 op.pop(); pos.pop();
0589 break;
0590 case 4: default:
0591 EVAL_STATUS = maker(iTop, val);
0592 if (EVAL_STATUS != EVAL::OK) {
0593 EVAL_EXIT( EVAL_STATUS, pos.top() );
0594 }
0595 op.pop(); pos.pop();
0596 continue;
0597 }
0598 break;
0599 }
0600 }
0601 }
0602
0603
0604 static int setItem(const char * prefix, const char * name,
0605 const Item & item, EVAL::Object::Struct* imp) {
0606
0607 if (name == 0 || *name == '\0') {
0608 return EVAL::ERROR_NOT_A_NAME;
0609 }
0610
0611
0612
0613 const char * pointer; int n; REMOVE_BLANKS;
0614
0615
0616
0617 if (n == 0) {
0618 return EVAL::ERROR_NOT_A_NAME;
0619 }
0620 for(int i=0; i<n; i++) {
0621 char c = *(pointer+i);
0622 if ( !(c == '_' || c== ':') && !isalnum(c)) {
0623 return EVAL::ERROR_NOT_A_NAME;
0624 }
0625 }
0626
0627
0628
0629 std::string item_name = prefix + std::string(pointer,n);
0630 EVAL::Object::Struct::WriteLock guard(imp);
0631 dic_type::iterator iter = imp->theDictionary.find(item_name);
0632 if (iter != imp->theDictionary.end()) {
0633 iter->second = item;
0634 if (item_name == name) {
0635 return EVAL::WARNING_EXISTING_VARIABLE;
0636 }else{
0637 return EVAL::WARNING_EXISTING_FUNCTION;
0638 }
0639 }
0640 imp->theDictionary[item_name] = item;
0641 return EVAL::OK;
0642 }
0643
0644
0645 static void print_error_status(std::ostream& os, int status, char const* extra) {
0646 static char prefix[] = "Evaluator::Object : ";
0647 const char* opt = (extra ? extra : "");
0648 switch (status) {
0649 case EVAL::WARNING_EXISTING_VARIABLE:
0650 os << prefix << "existing variable";
0651 return;
0652 case EVAL::WARNING_EXISTING_FUNCTION:
0653 os << prefix << "existing function";
0654 return;
0655 case EVAL::WARNING_BLANK_STRING:
0656 os << prefix << "blank string detected";
0657 return;
0658 case EVAL::ERROR_NOT_A_NAME:
0659 os << prefix << "invalid name : " << opt;
0660 return;
0661 case EVAL::ERROR_SYNTAX_ERROR:
0662 os << prefix << "systax error" ;
0663 return;
0664 case EVAL::ERROR_UNPAIRED_PARENTHESIS:
0665 os << prefix << "unpaired parenthesis";
0666 return;
0667 case EVAL::ERROR_UNEXPECTED_SYMBOL:
0668 os << prefix << "unexpected symbol : " << opt;
0669 return;
0670 case EVAL::ERROR_UNKNOWN_VARIABLE:
0671 os << prefix << "unknown variable : " << opt;
0672 return;
0673 case EVAL::ERROR_UNKNOWN_FUNCTION:
0674 os << prefix << "unknown function : " << opt;
0675 return;
0676 case EVAL::ERROR_EMPTY_PARAMETER:
0677 os << prefix << "empty parameter in function call: " << opt;
0678 return;
0679 case EVAL::ERROR_CALCULATION_ERROR:
0680 os << prefix << "calculation error";
0681 return;
0682 default:
0683 return;
0684 }
0685 }
0686
0687
0688 using namespace dd4hep::tools;
0689
0690
0691 Evaluator::Object::Object(double meter, double kilogram, double second, double ampere, double kelvin
0692 , double mole, double candela, double radians) : imp( new Struct()) {
0693 setStdMath();
0694 setSystemOfUnits(meter, kilogram, second, ampere, kelvin
0695 , mole, candela, radians );
0696 }
0697
0698
0699 Evaluator::Object::~Object() {
0700 delete imp;
0701 }
0702
0703
0704 Evaluator::Object::EvalStatus Evaluator::Object::evaluate(const char * expression) const {
0705 EvalStatus s;
0706 if (expression != 0) {
0707 Struct::ReadLock guard(imp);
0708 s.theStatus = engine(expression,
0709 expression+strlen(expression)-1,
0710 s.theResult,
0711 s.thePosition,
0712 imp->theDictionary);
0713 }
0714 return s;
0715 }
0716
0717
0718 int Evaluator::Object::EvalStatus::status() const {
0719 return theStatus;
0720 }
0721
0722
0723 double Evaluator::Object::EvalStatus::result() const {
0724 return theResult;
0725 }
0726
0727
0728 int Evaluator::Object::EvalStatus::error_position(const char* expression) const {
0729 return thePosition - expression;
0730 }
0731
0732
0733 void Evaluator::Object::EvalStatus::print_error() const {
0734 std::stringstream str;
0735 print_error(str);
0736 if ( str.str().empty() ) return;
0737 std::cerr << str.str() << std::endl;
0738 }
0739
0740
0741 void Evaluator::Object::EvalStatus::print_error(std::ostream& os) const {
0742 print_error_status(os, theStatus, thePosition);
0743 }
0744
0745
0746 int Evaluator::Object::setEnviron(const char* name, const char* value) {
0747 std::string prefix = "${";
0748 std::string item_name = prefix + std::string(name) + std::string("}");
0749
0750
0751
0752 Struct::WriteLock guard(imp);
0753 Item item;
0754 item.what = Item::STRING;
0755 item.expression = value;
0756 item.function = 0;
0757 item.variable = 0;
0758 dic_type::iterator iter = imp->theDictionary.find(item_name);
0759 if (iter != imp->theDictionary.end()) {
0760 iter->second = std::move(item);
0761 if (item_name == name) {
0762 return EVAL::WARNING_EXISTING_VARIABLE;
0763 }else{
0764 return EVAL::WARNING_EXISTING_FUNCTION;
0765 }
0766 }else{
0767 imp->theDictionary[item_name] = std::move(item);
0768 return EVAL::OK;
0769 }
0770 }
0771
0772
0773 std::pair<const char*,int> Evaluator::Object::getEnviron(const char* name) const {
0774 Struct::ReadLock guard(imp);
0775 Struct const* cImp = imp;
0776 dic_type::const_iterator iter = cImp->theDictionary.find(name);
0777 if (iter != cImp->theDictionary.end()) {
0778 return std::make_pair(iter->second.expression.c_str(), EVAL::OK);
0779 }
0780 if ( ::strlen(name) > 3 ) {
0781
0782 std::string env_name(name+2,::strlen(name)-3);
0783 const char* env_str = ::getenv(env_name.c_str());
0784 if ( 0 != env_str ) {
0785 return std::make_pair(env_str, EVAL::OK);
0786 }
0787 }
0788 return std::make_pair(nullptr,EVAL::ERROR_UNKNOWN_VARIABLE);
0789 }
0790
0791
0792 int Evaluator::Object::setVariable(const char * name, double value) {
0793 return setItem("", name, Item(value), imp);
0794 }
0795
0796 int Evaluator::Object::setVariable(const char * name, const char * expression) {
0797 Item item(expression);
0798 auto returnValue = setItem("", name, item, imp);
0799 {
0800
0801
0802 Struct::WriteLock guard(imp);
0803 item.expression = "";
0804 }
0805 return returnValue;
0806 }
0807
0808 void Evaluator::Object::setVariableNoLock(const char * name, double value) {
0809 std::string item_name = name;
0810 imp->theDictionary[item_name] = Item(value);
0811 }
0812
0813 int Evaluator::Object::setFunction(const char * name,double (*fun)()) {
0814 return setItem("0", name, Item(FCN(fun).ptr), imp);
0815 }
0816
0817 int Evaluator::Object::setFunction(const char * name,double (*fun)(double)) {
0818 return setItem("1", name, Item(FCN(fun).ptr), imp);
0819 }
0820
0821 int Evaluator::Object::setFunction(const char * name, double (*fun)(double,double)) {
0822 return setItem("2", name, Item(FCN(fun).ptr), imp);
0823 }
0824
0825 int Evaluator::Object::setFunction(const char * name, double (*fun)(double,double,double)) {
0826 return setItem("3", name, Item(FCN(fun).ptr), imp);
0827 }
0828
0829 int Evaluator::Object::setFunction(const char * name, double (*fun)(double,double,double,double)) {
0830 return setItem("4", name, Item(FCN(fun).ptr), imp);
0831 }
0832
0833 int Evaluator::Object::setFunction(const char * name, double (*fun)(double,double,double,double,double)) {
0834 return setItem("5", name, Item(FCN(fun).ptr), imp);
0835 }
0836
0837 void Evaluator::Object::setFunctionNoLock(const char * name,double (*fun)(double)) {
0838 std::string item_name = "1"+std::string(name);
0839 imp->theDictionary[item_name] = Item(FCN(fun).ptr);
0840 }
0841
0842 void Evaluator::Object::setFunctionNoLock(const char * name, double (*fun)(double,double)) {
0843 std::string item_name = "2"+std::string(name);
0844 imp->theDictionary[item_name] = Item(FCN(fun).ptr);
0845 }
0846
0847
0848
0849 bool Evaluator::Object::findVariable(const char * name) const {
0850 if (name == 0 || *name == '\0') return false;
0851 const char * pointer; int n; REMOVE_BLANKS;
0852 if (n == 0) return false;
0853 Struct::ReadLock guard(imp);
0854 return
0855 (imp->theDictionary.find(std::string(pointer,n)) == imp->theDictionary.end()) ?
0856 false : true;
0857 }
0858
0859
0860 bool Evaluator::Object::findFunction(const char * name, int npar) const {
0861 if (name == 0 || *name == '\0') return false;
0862 if (npar < 0 || npar > MAX_N_PAR) return false;
0863 const char * pointer; int n; REMOVE_BLANKS;
0864 if (n == 0) return false;
0865 Struct::ReadLock guard(imp);
0866 return (imp->theDictionary.find(sss[npar]+std::string(pointer,n)) ==
0867 imp->theDictionary.end()) ? false : true;
0868 }
0869
0870
0871 void Evaluator::Object::removeVariable(const char * name) {
0872 if (name == 0 || *name == '\0') return;
0873 const char * pointer; int n; REMOVE_BLANKS;
0874 if (n == 0) return;
0875 Struct::WriteLock guard(imp);
0876 imp->theDictionary.erase(std::string(pointer,n));
0877 }
0878
0879
0880 void Evaluator::Object::removeFunction(const char * name, int npar) {
0881 if (name == 0 || *name == '\0') return;
0882 if (npar < 0 || npar > MAX_N_PAR) return;
0883 const char * pointer; int n; REMOVE_BLANKS;
0884 if (n == 0) return;
0885 Struct::WriteLock guard(imp);
0886 imp->theDictionary.erase(sss[npar]+std::string(pointer,n));
0887 }
0888
0889
0890 Evaluator::Evaluator(double meter, double kilogram, double second, double ampere, double kelvin
0891 , double mole, double candela, double radians) {
0892 object = new Object(meter, kilogram, second, ampere, kelvin, mole, candela, radians);
0893 }
0894
0895
0896 Evaluator::Evaluator(Evaluator&& other):object(other.object) {
0897 other.object=nullptr;
0898 }
0899
0900
0901 Evaluator::~Evaluator() {
0902 delete object;
0903 }
0904
0905
0906 std::pair<int,double> Evaluator::evaluate(const std::string& expression) const {
0907 auto result = object->evaluate(expression.c_str());
0908 return std::make_pair(result.status(),result.result());
0909 }
0910
0911
0912 std::pair<int,double> Evaluator::evaluate(const std::string& expression, std::ostream& os) const {
0913 auto result = object->evaluate(expression.c_str());
0914 int status = result.status();
0915 if ( status != OK ) {
0916 result.print_error(os);
0917 }
0918 return std::make_pair(result.status(),result.result());
0919 }
0920
0921
0922 int Evaluator::setEnviron(const std::string& name, const std::string& value) const {
0923 int result = object->setEnviron(name.c_str(), value.c_str());
0924 return result;
0925 }
0926
0927
0928 std::pair<int,std::string> Evaluator::getEnviron(const std::string& name) const {
0929 std::pair<int,std::string> result;
0930 auto env_status = object->getEnviron(name.c_str());
0931 result.first = env_status.second;
0932 if( env_status.first ) result.second = env_status.first;
0933 return result;
0934 }
0935
0936
0937 std::pair<int,std::string> Evaluator::getEnviron(const std::string& name, std::ostream& os) const {
0938 std::pair<int,std::string> result;
0939 auto env_status = object->getEnviron(name.c_str());
0940 result.first = env_status.second;
0941 if ( env_status.first ) {
0942 result.second = env_status.first;
0943 }
0944 if ( result.first != OK ) {
0945 print_error_status(os, result.first, name.c_str());
0946 }
0947 return result;
0948 }
0949
0950
0951 int Evaluator::setVariable(const std::string& name, double value) const {
0952 int result = object->setVariable(name.c_str(), value);
0953 return result;
0954 }
0955
0956
0957 int Evaluator::setVariable(const std::string& name, double value, std::ostream& os) const {
0958 int result = object->setVariable(name.c_str(), value);
0959 if ( result != OK ) {
0960 print_error_status(os, result, name.c_str());
0961 }
0962 return result;
0963 }
0964
0965
0966 int Evaluator::setVariable(const std::string& name, const std::string& value) const {
0967 int result = object->setVariable(name.c_str(), value.c_str());
0968 return result;
0969 }
0970
0971
0972 int Evaluator::setVariable(const std::string& name, const std::string& value, std::ostream& os) const {
0973 int result = object->setVariable(name.c_str(), value.c_str());
0974 if ( result != OK ) {
0975 print_error_status(os, result, name.c_str());
0976 }
0977 return result;
0978 }
0979
0980
0981 bool Evaluator::findVariable(const std::string& name) const {
0982 bool ret;
0983 ret = object->findVariable(name.c_str());
0984 return ret;
0985 }
0986
0987
0988 int Evaluator::setFunction(const std::string& name, double (*fun)()) const {
0989 int result = object->setFunction(name.c_str(), fun);
0990 return result;
0991 }
0992
0993
0994 int Evaluator::setFunction(const std::string& name, double (*fun)(double)) const {
0995 int result = object->setFunction(name.c_str(), fun);
0996 return result;
0997 }
0998
0999
1000 int Evaluator::setFunction(const std::string& name, double (*fun)(double, double)) const {
1001 int result = object->setFunction(name.c_str(), fun);
1002 return result;
1003 }
1004
1005
1006 int Evaluator::setFunction(const std::string& name, double (*fun)(double, double, double)) const {
1007 int result = object->setFunction(name.c_str(), fun);
1008 return result;
1009 }
1010
1011
1012 int Evaluator::setFunction(const std::string& name, double (*fun)(double, double, double, double)) const {
1013 int result = object->setFunction(name.c_str(), fun);
1014 return result;
1015 }
1016
1017
1018 int Evaluator::setFunction(const std::string& name, double (*fun)(double, double, double, double, double)) const {
1019 int result =object->setFunction(name.c_str(), fun);
1020 return result;
1021 }
1022
1023
1024 bool Evaluator::findFunction(const std::string& name, int npar) const {
1025 bool ret;
1026 ret = object->findFunction(name.c_str(), npar);
1027 return ret;
1028 }