00001 #include <iostream>
00002 #include "DetectorDescription/ExprAlgo/interface/ClhepEvaluator.h"
00003 #include "DetectorDescription/Base/interface/DDException.h"
00004 #include "DetectorDescription/Base/interface/DDdebug.h"
00005
00006 ClhepEvaluator::ClhepEvaluator()
00007 {
00008
00009 evaluator_.setStdMath();
00010
00011
00012 evaluator_.setSystemOfUnits(1.e+3, 1./1.60217733e-25, 1.e+9, 1./1.60217733e-10,
00013 1.0, 1.0, 1.0);
00014
00015
00016
00017 evaluator_.setVariable("mum","1.e-3*mm");
00018 evaluator_.setVariable("fm","1.e-15*meter");
00019 }
00020
00021
00022 ClhepEvaluator::~ClhepEvaluator()
00023 {
00024 clear();
00025 }
00026
00027 void dd_exchange_value(std::vector<std::string> & vars, std::vector<std::string> & vals,
00028 const std::string & var, const std::string & val)
00029 {
00030 std::vector<std::string>::iterator it(vars.begin()), ed(vars.end());
00031 std::vector<std::string>::size_type count(0);
00032 for (; it != ed; ++it) {
00033 if ( *it == var) {
00034
00035 vals[count] = val;
00036 break;
00037 }
00038 ++count;
00039 }
00040 }
00041
00042
00043 void ClhepEvaluator::set(const std::string & ns, const std::string & name, const std::string & exprValue)
00044 {
00045 checkname(ns);
00046 checkname(name);
00047 std::string newVar;
00048 std::string newVal;
00049 prepare(ns,name,exprValue,newVar,newVal);
00050 DCOUT_V('C', "ClhepEvaluator: "
00051 << " in: " << ns << " " << name << " " << exprValue
00052 << " pr: " << newVar << " " << newVal);
00053
00054 evaluator_.setVariable(newVar.c_str(), newVal.c_str());
00055 switch(evaluator_.status()) {
00056 case HepTool::Evaluator::WARNING_EXISTING_VARIABLE:
00057 dd_exchange_value(variables_,values_,newVar,newVal);
00058 break;
00059 case HepTool::Evaluator::OK:
00060 case HepTool::Evaluator::WARNING_EXISTING_FUNCTION:
00061 case HepTool::Evaluator::WARNING_BLANK_STRING:
00062 variables_.push_back(newVar);
00063 values_.push_back(newVal);
00064 break;
00065 default:
00066 std::cout << "set-var: ns=" << ns << " nm=" << name << " val=" << exprValue << std::endl;
00067 evaluator_.print_error();
00068 throwex(ns,name,exprValue,"can't set parameter !");
00069 }
00070 }
00071
00072 void ClhepEvaluator::set(const std::string & n, const std::string & v)
00073 {
00074 evaluator_.setVariable(n.c_str(),v.c_str());
00075 switch(evaluator_.status()) {
00076 case HepTool::Evaluator::WARNING_EXISTING_VARIABLE:
00077 dd_exchange_value(variables_,values_,n,v);
00078 break;
00079 case HepTool::Evaluator::OK:
00080 case HepTool::Evaluator::WARNING_EXISTING_FUNCTION:
00081 case HepTool::Evaluator::WARNING_BLANK_STRING:
00082 variables_.push_back(n);
00083 values_.push_back(v);
00084 break;
00085 default:
00086 std::cout << "set-varname=" << n << " val=" << v << std::endl;
00087 evaluator_.print_error();
00088 throwex("",n,v,"can't set parameter !");
00089 }
00090 }
00091
00092
00093 double ClhepEvaluator::eval(const std::string & ns, const std::string & expr)
00094 {
00095
00096
00097
00098 std::string pseudo("(evaluating)");
00099 std::string prepared;
00100
00101 prepare(ns,pseudo,expr, pseudo,prepared);
00102
00103 double result = evaluator_.evaluate(prepared.c_str());
00104 if(evaluator_.status()!=HepTool::Evaluator::OK) {
00105 std::cout << "expr: " << prepared << std::endl;
00106 std::cout << "------";
00107 for (int i=0; i<evaluator_.error_position(); ++i) std::cout << "-";
00108 std::cout << "^" << std::endl;
00109 evaluator_.print_error();
00110 throwex(ns,prepared,expr,"can't evaluate: " + expr + std::string("!"));
00111 }
00112
00113 return result;
00114 }
00115
00116 double ClhepEvaluator::eval(const char * expression)
00117 {
00118 double result = evaluator_.evaluate(expression);
00119 if (evaluator_.status()!=HepTool::Evaluator::OK) {
00120 std::cout << "expr: " << expression << std::endl;
00121 std::cout << "------";
00122 for (int i=0; i<evaluator_.error_position(); ++i) std::cout << "-";
00123 std::cout << "^" << std::endl;
00124 evaluator_.print_error();
00125 throwex("",expression,"","can't evaluate: " + std::string(expression) + std::string("!"));
00126 }
00127 return result;
00128 }
00129
00130 bool ClhepEvaluator::isDefined(const std::string & ns,
00131 const std::string & name
00132 )
00133 {
00134 std::string newVar;
00135 std::string newVal;
00136 prepare(ns,name,"0", newVar,newVal);
00137 return evaluator_.findVariable(newVar.c_str());
00138 }
00139
00140
00141 void ClhepEvaluator::clear()
00142 {
00143
00144 evaluator_.clear();
00145
00146
00147 variables_.clear();
00148 values_.clear();
00149 }
00150
00151
00152 void ClhepEvaluator::prepare(const std::string & ns,
00153 const std::string & name,
00154 const std::string & exprValue,
00155 std::string & nameResult,
00156 std::string & valResult) const
00157 {
00158 static const std::string sep("___");
00159
00160
00161
00162
00163 nameResult = ns + sep + name;
00164
00165
00166 std::string temp;
00167
00168
00169
00170
00171
00172 std::string::size_type sz = exprValue.size();
00173 std::string::size_type idx =0;
00174 bool insideBracket = false;
00175 bool nsFound = false;
00176 int varCount=0;
00177 std::vector<int> hasNs(1);
00178
00179 while(idx<sz) {
00180 switch(exprValue[idx]) {
00181
00182 case '[':
00183 if (nsFound || insideBracket) {
00184 throwex(ns,name,exprValue,
00185 "found a ':' outside '[..]' , or too many '[' !",idx);
00186 }
00187 insideBracket=true;
00188 ++varCount;
00189 break;
00190
00191 case ']':
00192 if (!insideBracket) {
00193 throwex(ns,name,exprValue,"too many ']' !",idx);
00194 }
00195 insideBracket=false;
00196 if (nsFound) {
00197 nsFound=false;
00198 hasNs.push_back(1);
00199 }
00200 else {
00201 hasNs.push_back(0);
00202 }
00203 break;
00204
00205 case ':':
00206 if ( (!insideBracket) || nsFound ) {
00207 throwex(ns,name,exprValue,
00208 "found a ':' outside '[..]' , or multiple ':' inside '[..]'",idx);
00209 }
00210 nsFound=true;
00211 break;
00212
00213 default:
00214 ;
00215 }
00216
00217 ++idx;
00218 }
00219
00220
00221 if ( insideBracket || nsFound ) {
00222 throwex(ns,name,exprValue,
00223 "'[..]' not closed , or ':' outside of '[..]'",idx);
00224 }
00225
00226
00227
00228 idx=0;
00229 varCount=0;
00230
00231 while (idx<sz) {
00232 switch(exprValue[idx]) {
00233
00234 case '[':
00235 ++varCount;
00236 if ( !hasNs[varCount] ) {
00237 valResult = valResult + ns + sep;
00238 }
00239 break;
00240
00241 case ']':
00242 break;
00243
00244 case ':':
00245 valResult = valResult + sep;
00246 break;
00247
00248 default:
00249 valResult = valResult + exprValue[idx];
00250 }
00251
00252 ++idx;
00253 }
00254 }
00255
00256
00257
00258 void ClhepEvaluator::throwex(const std::string & ns,
00259 const std::string & name,
00260 const std::string & expr,
00261 const std::string & reason,
00262 int idx) const
00263 {
00264 std::string er = std::string("ClhepEvaluator ERROR: ") + reason + std::string("\n")
00265 + std::string(" nmspace=") + ns
00266 + std::string("\n varname=") + name
00267 + std::string("\n exp=") + expr
00268 + std::string("\n at=") + expr.substr(0,idx);
00269 throw DDException(er);
00270
00271 }
00272
00273
00274 void ClhepEvaluator::checkname(const std::string & s) const
00275 {
00276
00277 std::string::size_type sz = s.size();
00278 while(sz) {
00279 --sz;
00280
00281 switch (s[sz]) {
00282 case ']':
00283 case '[':
00284 case ' ':
00285 case ':':
00286 case '\n':
00287 case '\t':
00288
00289 case '&':
00290 case '*':
00291 case '+':
00292 case '-':
00293 case '/':
00294 case '^':
00295 std::string e = std::string("ClhepEvaluator ERROR: forbidden character '")
00296 + s[sz] + std::string("' found in '") + s + std::string("' !");
00297 throw DDException(e);
00298 break;
00299 }
00300 }
00301
00302 }
00303
00304