Bug Summary

File:alld2/home/sdobbs/Software/jana/jana_0.8.2/Linux_CentOS7.7-x86_64-gcc4.8.5/include/JANA/JEventLoop.h
Warning:line 398, column 7
Null pointer passed to 2nd parameter expecting 'nonnull'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -main-file-name DAnalysisUtilities.cc -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /w/halld-scifs17exp/home/sdobbs/clang/llvm-project/install/lib/clang/12.0.0 -D HAVE_CCDB -D HAVE_RCDB -D HAVE_EVIO -D HAVE_TMVA=1 -D RCDB_MYSQL=1 -D RCDB_SQLITE=1 -D SQLITE_USE_LEGACY_STRUCT=ON -I .Linux_CentOS7.7-x86_64-gcc4.8.5/libraries/ANALYSIS -I libraries/ANALYSIS -I . -I libraries -I libraries/include -I /w/halld-scifs17exp/home/sdobbs/clang/halld_recon/Linux_CentOS7.7-x86_64-gcc4.8.5/include -I external/xstream/include -I /usr/include/tirpc -I /group/halld/Software/builds/Linux_CentOS7.7-x86_64-gcc4.8.5/root/root-6.08.06/include -I /w/halld-scifs17exp/halld2/home/sdobbs/Software/jana/jana_0.8.2/Linux_CentOS7.7-x86_64-gcc4.8.5/include -I /group/halld/Software/builds/Linux_CentOS7.7-x86_64-gcc4.8.5/ccdb/ccdb_1.06.06/include -I /group/halld/Software/builds/Linux_CentOS7.7-x86_64-gcc4.8.5/rcdb/rcdb_0.06.00/cpp/include -I /usr/include/mysql -I /group/halld/Software/builds/Linux_CentOS7.7-x86_64-gcc4.8.5/sqlitecpp/SQLiteCpp-2.2.0^bs130/include -I /group/halld/Software/builds/Linux_CentOS7.7-x86_64-gcc4.8.5/sqlite/sqlite-3.13.0^bs130/include -I /group/halld/Software/builds/Linux_CentOS7.7-x86_64-gcc4.8.5/hdds/hdds-4.9.0/Linux_CentOS7.7-x86_64-gcc4.8.5/src -I /group/halld/Software/builds/Linux_CentOS7.7-x86_64-gcc4.8.5/xerces-c/xerces-c-3.1.4/include -I /group/halld/Software/builds/Linux_CentOS7.7-x86_64-gcc4.8.5/evio/evio-4.4.6/Linux-x86_64/include -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../include/c++/4.8.5 -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../include/c++/4.8.5/x86_64-redhat-linux -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../include/c++/4.8.5/backward -internal-isystem /usr/local/include -internal-isystem /w/halld-scifs17exp/home/sdobbs/clang/llvm-project/install/lib/clang/12.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -std=c++11 -fdeprecated-macro -fdebug-compilation-dir /home/sdobbs/work/clang/halld_recon/src -ferror-limit 19 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -o /tmp/scan-build-2021-01-21-110224-160369-1 -x c++ libraries/ANALYSIS/DAnalysisUtilities.cc

libraries/ANALYSIS/DAnalysisUtilities.cc

