#include <BLEvaluator.hh>
Uses HepTool::Evaluator, but fixes up a few minor bugs: automatically calls setStdMath() adds floor(x) and ceil(x) fixes unary +/- by enclosing them in parens
Public Member Functions | |
BLEvaluator () | |
Constructor. | |
double | evaluate (const char *expression) |
evaluate() will evaluate the expression. returns NAN if the expression is not valid (use either isOK() or std::isnan(double) or gsl_isnan(double) to check). | |
bool | isOK () |
isOK() returns true if the previous call to expression succeeded. | |
void | setTrackVariables (const G4Track *track, BLCoordinateType coordType, G4String suffix="", bool fields=false) |
setTrackVariables() devines variables in the evaluator corresponding to the usual track variables. These can then be used in expressions. | |
bool | isidchar (char c) |
isidchar() returns true if the char is valid for an identifier. | |
bool | isopchar (char c) |
isopchar() returns true if the character is an operator (no parens) | |
bool | isumchar (char c) |
isumchar() returns true if the char should be inside the parens generated to surround the unary minus (parens matched in evaluate()) |
BLEvaluator::BLEvaluator | ( | ) | [inline] |
double BLEvaluator::evaluate | ( | const char * | expression | ) | [inline] |
evaluate() will evaluate the expression. returns NAN if the expression is not valid (use either isOK() or std::isnan(double) or gsl_isnan(double) to check).
References BLAssert, isopchar(), and isumchar().
Referenced by BLTrackNTuple::appendTrack(), BLCommand::argDouble(), BLCommand::argInt(), BLCMDsetdecay::command(), BLCMDparam::command(), BLCMDif::command(), BLTune::defineTunableArg(), BLParam::getDouble(), BLCommand::getDouble(), FieldComputation::GetFieldValue(), BLCMDfieldexpr::handleTimeDependence(), BLCMDtrace::newTrace(), BLTune::update(), ParticleFilterPlacement::UserSteppingAction(), BLCMDtune::UserZSteppingAction(), BLCMDprofile::Entry::UserZSteppingAction(), and BLCMDprintf::UserZSteppingAction().
00042 { 00043 char out[1024]; 00044 BLAssert(strlen(expression) < sizeof(out)); 00045 // remove whitespace (simpler parsing below) 00046 int j=0; 00047 for(int i=0; expression[i]!='\0'; ++i) 00048 if(!isspace(expression[i])) out[j++] = expression[i]; 00049 out[j] = '\0'; 00050 // Workaround for serious bug in HepTool::Evaluator -- 00051 // it can only handle a unary +/- after a '(', so 00052 // put parens around unary +/- 00053 bool again=false; 00054 do { 00055 again = false; 00056 char *in = strdup(out); 00057 j = 0; 00058 char prev=' '; 00059 for(int i=0; in[i]!='\0'; ++i) { 00060 char c = in[i]; 00061 if((c == '-' || c == '+') && isopchar(prev)) { 00062 again = true; 00063 out[j++] = '('; 00064 out[j++] = c; 00065 ++i; 00066 int level = 0; 00067 while(isumchar(in[i]) || level > 0) { 00068 if(in[i] == '(') 00069 ++level; 00070 if(in[i] == ')') 00071 --level; 00072 // unary +/- after operator -- copy now, 00073 // handle during next loop (again = true) 00074 // (^ is the only op with higher precedence) 00075 if(in[i]=='^' && (in[i+1]=='-' || 00076 in[i+1]=='+')) 00077 out[j++] = in[i++]; 00078 out[j++] = in[i++]; 00079 } 00080 c = ')'; 00081 --i; 00082 } 00083 prev = out[j++] = c; 00084 } 00085 BLAssert((unsigned)j < sizeof(out)); 00086 out[j] = '\0'; 00087 // if empty or all whitespace, force invalid 00088 if(j == 0) strcpy(out,"x+-*/y"); 00089 free(in); 00090 } while(again); 00091 00092 double v = HepTool::Evaluator::evaluate(out); 00093 if(status() != OK) v = std::numeric_limits<double>::quiet_NaN(); 00094 return v; 00095 }
bool BLEvaluator::isOK | ( | ) | [inline] |
isOK() returns true if the previous call to expression succeeded.
Referenced by BLTrackNTuple::appendTrack(), BLCMDfieldexpr::checkValidExpr(), BLCMDtrace::newTrace(), and BLCMDprofile::Entry::UserZSteppingAction().
void BLEvaluator::setTrackVariables | ( | const G4Track * | track, | |
BLCoordinateType | coordType, | |||
G4String | suffix = "" , |
|||
bool | fields = false | |||
) | [inline] |
setTrackVariables() devines variables in the evaluator corresponding to the usual track variables. These can then be used in expressions.
References B, E, BLCoordinates::getCoords(), BLGlobalField::GetFieldValue(), BLManager::getObject(), BLGlobalField::getObject(), BLCoordinates::getRotation(), and BLCoordinates::isValid().
Referenced by BLCMDtrace::newTrace(), BLCMDtune::UserZSteppingAction(), BLCMDprofile::Entry::UserZSteppingAction(), and BLCMDprintf::UserZSteppingAction().
00104 { 00105 G4RunManager* runmgr = G4RunManager::GetRunManager(); 00106 const G4Event* event = runmgr->GetCurrentEvent(); 00107 int evId = event->GetEventID(); 00108 G4ThreeVector position = track->GetPosition(); 00109 G4double time = track->GetGlobalTime(); 00110 G4ThreeVector momentum = track->GetMomentum(); 00111 00112 // get B and E fields 00113 G4ThreeVector B, E; 00114 if(fields) { 00115 G4double point[4], field[6]; 00116 point[0] = position[0]; 00117 point[1] = position[1]; 00118 point[2] = position[2]; 00119 point[3] = time; 00120 BLGlobalField::getObject()->GetFieldValue(point,field); 00121 B = G4ThreeVector(field[0],field[1],field[2]); 00122 E = G4ThreeVector(field[3],field[4],field[5]); 00123 } 00124 00125 // transform to desired coordinates, if available 00126 BLCoordinates *c = (BLCoordinates *)track->GetUserInformation(); 00127 if(c && c->isValid()) { 00128 c->getCoords(coordType,position); 00129 momentum = c->getRotation() * momentum; 00130 B = c->getRotation() * B; 00131 E = c->getRotation() * E; 00132 } 00133 setVariable((G4String("x")+suffix).c_str(), position[0]/mm); 00134 setVariable((G4String("y")+suffix).c_str(), position[1]/mm); 00135 setVariable((G4String("z")+suffix).c_str(), position[2]/mm); 00136 setVariable((G4String("Px")+suffix).c_str(), momentum[0]/MeV); 00137 setVariable((G4String("Py")+suffix).c_str(), momentum[1]/MeV); 00138 setVariable((G4String("Pz")+suffix).c_str(), momentum[2]/MeV); 00139 setVariable((G4String("t")+suffix).c_str(), time/ns); 00140 setVariable((G4String("PDGid")+suffix).c_str(), track->GetDefinition()->GetPDGEncoding()); 00141 setVariable((G4String("EventID")+suffix).c_str(), evId); 00142 setVariable((G4String("TrackID")+suffix).c_str(), 00143 BLManager::getObject()-> 00144 getExternalTrackID(track)); 00145 setVariable((G4String("ParentID")+suffix).c_str(), 00146 BLManager::getObject()-> 00147 getExternalParentID(track)); 00148 setVariable((G4String("wt")+suffix).c_str(),track->GetWeight()); 00149 if(fields) { 00150 setVariable((G4String("Bx")+suffix).c_str(),B[0]/tesla); 00151 setVariable((G4String("By")+suffix).c_str(),B[1]/tesla); 00152 setVariable((G4String("Bz")+suffix).c_str(),B[2]/tesla); 00153 setVariable((G4String("Ex")+suffix).c_str(), 00154 E[0]/(megavolt/meter)); 00155 setVariable((G4String("Ey")+suffix).c_str(), 00156 E[1]/(megavolt/meter)); 00157 setVariable((G4String("Ez")+suffix).c_str(), 00158 E[2]/(megavolt/meter)); 00159 } 00160 }
bool BLEvaluator::isidchar | ( | char | c | ) | [inline] |
bool BLEvaluator::isopchar | ( | char | c | ) | [inline] |
isopchar() returns true if the character is an operator (no parens)
Referenced by evaluate().
00166 { return c=='+' || c=='-' || c=='*' || c=='/' || 00167 c=='^' || c=='<' || c=='>' || c=='!' || 00168 c=='|' || c=='&' || c=='=' || c=='%'; }
bool BLEvaluator::isumchar | ( | char | c | ) | [inline] |
isumchar() returns true if the char should be inside the parens generated to surround the unary minus (parens matched in evaluate())
References isidchar().
Referenced by evaluate().
00172 { return isidchar(c) || c=='.' || 00173 c=='^' || c=='(' || c==')'; }