#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
NOTE: This is expensive, and should not be used during tracking unless unavoidable.
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(), MaterialFilter::UserSteppingAction(), BLCMDtune::UserZSteppingAction(), BLCMDprofile::Entry::UserZSteppingAction(), and BLCMDprintf::UserZSteppingAction().
00045 { 00046 char out[1024]; 00047 BLAssert(strlen(expression) < sizeof(out)); 00048 // remove whitespace (simpler parsing below) 00049 int j=0; 00050 for(int i=0; expression[i]!='\0'; ++i) 00051 if(!isspace(expression[i])) out[j++] = expression[i]; 00052 out[j] = '\0'; 00053 // Workaround for serious bug in HepTool::Evaluator -- 00054 // it can only handle a unary +/- after a '(', so 00055 // put parens around unary +/- 00056 bool again=false; 00057 do { 00058 again = false; 00059 char *in = strdup(out); 00060 j = 0; 00061 char prev=' '; 00062 for(int i=0; in[i]!='\0'; ++i) { 00063 char c = in[i]; 00064 if((c == '-' || c == '+') && isopchar(prev)) { 00065 again = true; 00066 out[j++] = '('; 00067 out[j++] = c; 00068 ++i; 00069 int level = 0; 00070 while(isumchar(in[i]) || level > 0) { 00071 if(in[i] == '(') 00072 ++level; 00073 if(in[i] == ')') 00074 --level; 00075 // unary +/- after operator -- copy now, 00076 // handle during next loop (again = true) 00077 // (^ is the only op with higher precedence) 00078 if(in[i]=='^' && (in[i+1]=='-' || 00079 in[i+1]=='+')) 00080 out[j++] = in[i++]; 00081 out[j++] = in[i++]; 00082 } 00083 c = ')'; 00084 --i; 00085 } 00086 prev = out[j++] = c; 00087 } 00088 BLAssert((unsigned)j < sizeof(out)); 00089 out[j] = '\0'; 00090 // if empty or all whitespace, force invalid 00091 if(j == 0) strcpy(out,"x+-*/y"); 00092 free(in); 00093 } while(again); 00094 00095 double v = HepTool::Evaluator::evaluate(out); 00096 if(status() != OK) v = std::numeric_limits<double>::quiet_NaN(); 00097 return v; 00098 }
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(), MaterialFilter::UserSteppingAction(), BLCMDtune::UserZSteppingAction(), BLCMDprofile::Entry::UserZSteppingAction(), and BLCMDprintf::UserZSteppingAction().
00107 { 00108 G4RunManager* runmgr = G4RunManager::GetRunManager(); 00109 const G4Event* event = runmgr->GetCurrentEvent(); 00110 int evId = event->GetEventID(); 00111 G4ThreeVector position = track->GetPosition(); 00112 G4double time = track->GetGlobalTime(); 00113 G4ThreeVector momentum = track->GetMomentum(); 00114 00115 // get B and E fields 00116 G4ThreeVector B, E; 00117 if(fields) { 00118 G4double point[4], field[6]; 00119 point[0] = position[0]; 00120 point[1] = position[1]; 00121 point[2] = position[2]; 00122 point[3] = time; 00123 BLGlobalField::getObject()->GetFieldValue(point,field); 00124 B = G4ThreeVector(field[0],field[1],field[2]); 00125 E = G4ThreeVector(field[3],field[4],field[5]); 00126 } 00127 00128 // transform to desired coordinates, if available 00129 BLCoordinates *c = (BLCoordinates *)track->GetUserInformation(); 00130 if(c && c->isValid()) { 00131 c->getCoords(coordType,position); 00132 momentum = c->getRotation() * momentum; 00133 B = c->getRotation() * B; 00134 E = c->getRotation() * E; 00135 } 00136 setVariable((G4String("x")+suffix).c_str(), position[0]/mm); 00137 setVariable((G4String("y")+suffix).c_str(), position[1]/mm); 00138 setVariable((G4String("z")+suffix).c_str(), position[2]/mm); 00139 setVariable((G4String("Px")+suffix).c_str(), momentum[0]/MeV); 00140 setVariable((G4String("Py")+suffix).c_str(), momentum[1]/MeV); 00141 setVariable((G4String("Pz")+suffix).c_str(), momentum[2]/MeV); 00142 setVariable((G4String("t")+suffix).c_str(), time/ns); 00143 setVariable((G4String("PDGid")+suffix).c_str(), track->GetDefinition()->GetPDGEncoding()); 00144 setVariable((G4String("EventID")+suffix).c_str(), evId); 00145 setVariable((G4String("TrackID")+suffix).c_str(), 00146 BLManager::getObject()-> 00147 getExternalTrackID(track)); 00148 setVariable((G4String("ParentID")+suffix).c_str(), 00149 BLManager::getObject()-> 00150 getExternalParentID(track)); 00151 setVariable((G4String("wt")+suffix).c_str(),track->GetWeight()); 00152 if(fields) { 00153 setVariable((G4String("Bx")+suffix).c_str(),B[0]/tesla); 00154 setVariable((G4String("By")+suffix).c_str(),B[1]/tesla); 00155 setVariable((G4String("Bz")+suffix).c_str(),B[2]/tesla); 00156 setVariable((G4String("Ex")+suffix).c_str(), 00157 E[0]/(megavolt/meter)); 00158 setVariable((G4String("Ey")+suffix).c_str(), 00159 E[1]/(megavolt/meter)); 00160 setVariable((G4String("Ez")+suffix).c_str(), 00161 E[2]/(megavolt/meter)); 00162 } 00163 }
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().
00169 { return c=='+' || c=='-' || c=='*' || c=='/' || 00170 c=='^' || c=='<' || c=='>' || c=='!' || 00171 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().
00175 { return isidchar(c) || c=='.' || 00176 c=='^' || c=='(' || c==')'; }