1#ifdef VTRACE
2#include "vt_user.h"
3#endif
4
5#include "DAnalysisUtilities.h"
6#include "ANALYSIS/DParticleComboCreator.h"
7
8DAnalysisUtilities::DAnalysisUtilities(JEventLoop* locEventLoop)
9{
10 DEBUG_LEVEL=0;
11 gPARMS->SetDefaultParameter("DAnalysisUtilities:DEBUG_LEVEL",DEBUG_LEVEL);
12
13 locEventLoop->GetSingle(dPIDAlgorithm);
14
15 dTargetZCenter = 65.0;
16 // Get Target parameters from XML
17 DApplication *locApplication = dynamic_cast<DApplication*> (locEventLoop->GetJApplication());
18 DGeometry *locGeometry = locApplication ? locApplication->GetDGeometry(locEventLoop->GetJEvent().GetRunNumber()) : NULL__null;
19 locGeometry->GetTargetZ(dTargetZCenter);
20
21 //Get magnetic field map
22 dMagneticFieldMap = locApplication->GetBfield(locEventLoop->GetJEvent().GetRunNumber());
23 dIsNoFieldFlag = (dynamic_cast<const DMagneticFieldMapNoField*>(dMagneticFieldMap) != NULL__null);
24
25 //For "Unused" tracks/showers
26 //BEWARE: IF THIS IS CHANGED, CHANGE IN THE BLUEPRINT FACTORY AND THE EVENT WRITER ALSO!!
27 dTrackSelectionTag = "PreSelect";
28 dShowerSelectionTag = "PreSelect";
29 gPARMS->SetDefaultParameter("COMBO:TRACK_SELECT_TAG", dTrackSelectionTag);
30 gPARMS->SetDefaultParameter("COMBO:SHOWER_SELECT_TAG", dShowerSelectionTag);
31}
32
33bool DAnalysisUtilities::Check_IsBDTSignalEvent(JEventLoop* locEventLoop, const DReaction* locReaction, bool locExclusiveMatchFlag, bool locIncludeDecayingToReactionFlag) const
34{
35#ifdef VTRACE
36 VT_TRACER("DAnalysisUtilities::Check_IsBDTSignalEvent()");
37#endif
38
39 //IF DREACTION HAS A MISSING UNKNOWN PARTICLE, MUST USE locExclusiveMatchFlag = false
40
41 //if locIncludeDecayingToReactionFlag = true, will test whether the thrown reaction could decay to the DReaction
42 //Note that resonances, phi's, and omega's are automatically decayed
43 //e.g. if DReaction or thrown is g, p -> pi+, pi-, omega, p; will instead treat it as g, p -> 2pi+, 2pi-, pi0, p (or whatever the omega decay products are)
44 //e.g. g, p -> pi+, pi0, K0, Lambda can decay to g, p -> 2pi+, 2pi-, pi0, p
45 //if locIncludeDecayingToReactionFlag = true, then it would be included as "Signal," if false, then background
46 //locIncludeDecayingToReactionFlag should be true UNLESS you are explicitly checking all possible reactions that could decay to your channel in your BDT
47 //e.g. could kinfit to g, p -> pi+, pi0, K0, Lambda and include it as a BDT variable
48
49 if(dParticleComboCreator == nullptr) //Can't create in constructor: infinite recursion
50 dParticleComboCreator = new DParticleComboCreator(locEventLoop, nullptr, nullptr, nullptr);
51 DReaction_factory_Thrown* dThrownReactionFactory = static_cast<DReaction_factory_Thrown*>(locEventLoop->GetFactory("DReaction", "Thrown"));
52 if(!dThrownReactionFactory->brun_was_called())
53 {
54 dThrownReactionFactory->brun(locEventLoop, locEventLoop->GetJEvent().GetRunNumber());
55 dThrownReactionFactory->Set_brun_called();
56 }
57
58 vector<const DReaction*> locThrownReactions;
59 locEventLoop->Get(locThrownReactions, "Thrown");
60 if(locThrownReactions.empty())
61 return false;
62 auto locActualThrownReaction = locThrownReactions[0];
63
64 //Replace omega & phi in DReaction with their decay products
65 size_t locStepIndex = 0;
66 vector<DReactionStep> locNewReactionSteps;
67 const DReaction* locCurrentReaction = locReaction;
68 DReaction locNewReaction("Interim"); //if needed
69
70 do
71 {
72 const DReactionStep* locReactionStep = locCurrentReaction->Get_ReactionStep(locStepIndex);
73 Particle_t locInitialPID = locReactionStep->Get_InitialPID();
74 if((locInitialPID != omega) && (locInitialPID != phiMeson))
75 {
76 ++locStepIndex;
77 continue;
78 }
79
80 //is decaying phi or omega, replace it with its decay products
81 auto locDecayProducts = locReactionStep->Get_FinalPIDs();
82
83 //find the production step
84 for(size_t loc_i = 0; loc_i < locStepIndex; ++loc_i)
85 {
86 const DReactionStep* locProductionStep = locCurrentReaction->Get_ReactionStep(loc_i);
87 auto locPIDs = locProductionStep->Get_FinalPIDs();
88
89 //search for the decaying particle. when found, replace it with its decay products
90 bool locFoundFlag = false;
91 for(size_t loc_j = 0; loc_j < locPIDs.size(); ++loc_j)
92 {
93 Particle_t locFinalStatePID = locPIDs[loc_j];
94 if(locFinalStatePID != locInitialPID)
95 continue;
96 locPIDs.erase(locPIDs.begin() + loc_j);
97 locPIDs.insert(locPIDs.begin(), locDecayProducts.begin(), locDecayProducts.end());
98 locFoundFlag = true;
99 break;
100 }
101 if(!locFoundFlag)
102 continue;
103
104 //make a new reaction step
105 DReactionStep locNewReactionStep;
106 locNewReactionStep.Set_InitialParticleID(locProductionStep->Get_InitialPID());
107 locNewReactionStep.Set_TargetParticleID(locProductionStep->Get_TargetPID());
108 int locMissingParticleIndex = locProductionStep->Get_MissingParticleIndex();
109 for(int loc_j = 0; loc_j < int(locPIDs.size()); ++loc_j)
110 locNewReactionStep.Add_FinalParticleID(locPIDs[loc_j], (loc_j == locMissingParticleIndex));
111 locNewReactionSteps.push_back(locNewReactionStep);
112
113 //make a new reaction
114 DReaction locReactionBuild("Build");
115 locReactionBuild.Clear_ReactionSteps();
116 for(size_t loc_j = 0; loc_j < locCurrentReaction->Get_NumReactionSteps(); ++loc_j)
117 {
118 if(loc_j == loc_i)
119 locReactionBuild.Add_ReactionStep(&locNewReactionSteps.back());
120 else if(loc_j == locStepIndex)
121 continue;
122 else
123 locReactionBuild.Add_ReactionStep(locCurrentReaction->Get_ReactionStep(loc_j));
124 }
125 locNewReaction = locReactionBuild;
126 locCurrentReaction = &locNewReaction;
127 break;
128 }
129 }
130 while(locStepIndex < locCurrentReaction->Get_NumReactionSteps());
131
132 //Get thrown steps
133 deque<pair<const DMCThrown*, deque<const DMCThrown*> > > locThrownSteps;
134 Get_ThrownParticleSteps(locEventLoop, locThrownSteps);
135
136 if(locThrownSteps.size() == 1) //nothing to replace: it either works or it doesn't
137 return Check_ThrownsMatchReaction(locEventLoop, locCurrentReaction, locExclusiveMatchFlag);
138
139 //build maps of counts of the thrown & DReaction decaying particles
140 map<Particle_t, size_t> locNumDecayingParticles_Thrown;
141 for(size_t loc_i = 0; loc_i < locThrownSteps.size(); ++loc_i)
142 {
143 if(locThrownSteps[loc_i].first == NULL__null)
144 continue; //beam particle
145 Particle_t locPID = locThrownSteps[loc_i].first->PID();
146 if(locNumDecayingParticles_Thrown.find(locPID) == locNumDecayingParticles_Thrown.end())
147 locNumDecayingParticles_Thrown[locPID] = 1;
148 else
149 ++locNumDecayingParticles_Thrown[locPID];
150 }
151
152 map<Particle_t, size_t> locNumDecayingParticles_Reaction;
153 for(size_t loc_i = 0; loc_i < locCurrentReaction->Get_NumReactionSteps(); ++loc_i)
154 {
155 Particle_t locPID = locCurrentReaction->Get_ReactionStep(loc_i)->Get_InitialPID();
156 if(locPID == Gamma)
157 continue; //beam particle
158 if(locNumDecayingParticles_Reaction.find(locPID) == locNumDecayingParticles_Reaction.end())
159 locNumDecayingParticles_Reaction[locPID] = 1;
160 else
161 ++locNumDecayingParticles_Reaction[locPID];
162 }
163
164 //if there is a particle type in the DReaction that is not present in the thrown, it's gonna fail no matter what: check now
165 map<Particle_t, size_t>::iterator locIterator = locNumDecayingParticles_Reaction.begin();
166 for(; locIterator != locNumDecayingParticles_Reaction.end(); ++locIterator)
167 {
168 Particle_t locPID = locIterator->first;
169 if(locNumDecayingParticles_Thrown.find(locPID) == locNumDecayingParticles_Thrown.end())
170 return false;
171 }
172
173 //loop through thrown steps: replace phi's, omega's with their decay products
174 //also replace particles not in the DReaction with their decay products IF locIncludeDecayingToReactionFlag = true
175 locStepIndex = 1;
176 do
177 {
178 pair<const DMCThrown*, deque<const DMCThrown*> > locStepPair = locThrownSteps[locStepIndex];
179
180 //check to see if the thrown decaying particle is present in the dreaction
181 const DMCThrown* locThrownParent = locStepPair.first;
182 Particle_t locInitialPID = locThrownParent->PID();
183 bool locInitialPIDFoundFlag = (locNumDecayingParticles_Reaction.find(locInitialPID) != locNumDecayingParticles_Reaction.end());
184
185 //if it was not found, the only way it can be a match is if the decay products ARE in the reaction step: decay it in place
186 //also: omega and phi have non-negligible width: cannot constrain their peaks in kinfit or BDT: replace with their decay products
187 if(((!locInitialPIDFoundFlag) && locIncludeDecayingToReactionFlag) || (locInitialPID == omega) || (locInitialPID == phiMeson))
188 {
189 Replace_DecayingParticleWithProducts(locThrownSteps, locStepIndex);
190 if(locNumDecayingParticles_Thrown[locInitialPID] == 1)
191 locNumDecayingParticles_Thrown.erase(locInitialPID);
192 else
193 --locNumDecayingParticles_Thrown[locInitialPID];
194 }
195 else
196 ++locStepIndex;
197 }
198 while(locStepIndex < locThrownSteps.size());
199
200 if(!locIncludeDecayingToReactionFlag)
201 {
202 //don't try decaying thrown particles: compare as-is
203 DReaction* locThrownReaction = dThrownReactionFactory->Build_ThrownReaction(locEventLoop, locThrownSteps);
204 auto locThrownCombo = dParticleComboCreator->Build_ThrownCombo(locEventLoop, locThrownReaction, locThrownSteps);
205 bool locCheckResult = Check_ThrownsMatchReaction(locActualThrownReaction, locThrownCombo, locCurrentReaction, locExclusiveMatchFlag);
206
207 dParticleComboCreator->Reset();
208 dThrownReactionFactory->Recycle_Reaction(locThrownReaction);
209 return locCheckResult;
210 }
211
212 //at this point, #-steps are final. If exclusive, bail if they don't match
213 if(locExclusiveMatchFlag)
214 {
215 if(locReaction->Get_NumReactionSteps() != locThrownSteps.size())
216 return false;
217 }
218
219 //ok, if there are still an unequal # of parents for a given PID between thrown & DReaction (i.e. both #'s are non-zero):
220 //it's too confusing to figure out which should be replaced by their decay products and which shouldn't
221 //so, try all possibilities, and see if any of them match.
222
223 //build PIDs-to-replace vectors //easiest to manipulate a 1D vector
224 vector<Particle_t> locPIDVector;
225 vector<int> locResumeAtIndex;
226 for(locIterator = locNumDecayingParticles_Reaction.begin(); locIterator != locNumDecayingParticles_Reaction.end(); ++locIterator)
227 {
228 Particle_t locPID = locIterator->first;
229 size_t locNumThrown = locNumDecayingParticles_Thrown[locPID];
230 if(locNumThrown < locIterator->second)
231 return false; //thrown doesn't match
232 if(locNumThrown == locIterator->second)
233 continue; //all is well
234 for(size_t loc_i = 0; loc_i < locNumThrown - locIterator->second; ++loc_i)
235 {
236 locPIDVector.push_back(locPID);
237 locResumeAtIndex.push_back(0);
238 }
239 }
240
241 //if no additional replacements to make: check it
242 if(locPIDVector.empty())
243 {
244 DReaction* locThrownReaction = dThrownReactionFactory->Build_ThrownReaction(locEventLoop, locThrownSteps);
245 auto locThrownCombo = dParticleComboCreator->Build_ThrownCombo(locEventLoop, locThrownReaction, locThrownSteps);
246 bool locCheckResult = Check_ThrownsMatchReaction(locActualThrownReaction, locThrownCombo, locCurrentReaction, locExclusiveMatchFlag);
247
248 dParticleComboCreator->Reset();
249 dThrownReactionFactory->Recycle_Reaction(locThrownReaction);
250 return locCheckResult;
251 }
252
253 //loop through, making all combos of particles, (almost) just like in DParticleComboBlueprint_factory
254 //unlike that factory, the below may try a given combo twice: too hard to code against it though
255 //for a given PID, hard to compare current locResumeAtIndex to previous ones, since the thrown steps are continually replaced
256 deque<int> locDecayReplacementIndices;
257 int locParticleIndex = 0;
258 //below: contains "locThrownSteps" after each replacement
259 //1st deque index is replacement index,
260 deque<deque<pair<const DMCThrown*, deque<const DMCThrown*> > > > locReplacementThrownSteps(1, locThrownSteps);
261 do
262 {
263 if(locParticleIndex == -1)
264 break; //no success
265
266 deque<pair<const DMCThrown*, deque<const DMCThrown*> > > locCurrentThrownSteps = locReplacementThrownSteps.back();
267 if(locParticleIndex == int(locPIDVector.size()))
268 {
269 //combo defined: try it
270 DReaction* locThrownReaction = dThrownReactionFactory->Build_ThrownReaction(locEventLoop, locCurrentThrownSteps);
271 auto locThrownCombo = dParticleComboCreator->Build_ThrownCombo(locEventLoop, locThrownReaction, locCurrentThrownSteps);
272 bool locCheckResult = Check_ThrownsMatchReaction(locActualThrownReaction, locThrownCombo, locCurrentReaction, locExclusiveMatchFlag);
273
274 dParticleComboCreator->Reset();
275 dThrownReactionFactory->Recycle_Reaction(locThrownReaction);
276
277 if(locCheckResult)
278 return true; //it worked!
279 locReplacementThrownSteps.pop_back();
280 --locParticleIndex;
281 continue;
282 }
283
284 Particle_t locPID = locPIDVector[locParticleIndex];
285 //find the next instance of this step & replace it
286 bool locFoundFlag = false;
287 for(size_t loc_i = locResumeAtIndex[locParticleIndex]; loc_i < locCurrentThrownSteps.size(); ++loc_i)
288 {
289 if(locCurrentThrownSteps[loc_i].first == NULL__null)
290 continue;
291 Particle_t locInitialPID = locCurrentThrownSteps[loc_i].first->PID();
292 if(locInitialPID != locPID)
293 continue;
294 locFoundFlag = true;
295
296 Replace_DecayingParticleWithProducts(locCurrentThrownSteps, loc_i);
297 locReplacementThrownSteps.push_back(locCurrentThrownSteps);
298 locResumeAtIndex[locParticleIndex] = loc_i + 1;
299
300 break;
301 }
302
303 if(locFoundFlag)
304 ++locParticleIndex;
305 else
306 {
307 locResumeAtIndex[locParticleIndex] = 0;
308 locReplacementThrownSteps.pop_back();
309 --locParticleIndex;
310 }
311 }
312 while(true);
313
314 return false;
315}
316
317void DAnalysisUtilities::Replace_DecayingParticleWithProducts(deque<pair<const DMCThrown*, deque<const DMCThrown*> > >& locThrownSteps, size_t locStepIndex) const
318{
319 if(locStepIndex >= locThrownSteps.size())
320 return;
321
322 //find the step where this particle is produced at
323 int locInitialParticleDecayFromStepIndex = -1;
324 const DMCThrown* locThrownParent = locThrownSteps[locStepIndex].first;
325 if(locThrownParent == NULL__null)
326 return;
327
328 for(size_t loc_j = 0; loc_j < locStepIndex; ++loc_j)
329 {
330 for(size_t loc_k = 0; loc_k < locThrownSteps[loc_j].second.size(); ++loc_k)
331 {
332 if(locThrownParent != locThrownSteps[loc_j].second[loc_k])
333 continue;
334 locInitialParticleDecayFromStepIndex = loc_j;
335 break;
336 }
337 if(locInitialParticleDecayFromStepIndex != -1)
338 break;
339 }
340
341 if(locInitialParticleDecayFromStepIndex == -1)
342 {
343 cout << "ERROR: SOMETHING IS WRONG WITH DAnalysisUtilities::Replace_DecayingParticleWithProducts(). ABORTING." << endl;
344 abort();
345 }
346
347 //insert the decay products where the production occured
348 deque<const DMCThrown*>& locProductionStepFinalParticles = locThrownSteps[locInitialParticleDecayFromStepIndex].second;
349 deque<const DMCThrown*>& locDecayStepFinalParticles = locThrownSteps[locStepIndex].second;
350 for(size_t loc_j = 0; loc_j < locProductionStepFinalParticles.size(); ++loc_j)
351 {
352 if(locProductionStepFinalParticles[loc_j] != locThrownParent)
353 continue;
354 locProductionStepFinalParticles.erase(locProductionStepFinalParticles.begin() + loc_j);
355 locProductionStepFinalParticles.insert(locProductionStepFinalParticles.end(), locDecayStepFinalParticles.begin(), locDecayStepFinalParticles.end());
356 break;
357 }
358
359 locThrownSteps.erase(locThrownSteps.begin() + locStepIndex);
360}
361
362bool DAnalysisUtilities::Check_ThrownsMatchReaction(JEventLoop* locEventLoop, const DReaction* locReaction, bool locExclusiveMatchFlag) const
363{
364 //IF DREACTION HAS A MISSING UNKNOWN PARTICLE, MUST USE locExclusiveMatchFlag = false
365
366 //note, if you decay a final state particle (e.g. k+, pi+) in your input DReaction*, a match will NOT be found: the thrown reaction/combo is truncated
367 //if locExclusiveMatchFlag = false, then allow the input DReaction to be a subset of the thrown
368 if(dParticleComboCreator == nullptr) //Can't create in constructor: infinite recursion
369 dParticleComboCreator = new DParticleComboCreator(locEventLoop, nullptr, nullptr, nullptr);
370 auto locThrownCombo = dParticleComboCreator->Build_ThrownCombo(locEventLoop);
371
372 vector<const DReaction*> locReactions;
373 locEventLoop->Get(locReactions, "Thrown");
374 if(locReactions.empty())
375 return false;
376
377 auto locResult = Check_ThrownsMatchReaction(locReactions[0], locThrownCombo, locReaction, locExclusiveMatchFlag);
378 dParticleComboCreator->Reset();
379 return locResult;
380}
381
382bool DAnalysisUtilities::Check_ThrownsMatchReaction(const DReaction* locThrownReaction, const DParticleCombo* locThrownCombo, const DReaction* locReaction, bool locExclusiveMatchFlag) const
383{
384#ifdef VTRACE
385 VT_TRACER("DAnalysisUtilities::Check_ThrownsMatchReaction()");
386#endif
387
388 //IF DREACTION HAS A MISSING UNKNOWN PARTICLE, MUST USE locExclusiveMatchFlag = false
389
390 //note, if you decay a final state particle (e.g. k+, pi+) in your input DReaction*, a match will NOT be found: the thrown reaction/combo is truncated
391 //if locExclusiveMatchFlag = false, then allow the input DReaction to be a subset of the thrown
392
393 if(locThrownCombo == NULL__null)
394 return false;
395 if(locExclusiveMatchFlag)
396 {
397 if(locReaction->Get_NumReactionSteps() != locThrownCombo->Get_NumParticleComboSteps())
398 return false;
399 }
400
401 //build map of InitialParticleDecayFromStepIndex's for input reaction: assume that if it matters, the user wanted them in the input order
402 map<size_t, int> locReactionInitialParticleDecayFromStepIndexMap; //first is step index (of locReaction) where particle is initial, second is where is final state particle
403 for(size_t loc_i = 0; loc_i < locReaction->Get_NumReactionSteps(); ++loc_i)
404 {
405 const DReactionStep* locReactionStep = locReaction->Get_ReactionStep(loc_i);
406 if(loc_i == 0)
407 {
408 if(locReactionStep->Get_InitialPID() == Gamma)
409 locReactionInitialParticleDecayFromStepIndexMap[0] = -1;
410 }
411 //loop over final state particles, and if decaying, find the step they are a parent in
412 for(size_t loc_j = 0; loc_j < locReactionStep->Get_NumFinalPIDs(); ++loc_j)
413 {
414 Particle_t locFinalStatePID = locReactionStep->Get_FinalPID(loc_j);
415 //see if this pid is a parent in a future step
416 for(size_t loc_k = loc_i; loc_k < locReaction->Get_NumReactionSteps(); ++loc_k)
417 {
418 if(locReaction->Get_ReactionStep(loc_k)->Get_InitialPID() != locFinalStatePID)
419 continue;
420 if(locReactionInitialParticleDecayFromStepIndexMap.find(loc_k) != locReactionInitialParticleDecayFromStepIndexMap.end())
421 continue; //this step already accounted for
422 locReactionInitialParticleDecayFromStepIndexMap[loc_k] = loc_i;
423 break;
424 }
425 }
426 }
427
428 //since throwns are more organized, loop through those and back-check to dreaction
429 set<size_t> locMatchedInputStepIndices; //step indices in input locReaction that are already matched-to
430 map<int, int> locStepMatching; //locReaction map to thrown step map
431 map<int, int> locReverseStepMatching; //thrown map to locReaction step map
432 for(size_t loc_i = 0; loc_i < locThrownCombo->Get_NumParticleComboSteps(); ++loc_i)
433 {
434 int locInitialParticleDecayFromStepIndex = DAnalysis::Get_InitialParticleDecayFromIndices(locThrownReaction, loc_i).first;
435
436 //find where to start the search for this step in locReaction
437 size_t locStartSearchIndex = 0; //locReaction could be a subset of the total; start at the beginning unless ...:
438 if(locReverseStepMatching.find(locInitialParticleDecayFromStepIndex) != locReverseStepMatching.end())
439 locStartSearchIndex = locReverseStepMatching[locInitialParticleDecayFromStepIndex] + 1; //parent step was matched, start search for this one after it
440
441 //loop through locReaction and try to find this thrown step
442 bool locMatchFoundFlag = false;
443 int locPossibleMatchIndex = -1;
444 for(size_t loc_j = locStartSearchIndex; loc_j < locReaction->Get_NumReactionSteps(); ++loc_j)
445 {
446 const DReactionStep* locReactionStep = locReaction->Get_ReactionStep(loc_j);
447 if(locMatchedInputStepIndices.find(loc_j) != locMatchedInputStepIndices.end())
448 continue; //this step was already accounted for
449
450 //when not exact match: allow user step to have a missing unknown particle
451 if(!DAnalysis::Check_ChannelEquality(locThrownReaction->Get_ReactionStep(loc_i), locReactionStep, false, !locExclusiveMatchFlag))
452 continue; //particles aren't the same
453
454 //ok, now check to make sure that the parent particle in this step was produced the same way in both thrown & locReaction
455 if(locReactionInitialParticleDecayFromStepIndexMap.find(loc_j) == locReactionInitialParticleDecayFromStepIndexMap.end())
456 {
457 //this (loc_j) parent particle's production step wasn't listed in the locReaction: locReaction is probably a subset of the total
458 //a match is possible but not certain: (e.g. locReaction is pi0, eta -> pi0, pi0 and this step (loc_i) is a pi0)
459 locPossibleMatchIndex = loc_j;
460 continue; //keep searching in case a different one should be used instead //will use this if another isn't found
461 }
462
463 int locReactionInitialParticleDecayFromStepIndex = locReactionInitialParticleDecayFromStepIndexMap[loc_j];
464 if(locReactionInitialParticleDecayFromStepIndex != -1) //locReaction is not beam particle
465 {
466 if(locStepMatching.find(locReactionInitialParticleDecayFromStepIndex) == locStepMatching.end())
467 continue; //the step in locReaction where this (loc_j) parent particle was produced was not mapped to the thrown steps yet: this is not the step we want
468 int locReactionInitialParticleDecayFromStepIndexMappedBackToThrown = locStepMatching[locReactionInitialParticleDecayFromStepIndex];
469 if(locInitialParticleDecayFromStepIndex != locReactionInitialParticleDecayFromStepIndexMappedBackToThrown)
470 continue; //the decaying parent particle in this step (loc_j) comes from a different step in thrown (locInitialParticleDecayFromStepIndex)/reaction: continue
471 }
472 else if(locInitialParticleDecayFromStepIndex != -1)
473 continue; //reaction is beam but thrown is not beam
474
475 //finally, a match! register it
476 locMatchedInputStepIndices.insert(loc_j);
477 locStepMatching[loc_j] = loc_i;
478 locReverseStepMatching[loc_i] = loc_j;
479 locMatchFoundFlag = true;
480 break;
481 }
482
483 if((!locMatchFoundFlag) && (locPossibleMatchIndex != -1))
484 {
485 //need to use the possible match
486 locMatchedInputStepIndices.insert(locPossibleMatchIndex);
487 locStepMatching[locPossibleMatchIndex] = loc_i;
488 locReverseStepMatching[loc_i] = locPossibleMatchIndex;
489 locMatchFoundFlag = true;
490 }
491 if(locExclusiveMatchFlag && (!locMatchFoundFlag))
492 return false; //needed an exact match and it wasn't found: bail
493 }
494 if(locExclusiveMatchFlag)
495 return true;
496
497 //locReaction could be a subset of thrown: check if all locReaction steps found
498 for(size_t loc_i = 0; loc_i < locReaction->Get_NumReactionSteps(); ++loc_i)
499 {
500 if(locMatchedInputStepIndices.find(loc_i) == locMatchedInputStepIndices.end())
501 return false; //one of the input steps wasn't matched: abort!
502 }
503
504 return true;
505}
506
507void DAnalysisUtilities::Get_UnusedChargedTracks(JEventLoop* locEventLoop, const DParticleCombo* locParticleCombo, vector<const DChargedTrack*>& locUnusedChargedTracks) const
508{
509 locUnusedChargedTracks.clear();
510 locEventLoop->Get(locUnusedChargedTracks, "Combo");
511 std::sort(locUnusedChargedTracks.begin(), locUnusedChargedTracks.end());
512
513 auto locChargedSourceObjects = locParticleCombo->Get_FinalParticle_SourceObjects(d_Charged);
514 for(size_t loc_i = 0; loc_i < locChargedSourceObjects.size(); ++loc_i)
515 {
516 for(auto locIterator = locUnusedChargedTracks.begin(); locIterator != locUnusedChargedTracks.end();)
517 {
518 if(locChargedSourceObjects[loc_i] != *locIterator)
519 ++locIterator; //not-used (yet)
520 else
521 locIterator = locUnusedChargedTracks.erase(locIterator); //used
522 }
523 }
524}
525
526void DAnalysisUtilities::Get_UnusedTimeBasedTracks(JEventLoop* locEventLoop, const DParticleCombo* locParticleCombo, vector<const DTrackTimeBased*>& locUnusedTimeBasedTracks) const
527{
528 locUnusedTimeBasedTracks.clear();
529 locEventLoop->Get(locUnusedTimeBasedTracks);
530
531 vector<const DTrackTimeBased*> locComboTimeBasedTracks;
532 locEventLoop->Get(locComboTimeBasedTracks, "Combo");
533 locUnusedTimeBasedTracks.insert(locUnusedTimeBasedTracks.end(), locComboTimeBasedTracks.begin(), locComboTimeBasedTracks.end());
534
535 auto locChargedSourceObjects = locParticleCombo->Get_FinalParticle_SourceObjects(d_Charged);
536 for(size_t loc_i = 0; loc_i < locChargedSourceObjects.size(); ++loc_i)
537 {
538 //only need the candidate id: same for all hypotheses for a given track
539 auto locChargedTrack = static_cast<const DChargedTrack*>(locChargedSourceObjects[loc_i]);
540 for(auto locIterator = locUnusedTimeBasedTracks.begin(); locIterator != locUnusedTimeBasedTracks.end();)
541 {
542 if(locChargedTrack->candidateid != (*locIterator)->candidateid)
543 ++locIterator; //not-used (yet)
544 else
545 locIterator = locUnusedTimeBasedTracks.erase(locIterator); //used
546 }
547 }
548}
549
550void DAnalysisUtilities::Get_UnusedWireBasedTracks(JEventLoop* locEventLoop, const DParticleCombo* locParticleCombo, vector<const DTrackWireBased*>& locUnusedWireBasedTracks) const
551{
552 locUnusedWireBasedTracks.clear();
553 locEventLoop->Get(locUnusedWireBasedTracks);
554
555 auto locChargedSourceObjects = locParticleCombo->Get_FinalParticle_SourceObjects(d_Charged);
556 for(size_t loc_i = 0; loc_i < locChargedSourceObjects.size(); ++loc_i)
557 {
558 //only need the candidate id: same for all hypotheses for a given track
559 auto locChargedTrack = static_cast<const DChargedTrack*>(locChargedSourceObjects[loc_i]);
560 for(auto locIterator = locUnusedWireBasedTracks.begin(); locIterator != locUnusedWireBasedTracks.end();)
561 {
562 if(locChargedTrack->candidateid != (*locIterator)->candidateid)
563 ++locIterator; //not-used (yet)
564 else
565 locIterator = locUnusedWireBasedTracks.erase(locIterator); //used
566 }
567 }
568}
569
570void DAnalysisUtilities::Get_UnusedTrackCandidates(JEventLoop* locEventLoop, const DParticleCombo* locParticleCombo, vector<const DTrackCandidate*>& locUnusedTrackCandidates) const
571{
572 locUnusedTrackCandidates.clear();
573 locEventLoop->Get(locUnusedTrackCandidates);
1
Calling 'JEventLoop::Get'
574
575 auto locChargedSourceObjects = locParticleCombo->Get_FinalParticle_SourceObjects(d_Charged);
576 set<unsigned int> locUsedCandidateIndices;
577 for(size_t loc_i = 0; loc_i < locChargedSourceObjects.size(); ++loc_i)
578 {
579 //only need the candidate id: same for all hypotheses for a given track
580 auto locChargedTrack = static_cast<const DChargedTrack*>(locChargedSourceObjects[loc_i]);
581 locUsedCandidateIndices.insert(locChargedTrack->candidateid - 1); //id = index + 1
582 }
583
584 for(int loc_i = locUnusedTrackCandidates.size() - 1; loc_i >= 0; --loc_i)
585 {
586 if(locUsedCandidateIndices.find(loc_i) != locUsedCandidateIndices.end())
587 locUnusedTrackCandidates.erase(locUnusedTrackCandidates.begin() + loc_i);
588 }
589}
590
591void DAnalysisUtilities::Get_UnusedNeutralShowers(JEventLoop* locEventLoop, const DParticleCombo* locParticleCombo, vector<const DNeutralShower*>& locUnusedNeutralShowers) const
592{
593 locUnusedNeutralShowers.clear();
594 locEventLoop->Get(locUnusedNeutralShowers, dShowerSelectionTag.c_str());
595
596 auto locNeutralSourceObjects = locParticleCombo->Get_FinalParticle_SourceObjects(d_Neutral);
597 for(size_t loc_i = 0; loc_i < locNeutralSourceObjects.size(); ++loc_i)
598 {
599 auto locNeutralShower = static_cast<const DNeutralShower*>(locNeutralSourceObjects[loc_i]);
600 for(auto locIterator = locUnusedNeutralShowers.begin(); locIterator != locUnusedNeutralShowers.end();)
601 {
602 if(locNeutralShower != *locIterator)
603 ++locIterator;
604 else
605 locIterator = locUnusedNeutralShowers.erase(locIterator);
606 }
607 }
608}
609
610void DAnalysisUtilities::Get_UnusedNeutralParticles(JEventLoop* locEventLoop, const DParticleCombo* locParticleCombo, vector<const DNeutralParticle*>& locUnusedNeutralParticles) const
611{
612 locUnusedNeutralParticles.clear();
613 locEventLoop->Get(locUnusedNeutralParticles, dShowerSelectionTag.c_str());
614
615 auto locNeutralSourceObjects = locParticleCombo->Get_FinalParticle_SourceObjects(d_Neutral);
616 for(size_t loc_i = 0; loc_i < locNeutralSourceObjects.size(); ++loc_i)
617 {
618 auto locNeutralShower = static_cast<const DNeutralShower*>(locNeutralSourceObjects[loc_i]);
619 for(auto locIterator = locUnusedNeutralParticles.begin(); locIterator != locUnusedNeutralParticles.end();)
620 {
621 if(locNeutralShower != (*locIterator)->dNeutralShower)
622 ++locIterator;
623 else
624 locIterator = locUnusedNeutralParticles.erase(locIterator);
625 }
626 }
627}
628
629void DAnalysisUtilities::Get_ThrownParticleSteps(JEventLoop* locEventLoop, deque<pair<const DMCThrown*, deque<const DMCThrown*> > >& locThrownSteps) const
630{
631 vector<const DMCThrown*> locMCThrowns;
632 locEventLoop->Get(locMCThrowns);
633
634 map<size_t, const DMCThrown*> locIDMap; //size_t is the myid
635 for(size_t loc_i = 0; loc_i < locMCThrowns.size(); ++loc_i)
636 locIDMap[locMCThrowns[loc_i]->myid] = locMCThrowns[loc_i];
637
638 locThrownSteps.clear();
639 if(locMCThrowns.empty())
640 return;
641 locThrownSteps.push_back(pair<const DMCThrown*, deque<const DMCThrown*> >(NULL__null, deque<const DMCThrown*>() ) );
642
643 for(size_t loc_i = 0; loc_i < locMCThrowns.size(); ++loc_i)
644 {
645 if(IsResonance(locMCThrowns[loc_i]->PID()))
646 continue; //don't include resonances in DReaction!!
647
648 if(locMCThrowns[loc_i]->PID() == Unknown)
649 continue; //could be some weird pythia "resonance" like a diquark: just ignore them all
650
651 //initial checks of parent id
652 int locParentID = locMCThrowns[loc_i]->parentid;
653 if(locParentID == 0) //photoproduced
654 {
655 locThrownSteps[0].second.push_back(locMCThrowns[loc_i]);
656 continue;
657 }
658 if(locIDMap.find(locParentID) == locIDMap.end()) //produced from a particle that was not saved: spurious, don't save (e.g. product of BCAL shower)
659 continue;
660
661 //initial checks of parent pid
662 Particle_t locParentPID = locIDMap[locParentID]->PID();
663 bool locDoneFlag = false;
664 while(((locParentPID == Unknown) || IsResonance(locParentPID)) && (!locDoneFlag))
665 {
666 //intermediate particle, continue towards the source
667 locParentID = locIDMap[locParentID]->parentid; //parent's parent
668 if(locParentID == 0) //photoproduced
669 {
670 locThrownSteps[0].second.push_back(locMCThrowns[loc_i]);
671 locDoneFlag = true;
672 }
673 else if(locIDMap.find(locParentID) == locIDMap.end()) //produced from a particle that was not saved: spurious, don't save (e.g. product of BCAL shower)
674 locDoneFlag = true;
675 else
676 locParentPID = locIDMap[locParentID]->PID();
677 }
678
679 if(Is_FinalStateParticle(locParentPID) == 1)
680 continue; //e.g. parent is a final state particle (e.g. this is a neutrino from a pion decay)
681
682 //check to see if the parent is already listed as a decaying particle //if so, add it to that step
683 bool locListedAsDecayingFlag = false;
684 for(size_t loc_j = 1; loc_j < locThrownSteps.size(); ++loc_j)
685 {
686 if(locThrownSteps[loc_j].first->myid != locParentID)
687 continue;
688 locThrownSteps[loc_j].second.push_back(locMCThrowns[loc_i]);
689 locListedAsDecayingFlag = true;
690 break;
691 }
692 if(locListedAsDecayingFlag)
693 continue;
694
695 //would add a new decay step, but first make sure that its parent is a decay product of a previous step
696 //if the parent was not saved as a product, it may have been a decay product of a final state particle: don't save
697 const DMCThrown* locThrownParent = locIDMap[locParentID];
698 bool locFoundFlag = false;
699 for(size_t loc_j = 0; loc_j < locThrownSteps.size(); ++loc_j)
700 {
701 for(size_t loc_k = 0; loc_k < locThrownSteps[loc_j].second.size(); ++loc_k)
702 {
703 if(locThrownSteps[loc_j].second[loc_k] != locThrownParent)
704 continue;
705 locFoundFlag = true;
706 break;
707 }
708 if(locFoundFlag)
709 break;
710 }
711 if(!locFoundFlag)
712 continue;
713
714 //else add a new decay step and add this particle to it
715 locThrownSteps.push_back(pair<const DMCThrown*, deque<const DMCThrown*> >(locThrownParent, deque<const DMCThrown*>(1, locMCThrowns[loc_i]) ));
716 }
717
718/*
719cout << "THROWN STEPS: " << endl;
720for(size_t loc_i = 0; loc_i < locThrownSteps.size(); ++loc_i)
721{
722 cout << ((loc_i == 0) ? 0 : locThrownSteps[loc_i].first->myid) << ": ";
723 for(size_t loc_j = 0; loc_j < locThrownSteps[loc_i].second.size(); ++loc_j)
724 cout << locThrownSteps[loc_i].second[loc_j]->myid << ", ";
725 cout << endl;
726}
727*/
728}
729
730bool DAnalysisUtilities::Are_ThrownPIDsSameAsDesired(JEventLoop* locEventLoop, const deque<Particle_t>& locDesiredPIDs, Particle_t locMissingPID) const
731{
732 vector<const DMCThrown*> locMCThrowns;
733 locEventLoop->Get(locMCThrowns, "FinalState");
734 deque<Particle_t> locDesiredPIDs_Copy = locDesiredPIDs;
735
736 bool locMissingPIDMatchedFlag = false;
737 for(size_t loc_i = 0; loc_i < locMCThrowns.size(); ++loc_i)
738 {
739 Particle_t locPID = (Particle_t)(locMCThrowns[loc_i]->type);
740
741 if((!locMissingPIDMatchedFlag) && (locMissingPID == locPID))
742 {
743 //matched missing
744 locMissingPIDMatchedFlag = true;
745 continue;
746 }
747
748 bool locPIDFoundFlag = false;
749 for(deque<Particle_t>::iterator locIterator = locDesiredPIDs_Copy.begin(); locIterator != locDesiredPIDs_Copy.end(); ++locIterator)
750 {
751 if(*locIterator != locPID)
752 continue;
753 locDesiredPIDs_Copy.erase(locIterator);
754 locPIDFoundFlag = true;
755 break;
756 }
757 if(!locPIDFoundFlag)
758 return false;
759 }
760
761 return (locDesiredPIDs_Copy.empty());
762}
763
764DLorentzVector DAnalysisUtilities::Calc_MissingP4(const DReaction* locReaction, const DParticleCombo* locParticleCombo, bool locUseKinFitDataFlag) const
765{
766 set<pair<const JObject*, unsigned int> > locSourceObjects;
767 return Calc_MissingP4(locReaction, locParticleCombo, 0, -1, set<size_t>(), locSourceObjects, locUseKinFitDataFlag);
768}
769
770DLorentzVector DAnalysisUtilities::Calc_MissingP4(const DReaction* locReaction, const DParticleCombo* locParticleCombo, set<pair<const JObject*, unsigned int> >& locSourceObjects, bool locUseKinFitDataFlag) const
771{
772 return Calc_MissingP4(locReaction, locParticleCombo, 0, -1, set<size_t>(), locSourceObjects, locUseKinFitDataFlag);
773}
774
775DLorentzVector DAnalysisUtilities::Calc_MissingP4(const DReaction* locReaction, const DParticleCombo* locParticleCombo, size_t locStepIndex, int locUpToStepIndex, set<size_t> locUpThroughIndices, bool locUseKinFitDataFlag) const
776{
777 set<pair<const JObject*, unsigned int> > locSourceObjects;
778 return Calc_MissingP4(locReaction, locParticleCombo, locStepIndex, locUpToStepIndex, locUpThroughIndices, locSourceObjects, locUseKinFitDataFlag);
779}
780
781DLorentzVector DAnalysisUtilities::Calc_MissingP4(const DReaction* locReaction, const DParticleCombo* locParticleCombo, size_t locStepIndex, int locUpToStepIndex, set<size_t> locUpThroughIndices, set<pair<const JObject*, unsigned int> >& locSourceObjects, bool locUseKinFitDataFlag) const
782{
783 //NOTE: this routine assumes that the p4 of a charged decaying particle with a detached vertex is the same at both vertices!
784 //assumes missing particle is not the beam particle
785 if(locUseKinFitDataFlag && (locParticleCombo->Get_KinFitResults() == NULL__null))
786 return Calc_MissingP4(locReaction, locParticleCombo, locStepIndex, locUpToStepIndex, locUpThroughIndices, locSourceObjects, false); //kinematic fit failed
787
788 DLorentzVector locMissingP4;
789 const DParticleComboStep* locParticleComboStep = locParticleCombo->Get_ParticleComboStep(locStepIndex);
790 auto locReactionStep = locReaction->Get_ReactionStep(locStepIndex);
791
792 const DKinematicData* locKinematicData = NULL__null;
793 if(locStepIndex == 0)
794 {
795 //initial particle
796 locKinematicData = locParticleComboStep->Get_InitialParticle_Measured();
797 locSourceObjects.insert(pair<const JObject*, unsigned int>(locKinematicData, abs(PDGtype(locKinematicData->PID())))); //want to use source objects for comparing
798 if(locUseKinFitDataFlag) //kinfit
799 locKinematicData = locParticleComboStep->Get_InitialParticle();
800 locMissingP4 += locKinematicData->lorentzMomentum();
801 }
802
803 //target particle
804 Particle_t locPID = locReactionStep->Get_TargetPID();
805 if(locPID != Unknown)
806 {
807 double locMass = ParticleMass(locPID);
808 locMissingP4 += DLorentzVector(DVector3(0.0, 0.0, 0.0), locMass);
809 }
810
811 auto locParticles = locUseKinFitDataFlag ? locParticleComboStep->Get_FinalParticles() : locParticleComboStep->Get_FinalParticles_Measured();
812 for(size_t loc_j = 0; loc_j < locParticles.size(); ++loc_j)
813 {
814 if(int(loc_j) == locReactionStep->Get_MissingParticleIndex())
815 continue; //exclude missing particle
816 if((int(locStepIndex) == locUpToStepIndex) && (locUpThroughIndices.find(loc_j) == locUpThroughIndices.end()))
817 continue; //skip it: don't want to include it
818
819 int locDecayStepIndex = DAnalysis::Get_DecayStepIndex(locReaction, locStepIndex, loc_j);
820 if(locDecayStepIndex > 0) //decaying-particle
821 {
822 //why plus? because the minus-signs are already applied during the call below
823 locMissingP4 += Calc_MissingP4(locReaction, locParticleCombo, locDecayStepIndex, locUpToStepIndex, locUpThroughIndices, locSourceObjects, locUseKinFitDataFlag); //p4 returned is already < 0
824 }
825 else //detected
826 {
827 Particle_t locPID = locReactionStep->Get_FinalPID(loc_j);
828 auto locDetectedP4 = locParticles[loc_j]->lorentzMomentum();
829 locMissingP4 -= locDetectedP4;
830 locSourceObjects.insert(pair<const JObject*, unsigned int>(locParticleComboStep->Get_FinalParticle_SourceObject(loc_j), abs(PDGtype(locPID))));
831 }
832 }
833
834 return locMissingP4;
835}
836
837TMatrixFSym DAnalysisUtilities::Calc_MissingP3Covariance(const DReaction* locReaction, const DParticleCombo* locParticleCombo) const
838{
839 //uses measured data!
840 return Calc_MissingP3Covariance(locReaction, locParticleCombo, 0, -1, set<size_t>());
841}
842
843TMatrixFSym DAnalysisUtilities::Calc_MissingP3Covariance(const DReaction* locReaction, const DParticleCombo* locParticleCombo, size_t locStepIndex, int locUpToStepIndex, set<size_t> locUpThroughIndices) const
844{
845 //uses measured data!
846
847 //NOTE: this routine assumes that the p4 of a charged decaying particle with a detached vertex is the same at both vertices!
848 //assumes missing particle is not the beam particle
849
850 //missing covariance is just sum of covariance matrices of all particles used in the calculation
851 //because errors are uncorrelated: this doesn't work on kinfit data: just use kinfit matrix from missing particle then
852 const DParticleComboStep* locParticleComboStep = locParticleCombo->Get_ParticleComboStep(locStepIndex);
853 auto locReactionStep = locReaction->Get_ReactionStep(locStepIndex);
854 TMatrixFSym locMissingCovarianceMatrix(3);
855 locMissingCovarianceMatrix.Zero();
856
857 const DKinematicData* locKinematicData = NULL__null;
858 if(locStepIndex == 0)
859 {
860 //initial particle
861 locKinematicData = locParticleComboStep->Get_InitialParticle_Measured();
862 TMatrixFSym locParticleCovarianceMatrix = *(locKinematicData->errorMatrix().get());
863 locParticleCovarianceMatrix.ResizeTo(3, 3);
864 locMissingCovarianceMatrix += locParticleCovarianceMatrix;
865 }
866
867 auto locParticles = locParticleComboStep->Get_FinalParticles_Measured();
868 for(size_t loc_j = 0; loc_j < locParticles.size(); ++loc_j)
869 {
870 if(int(loc_j) == locReactionStep->Get_MissingParticleIndex())
871 continue; //exclude missing particle
872 if((int(locStepIndex) == locUpToStepIndex) && (locUpThroughIndices.find(loc_j) == locUpThroughIndices.end()))
873 continue; //skip it: don't want to include it
874
875 int locDecayStepIndex = DAnalysis::Get_DecayStepIndex(locReaction, locStepIndex, loc_j);
876 if(locDecayStepIndex > 0) //decaying-particle
877 locMissingCovarianceMatrix += Calc_MissingP3Covariance(locReaction, locParticleCombo, locDecayStepIndex, locUpToStepIndex, locUpThroughIndices);
878 else //detected
879 {
880 TMatrixFSym locParticleCovarianceMatrix = *(locParticles[loc_j]->errorMatrix().get());
881 locParticleCovarianceMatrix.ResizeTo(3, 3);
882 locMissingCovarianceMatrix += locParticleCovarianceMatrix;
883 }
884 }
885
886 return locMissingCovarianceMatrix;
887}
888
889DLorentzVector DAnalysisUtilities::Calc_FinalStateP4(const DReaction* locReaction, const DParticleCombo* locParticleCombo, size_t locStepIndex, bool locUseKinFitDataFlag) const
890{
891 set<pair<const JObject*, unsigned int> > locSourceObjects;
892 return Calc_FinalStateP4(locReaction, locParticleCombo, locStepIndex, set<size_t>(), locSourceObjects, locUseKinFitDataFlag);
893}
894
895DLorentzVector DAnalysisUtilities::Calc_FinalStateP4(const DReaction* locReaction, const DParticleCombo* locParticleCombo, size_t locStepIndex, set<pair<const JObject*, unsigned int> >& locSourceObjects, bool locUseKinFitDataFlag) const
896{
897 return Calc_FinalStateP4(locReaction, locParticleCombo, locStepIndex, set<size_t>(), locSourceObjects, locUseKinFitDataFlag);
898}
899
900DLorentzVector DAnalysisUtilities::Calc_FinalStateP4(const DReaction* locReaction, const DParticleCombo* locParticleCombo, size_t locStepIndex, set<size_t> locToIncludeIndices, bool locUseKinFitDataFlag) const
901{
902 set<pair<const JObject*, unsigned int> > locSourceObjects;
903 return Calc_FinalStateP4(locReaction, locParticleCombo, locStepIndex, locToIncludeIndices, locSourceObjects, locUseKinFitDataFlag);
904}
905
906DLorentzVector DAnalysisUtilities::Calc_FinalStateP4(const DReaction* locReaction, const DParticleCombo* locParticleCombo, size_t locStepIndex, set<size_t> locToIncludeIndices, set<pair<const JObject*, unsigned int> >& locSourceObjects, bool locUseKinFitDataFlag) const
907{
908 if(locUseKinFitDataFlag && (locParticleCombo->Get_KinFitResults() == NULL__null))
909 return Calc_FinalStateP4(locReaction, locParticleCombo, locStepIndex, locToIncludeIndices, locSourceObjects, false); //kinematic fit failed
910
911 DLorentzVector locFinalStateP4;
912 const DParticleComboStep* locParticleComboStep = locParticleCombo->Get_ParticleComboStep(locStepIndex);
913 if(locParticleComboStep == NULL__null)
914 return (DLorentzVector());
915 auto locReactionStep = locReaction->Get_ReactionStep(locStepIndex);
916
917 auto locParticles = locUseKinFitDataFlag ? locParticleComboStep->Get_FinalParticles() : locParticleComboStep->Get_FinalParticles_Measured();
918
919 //subtract rescattering target if any!!
920 if(locStepIndex != 0)
921 {
922 Particle_t locPID = locReactionStep->Get_TargetPID();
923 if(locPID != Unknown)
924 locFinalStateP4 -= DLorentzVector(DVector3(0.0, 0.0, 0.0), ParticleMass(locPID));
925 }
926
927 bool locDoSubsetFlag = !locToIncludeIndices.empty();
928 for(size_t loc_i = 0; loc_i < locParticles.size(); ++loc_i)
929 {
930 if(locDoSubsetFlag && (locToIncludeIndices.find(loc_i) == locToIncludeIndices.end()))
931 continue; //skip it: don't want to include it
932
933 if(locReactionStep->Get_MissingParticleIndex() == int(loc_i))
934 return (DLorentzVector()); //bad!
935
936 int locDecayStepIndex = DAnalysis::Get_DecayStepIndex(locReaction, locStepIndex, loc_i);
937 if(locDecayStepIndex >= 0) //decaying particle
938 {
939 //measured results, or not constrained by kinfit (either non-fixed mass or excluded from kinfit)
940 if((!locUseKinFitDataFlag) || (!IsFixedMass(locReactionStep->Get_FinalPID(loc_i))))
941 locFinalStateP4 += Calc_FinalStateP4(locReaction, locParticleCombo, locDecayStepIndex, set<size_t>(), locSourceObjects, locUseKinFitDataFlag);
942 else //want kinfit results, and decaying particle p4 is constrained by kinfit
943 {
944 locFinalStateP4 += locParticles[loc_i]->lorentzMomentum();
945 //still need source objects of decay products! dive down anyway, but ignore p4 result
946 Calc_FinalStateP4(locReaction, locParticleCombo, locDecayStepIndex, set<size_t>(), locSourceObjects, locUseKinFitDataFlag);
947 }
948 }
949 else //detected particle
950 {
951 locFinalStateP4 += locParticles[loc_i]->lorentzMomentum();
952 locSourceObjects.insert(pair<const JObject*, unsigned int>(locParticleComboStep->Get_FinalParticle_SourceObject(loc_i), abs(PDGtype(locParticles[loc_i]->PID()))));
953 }
954 }
955 return locFinalStateP4;
956}
957
958int DAnalysisUtilities::Calc_Energy_UnusedShowers(JEventLoop* locEventLoop, const DParticleCombo* locParticleCombo, double &locEnergy_UnusedShowers, int &locNumber_UnusedShowers_Quality, double &locEnergy_UnusedShowers_Quality) const
959{
960 DVector3 locVertex(0.0, 0.0, dTargetZCenter);
961 const DEventRFBunch* locEventRFBunch = locParticleCombo->Get_EventRFBunch();
962 double locRFTime = (locEventRFBunch != NULL__null) ? locEventRFBunch->dTime : numeric_limits<double>::quiet_NaN();
963
964 vector<const DNeutralShower*> locUnusedNeutralShowers;
965 Get_UnusedNeutralShowers(locEventLoop, locParticleCombo, locUnusedNeutralShowers);
966
967 int locNumber_UnusedShowers = 0;
968 locEnergy_UnusedShowers = 0.;
969 locEnergy_UnusedShowers_Quality = 0.;
970 locNumber_UnusedShowers_Quality = 0;
971 for(size_t loc_i = 0; loc_i < locUnusedNeutralShowers.size(); ++loc_i) {
972 const DNeutralShower* locUnusedNeutralShower = locUnusedNeutralShowers[loc_i];
973
974 // requirements on unused showers
975 double locFlightTime = (locUnusedNeutralShower->dSpacetimeVertex.Vect() - locVertex).Mag()/SPEED_OF_LIGHT29.9792458;
976 double locDeltaT = locUnusedNeutralShower->dSpacetimeVertex.T() - locFlightTime - locRFTime;
977 // next line commented out to suppress warnings
978 // double locDetectorTheta = (locUnusedNeutralShower->dSpacetimeVertex.Vect()-locVertex).Theta()*180./TMath::Pi();
979 if(fabs(locDeltaT) > 4.)
980 continue;
981
982 locEnergy_UnusedShowers += locUnusedNeutralShower->dEnergy;
983 locNumber_UnusedShowers++;
984
985 if(locUnusedNeutralShower->dQuality > 0.5) {
986 locEnergy_UnusedShowers_Quality += locUnusedNeutralShower->dEnergy;
987 locNumber_UnusedShowers_Quality++;
988 }
989 }
990
991 return locNumber_UnusedShowers;
992}
993
994int DAnalysisUtilities::Calc_Momentum_UnusedTracks(JEventLoop* locEventLoop, const DParticleCombo* locParticleCombo, double &locSumPMag_UnusedTracks, TVector3 &locSumP3_UnusedTracks) const
995{
996 vector<const DChargedTrack*> locUnusedChargedTracks;
997 Get_UnusedChargedTracks(locEventLoop, locParticleCombo, locUnusedChargedTracks);
998
999 for(size_t loc_i = 0; loc_i < locUnusedChargedTracks.size(); ++loc_i) {
1000 const DChargedTrack* locUnusedChargedTrack = locUnusedChargedTracks[loc_i];
1001 const DChargedTrackHypothesis *locUnusedChargedTrackHypothesis = locUnusedChargedTrack->Get_BestTrackingFOM();
1002
1003 locSumPMag_UnusedTracks += locUnusedChargedTrackHypothesis->pmag();
1004 locSumP3_UnusedTracks += locUnusedChargedTrackHypothesis->momentum();
1005 }
1006
1007 return (int)locUnusedChargedTracks.size();
1008}
1009
1010double DAnalysisUtilities::Calc_DOCAToVertex(const DKinematicData* locKinematicData, const DVector3& locVertex) const
1011{
1012 DVector3 locPOCA;
1013 return Calc_DOCAToVertex(locKinematicData, locVertex, locPOCA);
1014}
1015
1016double DAnalysisUtilities::Calc_DOCAToVertex(const DKinematicData* locKinematicData, const DVector3& locVertex, DVector3& locPOCA) const
1017{
1018 DVector3 locUnitDir = (1.0/locKinematicData->momentum().Mag())*locKinematicData->momentum();
1019 DVector3 locPosition = locKinematicData->position();
1020 return Calc_DOCAToVertex(locUnitDir, locPosition, locVertex, locPOCA);
1021}
1022
1023double DAnalysisUtilities::Calc_DOCAToVertex(const DKinFitParticle* locKinFitParticle, const DVector3& locVertex) const
1024{
1025 DVector3 locPOCA;
1026 return Calc_DOCAToVertex(locKinFitParticle, locVertex, locPOCA);
1027}
1028
1029double DAnalysisUtilities::Calc_DOCAToVertex(const DKinFitParticle* locKinFitParticle, const DVector3& locVertex, DVector3& locPOCA) const
1030{
1031 DVector3 locUnitDir(locKinFitParticle->Get_Momentum().Unit().X(),locKinFitParticle->Get_Momentum().Unit().Y(),locKinFitParticle->Get_Momentum().Unit().Z());
1032 DVector3 locPosition(locKinFitParticle->Get_Position().X(),locKinFitParticle->Get_Position().Y(),locKinFitParticle->Get_Position().Z());
1033 return Calc_DOCAToVertex(locUnitDir, locPosition, locVertex, locPOCA);
1034}
1035
1036double DAnalysisUtilities::Calc_DOCAToVertex(const DVector3& locUnitDir, const DVector3& locPosition, const DVector3& locVertex) const
1037{
1038 DVector3 locPOCA1, locPOCA2;
1039 return Calc_DOCA(locUnitDir, locUnitDir, locPosition, locVertex, locPOCA1, locPOCA2);
1040}
1041
1042double DAnalysisUtilities::Calc_DOCAToVertex(const DVector3& locUnitDir, const DVector3& locPosition, const DVector3& locVertex, DVector3& locPOCA) const
1043{
1044 DVector3 locPOCA2;
1045 return Calc_DOCA(locUnitDir, locUnitDir, locPosition, locVertex, locPOCA, locPOCA2);
1046}
1047
1048double DAnalysisUtilities::Calc_DOCAVertex(const DKinFitParticle* locKinFitParticle1, const DKinFitParticle* locKinFitParticle2, DVector3& locDOCAVertex) const
1049{
1050 DVector3 locPOCA1, locPOCA2;
1051 double locDOCA;
1052 // Try to use helical approximation if B!=0
1053 if (dIsNoFieldFlag==false && Calc_DOCA(locKinFitParticle1,locKinFitParticle2,
1054 locPOCA1,locPOCA2,locDOCA)==NOERROR){
1055 locDOCAVertex=0.5*(locPOCA1+locPOCA2);
1056 return locDOCA;
1057 }
1058
1059 // Use straight line approximation
1060 DVector3 locUnitDir1(locKinFitParticle1->Get_Momentum().Unit().X(),locKinFitParticle1->Get_Momentum().Unit().Y(),locKinFitParticle1->Get_Momentum().Unit().Z());
1061 DVector3 locUnitDir2(locKinFitParticle2->Get_Momentum().Unit().X(),locKinFitParticle2->Get_Momentum().Unit().Y(),locKinFitParticle2->Get_Momentum().Unit().Z());
1062 DVector3 locVertex1(locKinFitParticle1->Get_Position().X(),locKinFitParticle1->Get_Position().Y(),locKinFitParticle1->Get_Position().Z());
1063 DVector3 locVertex2(locKinFitParticle2->Get_Position().X(),locKinFitParticle2->Get_Position().Y(),locKinFitParticle2->Get_Position().Z());
1064 return Calc_DOCAVertex(locUnitDir1, locUnitDir2, locVertex1, locVertex2, locDOCAVertex);
1065}
1066
1067double DAnalysisUtilities::Calc_DOCAVertex(const DKinematicData* locKinematicData1, const DKinematicData* locKinematicData2, DVector3& locDOCAVertex) const
1068{
1069 DVector3 locPOCA1, locPOCA2;
1070 double locDOCA;
1071 // Try to use helical approximation if B!=0
1072 if (dIsNoFieldFlag==false && Calc_DOCA(locKinematicData1,locKinematicData2,
1073 locPOCA1,locPOCA2,locDOCA)==NOERROR){
1074 locDOCAVertex=0.5*(locPOCA1+locPOCA2);
1075 return locDOCA;
1076 }
1077
1078 // Use straight line approximation
1079 DVector3 locUnitDir1 = (1.0/locKinematicData1->momentum().Mag())*locKinematicData1->momentum();
1080 DVector3 locUnitDir2 = (1.0/locKinematicData2->momentum().Mag())*locKinematicData2->momentum();
1081 DVector3 locVertex1 = locKinematicData1->position();
1082 DVector3 locVertex2 = locKinematicData2->position();
1083 return Calc_DOCAVertex(locUnitDir1, locUnitDir2, locVertex1, locVertex2, locDOCAVertex);
1084}
1085
1086double DAnalysisUtilities::Calc_DOCAVertex(const DVector3 &locUnitDir1, const DVector3 &locUnitDir2, const DVector3 &locVertex1, const DVector3 &locVertex2, DVector3& locDOCAVertex) const
1087{
1088 DVector3 locPOCA1, locPOCA2;
1089 double locDOCA = Calc_DOCA(locUnitDir1, locUnitDir2, locVertex1, locVertex2, locPOCA1, locPOCA2);
1090 locDOCAVertex = 0.5*(locPOCA1 + locPOCA2);
1091 return locDOCA;
1092}
1093
1094double DAnalysisUtilities::Calc_DOCA(const DKinFitParticle* locKinFitParticle1, const DKinFitParticle* locKinFitParticle2) const
1095{
1096 DVector3 locPOCA1, locPOCA2;
1097 return Calc_DOCA(locKinFitParticle1, locKinFitParticle2, locPOCA1, locPOCA2);
1098}
1099
1100double DAnalysisUtilities::Calc_DOCA(const DKinematicData* locKinematicData1, const DKinematicData* locKinematicData2) const
1101{
1102 DVector3 locPOCA1, locPOCA2;
1103 return Calc_DOCA(locKinematicData1, locKinematicData2, locPOCA1, locPOCA2);
1104}
1105
1106double DAnalysisUtilities::Calc_DOCA(const DKinFitParticle* locKinFitParticle1, const DKinFitParticle* locKinFitParticle2, DVector3 &locPOCA1, DVector3 &locPOCA2) const
1107{
1108 DVector3 locUnitDir1(locKinFitParticle1->Get_Momentum().Unit().X(),locKinFitParticle1->Get_Momentum().Unit().Y(),locKinFitParticle1->Get_Momentum().Unit().Z());
1109 DVector3 locUnitDir2(locKinFitParticle2->Get_Momentum().Unit().X(),locKinFitParticle2->Get_Momentum().Unit().Y(),locKinFitParticle2->Get_Momentum().Unit().Z());
1110 DVector3 locVertex1(locKinFitParticle1->Get_Position().X(),locKinFitParticle1->Get_Position().Y(),locKinFitParticle1->Get_Position().Z());
1111 DVector3 locVertex2(locKinFitParticle2->Get_Position().X(),locKinFitParticle2->Get_Position().Y(),locKinFitParticle2->Get_Position().Z());
1112 return Calc_DOCA(locUnitDir1, locUnitDir2, locVertex1, locVertex2, locPOCA1, locPOCA2);
1113}
1114
1115double DAnalysisUtilities::Calc_DOCA(const DKinematicData* locKinematicData1, const DKinematicData* locKinematicData2, DVector3 &locPOCA1, DVector3 &locPOCA2) const
1116{
1117 DVector3 locUnitDir1 = (1.0/locKinematicData1->momentum().Mag())*locKinematicData1->momentum();
1118 DVector3 locUnitDir2 = (1.0/locKinematicData2->momentum().Mag())*locKinematicData2->momentum();
1119 DVector3 locVertex1 = locKinematicData1->position();
1120 DVector3 locVertex2 = locKinematicData2->position();
1121 return Calc_DOCA(locUnitDir1, locUnitDir2, locVertex1, locVertex2, locPOCA1, locPOCA2);
1122}
1123
1124double DAnalysisUtilities::Calc_DOCA(const DVector3 &locUnitDir1, const DVector3 &locUnitDir2, const DVector3 &locVertex1, const DVector3 &locVertex2) const
1125{
1126 DVector3 locPOCA1, locPOCA2;
1127 return Calc_DOCA(locUnitDir1, locUnitDir2, locVertex1, locVertex2, locPOCA1, locPOCA2);
1128}
1129
1130double DAnalysisUtilities::Calc_DOCA(const DVector3 &locUnitDir1, const DVector3 &locUnitDir2, const DVector3 &locVertex1, const DVector3 &locVertex2, DVector3 &locPOCA1, DVector3 &locPOCA2) const
1131{
1132 //originated from code by Jorn Langheinrich
1133 //you can use this function to find the DOCA to a fixed point by calling this function with locUnitDir1 and 2 parallel, and the fixed vertex as locVertex2
1134 double locUnitDot = locUnitDir1.Dot(locUnitDir2);
1135 double locDenominator = locUnitDot*locUnitDot - 1.0; // scalar product of directions
1136 double locDistVertToInterDOCA1 = 0.0, locDistVertToInterDOCA2 = 0.0; //distance from vertex to DOCA point
1137
1138 if(fabs(locDenominator) < 1.0e-15) //parallel
1139 {
1140 locDistVertToInterDOCA1 = (locVertex2 - locVertex1).Dot(locUnitDir2)/locUnitDot; //the opposite
1141 locDistVertToInterDOCA2 = (locVertex1 - locVertex2).Dot(locUnitDir1)/locUnitDot;
1142 }
1143 else
1144 {
1145 double locA = (locVertex1 - locVertex2).Dot(locUnitDir1);
1146 double locB = (locVertex1 - locVertex2).Dot(locUnitDir2);
1147 locDistVertToInterDOCA1 = (locA - locUnitDot*locB)/locDenominator;
1148 locDistVertToInterDOCA2 = (locUnitDot*locA - locB)/locDenominator;
1149 }
1150
1151 locPOCA1 = locVertex1 + locDistVertToInterDOCA1*locUnitDir1; //intersection point of DOCA line and track 1
1152 locPOCA2 = locVertex2 + locDistVertToInterDOCA2*locUnitDir2; //intersection point of DOCA line and track 2
1153 return (locPOCA1 - locPOCA2).Mag();
1154}
1155
1156// Routine for steering the code that uses a small arc length approximation to
1157// a helical trajectory to find the doca between two tracks curving in the
1158// magnetic field.
1159jerror_t
1160DAnalysisUtilities::Calc_DOCA(const DKinFitParticle* locKinFitParticle1,
1161 const DKinFitParticle* locKinFitParticle2,
1162 DVector3 &pos1_out,DVector3 &pos2_out,
1163 double &doca) const{
1164 // Charges for the two input tracks
1165 double q1=locKinFitParticle1->Get_Charge();
1166 double q2=locKinFitParticle2->Get_Charge();
1167
1168 // position info from the two input tracks
1169 DVector3 pos1_in=locKinFitParticle1->Get_Position();
1170 DVector3 pos2_in=locKinFitParticle2->Get_Position();
1171
1172 // momentum info from the two input tracks
1173 DVector3 mom1_in=locKinFitParticle1->Get_Momentum();
1174 DVector3 mom2_in=locKinFitParticle2->Get_Momentum();
1175
1176 return Calc_DOCA(q1,q2,pos1_in,pos2_in,mom1_in,mom2_in,pos1_out,pos2_out,
1177 doca);
1178}
1179
1180// Routine for steering the code that uses a small arc length approximation to
1181// a helical trajectory to find the doca between two tracks curving in the
1182// magnetic field.
1183jerror_t DAnalysisUtilities::Calc_DOCA(const DKinematicData* kinematicData1,
1184 const DKinematicData* kinematicData2,
1185 DVector3 &pos1_out,DVector3 &pos2_out,
1186 double &doca
1187 ) const {
1188 // Charges for the two input tracks
1189 double q1=kinematicData1->charge();
1190 double q2=kinematicData2->charge();
1191
1192 // position info from the two input tracks
1193 DVector3 pos1_in=kinematicData1->position();
1194 DVector3 pos2_in=kinematicData2->position();
1195
1196 // momentum info from the two input tracks
1197 DVector3 mom1_in=kinematicData1->momentum();
1198 DVector3 mom2_in=kinematicData2->momentum();
1199
1200 return Calc_DOCA(q1,q2,pos1_in,pos2_in,mom1_in,mom2_in,pos1_out,pos2_out,
1201 doca);
1202}
1203
1204// Use a small arc length approximation to a helical trajectory to find the
1205// doca between two tracks curving in the magnetic field.
1206jerror_t DAnalysisUtilities::Calc_DOCA(double q1,double q2,
1207 const DVector3 &pos1_in,
1208 const DVector3 &pos2_in,
1209 const DVector3 &mom1_in,
1210 const DVector3 &mom2_in,
1211 DVector3 &pos1_out,DVector3 &pos2_out,
1212 double &doca
1213 ) const {
1214 DVector3 avg_pos=0.5*(pos1_in+pos2_in);
1215 DVector3 diff_pos=pos1_in-pos2_in;
1216 double B=fabs(dMagneticFieldMap->GetBz(avg_pos.x(),avg_pos.y(),avg_pos.z()));
1217 double kap1=-0.003*B*q1/(2.*mom1_in.Perp());
1218 double kap2=-0.003*B*q2/(2.*mom2_in.Perp());
1219 double dx=diff_pos.x(),dy=diff_pos.y(),dz=diff_pos.z();
1220 double tan1=tan(M_PI_21.57079632679489661923-mom1_in.Theta());
1221 double tan1sq=tan1*tan1;
1222 double phi1=mom1_in.Phi();
1223 double cos1=cos(phi1),sin1=sin(phi1);
1224 double cos1sq=cos1*cos1,sin1sq=sin1*sin1;
1225 double tan2=tan(M_PI_21.57079632679489661923-mom2_in.Theta());
1226 double tan2sq=tan2*tan2;
1227 double phi2=mom2_in.Phi();
1228 double cos2=cos(phi2),sin2=sin(phi2);
1229 double cos2sq=cos2*cos2,sin2sq=sin2*sin2;
1230 double dx_sq=dx*dx,dy_sq=dy*dy;
1231 double cos2sin1_minus_cos1sin2=cos2*sin1 - cos1*sin2;
1232
1233 double B1=pow(2*dx*kap2*sin1sq*sin2 - 2*dx*kap1*sin1*sin2sq - sin1sq*sin2sq
1234 + tan1sq + 2*dx*kap2*sin2*tan1sq - 2*dx*kap1*sin1*tan2sq
1235 - 2*sin1*sin2*(2*dx_sq*kap1*kap2 + tan1*tan2)
1236 + sin1sq*(1 + tan2sq) + cos1sq*(-2*cos2*dy*kap2
1237 + 4*dx*kap2*sin2 + sin2sq
1238 + tan2sq)
1239 + 2*cos2*(-2*dy*kap2*sin1sq + dy*kap1*sin1*sin2
1240 - dy*kap2*tan1sq + sin1*(2*dx*dy*kap1*kap2
1241 - dz*kap2*tan1
1242 + dz*kap1*tan2))
1243 + 2*cos1*(cos2sq*dy*kap1 + dy*kap2*sin1*sin2 + dy*kap1*tan2sq
1244 + sin2*(2*dx*dy*kap1*kap2 + dz*kap2*tan1
1245 - dz*kap1*tan2)
1246 - cos2*(2*dy_sq*kap1*kap2 + dx*kap2*sin1
1247 + dx*kap1*sin2 + sin1*sin2 + tan1*tan2)),2)
1248 + 8*(cos2sin1_minus_cos1sin2)*(cos1*kap1*(cos2 - 2*dy*kap2)
1249 + kap2*(-1 + 2*dx*kap1*sin1 - tan1sq)
1250 + kap1*(sin1*sin2 + tan1*tan2))*
1251 (2*cos2*dy_sq*kap2*sin1 + cos2*dx*sin1*sin2 - dz*tan1
1252 - 2*dx*dz*kap2*sin2*tan1 + dz*sin1*sin2*tan2 + cos2*dx*tan1*tan2
1253 + dy*(-2*dx*kap2*sin1*sin2 + sin1*sin2sq + 2*cos2*dz*kap2*tan1
1254 + sin2*tan1*tan2 - sin1*(1 + tan2sq))
1255 + cos1*(cos2*(2*dx*dy*kap2 + dy*sin2 + dz*tan2)
1256 - dx*(2*dx*kap2*sin2 + sin2sq + tan2sq)));
1257 if (B1<0.){
1258 doca=9.9e9;
1259 return VALUE_OUT_OF_RANGE;
1260 }
1261
1262 double B2=pow(2*dx*kap2*sin1sq*sin2 - 2*dx*kap1*sin1*sin2sq - sin1sq*sin2sq
1263 + tan1sq + 2*dx*kap2*sin2*tan1sq - 2*dx*kap1*sin1*tan2sq
1264 - 2*sin1*sin2*(2*dx_sq*kap1*kap2 + tan1*tan2)
1265 + sin1sq*(1 + tan2sq) + cos1sq*(-2*cos2*dy*kap2
1266 + 4*dx*kap2*sin2 + sin2sq
1267 + tan2sq)
1268 + 2*cos2*(-2*dy*kap2*sin1sq + dy*kap1*sin1*sin2 -dy*kap2*tan1sq
1269 + sin1*(2*dx*dy*kap1*kap2 - dz*kap2*tan1
1270 + dz*kap1*tan2))
1271 + 2*cos1*(cos2sq*dy*kap1 + dy*kap2*sin1*sin2 + dy*kap1*tan2sq
1272 + sin2*(2*dx*dy*kap1*kap2 + dz*kap2*tan1
1273 - dz*kap1*tan2)
1274 - cos2*(2*dy_sq*kap1*kap2 + dx*kap2*sin1
1275 + dx*kap1*sin2 + sin1*sin2 + tan1*tan2)),2)
1276 + 8*(cos2sin1_minus_cos1sin2)*(cos1*kap1*(cos2 - 2*dy*kap2)
1277 + kap2*(-1 + 2*dx*kap1*sin1 - tan1sq)
1278 + kap1*(sin1*sin2 + tan1*tan2))
1279 * (2*cos2*dy_sq*kap2*sin1 + cos2*dx*sin1*sin2 - dz*tan1
1280 - 2*dx*dz*kap2*sin2*tan1 + dz*sin1*sin2*tan2 + cos2*dx*tan1*tan2
1281 + dy*(-2*dx*kap2*sin1*sin2 + sin1*sin2sq + 2*cos2*dz*kap2*tan1
1282 + sin2*tan1*tan2 - sin1*(1 + tan2sq))
1283 + cos1*(cos2*(2*dx*dy*kap2 + dy*sin2 + dz*tan2)
1284 - dx*(2*dx*kap2*sin2 + sin2sq + tan2sq)));
1285 if (B2<0){
1286 doca=9.9e9;
1287 return VALUE_OUT_OF_RANGE;
1288 }
1289
1290 double A1=2*cos1*cos2sq*dy*kap1 - 2*cos1sq*cos2*dy*kap2
1291 - 4*cos1*cos2*dy_sq*kap1*kap2 - 2*cos1*cos2*dx*kap2*sin1
1292 + 4*cos2*dx*dy*kap1*kap2*sin1 + cos2sq*sin1sq - 4*cos2*dy*kap2*sin1sq
1293 - 2*cos1*cos2*dx*kap1*sin2 + 4*cos1sq*dx*kap2*sin2
1294 + 4*cos1*dx*dy*kap1*kap2*sin2 - 2*cos1*cos2*sin1*sin2
1295 + 2*cos2*dy*kap1*sin1*sin2 + 2*cos1*dy*kap2*sin1*sin2
1296 - 4*dx_sq*kap1*kap2*sin1*sin2 + 2*dx*kap2*sin1sq*sin2 + cos1sq*sin2sq
1297 - 2*dx*kap1*sin1*sin2sq - 2*cos2*dz*kap2*sin1*tan1
1298 + 2*cos1*dz*kap2*sin2*tan1 + cos2sq*tan1sq - 2*cos2*dy*kap2*tan1sq
1299 + 2*dx*kap2*sin2*tan1sq + sin2sq*tan1sq + 2*cos2*dz*kap1*sin1*tan2
1300 - 2*cos1*dz*kap1*sin2*tan2 - 2*cos1*cos2*tan1*tan2 - 2*sin1*sin2*tan1*tan2
1301 + cos1sq*tan2sq + 2*cos1*dy*kap1*tan2sq - 2*dx*kap1*sin1*tan2sq
1302 + sin1sq*tan2sq;
1303 double C1=-4.*(cos2sin1_minus_cos1sin2)
1304 *(cos1*kap1*(cos2 - 2*dy*kap2) + kap2*(-1 + 2*dx*kap1*sin1 - tan1sq)
1305 + kap1*(sin1*sin2 + tan1*tan2));
1306
1307 double A2=2*cos1*cos2sq*dy*kap1 - 2*cos1sq*cos2*dy*kap2
1308 - 4*cos1*cos2*dy_sq*kap1*kap2 - 4*cos2sq*dx*kap1*sin1
1309 + 2*cos1*cos2*dx*kap2*sin1 + 4*cos2*dx*dy*kap1*kap2*sin1 + cos2sq*sin1sq
1310 + 2*cos1*cos2*dx*kap1*sin2 + 4*cos1*dx*dy*kap1*kap2*sin2
1311 - 2*cos1*cos2*sin1*sin2 - 2*cos2*dy*kap1*sin1*sin2
1312 - 2*cos1*dy*kap2*sin1*sin2 - 4*dx_sq*kap1*kap2*sin1*sin2
1313 + 2*dx*kap2*sin1sq*sin2 + cos1sq*sin2sq + 4*cos1*dy*kap1*sin2sq
1314 - 2*dx*kap1*sin1*sin2sq + 2*cos2*dz*kap2*sin1*tan1
1315 - 2*cos1*dz*kap2*sin2*tan1 + cos2sq*tan1sq - 2*cos2*dy*kap2*tan1sq
1316 + 2*dx*kap2*sin2*tan1sq + sin2sq*tan1sq - 2*cos2*dz*kap1*sin1*tan2
1317 + 2*cos1*dz*kap1*sin2*tan2 - 2*cos1*cos2*tan1*tan2 - 2*sin1*sin2*tan1*tan2
1318 + cos1sq*tan2sq + 2*cos1*dy*kap1*tan2sq - 2*dx*kap1*sin1*tan2sq
1319 + sin1sq*tan2sq;
1320 double C2=4.*(cos2sin1_minus_cos1sin2)
1321 *(kap2*(cos1*cos2 + sin1*sin2 + tan1*tan2)
1322 + kap1*(-1 + 2*cos2*dy*kap2 - 2*dx*kap2*sin2 - tan2sq));
1323
1324 // Arc lengths to doca points
1325 double s1_minus=(A1-sqrt(B1))/C1;
1326 double s2_minus=(A2-sqrt(B2))/C2;
1327 double s1_plus=(A1+sqrt(B1))/C1;
1328 double s2_plus=(A2+sqrt(B2))/C2;
1329
1330 // Position components
1331 double x1=pos1_in.x();
1332 double y1=pos1_in.y();
1333 double z1=pos1_in.z();
1334 double x2=pos2_in.x();
1335 double y2=pos2_in.y();
1336 double z2=pos2_in.z();
1337
1338 // Use solution corresponding to the smaller arc lengths
1339 if (fabs(s1_minus+s2_minus)<fabs(s1_plus+s2_plus)){
1340 pos1_out.SetXYZ(x1+cos1*s1_minus,y1+sin1*s1_minus,z1+tan1*s1_minus);
1341 pos2_out.SetXYZ(x2+cos2*s2_minus,y2+sin2*s2_minus,z2+tan2*s2_minus);
1342 }
1343 else{
1344 pos1_out.SetXYZ(x1+cos1*s1_plus,y1+sin1*s1_plus,z1+tan1*s1_plus);
1345 pos2_out.SetXYZ(x2+cos2*s2_plus,y2+sin2*s2_plus,z2+tan2*s2_plus);
1346 }
1347
1348 doca=(pos1_out-pos2_out).Mag();
1349
1350 if (DEBUG_LEVEL>0){
1351 DVector3 myvertex=0.5*(pos1_out+pos2_out);
1352 printf("Vertex position (x,y,z)=(%3.2f, %3.2f, %3.2f)\n",myvertex.x(),
1353 myvertex.y(),myvertex.z());
1354 }
1355
1356 return NOERROR;
1357}
1358
1359
1360
1361double DAnalysisUtilities::Calc_CrudeTime(const vector<const DKinematicData*>& locParticles, const DVector3& locCommonVertex) const
1362{
1363 //crudely propagate the track times to the common vertex and return the average track time
1364 DVector3 locPOCA;
1365 DVector3 locDeltaVertex;
1366 DVector3 locMomentum;
1367 double locAverageTime = 0.0;
1368 for(size_t loc_i = 0; loc_i < locParticles.size(); ++loc_i)
1369 {
1370 Calc_DOCAToVertex(locParticles[loc_i], locCommonVertex, locPOCA);
1371 locDeltaVertex = locPOCA - locParticles[loc_i]->position();
1372 locMomentum = locParticles[loc_i]->momentum();
1373 double locTime = locParticles[loc_i]->time() + locDeltaVertex.Dot(locMomentum)*locParticles[loc_i]->energy()/(29.9792458*locMomentum.Mag2());
1374 locAverageTime += locTime;
1375 }
1376 return locAverageTime/(double(locParticles.size()));
1377}
1378
1379double DAnalysisUtilities::Calc_CrudeTime(const vector<DKinFitParticle*>& locParticles, const DVector3& locCommonVertex) const
1380{
1381 //crudely propagate the track times to the common vertex and return the average track time
1382 DVector3 locPOCA;
1383 DVector3 locDeltaVertex;
1384 double locAverageTime = 0.0;
1385 for(size_t loc_i = 0; loc_i < locParticles.size(); ++loc_i)
1386 {
1387 double locTime = 0.0;
1388 double locE = locParticles[loc_i]->Get_ShowerEnergy();
1389 if((locParticles[loc_i]->Get_Charge() == 0) && (locE > 0.0))
1390 {
1391 double locMass = locParticles[loc_i]->Get_Mass();
1392 double locPMag = sqrt(locE*locE - locMass*locMass);
1393 DVector3 locPosition = locParticles[loc_i]->Get_Position();
1394 DVector3 locDPosition(locPosition.X(), locPosition.Y(), locPosition.Z());
1395 DVector3 locDeltaVertex = locDPosition - locCommonVertex;
1396 locTime = locParticles[loc_i]->Get_Time() + locDeltaVertex.Mag()*locE/(29.9792458*locPMag);
1397 }
1398 else
1399 {
1400 Calc_DOCAToVertex(locParticles[loc_i], locCommonVertex, locPOCA);
1401 locDeltaVertex = locPOCA - DVector3(locParticles[loc_i]->Get_Position().X(),locParticles[loc_i]->Get_Position().Y(),locParticles[loc_i]->Get_Position().Z());
1402 DVector3 locMomentum(locParticles[loc_i]->Get_Momentum().X(),locParticles[loc_i]->Get_Momentum().Y(),locParticles[loc_i]->Get_Momentum().Z());
1403 locTime = locParticles[loc_i]->Get_Time() + locDeltaVertex.Dot(locMomentum)*locParticles[loc_i]->Get_Energy()/(29.9792458*locMomentum.Mag2());
1404 }
1405 locAverageTime += locTime;
1406 }
1407 return locAverageTime/(double(locParticles.size()));
1408}
1409
1410DVector3 DAnalysisUtilities::Calc_CrudeVertex(const vector<const DTrackTimeBased*>& locParticles) const
1411{
1412 //assumes tracks are straight lines
1413 //uses the midpoint of the smallest DOCA line
1414 DVector3 locVertex(0.0, 0.0, dTargetZCenter);
1415
1416 if(locParticles.size() == 0)
1417 return locVertex;
1418 if(locParticles.size() == 1)
1419 return locParticles[0]->position();
1420
1421 double locDOCA, locSmallestDOCA;
1422 DVector3 locTempVertex;
1423
1424 locSmallestDOCA = 9.9E9;
1425 for(int loc_j = 0; loc_j < (int(locParticles.size()) - 1); ++loc_j)
1426 {
1427 for(size_t loc_k = loc_j + 1; loc_k < locParticles.size(); ++loc_k)
1428 {
1429 locDOCA = Calc_DOCAVertex(locParticles[loc_j], locParticles[loc_k], locTempVertex);
1430
1431 if(locDOCA < locSmallestDOCA)
1432 {
1433 locSmallestDOCA = locDOCA;
1434 locVertex = locTempVertex;
1435 }
1436 }
1437 }
1438 return locVertex;
1439}
1440
1441DVector3 DAnalysisUtilities::Calc_CrudeVertex(const vector<const DChargedTrackHypothesis*>& locParticles) const
1442{
1443 //assumes tracks are straight lines
1444 //uses the midpoint of the smallest DOCA line
1445 DVector3 locVertex(0.0, 0.0, dTargetZCenter);
1446
1447 if(locParticles.size() == 0)
1448 return locVertex;
1449 if(locParticles.size() == 1)
1450 return locParticles[0]->position();
1451
1452 double locDOCA, locSmallestDOCA;
1453 DVector3 locTempVertex;
1454
1455 locSmallestDOCA = 9.9E9;
1456 for(int loc_j = 0; loc_j < (int(locParticles.size()) - 1); ++loc_j)
1457 {
1458 for(size_t loc_k = loc_j + 1; loc_k < locParticles.size(); ++loc_k)
1459 {
1460 locDOCA = Calc_DOCAVertex(locParticles[loc_j], locParticles[loc_k], locTempVertex);
1461 if(locDOCA < locSmallestDOCA)
1462 {
1463 locSmallestDOCA = locDOCA;
1464 locVertex = locTempVertex;
1465 }
1466 }
1467 }
1468 return locVertex;
1469}
1470
1471DVector3 DAnalysisUtilities::Calc_CrudeVertex(const vector<const DKinematicData*>& locParticles) const
1472{
1473 //assumes tracks are straight lines
1474 //uses the midpoint of the smallest DOCA line
1475 DVector3 locVertex(0.0, 0.0, dTargetZCenter);
1476
1477 if(locParticles.size() == 0)
1478 return locVertex;
1479 if(locParticles.size() == 1)
1480 return locParticles[0]->position();
1481
1482 double locDOCA, locSmallestDOCA;
1483 DVector3 locTempVertex;
1484
1485 locSmallestDOCA = 9.9E9;
1486 for(int loc_j = 0; loc_j < (int(locParticles.size()) - 1); ++loc_j)
1487 {
1488 for(size_t loc_k = loc_j + 1; loc_k < locParticles.size(); ++loc_k)
1489 {
1490 locDOCA = Calc_DOCAVertex(locParticles[loc_j], locParticles[loc_k], locTempVertex);
1491 if(locDOCA < locSmallestDOCA)
1492 {
1493 locSmallestDOCA = locDOCA;
1494 locVertex = locTempVertex;
1495 }
1496 }
1497 }
1498 return locVertex;
1499}
1500
1501DVector3 DAnalysisUtilities::Calc_CrudeVertex(const vector<shared_ptr<DKinFitParticle>>& locParticles) const
1502{
1503 //assumes tracks are straight lines
1504 //uses the midpoint of the smallest DOCA line
1505 DVector3 locVertex(0.0, 0.0, dTargetZCenter);
1506
1507 if(locParticles.size() == 0)
1508 return locVertex;
1509
1510 if(locParticles.size() == 1)
1511 return DVector3(locParticles[0]->Get_Position().X(), locParticles[0]->Get_Position().Y(), locParticles[0]->Get_Position().Z());
1512
1513 double locDOCA, locSmallestDOCA;
1514 DVector3 locTempVertex;
1515
1516 locSmallestDOCA = 9.9E9;
1517 for(int loc_j = 0; loc_j < (int(locParticles.size()) - 1); ++loc_j)
1518 {
1519 for(size_t loc_k = loc_j + 1; loc_k < locParticles.size(); ++loc_k)
1520 {
1521 locDOCA = Calc_DOCAVertex(locParticles[loc_j].get(), locParticles[loc_k].get(), locTempVertex);
1522 if(locDOCA < locSmallestDOCA)
1523 {
1524 locSmallestDOCA = locDOCA;
1525 locVertex = locTempVertex;
1526 }
1527 }
1528 }
1529 return locVertex;
1530}
1531
1532set<set<size_t> > DAnalysisUtilities::Build_IndexCombos(const DReactionStep* locReactionStep, deque<Particle_t> locToIncludePIDs) const
1533{
1534 //if locToIncludePIDs is empty, will return one set with all (except missing)
1535 set<set<size_t> > locCombos;
1536
1537 auto locReactionStepPIDs = locReactionStep->Get_FinalPIDs();
1538 int locMissingParticleIndex = locReactionStep->Get_MissingParticleIndex();
1539
1540 if(locToIncludePIDs.empty())
1541 {
1542 set<size_t> locCombo;
1543 for(size_t loc_i = 0; loc_i < locReactionStepPIDs.size(); ++loc_i)
1544 {
1545 if(int(loc_i) == locMissingParticleIndex)
1546 continue;
1547 locCombo.insert(loc_i);
1548 }
1549 locCombos.insert(locCombo);
1550 return locCombos;
1551 }
1552
1553 //deque indices corresponds to locToIncludePIDs, and each set is what could pass for it
1554 deque<deque<size_t> > locPossibilities(locToIncludePIDs.size(), deque<size_t>());
1555 deque<int> locResumeAtIndices(locToIncludePIDs.size(), 0);
1556
1557 //build possibilities: loop over reaction PIDs
1558 for(size_t loc_i = 0; loc_i < locReactionStepPIDs.size(); ++loc_i)
1559 {
1560 if(int(loc_i) == locMissingParticleIndex)
1561 continue;
1562 Particle_t locPID = locReactionStepPIDs[loc_i];
1563
1564 //register where this is a valid option: loop over to-include PIDs
1565 for(size_t loc_j = 0; loc_j < locToIncludePIDs.size(); ++loc_j)
1566 {
1567 if(locToIncludePIDs[loc_j] == locPID)
1568 locPossibilities[loc_j].push_back(loc_i);
1569 }
1570 }
1571
1572 //build combos
1573 int locParticleIndex = 0;
1574 deque<size_t> locComboDeque;
1575 while(true)
1576 {
1577 if(locParticleIndex == int(locPossibilities.size())) //end of combo: save it
1578 {
1579 set<size_t> locComboSet; //convert set to deque
1580 for(size_t loc_i = 0; loc_i < locComboDeque.size(); ++loc_i)
1581 locComboSet.insert(locComboDeque[loc_i]);
1582 locCombos.insert(locComboSet); //saved
1583
1584 if(!Handle_Decursion(locParticleIndex, locComboDeque, locResumeAtIndices, locPossibilities))
1585 break;
1586 continue;
1587 }
1588
1589 int& locResumeAtIndex = locResumeAtIndices[locParticleIndex];
1590
1591 //if two identical pids: locResumeAtIndex must always be >= the previous locResumeAtIndex (prevents duplicates) e.g. g, p -> p, pi0, pi0
1592 //search for same pid previously in this step
1593 Particle_t locToIncludePID = locToIncludePIDs[locParticleIndex];
1594 for(int loc_i = locParticleIndex - 1; loc_i >= 0; --loc_i)
1595 {
1596 if(locToIncludePIDs[loc_i] == locToIncludePID)
1597 {
1598 if(locResumeAtIndex < locResumeAtIndices[loc_i])
1599 locResumeAtIndex = locResumeAtIndices[loc_i];
1600 break; //dupe type in step: resume-at advanced to next
1601 }
1602 }
1603
1604 if(locResumeAtIndex >= int(locPossibilities[locParticleIndex].size()))
1605 {
1606 if(!Handle_Decursion(locParticleIndex, locComboDeque, locResumeAtIndices, locPossibilities))
1607 break;
1608 continue;
1609 }
1610
1611 // pid found
1612 locComboDeque.push_back(locPossibilities[locParticleIndex][locResumeAtIndex]);
1613 ++locResumeAtIndex;
1614 ++locParticleIndex;
1615 }
1616
1617 return locCombos;
1618}
1619
1620bool DAnalysisUtilities::Handle_Decursion(int& locParticleIndex, deque<size_t>& locComboDeque, deque<int>& locResumeAtIndices, deque<deque<size_t> >& locPossibilities) const
1621{
1622 do
1623 {
1624 if(locParticleIndex < int(locResumeAtIndices.size())) //else just saved a combo
1625 locResumeAtIndices[locParticleIndex] = 0; //finding this particle failed: reset
1626
1627 --locParticleIndex; //go to previous particle
1628 if(locParticleIndex < 0)
1629 return false; //end of particles: end of finding all combos
1630
1631 locComboDeque.pop_back(); //reset this index
1632 }
1633 while(locResumeAtIndices[locParticleIndex] == int(locPossibilities[locParticleIndex].size()));
1634
1635 return true;
1636}
1637
1638//The POCA cannot technically be solved analytically, but we can approximate it pretty accurately
1639 //First, propagate the track to somewhere very close to the true POCA
1640 //Then, the equation can be solved by substituting cos(x) = 1, sin(x) = x
1641double DAnalysisUtilities::Propagate_Track(int locCharge, const DVector3& locPropagateToPoint, DLorentzVector& locMeasuredX4, DLorentzVector& locMeasuredP4, TMatrixFSym* locCovarianceMatrix) const
1642{
1643 //ASSUMES THAT THE B-FIELD IS IN THE +Z DIRECTION!!!!!!!!!!!!!!!
1644 double locDistance = (locMeasuredX4.Vect() - locPropagateToPoint).Mag();
1645 if(!Get_IsBFieldNearBeamline() || (locCharge == 0) || (locDistance < dMinDistanceForStraightTrack))
1646 {
1647 //use simpler methods
1648 DVector3 locPOCA;
1649 auto locP3 = locMeasuredP4.Vect();
1650 Calc_DOCAToVertex(locP3.Unit(), locMeasuredX4.Vect(), locPropagateToPoint, locPOCA);
1651 locMeasuredX4.SetVect(locPOCA);
1652 auto locDistanceVector = locPOCA - locMeasuredX4.Vect();
1653 //negative: if you had to propagate the track forwards, that means the path length is LESS than what you thought it was
1654 auto locDeltaPathLength = (locP3.Dot(locDistanceVector) > 0.0) ? -1.0*locDistanceVector.Mag() : locDistanceVector.Mag();
1655 locMeasuredX4.SetT(locMeasuredX4.T() - locDeltaPathLength/(locMeasuredP4.Beta()*SPEED_OF_LIGHT29.9792458)); //v = s/t, t = s/v = s/(beta*c) = s*E/(p*c) =
1656 return locDeltaPathLength;
1657 }
1658
1659 //propagate the track to the same z as the vertex (if pz != 0)
1660 double locTotalDeltaPathLength = 0.0;
1661 DLorentzVector locTempPropagatedPosition = locMeasuredX4;
1662 DLorentzVector locTempPropagatedMomentum = locMeasuredP4;
1663 if(fabs(locMeasuredP4.Pz()) > 0.0)
1664 {
1665 locTotalDeltaPathLength += (locPropagateToPoint.Z() - locMeasuredX4.Z())*locMeasuredP4.P()/locMeasuredP4.Pz(); //s = (z - z0)*p/p0z
1666 Propagate_Track(locTotalDeltaPathLength, locCharge, locTempPropagatedPosition, locTempPropagatedMomentum, NULL__null);
1667 }
1668
1669 //now, step along the track until we get close to the POCA
1670 locTotalDeltaPathLength += Calc_PathLength_Step(locCharge, locPropagateToPoint, locTempPropagatedPosition, locTempPropagatedMomentum);
1671
1672 //now, the path length is very close to accurate. get the rest of the way there
1673 locTotalDeltaPathLength += Calc_PathLength_FineGrained(locCharge, locPropagateToPoint, locTempPropagatedPosition.Vect(), locTempPropagatedMomentum.Vect());
1674
1675 //Finally, propagate the track the given distance and return
1676//cout << "FINAL: xyz, distance = " << locMeasuredX4.X() << ", " << locMeasuredX4.Y() << ", " << locMeasuredX4.Z() << ", " << locTotalDeltaPathLength << endl;
1677 Propagate_Track(locTotalDeltaPathLength, locCharge, locMeasuredX4, locMeasuredP4, locCovarianceMatrix);
1678
1679 //negative: if you had to propagate the track forwards, that means the path length is LESS than what you thought it was
1680 return -1.0*locTotalDeltaPathLength;
1681}
1682
1683double DAnalysisUtilities::Calc_PathLength_Step(int locCharge, const DVector3& locPropagateToPoint, DLorentzVector& locMeasuredX4, DLorentzVector& locMeasuredP4) const
1684{
1685 //now, step slowly along the track (in path length), trying to get closer to the POCA
1686 //for the final calculation to work, rho*s must be small: cos(rho*s) -> 1
1687 DVector3 locBField = Get_BField(locPropagateToPoint);
1688 double locA = -0.00299792458*(double(locCharge))*locBField.Mag();
1689
1690 double locPMag = locMeasuredP4.P();
1691 double locPathLengthOneRotation = 2.0*TMath::Pi()*locPMag/locA;
1692 double locStepDistance = locPathLengthOneRotation/12.0; //30 degrees //e.g. for 90 degree tracks
1693
1694 //guard against long steps in z (e.g. for 2 degree tracks)
1695 double locStepDeltaZ = locMeasuredP4.Pz()*locStepDistance/locPMag;
1696 double locTargetDeltaZ = 1.0;
1697 if(fabs(locStepDeltaZ) > 5.0)
1698 locStepDistance = locTargetDeltaZ*locPMag/locMeasuredP4.Pz();
1699
1700 //First, try stepping in +pvec direction
1701 double locStepDirection = 1.0;
1702 double locTotalDeltaPathLength = 0.0;
1703 double locDeltaX3 = (locMeasuredX4.Vect() - locPropagateToPoint).Mag();
1704 double locRhoS = locStepDistance*locA/locPMag;
1705 double locRhoSCutOff = 0.1;
1706 while(locRhoS > locRhoSCutOff) //at this point, cos(rho*s) = 0.995: close enough
1707 {
1708 double locDeltaPathLength = locStepDirection*locStepDistance;
1709 locTotalDeltaPathLength += locDeltaPathLength;
1710//cout << "STEP LOOP: xyz, distance = " << locMeasuredX4.X() << ", " << locMeasuredX4.Y() << ", " << locMeasuredX4.Z() << ", " << locDeltaPathLength << endl;
1711 Propagate_Track(locDeltaPathLength, locCharge, locMeasuredX4, locMeasuredP4, NULL__null);
1712
1713 double locNewDeltaX3 = (locMeasuredX4.Vect() - locPropagateToPoint).Mag();
1714 bool locGettingCloserFlag = (locNewDeltaX3 < locDeltaX3);
1715 locDeltaX3 = locNewDeltaX3;
1716
1717 if(locGettingCloserFlag)
1718 continue; //stepping in correct direction, can still try to get closer
1719
1720 //are now farther away than before: reverse direction, decrease step size
1721 locStepDirection *= -1.0;
1722 locStepDistance /= 2.0;
1723 locRhoS = locStepDistance*locA/locPMag;
1724
1725 //if about to break, revert to older, better position
1726 if(locRhoS < locRhoSCutOff)
1727 {
1728 locTotalDeltaPathLength -= locDeltaPathLength;
1729 Propagate_Track(-1.0*locDeltaPathLength, locCharge, locMeasuredX4, locMeasuredP4, NULL__null);
1730 }
1731 }
1732
1733 return locTotalDeltaPathLength;
1734}
1735
1736double DAnalysisUtilities::Calc_PathLength_FineGrained(int locCharge, const DVector3& locPropagateToPoint, DVector3 locMeasuredPosition, DVector3 locMeasuredMomentum) const
1737{
1738 //ASSUMES B-FIELD IS IN +Z DIRECTION!!
1739
1740 //distance = sqrt((delta-x)^2 + (delta-y)^2 + (delta-z)^2)
1741 //find the delta-path-length s that minimizes the distance equation
1742 //take derivative of the distance equation, set = 0
1743
1744 //Mathematica yields: F*(B*s + C) + D*cos(rho*s) + E*sin(rho*s) = 0
1745 //(where BCDEF are various, non-s-dependent terms)
1746 //This is unsolvable analytically. However, we know that s is small, since we're almost there
1747
1748 //So, substitute cos(x) = 1, sin(x) = x:
1749 //F*(B*s + C) + D + E*rho*s = 0
1750 //Solving gives: s = - (F*C + D) / (F*B + E*rho)
1751 //Note that B = F
1752
1753 DVector3 locBField = Get_BField(locMeasuredPosition);
1754 double locA = -0.00299792458*(double(locCharge))*locBField.Mag();
1755 double locPMag = locMeasuredMomentum.Mag();
1756 double locRho = locA/locPMag;
1757
1758 DVector3 locDeltaX3 = locMeasuredPosition - locPropagateToPoint;
1759 double locF = locMeasuredMomentum.Pz()/locPMag;
1760 double locC = locDeltaX3.Z();
1761 double locD = locRho*(locMeasuredMomentum.Px()*locDeltaX3.X() + locMeasuredMomentum.Py()*locDeltaX3.Y())/locA;
1762 double locPerpPSq = locMeasuredMomentum.Px()*locMeasuredMomentum.Px() + locMeasuredMomentum.Py()*locMeasuredMomentum.Py();
1763 double locE = locRho*(locPerpPSq/locA - locMeasuredMomentum.Py()*locDeltaX3.X() + locMeasuredMomentum.Px()*locDeltaX3.Y())/locA;
1764 return -1.0*(locF*locC + locD)/(locF*locF + locE*locRho);
1765}
1766
1767void DAnalysisUtilities::Propagate_Track(double locDeltaPathLength, int locCharge, DLorentzVector& locX4, DLorentzVector& locP4, TMatrixFSym* locCovarianceMatrix) const
1768{
1769 //ASSUMES THAT THE B-FIELD IS IN THE +Z DIRECTION!!!!!!!!!!!!!!!
1770
1771 DVector3 locBField = Get_BField(locX4.Vect());
1772 if(!(locBField.Mag() > 0.0))
1773 return;
1774 DVector3 locH = locBField.Unit();
1775 double locA = -0.00299792458*(double(locCharge))*locBField.Mag();
1776
1777 double locPMag = locP4.P();
1778 double locRhoS = locDeltaPathLength*locA/locPMag;
1779
1780 DLorentzVector locDeltaX4; //x - x0
1781 locDeltaX4.SetX(locP4.Px()*sin(locRhoS)/locA - locP4.Py()*(1.0 - cos(locRhoS))/locA);
1782 locDeltaX4.SetY(locP4.Py()*sin(locRhoS)/locA + locP4.Px()*(1.0 - cos(locRhoS))/locA);
1783 locDeltaX4.SetZ(locP4.Pz()*locDeltaPathLength/locPMag);
1784 locDeltaX4.SetT(locDeltaPathLength/(locP4.Beta()*SPEED_OF_LIGHT29.9792458)); //v = s/t, t = s/v = s/(beta*c) = s*E/(p*c) =
1785 locX4 += locDeltaX4;
1786
1787 if(locCovarianceMatrix == NULL__null)
1788 {
1789 locP4.SetVect(locP4.Vect() - locDeltaX4.Vect().Cross(locA*locH));
1790 return; //don't update error matrix
1791 }
1792
1793 //transform(i, j) = di/dj, i = new, j = old //pxyz, xyz, t
1794 TMatrixF locTransformMatrix(7, 7);
1795 locTransformMatrix.Zero();
1796
1797 double locPCubed = locPMag*locPMag*locPMag;
1798 double locSOverP3 = locDeltaPathLength/locPCubed;
1799
1800 double locSOverP3_PxPx = locSOverP3*locP4.Px()*locP4.Px();
1801 double locSOverP3_PxPy = locSOverP3*locP4.Px()*locP4.Py();
1802 double locSOverP3_PxPz = locSOverP3*locP4.Px()*locP4.Pz();
1803
1804 double locSOverP3_PyPy = locSOverP3*locP4.Py()*locP4.Py();
1805 double locSOverP3_PyPz = locSOverP3*locP4.Py()*locP4.Pz();
1806 double locSOverP3_PzPz = locSOverP3*locP4.Pz()*locP4.Pz();
1807
1808 //dpx
1809 locTransformMatrix(0, 0) = (1.0 + locA*locSOverP3_PxPy)*cos(locRhoS) + locA*locSOverP3_PxPx*sin(locRhoS);
1810 locTransformMatrix(0, 1) = (-1.0 + locA*locSOverP3_PxPy)*sin(locRhoS) + locA*locSOverP3_PyPy*cos(locRhoS);
1811 locTransformMatrix(0, 2) = locA*locSOverP3_PyPz*cos(locRhoS) + locA*locSOverP3_PxPz*sin(locRhoS);
1812
1813 //dpy
1814 locTransformMatrix(1, 0) = -1.0*locA*locSOverP3_PxPx*cos(locRhoS) + (1.0 + locA*locSOverP3_PxPy)*sin(locRhoS);
1815 locTransformMatrix(1, 1) = (1.0 - locA*locSOverP3_PxPy)*cos(locRhoS) + locA*locSOverP3_PyPy*sin(locRhoS);
1816 locTransformMatrix(1, 2) = locA*locSOverP3_PyPz*sin(locRhoS) - locA*locSOverP3_PxPz*cos(locRhoS);
1817
1818 //dpz
1819 locTransformMatrix(2, 2) = 1.0;
1820
1821 //dx
1822 locTransformMatrix(3, 0) = (1.0/locA + locSOverP3_PxPy)*sin(locRhoS) - locSOverP3_PxPx*cos(locRhoS);
1823 locTransformMatrix(3, 1) = -1.0/locA + (1.0/locA - locSOverP3_PxPy)*cos(locRhoS) + locSOverP3_PyPy*sin(locRhoS);
1824 locTransformMatrix(3, 2) = locSOverP3_PyPz*sin(locRhoS) - locSOverP3_PxPz*cos(locRhoS);
1825 locTransformMatrix(3, 3) = 1.0;
1826
1827 //dy
1828 locTransformMatrix(4, 0) = 1.0/locA - (1.0/locA + locSOverP3_PxPy)*cos(locRhoS) + locSOverP3_PxPx*sin(locRhoS);
1829 locTransformMatrix(4, 1) = (1.0/locA - locSOverP3_PxPy)*sin(locRhoS) - locSOverP3_PyPy*cos(locRhoS);
1830 locTransformMatrix(4, 2) = -1.0*locSOverP3_PyPz*cos(locRhoS) - locSOverP3_PxPz*sin(locRhoS);
1831 locTransformMatrix(4, 4) = 1.0;
1832
1833 //dz
1834 locTransformMatrix(5, 0) = -1.0*locSOverP3_PxPz;
1835 locTransformMatrix(5, 1) = -1.0*locSOverP3_PyPz;
1836 locTransformMatrix(5, 2) = locDeltaPathLength/locPMag - locSOverP3_PzPz;
1837 locTransformMatrix(5, 5) = 1.0;
1838
1839 //dt
1840 locTransformMatrix(6, 0) = -1.0*locP4.M2()*locSOverP3*locP4.Px()/(SPEED_OF_LIGHT29.9792458*locP4.E());
1841 locTransformMatrix(6, 1) = -1.0*locP4.M2()*locSOverP3*locP4.Py()/(SPEED_OF_LIGHT29.9792458*locP4.E());
1842 locTransformMatrix(6, 2) = -1.0*locP4.M2()*locSOverP3*locP4.Pz()/(SPEED_OF_LIGHT29.9792458*locP4.E());
1843 locTransformMatrix(6, 6) = 1.0;
1844
1845 //transform!!
1846 locCovarianceMatrix->Similarity(locTransformMatrix);
1847
1848 //update p3 //must do at the end!!
1849 locP4.SetVect(locP4.Vect() - locDeltaX4.Vect().Cross(locA*locH));
1850}

