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