File indexing completed on 2024-04-06 12:05:25
0001 #include <ext/alloc_traits.h>
0002 #include <iostream>
0003 #include <string>
0004 #include <vector>
0005
0006 #include "CLHEP/Evaluator/Evaluator.h"
0007 #include "DetectorDescription/Core/interface/ClhepEvaluator.h"
0008 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0009 #include "FWCore/Utilities/interface/Exception.h"
0010
0011 ClhepEvaluator::ClhepEvaluator() {
0012
0013 evaluator_.setStdMath();
0014
0015
0016 evaluator_.setSystemOfUnits(1.e+3, 1. / 1.60217733e-25, 1.e+9, 1. / 1.60217733e-10, 1.0, 1.0, 1.0);
0017
0018
0019
0020 evaluator_.setVariable("mum", "1.e-3*mm");
0021 evaluator_.setVariable("fm", "1.e-15*meter");
0022 }
0023
0024 ClhepEvaluator::~ClhepEvaluator() { clear(); }
0025
0026 void dd_exchange_value(std::vector<std::string>& vars,
0027 std::vector<std::string>& vals,
0028 const std::string& var,
0029 const std::string& val) {
0030 std::vector<std::string>::iterator it(vars.begin()), ed(vars.end());
0031 std::vector<std::string>::size_type count(0);
0032 for (; it != ed; ++it) {
0033 if (*it == var) {
0034
0035 vals[count] = val;
0036 break;
0037 }
0038 ++count;
0039 }
0040 }
0041
0042 void ClhepEvaluator::set(const std::string& ns, const std::string& name, const std::string& exprValue) {
0043 checkname(ns);
0044 checkname(name);
0045 std::string newVar;
0046 std::string newVal;
0047 prepare(ns, name, exprValue, newVar, newVal);
0048 evaluator_.setVariable(newVar.c_str(), newVal.c_str());
0049 switch (evaluator_.status()) {
0050 case HepTool::Evaluator::WARNING_EXISTING_VARIABLE:
0051 dd_exchange_value(variables_, values_, newVar, newVal);
0052 break;
0053 case HepTool::Evaluator::OK:
0054 case HepTool::Evaluator::WARNING_EXISTING_FUNCTION:
0055 case HepTool::Evaluator::WARNING_BLANK_STRING:
0056 variables_.emplace_back(newVar);
0057 values_.emplace_back(newVal);
0058 break;
0059 default:
0060 std::cout << "set-var: ns=" << ns << " nm=" << name << " val=" << exprValue << std::endl;
0061 evaluator_.print_error();
0062 throwex(ns, name, exprValue, "can't set parameter !");
0063 }
0064 }
0065
0066 void ClhepEvaluator::set(const std::string& n, const std::string& v) {
0067 evaluator_.setVariable(n.c_str(), v.c_str());
0068 switch (evaluator_.status()) {
0069 case HepTool::Evaluator::WARNING_EXISTING_VARIABLE:
0070 dd_exchange_value(variables_, values_, n, v);
0071 break;
0072 case HepTool::Evaluator::OK:
0073 case HepTool::Evaluator::WARNING_EXISTING_FUNCTION:
0074 case HepTool::Evaluator::WARNING_BLANK_STRING:
0075 variables_.emplace_back(n);
0076 values_.emplace_back(v);
0077 break;
0078 default:
0079 std::cout << "set-varname=" << n << " val=" << v << std::endl;
0080 evaluator_.print_error();
0081 throwex("", n, v, "can't set parameter !");
0082 }
0083 }
0084
0085 double ClhepEvaluator::eval(const std::string& ns, const std::string& expr) {
0086
0087
0088 std::string pseudo("(evaluating)");
0089 std::string prepared;
0090
0091 prepare(ns, pseudo, expr, pseudo, prepared);
0092
0093 double result = evaluator_.evaluate(prepared.c_str());
0094 if (evaluator_.status() != HepTool::Evaluator::OK) {
0095 std::cout << "expr: " << prepared << std::endl;
0096 std::cout << "------";
0097 for (int i = 0; i < evaluator_.error_position(); ++i)
0098 std::cout << "-";
0099 std::cout << "^" << std::endl;
0100 evaluator_.print_error();
0101 throwex(ns, prepared, expr, "can't evaluate: " + expr + std::string("!"));
0102 }
0103
0104 return result;
0105 }
0106
0107 double ClhepEvaluator::eval(const char* expression) {
0108 double result = evaluator_.evaluate(expression);
0109 if (evaluator_.status() != HepTool::Evaluator::OK) {
0110 std::cout << "expr: " << expression << std::endl;
0111 std::cout << "------";
0112 for (int i = 0; i < evaluator_.error_position(); ++i)
0113 std::cout << "-";
0114 std::cout << "^" << std::endl;
0115 evaluator_.print_error();
0116 throwex("", expression, "", "can't evaluate: " + std::string(expression) + std::string("!"));
0117 }
0118 return result;
0119 }
0120
0121 bool ClhepEvaluator::isDefined(const std::string& ns,
0122 const std::string& name
0123 ) {
0124 std::string newVar;
0125 std::string newVal;
0126 prepare(ns, name, "0", newVar, newVal);
0127 return evaluator_.findVariable(newVar.c_str());
0128 }
0129
0130 void ClhepEvaluator::clear() {
0131
0132 evaluator_.clear();
0133
0134
0135 variables_.clear();
0136 values_.clear();
0137 }
0138
0139 void ClhepEvaluator::prepare(const std::string& ns,
0140 const std::string& name,
0141 const std::string& exprValue,
0142 std::string& nameResult,
0143 std::string& valResult) const {
0144 static const std::string sep("___");
0145
0146
0147
0148
0149 nameResult = ns + sep + name;
0150
0151
0152 std::string temp;
0153
0154
0155
0156
0157
0158 std::string::size_type sz = exprValue.size();
0159 std::string::size_type idx = 0;
0160 bool insideBracket = false;
0161 bool nsFound = false;
0162 int varCount = 0;
0163 std::vector<int> hasNs(1);
0164
0165 while (idx < sz) {
0166 switch (exprValue[idx]) {
0167 case '[':
0168 if (nsFound || insideBracket) {
0169 throwex(ns, name, exprValue, "found a ':' outside '[..]' , or too many '[' !", idx);
0170 }
0171 insideBracket = true;
0172 ++varCount;
0173 break;
0174 case ']':
0175 if (!insideBracket) {
0176 throwex(ns, name, exprValue, "too many ']' !", idx);
0177 }
0178 insideBracket = false;
0179 if (nsFound) {
0180 nsFound = false;
0181 hasNs.emplace_back(1);
0182 } else {
0183 hasNs.emplace_back(0);
0184 }
0185 break;
0186 case ':':
0187 if ((!insideBracket) || nsFound) {
0188 throwex(ns, name, exprValue, "found a ':' outside '[..]' , or multiple ':' inside '[..]'", idx);
0189 }
0190 nsFound = true;
0191 break;
0192 default:;
0193 }
0194 ++idx;
0195 }
0196
0197
0198 if (insideBracket || nsFound) {
0199 throwex(ns, name, exprValue, "'[..]' not closed , or ':' outside of '[..]'", idx);
0200 }
0201
0202
0203
0204 idx = 0;
0205 varCount = 0;
0206
0207 while (idx < sz) {
0208 switch (exprValue[idx]) {
0209 case '[':
0210 ++varCount;
0211 if (!hasNs[varCount]) {
0212 valResult = valResult + ns + sep;
0213 }
0214 break;
0215 case ']':
0216 break;
0217 case ':':
0218 valResult = valResult + sep;
0219 break;
0220 default:
0221 valResult = valResult + exprValue[idx];
0222 }
0223 ++idx;
0224 }
0225 }
0226
0227 void ClhepEvaluator::throwex(
0228 const std::string& ns, const std::string& name, const std::string& expr, const std::string& reason, int idx) const {
0229 std::string er = std::string("ClhepEvaluator ERROR: ") + reason + std::string("\n") + std::string(" nmspace=") + ns +
0230 std::string("\n varname=") + name + std::string("\n exp=") + expr + std::string("\n at=") +
0231 expr.substr(0, idx);
0232 throw cms::Exception("DDException") << er;
0233 }
0234
0235 void ClhepEvaluator::checkname(const std::string& s) const {
0236
0237 std::string::size_type sz = s.size();
0238 while (sz) {
0239 --sz;
0240
0241 switch (s[sz]) {
0242 case ']':
0243 case '[':
0244 case ' ':
0245 case ':':
0246 case '\n':
0247 case '\t':
0248
0249 case '&':
0250 case '*':
0251 case '+':
0252 case '-':
0253 case '/':
0254 case '^':
0255 std::string e = std::string("ClhepEvaluator ERROR: forbidden character '") + s[sz] +
0256 std::string("' found in '") + s + std::string("' !");
0257 throw cms::Exception("DDException") << e;
0258 break;
0259 }
0260 }
0261 }