/w/halld-scifs17exp/halld2/home/sdobbs/Software/jana/jana_0.8.2/Linux_CentOS7.7-x86_64-gcc4.8.5/include/JANA/JEventLoop.h

1// $Id: JEventLoop.h 1763 2006-05-10 14:29:25Z davidl $
2//
3// File: JEventLoop.h
4// Created: Wed Jun 8 12:30:51 EDT 2005
5// Creator: davidl (on Darwin wire129.jlab.org 7.8.0 powerpc)
6//
7
8#ifndef _JEventLoop_
9#define _JEventLoop_
10
11#include <sys/time.h>
12
13#include <vector>
14#include <list>
15#include <string>
16#include <utility>
17#include <typeinfo>
18#include <string.h>
19#include <map>
20#include <utility>
21using std::vector;
22using std::list;
23using std::string;
24using std::type_info;
25
26#include <JANA/jerror.h>
27#include <JANA/JObject.h>
28#include <JANA/JException.h>
29#include <JANA/JEvent.h>
30#include <JANA/JThread.h>
31#include <JANA/JFactory_base.h>
32#include <JANA/JCalibration.h>
33#include <JANA/JGeometry.h>
34#include <JANA/JResourceManager.h>
35#include <JANA/JStreamLog.h>
36
37// The following is here just so we can use ROOT's THtml class to generate documentation.
38#include "cint.h"
39
40
41// Place everything in JANA namespace
42namespace jana{
43
44
45template<class T> class JFactory;
46class JApplication;
47class JEventProcessor;
48
49
50class JEventLoop{
51 public:
52
53 friend class JApplication;
54
55 enum data_source_t{
56 DATA_NOT_AVAILABLE = 1,
57 DATA_FROM_CACHE,
58 DATA_FROM_SOURCE,
59 DATA_FROM_FACTORY
60 };
61
62 typedef struct{
63 string caller_name;
64 string caller_tag;
65 string callee_name;
66 string callee_tag;
67 double start_time;
68 double end_time;
69 data_source_t data_source;
70 }call_stack_t;
71
72 typedef struct{
73 const char* factory_name;
74 string tag;
75 const char* filename;
76 int line;
77 }error_call_stack_t;
78
79 JEventLoop(JApplication *app); ///< Constructor
80 virtual ~JEventLoop(); ////< Destructor
81 virtual const char* className(void){return static_className();}
82 static const char* static_className(void){return "JEventLoop";}
83
84 JApplication* GetJApplication(void) const {return app;} ///< Get pointer to the JApplication object
85 void RefreshProcessorListFromJApplication(void); ///< Re-copy the list of JEventProcessors from JApplication
86 virtual jerror_t AddFactory(JFactory_base* factory); ///< Add a factory
87 jerror_t RemoveFactory(JFactory_base* factory); ///< Remove a factory
88 JFactory_base* GetFactory(const string data_name, const char *tag="", bool allow_deftag=true); ///< Get a specific factory pointer
89 vector<JFactory_base*> GetFactories(void) const {return factories;} ///< Get all factory pointers
90 void GetFactoryNames(vector<string> &factorynames); ///< Get names of all factories in name:tag format
91 void GetFactoryNames(map<string,string> &factorynames); ///< Get names of all factories in map with key=name, value=tag
92 map<string,string> GetDefaultTags(void) const {return default_tags;}
93 jerror_t ClearFactories(void); ///< Reset all factories in preparation for next event.
94 jerror_t PrintFactories(int sparsify=0); ///< Print a list of all factories.
95 jerror_t Print(const string data_name, const char *tag=""); ///< Print the data of the given type
96
97 JCalibration* GetJCalibration();
98 template<class T> bool GetCalib(string namepath, map<string,T> &vals);
99 template<class T> bool GetCalib(string namepath, vector<T> &vals);
100 template<class T> bool GetCalib(string namepath, T &val);
101
102 JGeometry* GetJGeometry();
103 template<class T> bool GetGeom(string namepath, map<string,T> &vals);
104 template<class T> bool GetGeom(string namepath, T &val);
105
106 JResourceManager* GetJResourceManager(void);
107 string GetResource(string namepath);
108 template<class T> bool GetResource(string namepath, T vals, int event_number=0);
109
110 void Initialize(void); ///< Do initializations just before event processing starts
111 jerror_t Loop(void); ///< Loop over events
112 jerror_t OneEvent(uint64_t event_number); ///< Process a specific single event (if source supports it)
113 jerror_t OneEvent(void); ///< Process a single event
114 inline void Pause(void){pause = 1;} ///< Pause event processing
115 inline void Resume(void){pause = 0;} ///< Resume event processing
116 inline void Quit(void){quit = 1;} ///< Clean up and exit the event loop
117 inline bool GetQuit(void) const {return quit;}
118 void QuitProgram(void);
119
120 // Support for random access of events
121 bool HasRandomAccess(void);
122 void AddToEventQueue(uint64_t event_number){ next_events_to_process.push_back(event_number); }
123 void AddToEventQueue(list<uint64_t> &event_numbers) { next_events_to_process.insert(next_events_to_process.end(), event_numbers.begin(), event_numbers.end()); }
124 list<uint64_t> GetEventQueue(void){ return next_events_to_process; }
125 void ClearEventQueue(void){ next_events_to_process.clear(); }
126
127 template<class T> JFactory<T>* GetSingle(const T* &t, const char *tag="", bool exception_if_not_one=true); ///< Get pointer to first data object from (source or factory).
128 template<class T> JFactory<T>* Get(vector<const T*> &t, const char *tag="", bool allow_deftag=true); ///< Get data object pointers from (source or factory)
129 template<class T> JFactory<T>* GetFromFactory(vector<const T*> &t, const char *tag="", data_source_t &data_source=null_data_source, bool allow_deftag=true); ///< Get data object pointers from factory
130 template<class T> jerror_t GetFromSource(vector<const T*> &t, JFactory_base *factory=NULL__null); ///< Get data object pointers from source.
131 inline JEvent& GetJEvent(void){return event;} ///< Get pointer to the current JEvent object.
132 inline void SetJEvent(JEvent *event){this->event = *event;} ///< Set the JEvent pointer.
133 inline void SetAutoFree(int auto_free){this->auto_free = auto_free;} ///< Set the Auto-Free flag on/off
134 inline pthread_t GetPThreadID(void) const {return pthread_id;} ///< Get the pthread of the thread to which this JEventLoop belongs
135 double GetInstantaneousRate(void) const {return rate_instantaneous;} ///< Get the current event processing rate
136 double GetIntegratedRate(void) const {return rate_integrated;} ///< Get the current event processing rate
137 double GetLastEventProcessingTime(void) const {return delta_time_single;}
138 unsigned int GetNevents(void) const {return Nevents;}
139
140 inline bool CheckEventBoundary(uint64_t event_numberA, uint64_t event_numberB);
141
142 inline bool GetCallStackRecordingStatus(void){ return record_call_stack; }
143 inline void DisableCallStackRecording(void){ record_call_stack = false; }
144 inline void EnableCallStackRecording(void){ record_call_stack = true; }
145 inline void CallStackStart(JEventLoop::call_stack_t &cs, const string &caller_name, const string &caller_tag, const string callee_name, const string callee_tag);
146 inline void CallStackEnd(JEventLoop::call_stack_t &cs);
147 inline vector<call_stack_t> GetCallStack(void){return call_stack;} ///< Get the current factory call stack
148 inline void AddToCallStack(call_stack_t &cs){if(record_call_stack) call_stack.push_back(cs);} ///< Add specified item to call stack record but only if record_call_stack is true
149 inline void AddToErrorCallStack(error_call_stack_t &cs){error_call_stack.push_back(cs);} ///< Add layer to the factory call stack
150 inline vector<error_call_stack_t> GetErrorCallStack(void){return error_call_stack;} ///< Get the current factory error call stack
151 void PrintErrorCallStack(void); ///< Print the current factory call stack
152
153 const JObject* FindByID(JObject::oid_t id); ///< Find a data object by its identifier.
154 template<class T> const T* FindByID(JObject::oid_t id); ///< Find a data object by its type and identifier
155 JFactory_base* FindOwner(const JObject *t); ///< Find the factory that owns a data object by pointer
156 JFactory_base* FindOwner(JObject::oid_t id); ///< Find a factory that owns a data object by identifier
157
158 // User defined references
159 template<class T> void SetRef(T *t); ///< Add a user reference to this JEventLoop (must be a pointer)
160 template<class T> T* GetRef(void); ///< Get a user-defined reference of a specific type
161 template<class T> vector<T*> GetRefsT(void); ///< Get all user-defined refrences of a specicif type
162 vector<pair<const char*, void*> > GetRefs(void){ return user_refs; } ///< Get copy of full list of user-defined references
163 template<class T> void RemoveRef(T *t); ///< Remove user reference from list
164
165 // Convenience methods wrapping JEvent methods of same name
166 uint64_t GetStatus(void){return event.GetStatus();}
167 bool GetStatusBit(uint32_t bit){return event.GetStatusBit(bit);}
168 bool SetStatusBit(uint32_t bit, bool val=true){return event.SetStatusBit(bit, val);}
169 bool ClearStatusBit(uint32_t bit){return event.ClearStatusBit(bit);}
170 void ClearStatus(void){event.ClearStatus();}
171 void SetStatusBitDescription(uint32_t bit, string description){event.SetStatusBitDescription(bit, description);}
172 string GetStatusBitDescription(uint32_t bit){return event.GetStatusBitDescription(bit);}
173 void GetStatusBitDescriptions(map<uint32_t, string> &status_bit_descriptions){return event.GetStatusBitDescriptions(status_bit_descriptions);}
174 string StatusWordToString(void);
175
176 private:
177 JEvent event;
178 vector<JFactory_base*> factories;
179 vector<JEventProcessor*> processors;
180 vector<error_call_stack_t> error_call_stack;
181 vector<call_stack_t> call_stack;
182 JApplication *app;
183 JThread *jthread;
184 bool initialized;
185 bool print_parameters_called;
186 int pause;
187 int quit;
188 int auto_free;
189 pthread_t pthread_id;
190 map<string, string> default_tags;
191 vector<pair<string,string> > auto_activated_factories;
192 bool record_call_stack;
193 string caller_name;
194 string caller_tag;
195 vector<uint64_t> event_boundaries;
196 int32_t event_boundaries_run; ///< Run number boundaries were retrieved from (possbily 0)
197 list<uint64_t> next_events_to_process;
198
199 uint64_t Nevents; ///< Total events processed (this thread)
200 uint64_t Nevents_rate; ///< Num. events accumulated for "instantaneous" rate
201 double delta_time_single; ///< Time spent processing last event
202 double delta_time_rate; ///< Integrated time accumulated "instantaneous" rate (partial number of events)
203 double delta_time; ///< Total time spent processing events (this thread)
204 double rate_instantaneous; ///< Latest instantaneous rate
205 double rate_integrated; ///< Rate integrated over all events
206
207 static data_source_t null_data_source;
208
209 vector<pair<const char*, void*> > user_refs;
210};
211
212
213// The following is here just so we can use ROOT's THtml class to generate documentation.
214#ifdef G__DICTIONARY
215typedef JEventLoop::call_stack_t call_stack_t;
216typedef JEventLoop::error_call_stack_t error_call_stack_t;
217#endif
218
219#if !defined(__CINT__) && !defined(__CLING__)
220
221//-------------
222// GetSingle
223//-------------
224template<class T>
225JFactory<T>* JEventLoop::GetSingle(const T* &t, const char *tag, bool exception_if_not_one)
226{
227 /// This is a convenience method that can be used to get a pointer to the single
228 /// object of type T from the specified factory. It simply calls the Get(vector<...>) method
229 /// and copies the first pointer into "t" (or NULL if something other than 1 object is returned).
230 ///
231 /// This is intended to address the common situation in which there is an interest
232 /// in the event if and only if there is exactly 1 object of type T. If the event
233 /// has no objects of that type or more than 1 object of that type (for the specified
234 /// factory) then an exception of type "unsigned long" is thrown with the value
235 /// being the number of objects of type T. You can supress the exception by setting
236 /// exception_if_not_one to false. In that case, you will have to check if t==NULL to
237 /// know if the call succeeded.
238 vector<const T*> v;
239 JFactory<T> *fac = Get(v, tag);
240
241 if(v.size()!=1){
242 t = NULL__null;
243 if(exception_if_not_one) throw v.size();
244 }
245
246 t = v[0];
247
248 return fac;
249}
250
251//-------------
252// Get
253//-------------
254template<class T>
255JFactory<T>* JEventLoop::Get(vector<const T*> &t, const char *tag, bool allow_deftag)
256{
257 /// Retrieve or generate the array of objects of
258 /// type T for the curent event being processed
259 /// by this thread.
260 ///
261 /// By default, preference is given to reading the
262 /// objects from the data source(e.g. file) before generating
263 /// them in the factory. A flag exists in the factory
264 /// however to change this so that the factory is
265 /// given preference.
266 ///
267 /// Note that regardless of the setting of this flag,
268 /// the data are only either read in or generated once.
269 /// Ownership of the objects will always be with the
270 /// factory so subsequent calls will always return pointers to
271 /// the same data.
272 ///
273 /// If the factory is called on to generate the data,
274 /// it is done by calling the factory's Get() method
275 /// which, in turn, calls the evnt() method.
276 ///
277 /// First, we just call the GetFromFactory() method.
278 /// It will make the initial decision as to whether
279 /// it should look in the source first or not. If
280 /// it returns NULL, then the factory couldn't be
281 /// found so we automatically try the file.
282 ///
283 /// Note that if no factory exists to hold the objects
284 /// from the file, one can be created automatically
285 /// providing the <i>JANA:AUTOFACTORYCREATE</i>
286 /// configuration parameter is set.
287
288 // Check if a tag was specified for this data type to use for the
289 // default.
290 const char *mytag = tag
1.1
'tag' is not equal to NULL
1.1
'tag' is not equal to NULL
1.1
'tag' is not equal to NULL
==NULL__null ? "":tag; // protection against NULL tags
2
'?' condition is false
291 if(strlen(mytag)==0 && allow_deftag
2.1
'allow_deftag' is true
2.1
'allow_deftag' is true
2.1
'allow_deftag' is true
){
3
Taking true branch
292 map<string, string>::const_iterator iter = default_tags.find(T::static_className());
293 if(iter!=default_tags.end())tag = iter->second.c_str();
4
Assuming the condition is true
5
Taking true branch
6
Value assigned to 'tag'
294 }
295
296
297 // If we are trying to keep track of the call stack then we
298 // need to add a new call_stack_t object to the the list
299 // and initialize it with the start time and caller/callee
300 // info.
301 call_stack_t cs;
302
303 // Optionally record starting info of call stack entry
304 if(record_call_stack) CallStackStart(cs, caller_name, caller_tag, T::static_className(), tag);
7
Assuming field 'record_call_stack' is false
8
Taking false branch
305
306 // Get the data (or at least try to)
307 JFactory<T>* factory=NULL__null;
308 try{
309 factory = GetFromFactory(t, tag, cs.data_source, allow_deftag);
9
Passing value via 2nd parameter 'tag'
10
Calling 'JEventLoop::GetFromFactory'
310 if(!factory){
311 // No factory exists for this type and tag. It's possible
312 // that the source may be able to provide the objects
313 // but it will need a place to put them. We can create a
314 // dumb JFactory just to hold the data in case the source
315 // can provide the objects. Before we do though, make sure
316 // the user condones this via the presence of the
317 // "JANA:AUTOFACTORYCREATE" config parameter.
318 string p;
319 try{
320 gPARMS->GetParameter("JANA:AUTOFACTORYCREATE", p);
321 }catch(...){}
322 if(p.size()==0){
323 jout<<std::endl;
324 _DBG__std::cerr<<"/w/halld-scifs17exp/halld2/home/sdobbs/Software/jana/jana_0.8.2/Linux_CentOS7.7-x86_64-gcc4.8.5/include/JANA/JEventLoop.h"
<<":"<<324<<std::endl
;
325 jout<<"No factory of type \""<<T::static_className()<<"\" with tag \""<<tag<<"\" exists."<<std::endl;
326 jout<<"If you are reading objects from a file, I can auto-create a factory"<<std::endl;
327 jout<<"of the appropriate type to hold the objects, but this feature is turned"<<std::endl;
328 jout<<"off by default. To turn it on, set the \"JANA:AUTOFACTORYCREATE\""<<std::endl;
329 jout<<"configuration parameter. This can usually be done by passing the"<<std::endl;
330 jout<<"following argument to the program from the command line:"<<std::endl;
331 jout<<std::endl;
332 jout<<" -PJANA:AUTOFACTORYCREATE=1"<<std::endl;
333 jout<<std::endl;
334 jout<<"Note that since the most commonly expected occurance of this situation."<<std::endl;
335 jout<<"is an error, the program will now throw an exception so that the factory."<<std::endl;
336 jout<<"call stack can be printed."<<std::endl;
337 jout<<std::endl;
338 throw exception();
339 }else{
340 AddFactory(new JFactory<T>(tag));
341 jout<<__FILE__"/w/halld-scifs17exp/halld2/home/sdobbs/Software/jana/jana_0.8.2/Linux_CentOS7.7-x86_64-gcc4.8.5/include/JANA/JEventLoop.h"<<":"<<__LINE__341<<" Auto-created "<<T::static_className()<<":"<<tag<<" factory"<<std::endl;
342
343 // Now try once more. The GetFromFactory method will call
344 // GetFromSource since it's empty.
345 factory = GetFromFactory(t, tag, cs.data_source, allow_deftag);
346 }
347 }
348 }catch(exception &e){
349 // Uh-oh, an exception was thrown. Add us to the call stack
350 // and re-throw the exception
351 error_call_stack_t ecs;
352 ecs.factory_name = T::static_className();
353 ecs.tag = tag;
354 ecs.filename = NULL__null;
355 error_call_stack.push_back(ecs);
356 throw e;
357 }
358
359 // If recording the call stack, update the end_time field and add to stack
360 if(record_call_stack) CallStackEnd(cs);
361
362 return factory;
363}
364
365//-------------
366// GetFromFactory
367//-------------
368template<class T>
369JFactory<T>* JEventLoop::GetFromFactory(vector<const T*> &t, const char *tag, data_source_t &data_source, bool allow_deftag)
370{
371 // We need to find the factory providing data type T with
372 // tag given by "tag".
373 vector<JFactory_base*>::iterator iter=factories.begin();
374 JFactory<T> *factory = NULL__null;
375 string className(T::static_className());
376
377 // Check if a tag was specified for this data type to use for the
378 // default.
379 const char *mytag = tag==NULL__null ? "":tag; // protection against NULL tags
11
Assuming 'tag' is equal to NULL
12
Assuming pointer value is null
13
'?' condition is true
380 if(strlen(mytag)==0 && allow_deftag
13.1
'allow_deftag' is true
13.1
'allow_deftag' is true
13.1
'allow_deftag' is true
){
14
Taking true branch
381 map<string, string>::const_iterator iter = default_tags.find(className);
382 if(iter!=default_tags.end())tag = iter->second.c_str();
15
Assuming the condition is false
16
Taking false branch
383 }
384
385 for(; iter!=factories.end(); iter++){
17
Calling 'operator!=<jana::JFactory_base **, std::vector<jana::JFactory_base *>>'
20
Returning from 'operator!=<jana::JFactory_base **, std::vector<jana::JFactory_base *>>'
21
Loop condition is true. Entering loop body
386 // It turns out a long standing bug in g++ makes dynamic_cast return
387 // zero improperly when used on objects created on one side of
388 // a dynamically shared object (DSO) and the cast occurs on the
389 // other side. I saw bug reports ranging from 2001 to 2004. I saw
390 // saw it first-hand on LinuxEL4 using g++ 3.4.5. This is too bad
391 // since it is much more elegant (and safe) to use dynamic_cast.
392 // To avoid this problem which can occur with plugins, we check
393 // the name of the data classes are the same. (sigh)
394 //factory = dynamic_cast<JFactory<T> *>(*iter);
395 if(className == (*iter)->GetDataClassName())factory = (JFactory<T>*)(*iter);
22
Taking true branch
396 if(factory == NULL__null)continue;
23
Assuming 'factory' is not equal to NULL
24
Taking false branch
397 const char *factag = factory->Tag()==NULL__null ? "":factory->Tag();
25
Assuming the condition is true
26
'?' condition is true
398 if(!strcmp(factag, tag)){
27
Null pointer passed to 2nd parameter expecting 'nonnull'
399 break;
400 }else{
401 factory=NULL__null;
402 }
403 }
404
405 // If factory not found, just return now
406 if(!factory){
407 data_source = DATA_NOT_AVAILABLE;
408 return NULL__null;
409 }
410
411 // OK, we found the factory. If the evnt() routine has already
412 // been called, then just call the factory's Get() routine
413 // to return a copy of the existing data
414 if(factory->evnt_was_called()){
415 factory->CopyFrom(t);
416 data_source = DATA_FROM_CACHE;
417 return factory;
418 }
419
420 // Next option is to get the objects from the data source
421 if(factory->GetCheckSourceFirst()){
422 // If the object type/tag is found in the source, it
423 // will return NOERROR, even if there are zero instances
424 // of it. If it is not available in the source then it
425 // will return OBJECT_NOT_AVAILABLE.
426
427 jerror_t err = GetFromSource(t, factory);
428 if(err == NOERROR){
429 // A return value of NOERROR means the source had the objects
430 // even if there were zero of them.(If the source had no
431 // information about the objects OBJECT_NOT_AVAILABLE would
432 // have been returned.)
433 // The GetFromSource() call will eventually lead to a call to
434 // the GetObjects() method of the concrete class derived
435 // from JEventSource. That routine should copy the object
436 // pointers into the factory using the factory's CopyTo()
437 // method which also sets the evnt_called flag for the factory.
438 // Note also that the "t" vector is then filled with a call
439 // to the factory's CopyFrom() method in JEvent::GetObjects().
440 // All we need to do now is just set the factory pointers in
441 // the newly generated JObjects and return the factory pointer.
442
443 factory->SetFactoryPointers();
444 data_source = DATA_FROM_SOURCE;
445
446 return factory;
447 }
448 }
449
450 // OK. It looks like we have to have the factory make this.
451 // Get pointers to data from the factory.
452 factory->Get(t);
453 factory->SetFactoryPointers();
454 data_source = DATA_FROM_FACTORY;
455
456 return factory;
457}
458
459//-------------
460// GetFromSource
461//-------------
462template<class T>
463jerror_t JEventLoop::GetFromSource(vector<const T*> &t, JFactory_base *factory)
464{
465 /// This tries to get objects from the event source.
466 /// "factory" must be a valid pointer to a JFactory
467 /// object since that will take ownership of the objects
468 /// created by the source.
469 /// This should usually be called from JEventLoop::GetFromFactory
470 /// which is called from JEventLoop::Get. The latter will
471 /// create a dummy JFactory of the proper flavor and tag if
472 /// one does not already exist so if objects exist in the
473 /// file without a corresponding factory to create them, they
474 /// can still be used.
475 if(!factory)throw OBJECT_NOT_AVAILABLE;
476
477 return event.GetObjects(t, factory);
478}
479
480//-------------
481// CallStackStart
482//-------------
483inline void JEventLoop::CallStackStart(JEventLoop::call_stack_t &cs, const string &caller_name, const string &caller_tag, const string callee_name, const string callee_tag)
484{
485 /// This is used to fill initial info into a call_stack_t stucture
486 /// for recording the call stack. It should be matched with a call
487 /// to CallStackEnd. It is normally called from the Get() method
488 /// above, but may also be used by external actors to manipulate
489 /// the call stack (presumably for good and not evil).
490
491 struct itimerval tmr;
492 getitimer(ITIMER_PROFITIMER_PROF, &tmr);
493
494 cs.caller_name = this->caller_name;
495 cs.caller_tag = this->caller_tag;
496 this->caller_name = cs.callee_name = callee_name;
497 this->caller_tag = cs.callee_tag = callee_tag;
498 cs.start_time = tmr.it_value.tv_sec + tmr.it_value.tv_usec/1.0E6;
499}
500
501//-------------
502// CallStackEnd
503//-------------
504inline void JEventLoop::CallStackEnd(JEventLoop::call_stack_t &cs)
505{
506 /// Complete a call stack entry. This should be matched
507 /// with a previous call to CallStackStart which was
508 /// used to fill the cs structure.
509
510 struct itimerval tmr;
511 getitimer(ITIMER_PROFITIMER_PROF, &tmr);
512 cs.end_time = tmr.it_value.tv_sec + tmr.it_value.tv_usec/1.0E6;
513 caller_name = cs.caller_name;
514 caller_tag = cs.caller_tag;
515 call_stack.push_back(cs);
516}
517
518//-------------
519// CheckEventBoundary
520//-------------
521inline bool JEventLoop::CheckEventBoundary(uint64_t event_numberA, uint64_t event_numberB)
522{
523 /// Check whether the two event numbers span one or more boundaries
524 /// in the calibration/conditions database for the current run number.
525 /// Return true if they do and false if they don't. The first parameter
526 /// "event_numberA" is also checked if it lands on a boundary in which
527 /// case true is also returned. If event_numberB lands on a boundary,
528 /// but event_numberA does not, then false is returned.
529 ///
530 /// This method is not expected to be called by a user. It is, however called,
531 /// everytime a JFactory's Get() method is called.
532
533 // Make sure our copy of the boundaries is up to date
534 if(event.GetRunNumber()!=event_boundaries_run){
535 event_boundaries.clear(); // in case we can't get the JCalibration pointer
536 JCalibration *jcalib = GetJCalibration();
537 if(jcalib)jcalib->GetEventBoundaries(event_boundaries);
538 event_boundaries_run = event.GetRunNumber();
539 }
540
541 // Loop over boundaries
542 for(unsigned int i=0; i<event_boundaries.size(); i++){
543 uint64_t eb = event_boundaries[i];
544 if((eb - event_numberA)*(eb - event_numberB) < 0.0 || eb==event_numberA){ // think about it ....
545 // events span a boundary or is on a boundary. Return true
546 return true;
547 }
548 }
549
550 return false;
551}
552
553//-------------
554// FindByID
555//-------------
556template<class T>
557const T* JEventLoop::FindByID(JObject::oid_t id)
558{
559 /// This is a templated method that can be used in place
560 /// of the non-templated FindByID(oid_t) method if one knows
561 /// the class of the object with the specified id.
562 /// This method is faster than calling the non-templated
563 /// FindByID and dynamic_cast-ing the JObject since
564 /// this will only search the objects of factories that
565 /// produce the desired data type.
566 /// This method will cast the JObject pointer to one
567 /// of the specified type. To use this method,
568 /// a type is specified in the call as follows:
569 ///
570 /// const DMyType *t = loop->FindByID<DMyType>(id);
571
572 // Loop over factories looking for ones that provide
573 // specified data type.
574 for(unsigned int i=0; i<factories.size(); i++){
575 if(factories[i]->GetDataClassName() != T::static_className())continue;
576
577 // This factory provides data of type T. Search it for
578 // the object with the specified id.
579 const JObject *my_obj = factories[i]->GetByID(id);
580 if(my_obj)return dynamic_cast<const T*>(my_obj);
581 }
582
583 return NULL__null;
584}
585
586//-------------
587// GetCalib (map)
588//-------------
589template<class T>
590bool JEventLoop::GetCalib(string namepath, map<string,T> &vals)
591{
592 /// Get the JCalibration object from JApplication for the run number of
593 /// the current event and call its Get() method to get the constants.
594
595 // Note that we could do this by making "vals" a generic type T thus, combining
596 // this with the vector version below. However, doing this explicitly will make
597 // it easier for the user to understand how to call us.
598
599 vals.clear();
600
601 JCalibration *calib = GetJCalibration();
602 if(!calib){
603 _DBG_std::cerr<<"/w/halld-scifs17exp/halld2/home/sdobbs/Software/jana/jana_0.8.2/Linux_CentOS7.7-x86_64-gcc4.8.5/include/JANA/JEventLoop.h"
<<":"<<603<<" "
<<"Unable to get JCalibration object for run "<<event.GetRunNumber()<<std::endl;
604 return true;
605 }
606
607 return calib->Get(namepath, vals, event.GetEventNumber());
608}
609
610//-------------
611// GetCalib (vector)
612//-------------
613template<class T> bool JEventLoop::GetCalib(string namepath, vector<T> &vals)
614{
615 /// Get the JCalibration object from JApplication for the run number of
616 /// the current event and call its Get() method to get the constants.
617
618 vals.clear();
619
620 JCalibration *calib = GetJCalibration();
621 if(!calib){
622 _DBG_std::cerr<<"/w/halld-scifs17exp/halld2/home/sdobbs/Software/jana/jana_0.8.2/Linux_CentOS7.7-x86_64-gcc4.8.5/include/JANA/JEventLoop.h"
<<":"<<622<<" "
<<"Unable to get JCalibration object for run "<<event.GetRunNumber()<<std::endl;
623 return true;
624 }
625
626 return calib->Get(namepath, vals, event.GetEventNumber());
627}
628
629//-------------
630// GetCalib (single)
631//-------------
632template<class T> bool JEventLoop::GetCalib(string namepath, T &val)
633{
634 /// This is a convenience method for getting a single entry. It
635 /// simply calls the vector version and returns the first entry.
636 /// It returns true if the vector version returns true AND there
637 /// is at least one entry in the vector. No check is made for there
638 /// there being more than one entry in the vector.
639
640 vector<T> vals;
641 bool ret = GetCalib(namepath, vals);
642 if(vals.empty()) return true;
643 val = vals[0];
644
645 return ret;
646}
647
648//-------------
649// GetGeom (map)
650//-------------
651template<class T>
652bool JEventLoop::GetGeom(string namepath, map<string,T> &vals)
653{
654 /// Get the JGeometry object from JApplication for the run number of
655 /// the current event and call its Get() method to get the constants.
656
657 // Note that we could do this by making "vals" a generic type T thus, combining
658 // this with the vector version below. However, doing this explicitly will make
659 // it easier for the user to understand how to call us.
660
661 vals.clear();
662
663 JGeometry *geom = GetJGeometry();
664 if(!geom){
665 _DBG_std::cerr<<"/w/halld-scifs17exp/halld2/home/sdobbs/Software/jana/jana_0.8.2/Linux_CentOS7.7-x86_64-gcc4.8.5/include/JANA/JEventLoop.h"
<<":"<<665<<" "
<<"Unable to get JGeometry object for run "<<event.GetRunNumber()<<std::endl;
666 return true;
667 }
668
669 return geom->Get(namepath, vals);
670}
671
672//-------------
673// GetGeom (atomic)
674//-------------
675template<class T> bool JEventLoop::GetGeom(string namepath, T &val)
676{
677 /// Get the JCalibration object from JApplication for the run number of
678 /// the current event and call its Get() method to get the constants.
679
680 JGeometry *geom = GetJGeometry();
681 if(!geom){
682 _DBG_std::cerr<<"/w/halld-scifs17exp/halld2/home/sdobbs/Software/jana/jana_0.8.2/Linux_CentOS7.7-x86_64-gcc4.8.5/include/JANA/JEventLoop.h"
<<":"<<682<<" "
<<"Unable to get JGeometry object for run "<<event.GetRunNumber()<<std::endl;
683 return true;
684 }
685
686 return geom->Get(namepath, val);
687}
688
689//-------------
690// SetRef
691//-------------
692template<class T>
693void JEventLoop::SetRef(T *t)
694{
695 pair<const char*, void*> p(typeid(T).name(), (void*)t);
696 user_refs.push_back(p);
697}
698
699//-------------
700// GetResource
701//-------------
702template<class T> bool JEventLoop::GetResource(string namepath, T vals, int event_number)
703{
704 JResourceManager *resource_manager = GetJResourceManager();
705 if(!resource_manager){
706 string mess = string("Unable to get the JResourceManager object (namepath=\"")+namepath+"\")";
707 throw JException(mess);
708 }
709
710 return resource_manager->Get(namepath, vals, event_number);
711}
712
713//-------------
714// GetRef
715//-------------
716template<class T>
717T* JEventLoop::GetRef(void)
718{
719 /// Get a user-defined reference (a pointer)
720 for(unsigned int i=0; i<user_refs.size(); i++){
721 if(user_refs[i].first == typeid(T).name()) return (T*)user_refs[i].second;
722 }
723
724 return NULL__null;
725}
726
727//-------------
728// GetRefsT
729//-------------
730template<class T>
731vector<T*> JEventLoop::GetRefsT(void)
732{
733 vector<T*> refs;
734 for(unsigned int i=0; i<user_refs.size(); i++){
735 if(user_refs[i].first == typeid(T).name()){
736 refs.push_back((T*)user_refs[i].second);
737 }
738 }
739
740 return refs;
741}
742
743//-------------
744// RemoveRef
745//-------------
746template<class T>
747void JEventLoop::RemoveRef(T *t)
748{
749 vector<pair<const char*, void*> >::iterator iter;
750 for(iter=user_refs.begin(); iter!= user_refs.end(); iter++){
751 if(iter->second == (void*)t){
752 user_refs.erase(iter);
753 return;
754 }
755 }
756 _DBG_std::cerr<<"/w/halld-scifs17exp/halld2/home/sdobbs/Software/jana/jana_0.8.2/Linux_CentOS7.7-x86_64-gcc4.8.5/include/JANA/JEventLoop.h"
<<":"<<756<<" "
<<" Attempt to remove user reference not in event loop!" << std::endl;
757}
758
759
760#endif //__CINT__ __CLING__
761
762} // Close JANA namespace
763
764
765
766#endif // _JEventLoop_
767

/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../include/c++/4.8.5/bits/stl_iterator.h

1// Iterators -*- C++ -*-
2
3// Copyright (C) 2001-2013 Free Software Foundation, Inc.
4//
5// This file is part of the GNU ISO C++ Library. This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 3, or (at your option)
9// any later version.
10
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
19
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23// <http://www.gnu.org/licenses/>.
24
25/*
26 *
27 * Copyright (c) 1994
28 * Hewlett-Packard Company
29 *
30 * Permission to use, copy, modify, distribute and sell this software
31 * and its documentation for any purpose is hereby granted without fee,
32 * provided that the above copyright notice appear in all copies and
33 * that both that copyright notice and this permission notice appear
34 * in supporting documentation. Hewlett-Packard Company makes no
35 * representations about the suitability of this software for any
36 * purpose. It is provided "as is" without express or implied warranty.
37 *
38 *
39 * Copyright (c) 1996-1998
40 * Silicon Graphics Computer Systems, Inc.
41 *
42 * Permission to use, copy, modify, distribute and sell this software
43 * and its documentation for any purpose is hereby granted without fee,
44 * provided that the above copyright notice appear in all copies and
45 * that both that copyright notice and this permission notice appear
46 * in supporting documentation. Silicon Graphics makes no
47 * representations about the suitability of this software for any
48 * purpose. It is provided "as is" without express or implied warranty.
49 */
50
51/** @file bits/stl_iterator.h
52 * This is an internal header file, included by other library headers.
53 * Do not attempt to use it directly. @headername{iterator}
54 *
55 * This file implements reverse_iterator, back_insert_iterator,
56 * front_insert_iterator, insert_iterator, __normal_iterator, and their
57 * supporting functions and overloaded operators.
58 */
59
60#ifndef _STL_ITERATOR_H1
61#define _STL_ITERATOR_H1 1
62
63#include <bits/cpp_type_traits.h>
64#include <ext/type_traits.h>
65#include <bits/move.h>
66
67namespace std _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default")))
68{
69_GLIBCXX_BEGIN_NAMESPACE_VERSION
70
71 /**
72 * @addtogroup iterators
73 * @{
74 */
75
76 // 24.4.1 Reverse iterators
77 /**
78 * Bidirectional and random access iterators have corresponding reverse
79 * %iterator adaptors that iterate through the data structure in the
80 * opposite direction. They have the same signatures as the corresponding
81 * iterators. The fundamental relation between a reverse %iterator and its
82 * corresponding %iterator @c i is established by the identity:
83 * @code
84 * &*(reverse_iterator(i)) == &*(i - 1)
85 * @endcode
86 *
87 * <em>This mapping is dictated by the fact that while there is always a
88 * pointer past the end of an array, there might not be a valid pointer
89 * before the beginning of an array.</em> [24.4.1]/1,2
90 *
91 * Reverse iterators can be tricky and surprising at first. Their
92 * semantics make sense, however, and the trickiness is a side effect of
93 * the requirement that the iterators must be safe.
94 */
95 template<typename _Iterator>
96 class reverse_iterator
97 : public iterator<typename iterator_traits<_Iterator>::iterator_category,
98 typename iterator_traits<_Iterator>::value_type,
99 typename iterator_traits<_Iterator>::difference_type,
100 typename iterator_traits<_Iterator>::pointer,
101 typename iterator_traits<_Iterator>::reference>
102 {
103 protected:
104 _Iterator current;
105
106 typedef iterator_traits<_Iterator> __traits_type;
107
108 public:
109 typedef _Iterator iterator_type;
110 typedef typename __traits_type::difference_type difference_type;
111 typedef typename __traits_type::pointer pointer;
112 typedef typename __traits_type::reference reference;
113
114 /**
115 * The default constructor value-initializes member @p current.
116 * If it is a pointer, that means it is zero-initialized.
117 */
118 // _GLIBCXX_RESOLVE_LIB_DEFECTS
119 // 235 No specification of default ctor for reverse_iterator
120 reverse_iterator() : current() { }
121
122 /**
123 * This %iterator will move in the opposite direction that @p x does.
124 */
125 explicit
126 reverse_iterator(iterator_type __x) : current(__x) { }
127
128 /**
129 * The copy constructor is normal.
130 */
131 reverse_iterator(const reverse_iterator& __x)
132 : current(__x.current) { }
133
134 /**
135 * A %reverse_iterator across other types can be copied if the
136 * underlying %iterator can be converted to the type of @c current.
137 */
138 template<typename _Iter>
139 reverse_iterator(const reverse_iterator<_Iter>& __x)
140 : current(__x.base()) { }
141
142 /**
143 * @return @c current, the %iterator used for underlying work.
144 */
145 iterator_type
146 base() const
147 { return current; }
148
149 /**
150 * @return A reference to the value at @c --current
151 *
152 * This requires that @c --current is dereferenceable.
153 *
154 * @warning This implementation requires that for an iterator of the
155 * underlying iterator type, @c x, a reference obtained by
156 * @c *x remains valid after @c x has been modified or
157 * destroyed. This is a bug: http://gcc.gnu.org/PR51823
158 */
159 reference
160 operator*() const
161 {
162 _Iterator __tmp = current;
163 return *--__tmp;
164 }
165
166 /**
167 * @return A pointer to the value at @c --current
168 *
169 * This requires that @c --current is dereferenceable.
170 */
171 pointer
172 operator->() const
173 { return &(operator*()); }
174
175 /**
176 * @return @c *this
177 *
178 * Decrements the underlying iterator.
179 */
180 reverse_iterator&
181 operator++()
182 {
183 --current;
184 return *this;
185 }
186
187 /**
188 * @return The original value of @c *this
189 *
190 * Decrements the underlying iterator.
191 */
192 reverse_iterator
193 operator++(int)
194 {
195 reverse_iterator __tmp = *this;
196 --current;
197 return __tmp;
198 }
199
200 /**
201 * @return @c *this
202 *
203 * Increments the underlying iterator.
204 */
205 reverse_iterator&
206 operator--()
207 {
208 ++current;
209 return *this;
210 }
211
212 /**
213 * @return A reverse_iterator with the previous value of @c *this
214 *
215 * Increments the underlying iterator.
216 */
217 reverse_iterator
218 operator--(int)
219 {
220 reverse_iterator __tmp = *this;
221 ++current;
222 return __tmp;
223 }
224
225 /**
226 * @return A reverse_iterator that refers to @c current - @a __n
227 *
228 * The underlying iterator must be a Random Access Iterator.
229 */
230 reverse_iterator
231 operator+(difference_type __n) const
232 { return reverse_iterator(current - __n); }
233
234 /**
235 * @return *this
236 *
237 * Moves the underlying iterator backwards @a __n steps.
238 * The underlying iterator must be a Random Access Iterator.
239 */
240 reverse_iterator&
241 operator+=(difference_type __n)
242 {
243 current -= __n;
244 return *this;
245 }
246
247 /**
248 * @return A reverse_iterator that refers to @c current - @a __n
249 *
250 * The underlying iterator must be a Random Access Iterator.
251 */
252 reverse_iterator
253 operator-(difference_type __n) const
254 { return reverse_iterator(current + __n); }
255
256 /**
257 * @return *this
258 *
259 * Moves the underlying iterator forwards @a __n steps.
260 * The underlying iterator must be a Random Access Iterator.
261 */
262 reverse_iterator&
263 operator-=(difference_type __n)
264 {
265 current += __n;
266 return *this;
267 }
268
269 /**
270 * @return The value at @c current - @a __n - 1
271 *
272 * The underlying iterator must be a Random Access Iterator.
273 */
274 reference
275 operator[](difference_type __n) const
276 { return *(*this + __n); }
277 };
278
279 //@{
280 /**
281 * @param __x A %reverse_iterator.
282 * @param __y A %reverse_iterator.
283 * @return A simple bool.
284 *
285 * Reverse iterators forward many operations to their underlying base()
286 * iterators. Others are implemented in terms of one another.
287 *
288 */
289 template<typename _Iterator>
290 inline bool
291 operator==(const reverse_iterator<_Iterator>& __x,
292 const reverse_iterator<_Iterator>& __y)
293 { return __x.base() == __y.base(); }
294
295 template<typename _Iterator>
296 inline bool
297 operator<(const reverse_iterator<_Iterator>& __x,
298 const reverse_iterator<_Iterator>& __y)
299 { return __y.base() < __x.base(); }
300
301 template<typename _Iterator>
302 inline bool
303 operator!=(const reverse_iterator<_Iterator>& __x,
304 const reverse_iterator<_Iterator>& __y)
305 { return !(__x == __y); }
306
307 template<typename _Iterator>
308 inline bool
309 operator>(const reverse_iterator<_Iterator>& __x,
310 const reverse_iterator<_Iterator>& __y)
311 { return __y < __x; }
312
313 template<typename _Iterator>
314 inline bool
315 operator<=(const reverse_iterator<_Iterator>& __x,
316 const reverse_iterator<_Iterator>& __y)
317 { return !(__y < __x); }
318
319 template<typename _Iterator>
320 inline bool
321 operator>=(const reverse_iterator<_Iterator>& __x,
322 const reverse_iterator<_Iterator>& __y)
323 { return !(__x < __y); }
324
325 template<typename _Iterator>
326 inline typename reverse_iterator<_Iterator>::difference_type
327 operator-(const reverse_iterator<_Iterator>& __x,
328 const reverse_iterator<_Iterator>& __y)
329 { return __y.base() - __x.base(); }
330
331 template<typename _Iterator>
332 inline reverse_iterator<_Iterator>
333 operator+(typename reverse_iterator<_Iterator>::difference_type __n,
334 const reverse_iterator<_Iterator>& __x)
335 { return reverse_iterator<_Iterator>(__x.base() - __n); }
336
337 // _GLIBCXX_RESOLVE_LIB_DEFECTS
338 // DR 280. Comparison of reverse_iterator to const reverse_iterator.
339 template<typename _IteratorL, typename _IteratorR>
340 inline bool
341 operator==(const reverse_iterator<_IteratorL>& __x,
342 const reverse_iterator<_IteratorR>& __y)
343 { return __x.base() == __y.base(); }
344
345 template<typename _IteratorL, typename _IteratorR>
346 inline bool
347 operator<(const reverse_iterator<_IteratorL>& __x,
348 const reverse_iterator<_IteratorR>& __y)
349 { return __y.base() < __x.base(); }
350
351 template<typename _IteratorL, typename _IteratorR>
352 inline bool
353 operator!=(const reverse_iterator<_IteratorL>& __x,
354 const reverse_iterator<_IteratorR>& __y)
355 { return !(__x == __y); }
356
357 template<typename _IteratorL, typename _IteratorR>
358 inline bool
359 operator>(const reverse_iterator<_IteratorL>& __x,
360 const reverse_iterator<_IteratorR>& __y)
361 { return __y < __x; }
362
363 template<typename _IteratorL, typename _IteratorR>
364 inline bool
365 operator<=(const reverse_iterator<_IteratorL>& __x,
366 const reverse_iterator<_IteratorR>& __y)
367 { return !(__y < __x); }
368
369 template<typename _IteratorL, typename _IteratorR>
370 inline bool
371 operator>=(const reverse_iterator<_IteratorL>& __x,
372 const reverse_iterator<_IteratorR>& __y)
373 { return !(__x < __y); }
374
375 template<typename _IteratorL, typename _IteratorR>
376#if __cplusplus201103L >= 201103L
377 // DR 685.
378 inline auto
379 operator-(const reverse_iterator<_IteratorL>& __x,
380 const reverse_iterator<_IteratorR>& __y)
381 -> decltype(__y.base() - __x.base())
382#else
383 inline typename reverse_iterator<_IteratorL>::difference_type
384 operator-(const reverse_iterator<_IteratorL>& __x,
385 const reverse_iterator<_IteratorR>& __y)
386#endif
387 { return __y.base() - __x.base(); }
388 //@}
389
390 // 24.4.2.2.1 back_insert_iterator
391 /**
392 * @brief Turns assignment into insertion.
393 *
394 * These are output iterators, constructed from a container-of-T.
395 * Assigning a T to the iterator appends it to the container using
396 * push_back.
397 *
398 * Tip: Using the back_inserter function to create these iterators can
399 * save typing.
400 */
401 template<typename _Container>
402 class back_insert_iterator
403 : public iterator<output_iterator_tag, void, void, void, void>
404 {
405 protected:
406 _Container* container;
407
408 public:
409 /// A nested typedef for the type of whatever container you used.
410 typedef _Container container_type;
411
412 /// The only way to create this %iterator is with a container.
413 explicit
414 back_insert_iterator(_Container& __x) : container(&__x) { }
415
416 /**
417 * @param __value An instance of whatever type
418 * container_type::const_reference is; presumably a
419 * reference-to-const T for container<T>.
420 * @return This %iterator, for chained operations.
421 *
422 * This kind of %iterator doesn't really have a @a position in the
423 * container (you can think of the position as being permanently at
424 * the end, if you like). Assigning a value to the %iterator will
425 * always append the value to the end of the container.
426 */
427#if __cplusplus201103L < 201103L
428 back_insert_iterator&
429 operator=(typename _Container::const_reference __value)
430 {
431 container->push_back(__value);
432 return *this;
433 }
434#else
435 back_insert_iterator&
436 operator=(const typename _Container::value_type& __value)
437 {
438 container->push_back(__value);
439 return *this;
440 }
441
442 back_insert_iterator&
443 operator=(typename _Container::value_type&& __value)
444 {
445 container->push_back(std::move(__value));
446 return *this;
447 }
448#endif
449
450 /// Simply returns *this.
451 back_insert_iterator&
452 operator*()
453 { return *this; }
454
455 /// Simply returns *this. (This %iterator does not @a move.)
456 back_insert_iterator&
457 operator++()
458 { return *this; }
459
460 /// Simply returns *this. (This %iterator does not @a move.)
461 back_insert_iterator
462 operator++(int)
463 { return *this; }
464 };
465
466 /**
467 * @param __x A container of arbitrary type.
468 * @return An instance of back_insert_iterator working on @p __x.
469 *
470 * This wrapper function helps in creating back_insert_iterator instances.
471 * Typing the name of the %iterator requires knowing the precise full
472 * type of the container, which can be tedious and impedes generic
473 * programming. Using this function lets you take advantage of automatic
474 * template parameter deduction, making the compiler match the correct
475 * types for you.
476 */
477 template<typename _Container>
478 inline back_insert_iterator<_Container>
479 back_inserter(_Container& __x)
480 { return back_insert_iterator<_Container>(__x); }
481
482 /**
483 * @brief Turns assignment into insertion.
484 *
485 * These are output iterators, constructed from a container-of-T.
486 * Assigning a T to the iterator prepends it to the container using
487 * push_front.
488 *
489 * Tip: Using the front_inserter function to create these iterators can
490 * save typing.
491 */
492 template<typename _Container>
493 class front_insert_iterator
494 : public iterator<output_iterator_tag, void, void, void, void>
495 {
496 protected:
497 _Container* container;
498
499 public:
500 /// A nested typedef for the type of whatever container you used.
501 typedef _Container container_type;
502
503 /// The only way to create this %iterator is with a container.
504 explicit front_insert_iterator(_Container& __x) : container(&__x) { }
505
506 /**
507 * @param __value An instance of whatever type
508 * container_type::const_reference is; presumably a
509 * reference-to-const T for container<T>.
510 * @return This %iterator, for chained operations.
511 *
512 * This kind of %iterator doesn't really have a @a position in the
513 * container (you can think of the position as being permanently at
514 * the front, if you like). Assigning a value to the %iterator will
515 * always prepend the value to the front of the container.
516 */
517#if __cplusplus201103L < 201103L
518 front_insert_iterator&
519 operator=(typename _Container::const_reference __value)
520 {
521 container->push_front(__value);
522 return *this;
523 }
524#else
525 front_insert_iterator&
526 operator=(const typename _Container::value_type& __value)
527 {
528 container->push_front(__value);
529 return *this;
530 }
531
532 front_insert_iterator&
533 operator=(typename _Container::value_type&& __value)
534 {
535 container->push_front(std::move(__value));
536 return *this;
537 }
538#endif
539
540 /// Simply returns *this.
541 front_insert_iterator&
542 operator*()
543 { return *this; }
544
545 /// Simply returns *this. (This %iterator does not @a move.)
546 front_insert_iterator&
547 operator++()
548 { return *this; }
549
550 /// Simply returns *this. (This %iterator does not @a move.)
551 front_insert_iterator
552 operator++(int)
553 { return *this; }
554 };
555
556 /**
557 * @param __x A container of arbitrary type.
558 * @return An instance of front_insert_iterator working on @p x.
559 *
560 * This wrapper function helps in creating front_insert_iterator instances.
561 * Typing the name of the %iterator requires knowing the precise full
562 * type of the container, which can be tedious and impedes generic
563 * programming. Using this function lets you take advantage of automatic
564 * template parameter deduction, making the compiler match the correct
565 * types for you.
566 */
567 template<typename _Container>
568 inline front_insert_iterator<_Container>
569 front_inserter(_Container& __x)
570 { return front_insert_iterator<_Container>(__x); }
571
572 /**
573 * @brief Turns assignment into insertion.
574 *
575 * These are output iterators, constructed from a container-of-T.
576 * Assigning a T to the iterator inserts it in the container at the
577 * %iterator's position, rather than overwriting the value at that
578 * position.
579 *
580 * (Sequences will actually insert a @e copy of the value before the
581 * %iterator's position.)
582 *
583 * Tip: Using the inserter function to create these iterators can
584 * save typing.
585 */
586 template<typename _Container>
587 class insert_iterator
588 : public iterator<output_iterator_tag, void, void, void, void>
589 {
590 protected:
591 _Container* container;
592 typename _Container::iterator iter;
593
594 public:
595 /// A nested typedef for the type of whatever container you used.
596 typedef _Container container_type;
597
598 /**
599 * The only way to create this %iterator is with a container and an
600 * initial position (a normal %iterator into the container).
601 */
602 insert_iterator(_Container& __x, typename _Container::iterator __i)
603 : container(&__x), iter(__i) {}
604
605 /**
606 * @param __value An instance of whatever type
607 * container_type::const_reference is; presumably a
608 * reference-to-const T for container<T>.
609 * @return This %iterator, for chained operations.
610 *
611 * This kind of %iterator maintains its own position in the
612 * container. Assigning a value to the %iterator will insert the
613 * value into the container at the place before the %iterator.
614 *
615 * The position is maintained such that subsequent assignments will
616 * insert values immediately after one another. For example,
617 * @code
618 * // vector v contains A and Z
619 *
620 * insert_iterator i (v, ++v.begin());
621 * i = 1;
622 * i = 2;
623 * i = 3;
624 *
625 * // vector v contains A, 1, 2, 3, and Z
626 * @endcode
627 */
628#if __cplusplus201103L < 201103L
629 insert_iterator&
630 operator=(typename _Container::const_reference __value)
631 {
632 iter = container->insert(iter, __value);
633 ++iter;
634 return *this;
635 }
636#else
637 insert_iterator&
638 operator=(const typename _Container::value_type& __value)
639 {
640 iter = container->insert(iter, __value);
641 ++iter;
642 return *this;
643 }
644
645 insert_iterator&
646 operator=(typename _Container::value_type&& __value)
647 {
648 iter = container->insert(iter, std::move(__value));
649 ++iter;
650 return *this;
651 }
652#endif
653
654 /// Simply returns *this.
655 insert_iterator&
656 operator*()
657 { return *this; }
658
659 /// Simply returns *this. (This %iterator does not @a move.)
660 insert_iterator&
661 operator++()
662 { return *this; }
663
664 /// Simply returns *this. (This %iterator does not @a move.)
665 insert_iterator&
666 operator++(int)
667 { return *this; }
668 };
669
670 /**
671 * @param __x A container of arbitrary type.
672 * @return An instance of insert_iterator working on @p __x.
673 *
674 * This wrapper function helps in creating insert_iterator instances.
675 * Typing the name of the %iterator requires knowing the precise full
676 * type of the container, which can be tedious and impedes generic
677 * programming. Using this function lets you take advantage of automatic
678 * template parameter deduction, making the compiler match the correct
679 * types for you.
680 */
681 template<typename _Container, typename _Iterator>
682 inline insert_iterator<_Container>
683 inserter(_Container& __x, _Iterator __i)
684 {
685 return insert_iterator<_Container>(__x,
686 typename _Container::iterator(__i));
687 }
688
689 // @} group iterators
690
691_GLIBCXX_END_NAMESPACE_VERSION
692} // namespace
693
694namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default")))
695{
696_GLIBCXX_BEGIN_NAMESPACE_VERSION
697
698 // This iterator adapter is @a normal in the sense that it does not
699 // change the semantics of any of the operators of its iterator
700 // parameter. Its primary purpose is to convert an iterator that is
701 // not a class, e.g. a pointer, into an iterator that is a class.
702 // The _Container parameter exists solely so that different containers
703 // using this template can instantiate different types, even if the
704 // _Iterator parameter is the same.
705 using std::iterator_traits;
706 using std::iterator;
707 template<typename _Iterator, typename _Container>
708 class __normal_iterator
709 {
710 protected:
711 _Iterator _M_current;
712
713 typedef iterator_traits<_Iterator> __traits_type;
714
715 public:
716 typedef _Iterator iterator_type;
717 typedef typename __traits_type::iterator_category iterator_category;
718 typedef typename __traits_type::value_type value_type;
719 typedef typename __traits_type::difference_type difference_type;
720 typedef typename __traits_type::reference reference;
721 typedef typename __traits_type::pointer pointer;
722
723 _GLIBCXX_CONSTEXPRconstexpr __normal_iterator() : _M_current(_Iterator()) { }
724
725 explicit
726 __normal_iterator(const _Iterator& __i) : _M_current(__i) { }
727
728 // Allow iterator to const_iterator conversion
729 template<typename _Iter>
730 __normal_iterator(const __normal_iterator<_Iter,
731 typename __enable_if<
732 (std::__are_same<_Iter, typename _Container::pointer>::__value),
733 _Container>::__type>& __i)
734 : _M_current(__i.base()) { }
735
736 // Forward iterator requirements
737 reference
738 operator*() const
739 { return *_M_current; }
740
741 pointer
742 operator->() const
743 { return _M_current; }
744
745 __normal_iterator&
746 operator++()
747 {
748 ++_M_current;
749 return *this;
750 }
751
752 __normal_iterator
753 operator++(int)
754 { return __normal_iterator(_M_current++); }
755
756 // Bidirectional iterator requirements
757 __normal_iterator&
758 operator--()
759 {
760 --_M_current;
761 return *this;
762 }
763
764 __normal_iterator
765 operator--(int)
766 { return __normal_iterator(_M_current--); }
767
768 // Random access iterator requirements
769 reference
770 operator[](const difference_type& __n) const
771 { return _M_current[__n]; }
772
773 __normal_iterator&
774 operator+=(const difference_type& __n)
775 { _M_current += __n; return *this; }
776
777 __normal_iterator
778 operator+(const difference_type& __n) const
779 { return __normal_iterator(_M_current + __n); }
780
781 __normal_iterator&
782 operator-=(const difference_type& __n)
783 { _M_current -= __n; return *this; }
784
785 __normal_iterator
786 operator-(const difference_type& __n) const
787 { return __normal_iterator(_M_current - __n); }
788
789 const _Iterator&
790 base() const
791 { return _M_current; }
792 };
793
794 // Note: In what follows, the left- and right-hand-side iterators are
795 // allowed to vary in types (conceptually in cv-qualification) so that
796 // comparison between cv-qualified and non-cv-qualified iterators be
797 // valid. However, the greedy and unfriendly operators in std::rel_ops
798 // will make overload resolution ambiguous (when in scope) if we don't
799 // provide overloads whose operands are of the same type. Can someone
800 // remind me what generic programming is about? -- Gaby
801
802 // Forward iterator requirements
803 template<typename _IteratorL, typename _IteratorR, typename _Container>
804 inline bool
805 operator==(const __normal_iterator<_IteratorL, _Container>& __lhs,
806 const __normal_iterator<_IteratorR, _Container>& __rhs)
807 { return __lhs.base() == __rhs.base(); }
808
809 template<typename _Iterator, typename _Container>
810 inline bool
811 operator==(const __normal_iterator<_Iterator, _Container>& __lhs,
812 const __normal_iterator<_Iterator, _Container>& __rhs)
813 { return __lhs.base() == __rhs.base(); }
814
815 template<typename _IteratorL, typename _IteratorR, typename _Container>
816 inline bool
817 operator!=(const __normal_iterator<_IteratorL, _Container>& __lhs,
818 const __normal_iterator<_IteratorR, _Container>& __rhs)
819 { return __lhs.base() != __rhs.base(); }
820
821 template<typename _Iterator, typename _Container>
822 inline bool
823 operator!=(const __normal_iterator<_Iterator, _Container>& __lhs,
824 const __normal_iterator<_Iterator, _Container>& __rhs)
825 { return __lhs.base() != __rhs.base(); }
18
Assuming the condition is true
19
Returning the value 1, which participates in a condition later
826
827 // Random access iterator requirements
828 template<typename _IteratorL, typename _IteratorR, typename _Container>
829 inline bool
830 operator<(const __normal_iterator<_IteratorL, _Container>& __lhs,
831 const __normal_iterator<_IteratorR, _Container>& __rhs)
832 { return __lhs.base() < __rhs.base(); }
833
834 template<typename _Iterator, typename _Container>
835 inline bool
836 operator<(const __normal_iterator<_Iterator, _Container>& __lhs,
837 const __normal_iterator<_Iterator, _Container>& __rhs)
838 { return __lhs.base() < __rhs.base(); }
839
840 template<typename _IteratorL, typename _IteratorR, typename _Container>
841 inline bool
842 operator>(const __normal_iterator<_IteratorL, _Container>& __lhs,
843 const __normal_iterator<_IteratorR, _Container>& __rhs)
844 { return __lhs.base() > __rhs.base(); }
845
846 template<typename _Iterator, typename _Container>
847 inline bool
848 operator>(const __normal_iterator<_Iterator, _Container>& __lhs,
849 const __normal_iterator<_Iterator, _Container>& __rhs)
850 { return __lhs.base() > __rhs.base(); }
851
852 template<typename _IteratorL, typename _IteratorR, typename _Container>
853 inline bool
854 operator<=(const __normal_iterator<_IteratorL, _Container>& __lhs,
855 const __normal_iterator<_IteratorR, _Container>& __rhs)
856 { return __lhs.base() <= __rhs.base(); }
857
858 template<typename _Iterator, typename _Container>
859 inline bool
860 operator<=(const __normal_iterator<_Iterator, _Container>& __lhs,
861 const __normal_iterator<_Iterator, _Container>& __rhs)
862 { return __lhs.base() <= __rhs.base(); }
863
864 template<typename _IteratorL, typename _IteratorR, typename _Container>
865 inline bool
866 operator>=(const __normal_iterator<_IteratorL, _Container>& __lhs,
867 const __normal_iterator<_IteratorR, _Container>& __rhs)
868 { return __lhs.base() >= __rhs.base(); }
869
870 template<typename _Iterator, typename _Container>
871 inline bool
872 operator>=(const __normal_iterator<_Iterator, _Container>& __lhs,
873 const __normal_iterator<_Iterator, _Container>& __rhs)
874 { return __lhs.base() >= __rhs.base(); }
875
876 // _GLIBCXX_RESOLVE_LIB_DEFECTS
877 // According to the resolution of DR179 not only the various comparison
878 // operators but also operator- must accept mixed iterator/const_iterator
879 // parameters.
880 template<typename _IteratorL, typename _IteratorR, typename _Container>
881#if __cplusplus201103L >= 201103L
882 // DR 685.
883 inline auto
884 operator-(const __normal_iterator<_IteratorL, _Container>& __lhs,
885 const __normal_iterator<_IteratorR, _Container>& __rhs)
886 -> decltype(__lhs.base() - __rhs.base())
887#else
888 inline typename __normal_iterator<_IteratorL, _Container>::difference_type
889 operator-(const __normal_iterator<_IteratorL, _Container>& __lhs,
890 const __normal_iterator<_IteratorR, _Container>& __rhs)
891#endif
892 { return __lhs.base() - __rhs.base(); }
893
894 template<typename _Iterator, typename _Container>
895 inline typename __normal_iterator<_Iterator, _Container>::difference_type
896 operator-(const __normal_iterator<_Iterator, _Container>& __lhs,
897 const __normal_iterator<_Iterator, _Container>& __rhs)
898 { return __lhs.base() - __rhs.base(); }
899
900 template<typename _Iterator, typename _Container>
901 inline __normal_iterator<_Iterator, _Container>
902 operator+(typename __normal_iterator<_Iterator, _Container>::difference_type
903 __n, const __normal_iterator<_Iterator, _Container>& __i)
904 { return __normal_iterator<_Iterator, _Container>(__i.base() + __n); }
905
906_GLIBCXX_END_NAMESPACE_VERSION
907} // namespace
908
909#if __cplusplus201103L >= 201103L
910
911namespace std _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default")))
912{
913_GLIBCXX_BEGIN_NAMESPACE_VERSION
914
915 /**
916 * @addtogroup iterators
917 * @{
918 */
919
920 // 24.4.3 Move iterators
921 /**
922 * Class template move_iterator is an iterator adapter with the same
923 * behavior as the underlying iterator except that its dereference
924 * operator implicitly converts the value returned by the underlying
925 * iterator's dereference operator to an rvalue reference. Some
926 * generic algorithms can be called with move iterators to replace
927 * copying with moving.
928 */
929 template<typename _Iterator>
930 class move_iterator
931 {
932 protected:
933 _Iterator _M_current;
934
935 typedef iterator_traits<_Iterator> __traits_type;
936
937 public:
938 typedef _Iterator iterator_type;
939 typedef typename __traits_type::iterator_category iterator_category;
940 typedef typename __traits_type::value_type value_type;
941 typedef typename __traits_type::difference_type difference_type;
942 // NB: DR 680.
943 typedef _Iterator pointer;
944 typedef value_type&& reference;
945
946 move_iterator()
947 : _M_current() { }
948
949 explicit
950 move_iterator(iterator_type __i)
951 : _M_current(__i) { }
952
953 template<typename _Iter>
954 move_iterator(const move_iterator<_Iter>& __i)
955 : _M_current(__i.base()) { }
956
957 iterator_type
958 base() const
959 { return _M_current; }
960
961 reference
962 operator*() const
963 { return std::move(*_M_current); }
964
965 pointer
966 operator->() const
967 { return _M_current; }
968
969 move_iterator&
970 operator++()
971 {
972 ++_M_current;
973 return *this;
974 }
975
976 move_iterator
977 operator++(int)
978 {
979 move_iterator __tmp = *this;
980 ++_M_current;
981 return __tmp;
982 }
983
984 move_iterator&
985 operator--()
986 {
987 --_M_current;
988 return *this;
989 }
990
991 move_iterator
992 operator--(int)
993 {
994 move_iterator __tmp = *this;
995 --_M_current;
996 return __tmp;
997 }
998
999 move_iterator
1000 operator+(difference_type __n) const
1001 { return move_iterator(_M_current + __n); }
1002
1003 move_iterator&
1004 operator+=(difference_type __n)
1005 {
1006 _M_current += __n;
1007 return *this;
1008 }
1009
1010 move_iterator
1011 operator-(difference_type __n) const
1012 { return move_iterator(_M_current - __n); }
1013
1014 move_iterator&
1015 operator-=(difference_type __n)
1016 {
1017 _M_current -= __n;
1018 return *this;
1019 }
1020
1021 reference
1022 operator[](difference_type __n) const
1023 { return std::move(_M_current[__n]); }
1024 };
1025
1026 // Note: See __normal_iterator operators note from Gaby to understand
1027 // why there are always 2 versions for most of the move_iterator
1028 // operators.
1029 template<typename _IteratorL, typename _IteratorR>
1030 inline bool
1031 operator==(const move_iterator<_IteratorL>& __x,
1032 const move_iterator<_IteratorR>& __y)
1033 { return __x.base() == __y.base(); }
1034
1035 template<typename _Iterator>
1036 inline bool
1037 operator==(const move_iterator<_Iterator>& __x,
1038 const move_iterator<_Iterator>& __y)
1039 { return __x.base() == __y.base(); }
1040
1041 template<typename _IteratorL, typename _IteratorR>
1042 inline bool
1043 operator!=(const move_iterator<_IteratorL>& __x,
1044 const move_iterator<_IteratorR>& __y)
1045 { return !(__x == __y); }
1046
1047 template<typename _Iterator>
1048 inline bool
1049 operator!=(const move_iterator<_Iterator>& __x,
1050 const move_iterator<_Iterator>& __y)
1051 { return !(__x == __y); }
1052
1053 template<typename _IteratorL, typename _IteratorR>
1054 inline bool
1055 operator<(const move_iterator<_IteratorL>& __x,
1056 const move_iterator<_IteratorR>& __y)
1057 { return __x.base() < __y.base(); }
1058
1059 template<typename _Iterator>
1060 inline bool
1061 operator<(const move_iterator<_Iterator>& __x,
1062 const move_iterator<_Iterator>& __y)
1063 { return __x.base() < __y.base(); }
1064
1065 template<typename _IteratorL, typename _IteratorR>
1066 inline bool
1067 operator<=(const move_iterator<_IteratorL>& __x,
1068 const move_iterator<_IteratorR>& __y)
1069 { return !(__y < __x); }
1070
1071 template<typename _Iterator>
1072 inline bool
1073 operator<=(const move_iterator<_Iterator>& __x,
1074 const move_iterator<_Iterator>& __y)
1075 { return !(__y < __x); }
1076
1077 template<typename _IteratorL, typename _IteratorR>
1078 inline bool
1079 operator>(const move_iterator<_IteratorL>& __x,
1080 const move_iterator<_IteratorR>& __y)
1081 { return __y < __x; }
1082
1083 template<typename _Iterator>
1084 inline bool
1085 operator>(const move_iterator<_Iterator>& __x,
1086 const move_iterator<_Iterator>& __y)
1087 { return __y < __x; }
1088
1089 template<typename _IteratorL, typename _IteratorR>
1090 inline bool
1091 operator>=(const move_iterator<_IteratorL>& __x,
1092 const move_iterator<_IteratorR>& __y)
1093 { return !(__x < __y); }
1094
1095 template<typename _Iterator>
1096 inline bool
1097 operator>=(const move_iterator<_Iterator>& __x,
1098 const move_iterator<_Iterator>& __y)
1099 { return !(__x < __y); }
1100
1101 // DR 685.
1102 template<typename _IteratorL, typename _IteratorR>
1103 inline auto
1104 operator-(const move_iterator<_IteratorL>& __x,
1105 const move_iterator<_IteratorR>& __y)
1106 -> decltype(__x.base() - __y.base())
1107 { return __x.base() - __y.base(); }
1108
1109 template<typename _Iterator>
1110 inline auto
1111 operator-(const move_iterator<_Iterator>& __x,
1112 const move_iterator<_Iterator>& __y)
1113 -> decltype(__x.base() - __y.base())
1114 { return __x.base() - __y.base(); }
1115
1116 template<typename _Iterator>
1117 inline move_iterator<_Iterator>
1118 operator+(typename move_iterator<_Iterator>::difference_type __n,
1119 const move_iterator<_Iterator>& __x)
1120 { return __x + __n; }
1121
1122 template<typename _Iterator>
1123 inline move_iterator<_Iterator>
1124 make_move_iterator(_Iterator __i)
1125 { return move_iterator<_Iterator>(__i); }
1126
1127 template<typename _Iterator, typename _ReturnType
1128 = typename conditional<__move_if_noexcept_cond
1129 <typename iterator_traits<_Iterator>::value_type>::value,
1130 _Iterator, move_iterator<_Iterator>>::type>
1131 inline _ReturnType
1132 __make_move_if_noexcept_iterator(_Iterator __i)
1133 { return _ReturnType(__i); }
1134
1135 // @} group iterators
1136
1137_GLIBCXX_END_NAMESPACE_VERSION
1138} // namespace
1139
1140#define _GLIBCXX_MAKE_MOVE_ITERATOR(_Iter)std::make_move_iterator(_Iter) std::make_move_iterator(_Iter)
1141#define _GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(_Iter)std::__make_move_if_noexcept_iterator(_Iter) \
1142 std::__make_move_if_noexcept_iterator(_Iter)
1143#else
1144#define _GLIBCXX_MAKE_MOVE_ITERATOR(_Iter)std::make_move_iterator(_Iter) (_Iter)
1145#define _GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(_Iter)std::__make_move_if_noexcept_iterator(_Iter) (_Iter)
1146#endif // C++11
1147
1148#endif