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 DTrackTimeBased_factory.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/TRACKING -I libraries/TRACKING -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/TRACKING/DTrackTimeBased_factory.cc

libraries/TRACKING/DTrackTimeBased_factory.cc

1// $Id$
2//
3// File: DTrackTimeBased_factory.cc
4// Created: Thu Sep 4 14:02:44 EDT 2008
5// Creator: davidl (on Darwin harriet.jlab.org 8.11.1 i386)
6//
7
8
9#include <iostream>
10#include <iomanip>
11#include <set>
12#include <mutex>
13#include <TMath.h>
14using namespace std;
15
16#define TOF_SIGMA0.080 0.080 // TOF resolution in ns
17
18#include <TROOT.h>
19
20#include "DTrackTimeBased_factory.h"
21#include <TRACKING/DTrackWireBased.h>
22#include <TRACKING/DReferenceTrajectory.h>
23#include <TRACKING/DTrackFitter.h>
24#include <TRACKING/DTrackHitSelector.h>
25#include <TRACKING/DMCTrackHit.h>
26#include <SplitString.h>
27#include "HDGEOMETRY/DMagneticFieldMapNoField.h"
28#include <deque>
29
30using namespace jana;
31
32// Routine for sorting start times
33bool DTrackTimeBased_T0_cmp(DTrackTimeBased::DStartTime_t a,
34 DTrackTimeBased::DStartTime_t b){
35 return (a.system>b.system);
36}
37
38bool DTrackTimeBased_cmp(DTrackTimeBased *a,DTrackTimeBased *b){
39 if (a->candidateid==b->candidateid) return a->mass()<b->mass();
40 return a->candidateid<b->candidateid;
41}
42
43
44// count_common_members
45//------------------
46template<typename T>
47static unsigned int count_common_members(vector<T> &a, vector<T> &b)
48{
49 unsigned int n=0;
50 for(unsigned int i=0; i<a.size(); i++){
51 for(unsigned int j=0; j<b.size(); j++){
52 if(a[i]==b[j])n++;
53 }
54 }
55
56 return n;
57}
58
59
60
61//------------------
62// init
63//------------------
64jerror_t DTrackTimeBased_factory::init(void)
65{
66 fitter = NULL__null;
67
68 DEBUG_HISTS = false;
69 //DEBUG_HISTS = true;
70 DEBUG_LEVEL = 0;
71
72 USE_HITS_FROM_WIREBASED_FIT=false;
73 gPARMS->SetDefaultParameter("TRKFIT:USE_HITS_FROM_WIREBASED_FIT",
74 USE_HITS_FROM_WIREBASED_FIT);
75 INSERT_MISSING_HYPOTHESES=true;
76 gPARMS->SetDefaultParameter("TRKFIT:INSERT_MISSING_HYPOTHESES",
77 INSERT_MISSING_HYPOTHESES);
78
79 gPARMS->SetDefaultParameter("TRKFIT:DEBUG_HISTS",DEBUG_HISTS);
80 gPARMS->SetDefaultParameter("TRKFIT:DEBUG_LEVEL",DEBUG_LEVEL);
81
82 vector<int> hypotheses;
83 hypotheses.push_back(Positron);
84 hypotheses.push_back(PiPlus);
85 hypotheses.push_back(KPlus);
86 hypotheses.push_back(Proton);
87 hypotheses.push_back(Electron);
88 hypotheses.push_back(PiMinus);
89 hypotheses.push_back(KMinus);
90 hypotheses.push_back(AntiProton);
91
92 ostringstream locMassStream;
93 for(size_t loc_i = 0; loc_i < hypotheses.size(); ++loc_i)
94 {
95 locMassStream << hypotheses[loc_i];
96 if(loc_i != (hypotheses.size() - 1))
97 locMassStream << ",";
98 }
99
100 string HYPOTHESES = locMassStream.str();
101 gPARMS->SetDefaultParameter("TRKFIT:HYPOTHESES", HYPOTHESES);
102
103 // Parse MASS_HYPOTHESES strings to make list of masses to try
104 hypotheses.clear();
105 SplitString(HYPOTHESES, hypotheses, ",");
106 for(size_t loc_i = 0; loc_i < hypotheses.size(); ++loc_i)
107 {
108 if(ParticleCharge(Particle_t(hypotheses[loc_i])) > 0){
109 mass_hypotheses_positive.push_back(hypotheses[loc_i]);
110 }
111 else if(ParticleCharge(Particle_t(hypotheses[loc_i])) < 0){
112 mass_hypotheses_negative.push_back(hypotheses[loc_i]);
113 }
114 }
115
116 if(mass_hypotheses_positive.empty()){
117 static once_flag pwarn_flag;
118 call_once(pwarn_flag, [](){
119 jout << endl;
120 jout << "############# WARNING !! ################ " <<endl;
121 jout << "There are no mass hypotheses for positive tracks!" << endl;
122 jout << "Be SURE this is what you really want!" << endl;
123 jout << "######################################### " <<endl;
124 jout << endl;
125 });
126 }
127 if(mass_hypotheses_negative.empty()){
128 static once_flag nwarn_flag;
129 call_once(nwarn_flag, [](){
130 jout << endl;
131 jout << "############# WARNING !! ################ " <<endl;
132 jout << "There are no mass hypotheses for negative tracks!" << endl;
133 jout << "Be SURE this is what you really want!" << endl;
134 jout << "######################################### " <<endl;
135 jout << endl;
136 });
137 }
138
139 mNumHypPlus=mass_hypotheses_positive.size();
140 mNumHypMinus=mass_hypotheses_negative.size();
141
142 // Forces correct particle id (when available)
143 PID_FORCE_TRUTH = false;
144 gPARMS->SetDefaultParameter("TRKFIT:PID_FORCE_TRUTH", PID_FORCE_TRUTH);
145
146 USE_SC_TIME=true;
147 gPARMS->SetDefaultParameter("TRKFIT:USE_SC_TIME",USE_SC_TIME);
148
149 USE_TOF_TIME=true;
150 gPARMS->SetDefaultParameter("TRKFIT:USE_TOF_TIME",USE_TOF_TIME);
151
152 USE_FCAL_TIME=true;
153 gPARMS->SetDefaultParameter("TRKFIT:USE_FCAL_TIME",USE_FCAL_TIME);
154
155 USE_BCAL_TIME=true;
156 gPARMS->SetDefaultParameter("TRKFIT:USE_BCAL_TIME",USE_BCAL_TIME);
157
158 return NOERROR;
159}
160
161//------------------
162// brun
163//------------------
164jerror_t DTrackTimeBased_factory::brun(jana::JEventLoop *loop, int32_t runnumber)
165{
166 // Get the geometry
167 DApplication* dapp=dynamic_cast<DApplication*>(loop->GetJApplication());
168 geom = dapp->GetDGeometry(runnumber);
169 // Check for magnetic field
170 dIsNoFieldFlag = (dynamic_cast<const DMagneticFieldMapNoField*>(dapp->GetBfield(runnumber)) != NULL__null);
1
Assuming the condition is false
171
172 if(dIsNoFieldFlag
1.1
Field 'dIsNoFieldFlag' is false
1.1
Field 'dIsNoFieldFlag' is false
1.1
Field 'dIsNoFieldFlag' is false
){
2
Taking false branch
173 //Setting this flag makes it so that JANA does not delete the objects in
174 //_data. This factory will manage this memory.
175 //This is all of these pointers are just copied from the "StraightLine"
176 //factory, and should not be re-deleted.
177 SetFactoryFlag(NOT_OBJECT_OWNER);
178 }
179 else{
180 ClearFactoryFlag(NOT_OBJECT_OWNER); //This factory will create it's own obje
181 }
182
183 // Get pointer to TrackFitter object that actually fits a track
184 vector<const DTrackFitter *> fitters;
185 loop->Get(fitters);
3
Calling 'JEventLoop::Get'
186 if(fitters.size()<1){
187 _DBG_std::cerr<<"libraries/TRACKING/DTrackTimeBased_factory.cc"
<<":"<<187<<" "
<<"Unable to get a DTrackFitter object! NO Charged track fitting will be done!"<<endl;
188 return RESOURCE_UNAVAILABLE;
189 }
190
191 // Drop the const qualifier from the DTrackFitter pointer (I'm surely going to hell for this!)
192 fitter = const_cast<DTrackFitter*>(fitters[0]);
193
194 // Warn user if something happened that caused us NOT to get a fitter object pointer
195 if(!fitter){
196 _DBG_std::cerr<<"libraries/TRACKING/DTrackTimeBased_factory.cc"
<<":"<<196<<" "
<<"Unable to get a DTrackFitter object! NO Charged track fitting will be done!"<<endl;
197 return RESOURCE_UNAVAILABLE;
198 }
199
200 // Get the particle ID algorithms
201 vector<const DParticleID *> pid_algorithms;
202 loop->Get(pid_algorithms);
203 if(pid_algorithms.size()<1){
204 _DBG_std::cerr<<"libraries/TRACKING/DTrackTimeBased_factory.cc"
<<":"<<204<<" "
<<"Unable to get a DParticleID object! NO PID will be done!"<<endl;
205 return RESOURCE_UNAVAILABLE;
206 }
207
208 pid_algorithm = pid_algorithms[0];
209
210 // Warn user if something happened that caused us NOT to get a pid_algorithm object pointer
211 if(!pid_algorithm){
212 _DBG_std::cerr<<"libraries/TRACKING/DTrackTimeBased_factory.cc"
<<":"<<212<<" "
<<"Unable to get a DParticleID object! NO PID will be done!"<<endl;
213 return RESOURCE_UNAVAILABLE;
214 }
215
216
217 if(DEBUG_HISTS){
218 dapp->Lock();
219
220 // Histograms may already exist. (Another thread may have created them)
221 // Try and get pointers to the existing ones.
222 fom_chi2_trk = (TH1F*)gROOT(ROOT::GetROOT())->FindObject("fom_chi2_trk");
223 fom = (TH1F*)gROOT(ROOT::GetROOT())->FindObject("fom");
224 hitMatchFOM = (TH1F*)gROOT(ROOT::GetROOT())->FindObject("hitMatchFOM");
225 chi2_trk_mom = (TH2F*)gROOT(ROOT::GetROOT())->FindObject("chi2_trk_mom");
226
227 if(!fom_chi2_trk)fom_chi2_trk = new TH1F("fom_chi2_trk","PID FOM: #chi^{2}/Ndf from tracking", 1000, 0.0, 100.0);
228 if(!fom)fom = new TH1F("fom","Combined PID FOM", 1000, 0.0, 1.01);
229 if(!hitMatchFOM)hitMatchFOM = new TH1F("hitMatchFOM","Total Fraction of Hit Matches", 101, 0.0, 1.01);
230 if(!chi2_trk_mom)chi2_trk_mom = new TH2F("chi2_trk_mom","Track #chi^{2}/Ndf versus Kinematic #chi^{2}/Ndf", 1000, 0.0, 100.0, 1000, 0.,100.);
231
232
233 Hstart_time=(TH2F*)gROOT(ROOT::GetROOT())->FindObject("Hstart_time");
234 if (!Hstart_time) Hstart_time=new TH2F("Hstart_time",
235 "vertex time source vs. time",
236 300,-50,50,9,-0.5,8.5);
237
238 dapp->Unlock();
239
240 }
241
242 return NOERROR;
243}
244
245//------------------
246// evnt
247//------------------
248jerror_t DTrackTimeBased_factory::evnt(JEventLoop *loop, uint64_t eventnumber)
249{
250 // Save event number to help with debugging
251 myevt=eventnumber;
252 if(!fitter)return NOERROR;
253
254 if(dIsNoFieldFlag){
255 //Clear previous objects:
256 //JANA doesn't do it because NOT_OBJECT_OWNER was set
257 //It DID delete them though, in the "StraightLine" factory
258 _data.clear();
259
260 vector<const DTrackTimeBased*> locTimeBasedTracks;
261 loop->Get(locTimeBasedTracks, "StraightLine");
262 for(size_t loc_i = 0; loc_i < locTimeBasedTracks.size(); ++loc_i)
263 _data.push_back(const_cast<DTrackTimeBased*>(locTimeBasedTracks[loc_i]));
264 return NOERROR;
265 }
266
267 // Get candidates and hits
268 vector<const DTrackWireBased*> tracks;
269 loop->Get(tracks);
270 if (tracks.size()==0) return NOERROR;
271
272 // get start counter hits
273 vector<const DSCHit*>sc_hits;
274 if (USE_SC_TIME){
275 loop->Get(sc_hits);
276 }
277
278 // Get TOF points
279 vector<const DTOFPoint*> tof_points;
280 if (USE_TOF_TIME){
281 loop->Get(tof_points);
282 }
283
284 // Get BCAL and FCAL showers
285 vector<const DBCALShower*>bcal_showers;
286 if (USE_BCAL_TIME){
287 loop->Get(bcal_showers);
288 }
289 vector<const DFCALShower*>fcal_showers;
290 if (USE_FCAL_TIME){
291 loop->Get(fcal_showers);
292 }
293
294 vector<const DMCThrown*> mcthrowns;
295 loop->Get(mcthrowns, "FinalState");
296
297 // Loop over candidates
298 for(unsigned int i=0; i<tracks.size(); i++){
299 const DTrackWireBased *track = tracks[i];
300
301 unsigned int num=_data.size();
302
303 // Create vector of start times from various sources
304 vector<DTrackTimeBased::DStartTime_t>start_times;
305 CreateStartTimeList(track,sc_hits,tof_points,bcal_showers,fcal_showers,start_times);
306
307 // Fit the track
308 DoFit(track,start_times,loop,track->mass());
309
310 //_DBG_<< "eventnumber: " << eventnumber << endl;
311 if (PID_FORCE_TRUTH && _data.size()>num) {
312 // Add figure-of-merit based on difference between thrown and reconstructed momentum
313 // if more than half of the track's hits match MC truth hits and also (charge,mass)
314 // match; add FOM=0 otherwise
315 _data[_data.size()-1]->FOM=GetTruthMatchingFOM(i,_data[_data.size()-1],
316 mcthrowns);
317 }
318 } // loop over track candidates
319
320 // Filter out duplicate tracks
321 FilterDuplicates();
322
323 // Fill in track data for missing hypotheses
324 if (INSERT_MISSING_HYPOTHESES){
325 InsertMissingHypotheses(loop);
326 }
327
328 // Set MC Hit-matching information
329 for(size_t loc_i = 0; loc_i < _data.size(); ++loc_i)
330 {
331 if(!mcthrowns.empty())
332 {
333 double hitFraction;
334 int thrownIndex = GetThrownIndex(mcthrowns, (DKinematicData*)_data[loc_i], hitFraction);
335 _data[loc_i]->dMCThrownMatchMyID = thrownIndex;
336 _data[loc_i]->dNumHitsMatchedToThrown = int(hitFraction * float(Get_NumTrackHits(_data[loc_i])) + 0.01); // + 0.01 so that it rounds down properly
337 }
338 else
339 {
340 _data[loc_i]->dMCThrownMatchMyID = -1;
341 _data[loc_i]->dNumHitsMatchedToThrown = 0;
342 }
343 }
344
345 return NOERROR;
346}
347
348//------------------
349// erun
350//------------------
351jerror_t DTrackTimeBased_factory::erun(void)
352{
353 return NOERROR;
354}
355
356//------------------
357// fini
358//------------------
359jerror_t DTrackTimeBased_factory::fini(void)
360{
361 return NOERROR;
362}
363
364//------------------
365// FilterDuplicates
366//------------------
367void DTrackTimeBased_factory::FilterDuplicates(void)
368{
369 /// Look through all current DTrackTimeBased objects and remove any
370 /// that have most of their hits in common with another track
371
372 if(_data.size()==0)return;
373
374 if(DEBUG_LEVEL>2)_DBG_std::cerr<<"libraries/TRACKING/DTrackTimeBased_factory.cc"
<<":"<<374<<" "
<<"Looking for clones of time-based tracks ..."<<endl;
375 // We want to remove duplicate tracks corresponding to actual particles,
376 // not just duplicate fitted tracks for certain mass hypotheses -- this
377 // is partly because at a later stage the holes in the list of mass
378 // hypotheses are filled in, thereby spoiling the whole point of this
379 // part of the code!
380 // Keep track of pairs of candididate id's, one for which we want to
381 // keep all the results of fitting with different mass hypotheses,
382 // the other for which we want to delete all the results of fitting.
383 // We need both vectors to take into account potential ambiguities:
384 // for one mass hypothesis starting with one candidate may be "better"
385 // than starting with a second clone candidate, whereas for a second
386 // mass hypothesis, the opposite may be true.
387 vector<unsigned int> candidates_to_keep;
388 vector<unsigned int> candidates_to_delete;
389 for(unsigned int i=0; i<_data.size()-1; i++){
390 DTrackTimeBased *dtrack1 = _data[i];
391
392 vector<const DCDCTrackHit*> cdchits1;
393 vector<const DFDCPseudo*> fdchits1;
394 dtrack1->Get(cdchits1);
395 dtrack1->Get(fdchits1);
396 // Total number of hits in this candidate
397 unsigned int num_cdc1=cdchits1.size();
398 unsigned int num_fdc1=fdchits1.size();
399 unsigned int total1 = num_cdc1+num_fdc1;
400
401 JObject::oid_t cand1=dtrack1->candidateid;
402 for(unsigned int j=i+1; j<_data.size(); j++){
403 DTrackTimeBased *dtrack2 = _data[j];
404 if (dtrack2->candidateid==cand1) continue;
405
406 vector<const DCDCTrackHit*> cdchits2;
407 vector<const DFDCPseudo*> fdchits2;
408 dtrack2->Get(cdchits2);
409 dtrack2->Get(fdchits2);
410
411 // Total number of hits in this candidate
412 unsigned int num_cdc2=cdchits2.size();
413 unsigned int num_fdc2=fdchits2.size();
414 unsigned int total2 = num_cdc2+num_fdc2;
415
416 // Count number of cdc and fdc hits in common
417 unsigned int Ncdc = count_common_members(cdchits1, cdchits2);
418 unsigned int Nfdc = count_common_members(fdchits1, fdchits2);
419
420 if(DEBUG_LEVEL>3){
421 _DBG_std::cerr<<"libraries/TRACKING/DTrackTimeBased_factory.cc"
<<":"<<421<<" "
<<"cand1:"<<cand1<<" cand2:"<<dtrack2->candidateid<<endl;
422 _DBG_std::cerr<<"libraries/TRACKING/DTrackTimeBased_factory.cc"
<<":"<<422<<" "
<<" Ncdc="<<Ncdc<<" num_cdc1="<<num_cdc1<<" num_cdc2="<<num_cdc2<<endl;
423 _DBG_std::cerr<<"libraries/TRACKING/DTrackTimeBased_factory.cc"
<<":"<<423<<" "
<<" Nfdc="<<Nfdc<<" num_fdc1="<<num_fdc1<<" num_fdc2="<<num_fdc2<<endl;
424 }
425 unsigned int total = Ncdc + Nfdc;
426 // If the tracks share at most one hit, consider them
427 // to be separate tracks
428 if (total<=1) continue;
429
430 // Deal with the case where there are cdc hits in
431 // common between the tracks but there were no fdc
432 // hits used in one of the tracks.
433 if (Ncdc>0 && (num_fdc1>0 || num_fdc2>0)
434 && (num_fdc1*num_fdc2)==0) continue;
435
436 // Deal with the case where there are fdc hits in
437 // common between the tracks but no cdc hits used in
438 // one of the tracks.
439 if (Nfdc>0 && (num_cdc1>0 || num_cdc2>0)
440 && (num_cdc1*num_cdc2)==0) continue;
441
442 // Look for tracks with many common hits in the CDC
443 if (num_cdc1>0 && num_cdc2>0){
444 if (double(Ncdc)/double(num_cdc1)<0.9) continue;
445 if (double(Ncdc)/double(num_cdc2)<0.9) continue;
446 }
447 // Look for tracks with many common hits in the FDC
448 if (num_fdc1>0 && num_fdc2>0){
449 if (double(Nfdc)/double(num_fdc1)<0.9) continue;
450 if (double(Nfdc)/double(num_fdc2)<0.9) continue;
451 }
452
453 if(total1<total2){
454 candidates_to_delete.push_back(cand1);
455 candidates_to_keep.push_back(dtrack2->candidateid);
456 }else if(total2<total1){
457 candidates_to_delete.push_back(dtrack2->candidateid);
458 candidates_to_keep.push_back(cand1);
459 }else if(dtrack1->FOM > dtrack2->FOM){
460 candidates_to_delete.push_back(dtrack2->candidateid);
461 candidates_to_keep.push_back(cand1);
462 }else{
463 candidates_to_delete.push_back(cand1);
464 candidates_to_keep.push_back(dtrack2->candidateid);
465 }
466 }
467 }
468
469 if(DEBUG_LEVEL>2)_DBG_std::cerr<<"libraries/TRACKING/DTrackTimeBased_factory.cc"
<<":"<<469<<" "
<<"Found "<<candidates_to_delete.size()<<" time-based clones"<<endl;
470
471
472 // Return now if we're keeping everyone
473 if(candidates_to_delete.size()==0)return;
474
475 // Deal with the ambiguity problem mentioned above
476 for (unsigned int i=0;i<candidates_to_keep.size();i++){
477 for (unsigned int j=0;j<candidates_to_delete.size();j++){
478 if (candidates_to_keep[i]==candidates_to_delete[j]){
479 candidates_to_delete.erase(candidates_to_delete.begin()+j);
480 break;
481 }
482 }
483
484 }
485
486 // Copy pointers that we want to keep to a new container and delete
487 // the clone objects
488 vector<DTrackTimeBased*> new_data;
489 sort(_data.begin(),_data.end(),DTrackTimeBased_cmp);
490 for (unsigned int i=0;i<_data.size();i++){
491 bool keep_track=true;
492 for (unsigned int j=0;j<candidates_to_delete.size();j++){
493 if (_data[i]->candidateid==candidates_to_delete[j]){
494 keep_track=false;
495 if(DEBUG_LEVEL>1){
496 _DBG_std::cerr<<"libraries/TRACKING/DTrackTimeBased_factory.cc"
<<":"<<496<<" "
<<"Deleting clone time-based fitted result "<<i
497 << " in event " << myevt << endl;
498 }
499 break;
500 }
501 }
502 if (keep_track){
503 new_data.push_back(_data[i]);
504 }
505 else delete _data[i];
506 }
507 _data = new_data;
508}
509
510// Returns a FOM based on difference between thrown and reconstructed momentum if track matches MC truth information,
511// returns a FOM=0 otherwise;
512// a match requires identical masses and charges, and that more than half of the track's hits match the truth hits
513double DTrackTimeBased_factory::GetTruthMatchingFOM(int trackIndex,DTrackTimeBased *track,vector<const DMCThrown*>mcthrowns) {
514 bool match=false;
515
516 DLorentzVector fourMom = track->lorentzMomentum();
517 //DLorentzVector gen_fourMom[mcthrowns.size()];
518 vector<DLorentzVector> gen_fourMom(mcthrowns.size());
519 for(unsigned int i=0; i<mcthrowns.size(); i++){
520 gen_fourMom[i] = mcthrowns[i]->lorentzMomentum();
521 }
522
523 // Get info for thrown track
524 double f = 0.;
525 int thrownIndex = GetThrownIndex(mcthrowns, track, f);
526 if(thrownIndex<=0 || f<=0.5) return 0.;
527
528 double delta_pt_over_pt = (fourMom.Pt()-gen_fourMom[thrownIndex-1].Pt())/gen_fourMom[thrownIndex-1].Pt();
529 double delta_theta = (fourMom.Theta()-gen_fourMom[thrownIndex-1].Theta())*1000.0; // in milliradians
530 double delta_phi = (fourMom.Phi()-gen_fourMom[thrownIndex-1].Phi())*1000.0; // in milliradians
531 double chisq = pow(delta_pt_over_pt/0.04, 2.0) + pow(delta_theta/20.0, 2.0) + pow(delta_phi/20.0, 2.0);
532
533 if (fabs(track->mass()-mcthrowns[thrownIndex-1]->mass())<0.01 && track->charge()==mcthrowns[thrownIndex-1]->charge())
534 match = true;
535
536 double trk_chi2=track->chisq;
537 unsigned int ndof=track->Ndof;
538
539 if(DEBUG_HISTS&&match){
540 fom_chi2_trk->Fill(track->chisq);
541 chi2_trk_mom->Fill(chisq/3.,trk_chi2/ndof);
542 fom->Fill(TMath::Prob(chisq,3));
543 }
544
545 /*_DBG_ << "f: " << f << endl;
546 _DBG_ << "trk_chi2: " << trk_chi2 << endl;
547 _DBG_ << "ndof: " << ndof << endl;
548 _DBG_ << "throwncharge: " << mcthrowns[thrownIndex-1]->charge() << endl;
549 _DBG_ << "trackcharge: " << track->charge() << endl;
550 _DBG_ << "chargediff: " << fabs(track->charge()-mcthrowns[thrownIndex-1]->charge()) << endl;
551 _DBG_ << "thrownmass: " << mcthrowns[thrownIndex-1]->mass() << endl;
552 _DBG_ << "trackmass: " << track->mass() << endl;
553 _DBG_ << "massdiff: " << fabs(track->mass()-mcthrowns[thrownIndex-1]->mass()) << endl;
554 _DBG_ << "chisq: " << chisq << endl;
555 _DBG_ << "match?: " << match << endl;
556 _DBG_ << "thrownIndex: " << thrownIndex << " trackIndex: " << trackIndex << endl;
557 _DBG_<< "track " << setprecision(4) << "Px: " << fourMom.Px() << " Py: " << fourMom.Py() << " Pz: " << fourMom.Pz() << " E: " << fourMom.E() << " M: " << fourMom.M() << " pt: " << fourMom.Pt() << " theta: " << fourMom.Theta() << " phi: " << fourMom.Phi() << endl;
558 _DBG_<< "thrown " << setprecision(4) << "Px: " << gen_fourMom[thrownIndex-1].Px() << " Py: " << gen_fourMom[thrownIndex-1].Py() << " Pz: " << gen_fourMom[thrownIndex-1].Pz() << " E: " << gen_fourMom[thrownIndex-1].E() << " M: " << gen_fourMom[thrownIndex-1].M() << " pt: " << gen_fourMom[thrownIndex-1].Pt() << " theta: " << gen_fourMom[thrownIndex-1].Theta() << " phi: " << gen_fourMom[thrownIndex-1].Phi() << endl;*/
559
560 return (match) ? TMath::Prob(chisq,3) : 0.0;
561}
562
563//------------------
564// GetThrownIndex
565//------------------
566int DTrackTimeBased_factory::GetThrownIndex(vector<const DMCThrown*>& locMCThrowns, const DKinematicData *kd, double &f)
567{
568 // The DKinematicData object should be a DTrackCandidate, DTrackWireBased, or DParticle which
569 // has associated objects for the hits
570 vector<const DCDCTrackHit*> cdctrackhits;
571 kd->Get(cdctrackhits);
572 vector<const DFDCPseudo*> fdcpseudos;
573 kd->Get(fdcpseudos);
574
575 int locTotalNumHits = cdctrackhits.size() + fdcpseudos.size();
576 if(locTotalNumHits == 0)
577 {
578 f = 0;
579 return -1;
580 }
581
582 // The track number is buried in the truth hit objects of type DMCTrackHit. These should be
583 // associated objects for the individual hit objects. We need to loop through them and
584 // keep track of how many hits for each track number we find
585
586 map<int, int> locHitMatches; //first int is MC my id, second is num hits
587 for(size_t loc_i = 0; loc_i < locMCThrowns.size(); ++loc_i)
588 {
589 if(fabs(locMCThrowns[loc_i]->charge()) > 0.9)
590 locHitMatches[locMCThrowns[loc_i]->myid] = 0;
591 }
592
593 // CDC hits
594 for(size_t loc_i = 0; loc_i < cdctrackhits.size(); ++loc_i)
595 {
596 const DCDCHit* locCDCHit = NULL__null;
597 cdctrackhits[loc_i]->GetSingle(locCDCHit);
598 vector<const DCDCHit*> locTruthCDCHits;
599 locCDCHit->Get(locTruthCDCHits);
600 if(locTruthCDCHits.empty()) continue;
601
602 int itrack = locTruthCDCHits[0]->itrack;
603 if(locHitMatches.find(itrack) == locHitMatches.end())
604 continue;
605 ++locHitMatches[itrack];
606 }
607
608 // FDC hits
609 for(size_t loc_i = 0; loc_i < fdcpseudos.size(); ++loc_i)
610 {
611 vector<const DMCTrackHit*> mctrackhits;
612 fdcpseudos[loc_i]->Get(mctrackhits);
613 if(mctrackhits.empty())
614 continue;
615 if(!mctrackhits[0]->primary)
616 continue;
617
618 int itrack = mctrackhits[0]->itrack;
619 if(locHitMatches.find(itrack) == locHitMatches.end())
620 continue;
621 ++locHitMatches[itrack];
622 }
623
624 // Find DMCThrown::myid with most wires hit
625 map<int, int>::iterator locIterator = locHitMatches.begin();
626 int locBestMyID = -1;
627 int locBestNumHits = 0;
628 for(; locIterator != locHitMatches.end(); ++locIterator)
629 {
630 if(locIterator->second <= locBestNumHits)
631 continue;
632 locBestNumHits = locIterator->second;
633 locBestMyID = locIterator->first;
634 }
635
636 // total fraction of reconstructed hits that match truth hits
637 f = 1.0*locBestNumHits/locTotalNumHits;
638 if(DEBUG_HISTS)hitMatchFOM->Fill(f);
639
640 return locBestMyID;
641}
642
643
644// Create a list of start (vertex) times from various sources, ordered by
645// uncertainty.
646void DTrackTimeBased_factory
647 ::CreateStartTimeList(const DTrackWireBased *track,
648 vector<const DSCHit*>&sc_hits,
649 vector<const DTOFPoint*>&tof_points,
650 vector<const DBCALShower*>&bcal_showers,
651 vector<const DFCALShower*>&fcal_showers,
652 vector<DTrackTimeBased::DStartTime_t>&start_times){
653 DTrackTimeBased::DStartTime_t start_time;
654
655 // Match to the start counter and the outer detectors
656 double locStartTimeVariance = 0.0;
657 double track_t0=track->t0();
658 double locStartTime = track_t0; // initial guess from tracking
659
660 // Get start time estimate from Start Counter
661 if (pid_algorithm->Get_StartTime(track->extrapolations.at(SYS_START),sc_hits,locStartTime)){
662 start_time.t0=locStartTime;
663 // start_time.t0_sigma=sqrt(locTimeVariance); //uncomment when ready
664 start_time.t0_sigma=sqrt(locStartTimeVariance);
665 start_time.system=SYS_START;
666 start_times.push_back(start_time);
667 }
668 // Get start time estimate from TOF
669 locStartTime = track_t0; // initial guess from tracking
670 if (pid_algorithm->Get_StartTime(track->extrapolations.at(SYS_TOF),tof_points,locStartTime)){
671 // Fill in the start time vector
672 start_time.t0=locStartTime;
673 start_time.t0_sigma=sqrt(locStartTimeVariance);
674 // start_time.t0_sigma=sqrt(locTimeVariance); //uncomment when ready
675 start_time.system=SYS_TOF;
676 start_times.push_back(start_time);
677 }
678 // Get start time estimate from FCAL
679 locStartTime = track_t0; // initial guess from tracking
680 if (pid_algorithm->Get_StartTime(track->extrapolations.at(SYS_FCAL),fcal_showers,locStartTime)){
681 // Fill in the start time vector
682 start_time.t0=locStartTime;
683 start_time.t0_sigma=sqrt(locStartTimeVariance);
684 // start_time.t0_sigma=sqrt(locTimeVariance); //uncomment when ready
685 start_time.system=SYS_FCAL;
686 start_times.push_back(start_time);
687 }
688 // Get start time estimate from BCAL
689 locStartTime=track_t0;
690 if (pid_algorithm->Get_StartTime(track->extrapolations.at(SYS_BCAL),bcal_showers,locStartTime)){
691 // Fill in the start time vector
692 start_time.t0=locStartTime;
693 start_time.t0_sigma=0.5;
694 // start_time.t0_sigma=sqrt(locTimeVariance); //uncomment when ready
695 start_time.system=SYS_BCAL;
696 start_times.push_back(start_time);
697 }
698 // Add the t0 estimate from the tracking
699 start_time.t0=track_t0;
700 start_time.t0_sigma=5.;
701 start_time.system=track->t0_detector();
702 start_times.push_back(start_time);
703
704 // Set t0 for the fit to the first entry in the list. Usually this will be
705 // from the start counter.
706 mStartTime=start_times[0].t0;
707 mStartDetector=start_times[0].system;
708
709 // _DBG_ << mStartDetector << " " << mStartTime << endl;
710
711}
712
713// Create a list of start times and do the fit for a particular mass hypothesis
714bool DTrackTimeBased_factory::DoFit(const DTrackWireBased *track,
715 vector<DTrackTimeBased::DStartTime_t>&start_times,
716 JEventLoop *loop,
717 double mass){
718 if(DEBUG_LEVEL>1){_DBG__std::cerr<<"libraries/TRACKING/DTrackTimeBased_factory.cc"
<<":"<<718<<std::endl
;_DBG_std::cerr<<"libraries/TRACKING/DTrackTimeBased_factory.cc"
<<":"<<718<<" "
<<"---- Starting time based fit with mass: "<<mass<<endl;}
719 // Get the hits from the wire-based track
720 vector<const DFDCPseudo*>myfdchits;
721 track->GetT(myfdchits);
722 vector<const DCDCTrackHit *>mycdchits;
723 track->GetT(mycdchits);
724
725 // Do the fit
726 DTrackFitter::fit_status_t status = DTrackFitter::kFitNotDone;
727 if (USE_HITS_FROM_WIREBASED_FIT) {
728 fitter->Reset();
729 fitter->SetFitType(DTrackFitter::kTimeBased);
730
731 fitter->AddHits(myfdchits);
732 fitter->AddHits(mycdchits);
733
734 status=fitter->FitTrack(track->position(),track->momentum(),
735 track->charge(),mass,mStartTime,mStartDetector);
736 }
737 else{
738 fitter->Reset();
739 fitter->SetFitType(DTrackFitter::kTimeBased);
740 status = fitter->FindHitsAndFitTrack(*track, track->extrapolations,loop,
741 mass,
742 mycdchits.size()+2*myfdchits.size(),
743 mStartTime,mStartDetector);
744
745 // If the status is kFitNotDone, then not enough hits were attached to this
746 // track using the hit-gathering algorithm. In this case get the hits
747 // from the wire-based track
748 if (status==DTrackFitter::kFitNotDone){
749 //_DBG_ << " Using wire-based hits " << endl;
750 fitter->Reset();
751 fitter->SetFitType(DTrackFitter::kTimeBased);
752 fitter->AddHits(myfdchits);
753 fitter->AddHits(mycdchits);
754
755 status=fitter->FitTrack(track->position(),track->momentum(),
756 track->charge(),mass,mStartTime,mStartDetector);
757 }
758
759 }
760
761 // if the fit returns chisq=-1, something went terribly wrong. We may still
762 // have a usable track from the wire-based pass. In this case set
763 // kFitNoImprovement so we can save the wire-based results.
764 if (fitter->GetChisq()<0){
765 status=DTrackFitter::kFitNoImprovement;
766 }
767
768 // In the transition region between the CDC and the FDC where the track
769 // contains both CDC and FDC hits, sometimes too many hits are discarded in
770 // the time-based phase and the time-based fit result does not improve on the
771 // wire-based fit result. In this case set the status word to
772 // kFitNoImprovement and copy the wire-based parameters into the time-based
773 // class.
774 if (myfdchits.size()>3 && mycdchits.size()>3){
775 unsigned int ndof=fitter->GetNdof();
776 if (TMath::Prob(track->chisq,track->Ndof)>
777 TMath::Prob(fitter->GetChisq(),ndof)&&ndof<5)
778 status=DTrackFitter::kFitNoImprovement;
779 }
780
781 // Check the status value from the fit
782 switch(status){
783 case DTrackFitter::kFitNotDone:
784 //_DBG_<<"Fitter returned kFitNotDone. This should never happen!!"<<endl;
785 case DTrackFitter::kFitFailed:
786 break;
787 case DTrackFitter::kFitNoImprovement:
788 {
789 // Create a new time-based track object
790 DTrackTimeBased *timebased_track = new DTrackTimeBased();
791 *static_cast<DTrackingData*>(timebased_track) = *static_cast<const DTrackingData*>(track);
792
793 timebased_track->chisq = track->chisq;
794 timebased_track->Ndof = track->Ndof;
795 timebased_track->pulls = track->pulls;
796 timebased_track->extrapolations = track->extrapolations;
797 timebased_track->trackid = track->id;
798 timebased_track->candidateid=track->candidateid;
799 timebased_track->FOM=track->FOM;
800 timebased_track->flags=DTrackTimeBased::FLAG__USED_WIREBASED_FIT;
801
802 // add the list of start times
803 timebased_track->start_times.assign(start_times.begin(),
804 start_times.end());
805
806 for(unsigned int m=0; m<myfdchits.size(); m++)
807 timebased_track->AddAssociatedObject(myfdchits[m]);
808 for(unsigned int m=0; m<mycdchits.size(); m++)
809 timebased_track->AddAssociatedObject(mycdchits[m]);
810
811 timebased_track->measured_cdc_hits_on_track = mycdchits.size();
812 timebased_track->measured_fdc_hits_on_track = myfdchits.size();
813
814 // dEdx
815 double locdEdx_FDC, locdx_FDC, locdEdx_CDC, locdEdx_CDC_amp;
816 double locdx_CDC_amp,locdx_CDC;
817 unsigned int locNumHitsUsedFordEdx_FDC, locNumHitsUsedFordEdx_CDC;
818 pid_algorithm->CalcDCdEdx(timebased_track, locdEdx_FDC, locdx_FDC, locdEdx_CDC, locdEdx_CDC_amp, locdx_CDC, locdx_CDC_amp,locNumHitsUsedFordEdx_FDC, locNumHitsUsedFordEdx_CDC);
819
820 timebased_track->ddEdx_FDC = locdEdx_FDC;
821 timebased_track->ddx_FDC = locdx_FDC;
822 timebased_track->dNumHitsUsedFordEdx_FDC = locNumHitsUsedFordEdx_FDC;
823 timebased_track->ddEdx_CDC = locdEdx_CDC;
824 timebased_track->ddEdx_CDC_amp = locdEdx_CDC_amp;
825 timebased_track->ddx_CDC = locdx_CDC;
826 timebased_track->ddx_CDC_amp = locdx_CDC_amp;
827 timebased_track->dNumHitsUsedFordEdx_CDC = locNumHitsUsedFordEdx_CDC;
828
829 timebased_track->potential_cdc_hits_on_track = fitter->GetNumPotentialCDCHits();
830 timebased_track->potential_fdc_hits_on_track = fitter->GetNumPotentialFDCHits();
831
832 timebased_track->AddAssociatedObject(track);
833 _data.push_back(timebased_track);
834
835 return true;
836 break;
837 }
838 case DTrackFitter::kFitSuccess:
839 {
840 // Create a new time-based track object
841 DTrackTimeBased *timebased_track = new DTrackTimeBased();
842 *static_cast<DTrackingData*>(timebased_track) = fitter->GetFitParameters();
843
844 timebased_track->setTime(mStartTime);
845 timebased_track->chisq = fitter->GetChisq();
846 timebased_track->Ndof = fitter->GetNdof();
847 timebased_track->pulls = std::move(fitter->GetPulls());
848 timebased_track->extrapolations=std::move(fitter->GetExtrapolations());
849 timebased_track->IsSmoothed = fitter->GetIsSmoothed();
850 timebased_track->trackid = track->id;
851 timebased_track->candidateid=track->candidateid;
852 timebased_track->flags=DTrackTimeBased::FLAG__GOODFIT;
853
854 // Set the start time and add the list of start times
855 timebased_track->setT0(mStartTime,start_times[0].t0_sigma, mStartDetector);
856 timebased_track->start_times.assign(start_times.begin(), start_times.end());
857
858 if (DEBUG_HISTS){
859 int id=0;
860 if (mStartDetector==SYS_CDC) id=1;
861 else if (mStartDetector==SYS_FDC) id=2;
862 else if (mStartDetector==SYS_BCAL) id=3;
863 else if (mStartDetector==SYS_FCAL) id=4;
864 else if (mStartDetector==SYS_TOF) id=5;
865
866 Hstart_time->Fill(start_times[0].t0,id);
867 }
868
869
870 // Add hits used as associated objects
871 const vector<const DCDCTrackHit*> &cdchits = fitter->GetCDCFitHits();
872 const vector<const DFDCPseudo*> &fdchits = fitter->GetFDCFitHits();
873
874 unsigned int num_fdc_potential=fitter->GetNumPotentialFDCHits();
875 unsigned int num_cdc_potential=fitter->GetNumPotentialCDCHits();
876
877 DTrackTimeBased::hit_usage_t temp;
878 temp.inner_layer=0;
879 temp.outer_layer=0;
880 temp.total_hits=num_cdc_potential;
881 if (cdchits.size()>0){
882 temp.inner_layer=cdchits[0]->wire->ring;
883 temp.outer_layer=cdchits[cdchits.size()-1]->wire->ring;
884 }
885 timebased_track->cdc_hit_usage=temp;
886
887 // Reset the structure
888 temp.inner_layer=0;
889 temp.outer_layer=0;
890 temp.total_hits=num_fdc_potential;
891 if (fdchits.size()>0){
892 temp.inner_layer=fdchits[0]->wire->layer;
893 temp.outer_layer=fdchits[fdchits.size()-1]->wire->layer;
894 }
895 timebased_track->fdc_hit_usage=temp;
896
897 for(unsigned int m=0; m<cdchits.size(); m++)
898 timebased_track->AddAssociatedObject(cdchits[m]);
899 for(unsigned int m=0; m<fdchits.size(); m++)
900 timebased_track->AddAssociatedObject(fdchits[m]);
901
902 timebased_track->measured_cdc_hits_on_track = cdchits.size();
903 timebased_track->measured_fdc_hits_on_track = fdchits.size();
904
905 // dEdx
906 double locdEdx_FDC, locdx_FDC, locdEdx_CDC, locdEdx_CDC_amp;
907 double locdx_CDC,locdx_CDC_amp;
908 unsigned int locNumHitsUsedFordEdx_FDC, locNumHitsUsedFordEdx_CDC;
909 pid_algorithm->CalcDCdEdx(timebased_track, locdEdx_FDC, locdx_FDC, locdEdx_CDC, locdEdx_CDC_amp,locdx_CDC,locdx_CDC_amp, locNumHitsUsedFordEdx_FDC, locNumHitsUsedFordEdx_CDC);
910
911 timebased_track->ddEdx_FDC = locdEdx_FDC;
912 timebased_track->ddx_FDC = locdx_FDC;
913 timebased_track->dNumHitsUsedFordEdx_FDC = locNumHitsUsedFordEdx_FDC;
914 timebased_track->ddEdx_CDC = locdEdx_CDC;
915 timebased_track->ddEdx_CDC_amp= locdEdx_CDC_amp;
916 timebased_track->ddx_CDC = locdx_CDC;
917 timebased_track->ddx_CDC_amp= locdx_CDC_amp;
918 timebased_track->dNumHitsUsedFordEdx_CDC = locNumHitsUsedFordEdx_CDC;
919
920 // Set CDC ring & FDC plane hit patterns before candidate and wirebased tracks are associated
921 vector<const DCDCTrackHit*> tempCDCTrackHits;
922 vector<const DFDCPseudo*> tempFDCPseudos;
923 timebased_track->Get(tempCDCTrackHits);
924 timebased_track->Get(tempFDCPseudos);
925 timebased_track->dCDCRings = pid_algorithm->Get_CDCRingBitPattern(tempCDCTrackHits);
926 timebased_track->dFDCPlanes = pid_algorithm->Get_FDCPlaneBitPattern(tempFDCPseudos);
927
928 timebased_track->potential_cdc_hits_on_track = fitter->GetNumPotentialCDCHits();
929 timebased_track->potential_fdc_hits_on_track = fitter->GetNumPotentialFDCHits();
930
931 // Add DTrack object as associate object
932 timebased_track->AddAssociatedObject(track);
933
934 // Compute the figure-of-merit based on tracking
935 timebased_track->FOM = TMath::Prob(timebased_track->chisq, timebased_track->Ndof);
936 //_DBG_<< "FOM: " << timebased_track->FOM << endl;
937
938 _data.push_back(timebased_track);
939
940 return true;
941 break;
942
943 }
944 default:
945 break;
946 }
947 return false;
948}
949
950
951// Create a track with a mass hypothesis that was not present in the list of
952// fitted tracks from an existing fitted track.
953void DTrackTimeBased_factory::AddMissingTrackHypothesis(vector<DTrackTimeBased*>&tracks_to_add,
954 const DTrackTimeBased *src_track,
955 double my_mass,
956 double q,
957 JEventLoop *loop){
958
959 // Create a new time-based track object
960 DTrackTimeBased *timebased_track = new DTrackTimeBased();
961 *static_cast<DTrackingData*>(timebased_track) = *static_cast<const DTrackingData*>(src_track);
962
963 // Get the hits used in the fit
964 vector<const DCDCTrackHit *>src_cdchits;
965 src_track->GetT(src_cdchits);
966 vector<const DFDCPseudo *>src_fdchits;
967 src_track->GetT(src_fdchits);
968
969 // Copy over DKinematicData part from the result of a successful fit
970 timebased_track->setPID(IDTrack(q, my_mass));
971 timebased_track->chisq = src_track->chisq;
972 timebased_track->Ndof = src_track->Ndof;
973 timebased_track->pulls = src_track->pulls;
974 timebased_track->extrapolations = src_track->extrapolations;
975 timebased_track->trackid = src_track->id;
976 timebased_track->candidateid=src_track->candidateid;
977 timebased_track->FOM=src_track->FOM;
978 timebased_track->cdc_hit_usage=src_track->cdc_hit_usage;
979 timebased_track->fdc_hit_usage=src_track->fdc_hit_usage;
980 timebased_track->flags=DTrackTimeBased::FLAG__USED_OTHER_HYPOTHESIS;
981
982 // Add list of start times
983 timebased_track->start_times.assign(src_track->start_times.begin(),
984 src_track->start_times.end());
985 // Set the start time we used
986 timebased_track->setT0(timebased_track->start_times[0].t0,
987 timebased_track->start_times[0].t0_sigma,
988 timebased_track->start_times[0].system);
989
990 // Add DTrack object as associate object
991 vector<const DTrackWireBased*>wire_based_track;
992 src_track->GetT(wire_based_track);
993 timebased_track->AddAssociatedObject(wire_based_track[0]);
994
995 // (Partially) compensate for the difference in energy loss between the
996 // source track and a particle of mass my_mass
997 DVector3 position,momentum;
998 if (timebased_track->extrapolations.at(SYS_CDC).size()>0){
999 unsigned int index=timebased_track->extrapolations.at(SYS_CDC).size()-1;
1000 position=timebased_track->extrapolations[SYS_CDC][index].position;
1001 momentum=timebased_track->extrapolations[SYS_CDC][index].momentum;
1002 }
1003 else if (timebased_track->extrapolations.at(SYS_FDC).size()>0){
1004 unsigned int index=timebased_track->extrapolations.at(SYS_FDC).size()-1;
1005 position=timebased_track->extrapolations[SYS_FDC][index].position;
1006 momentum=timebased_track->extrapolations[SYS_FDC][index].momentum;
1007 }
1008
1009 DTrackFitter::fit_status_t status=DTrackFitter::kFitNotDone;
1010 if (momentum.Mag()>0.){
1011 CorrectForELoss(position,momentum,q,my_mass);
1012 timebased_track->setMomentum(momentum);
1013 timebased_track->setPosition(position);
1014 // Redo the fit with the new position and momentum as initial guesses
1015 fitter->Reset();
1016 fitter->SetFitType(DTrackFitter::kTimeBased);
1017 status = fitter->FindHitsAndFitTrack(*timebased_track,
1018 timebased_track->extrapolations,loop,
1019 my_mass,
1020 src_cdchits.size()+2*src_fdchits.size(),
1021 timebased_track->t0(),
1022 timebased_track->t0_detector());
1023 // if the fit returns chisq=-1, something went terribly wrong. Do not
1024 // update the parameters for the track...
1025 if (fitter->GetChisq()<0) status=DTrackFitter::kFitFailed;
1026
1027 // if the fit flips the charge of the track, then this is bad as well
1028 if(q != fitter->GetFitParameters().charge())
1029 status=DTrackFitter::kFitFailed;
1030
1031 // if we can't refit the track, it is likely of poor quality, so stop here and do not add the hypothesis
1032 if(status == DTrackFitter::kFitFailed) {
1033 delete timebased_track;
1034 return;
1035 }
1036
1037 if (status==DTrackFitter::kFitSuccess){
1038 timebased_track->chisq = fitter->GetChisq();
1039 timebased_track->Ndof = fitter->GetNdof();
1040 timebased_track->pulls = std::move(fitter->GetPulls());
1041 timebased_track->extrapolations=std::move(fitter->GetExtrapolations());
1042 timebased_track->IsSmoothed = fitter->GetIsSmoothed();
1043 *static_cast<DTrackingData*>(timebased_track) = fitter->GetFitParameters();
1044 timebased_track->flags=DTrackTimeBased::FLAG__GOODFIT;
1045
1046 timebased_track->setTime(timebased_track->start_times[0].t0);
1047
1048 // Add hits used as associated objects
1049 const vector<const DCDCTrackHit*> &cdchits = fitter->GetCDCFitHits();
1050 const vector<const DFDCPseudo*> &fdchits = fitter->GetFDCFitHits();
1051
1052 unsigned int num_fdc_potential=fitter->GetNumPotentialFDCHits();
1053 unsigned int num_cdc_potential=fitter->GetNumPotentialCDCHits();
1054
1055 DTrackTimeBased::hit_usage_t temp;
1056 temp.inner_layer=0;
1057 temp.outer_layer=0;
1058 temp.total_hits=num_cdc_potential;
1059 if (cdchits.size()>0){
1060 temp.inner_layer=cdchits[0]->wire->ring;
1061 temp.outer_layer=cdchits[cdchits.size()-1]->wire->ring;
1062 }
1063 timebased_track->cdc_hit_usage=temp;
1064
1065 // Reset the structure
1066 temp.inner_layer=0;
1067 temp.outer_layer=0;
1068 temp.total_hits=num_fdc_potential;
1069 if (fdchits.size()>0){
1070 temp.inner_layer=fdchits[0]->wire->layer;
1071 temp.outer_layer=fdchits[fdchits.size()-1]->wire->layer;
1072 }
1073 timebased_track->fdc_hit_usage=temp;
1074
1075 for(unsigned int m=0; m<cdchits.size(); m++)
1076 timebased_track->AddAssociatedObject(cdchits[m]);
1077 for(unsigned int m=0; m<fdchits.size(); m++)
1078 timebased_track->AddAssociatedObject(fdchits[m]);
1079
1080 timebased_track->measured_cdc_hits_on_track = cdchits.size();
1081 timebased_track->measured_fdc_hits_on_track = fdchits.size();
1082
1083 // Compute the figure-of-merit based on tracking
1084 timebased_track->FOM = TMath::Prob(timebased_track->chisq, timebased_track->Ndof);
1085
1086 }
1087 }
1088
1089 if (status!=DTrackFitter::kFitSuccess){
1090 for(unsigned int m=0; m<src_fdchits.size(); m++)
1091 timebased_track->AddAssociatedObject(src_fdchits[m]);
1092 for(unsigned int m=0; m<src_cdchits.size(); m++)
1093 timebased_track->AddAssociatedObject(src_cdchits[m]);
1094
1095 timebased_track->measured_cdc_hits_on_track = src_cdchits.size();
1096 timebased_track->measured_fdc_hits_on_track = src_fdchits.size();
1097 }
1098
1099 // dEdx
1100 double locdEdx_FDC, locdx_FDC, locdEdx_CDC, locdEdx_CDC_amp;
1101 double locdx_CDC,locdx_CDC_amp;
1102 unsigned int locNumHitsUsedFordEdx_FDC, locNumHitsUsedFordEdx_CDC;
1103 pid_algorithm->CalcDCdEdx(timebased_track, locdEdx_FDC, locdx_FDC, locdEdx_CDC, locdEdx_CDC_amp,locdx_CDC,locdx_CDC_amp, locNumHitsUsedFordEdx_FDC, locNumHitsUsedFordEdx_CDC);
1104
1105 timebased_track->ddEdx_FDC = locdEdx_FDC;
1106 timebased_track->ddx_FDC = locdx_FDC;
1107 timebased_track->dNumHitsUsedFordEdx_FDC = locNumHitsUsedFordEdx_FDC;
1108 timebased_track->ddEdx_CDC = locdEdx_CDC;
1109 timebased_track->ddEdx_CDC_amp = locdEdx_CDC_amp;
1110 timebased_track->ddx_CDC = locdx_CDC;
1111 timebased_track->ddx_CDC_amp = locdx_CDC_amp;
1112 timebased_track->dNumHitsUsedFordEdx_CDC = locNumHitsUsedFordEdx_CDC;
1113
1114 // Set CDC ring & FDC plane hit patterns before candidate and wirebased tracks are associated
1115 vector<const DCDCTrackHit*> tempCDCTrackHits;
1116 vector<const DFDCPseudo*> tempFDCPseudos;
1117 timebased_track->Get(tempCDCTrackHits);
1118 timebased_track->Get(tempFDCPseudos);
1119 timebased_track->dCDCRings = pid_algorithm->Get_CDCRingBitPattern(tempCDCTrackHits);
1120 timebased_track->dFDCPlanes = pid_algorithm->Get_FDCPlaneBitPattern(tempFDCPseudos);
1121
1122 timebased_track->potential_cdc_hits_on_track = fitter->GetNumPotentialCDCHits();
1123 timebased_track->potential_fdc_hits_on_track = fitter->GetNumPotentialFDCHits();
1124
1125 tracks_to_add.push_back(timebased_track);
1126}
1127
1128
1129// If the fit failed for certain hypotheses, fill in the gaps using data from
1130// successful fits for each candidate.
1131bool DTrackTimeBased_factory::InsertMissingHypotheses(JEventLoop *loop){
1132 if (_data.size()==0) return false;
1133
1134 // Make sure the tracks are ordered by candidate id
1135 sort(_data.begin(),_data.end(),DTrackTimeBased_cmp);
1136
1137 JObject::oid_t old_id=_data[0]->candidateid;
1138 unsigned int mass_bits=0;
1139 double q=_data[0]->charge();
1140 bool flipped_charge=false;
1141 vector<DTrackTimeBased*>myhypotheses;
1142 vector<DTrackTimeBased*>tracks_to_add;
1143 for (size_t i=0;i<_data.size();i++){
1144 if (_data[i]->candidateid!=old_id){
1145 AddMissingTrackHypotheses(mass_bits,tracks_to_add,myhypotheses,q,
1146 flipped_charge,loop);
1147
1148 // Clear the myhypotheses vector for the next track
1149 myhypotheses.clear();
1150 // Reset flags and charge
1151 q=_data[i]->charge();
1152 flipped_charge=false;
1153 // Set the bit for this mass hypothesis
1154 mass_bits = 1<<_data[i]->PID();
1155
1156 // Add the data to the myhypotheses vector
1157 myhypotheses.push_back(_data[i]);
1158 }
1159 else{
1160 myhypotheses.push_back(_data[i]);
1161
1162 // Set the bit for this mass hypothesis
1163 mass_bits |= 1<< _data[i]->PID();
1164
1165 // Check if the sign of the charge has flipped
1166 if (_data[i]->charge()!=q) flipped_charge=true;
1167 }
1168
1169 old_id=_data[i]->candidateid;
1170 }
1171 // Deal with last track candidate
1172 AddMissingTrackHypotheses(mass_bits,tracks_to_add,myhypotheses,q,
1173 flipped_charge,loop);
1174
1175 // Add the new list of tracks to the output list
1176 if (tracks_to_add.size()>0){
1177 for (size_t i=0;i<tracks_to_add.size();i++){
1178 _data.push_back(tracks_to_add[i]);
1179 }
1180 // Make sure the tracks are ordered by candidate id
1181 sort(_data.begin(),_data.end(),DTrackTimeBased_cmp);
1182 }
1183
1184 return true;
1185}
1186
1187// Use the FastSwim method in DReferenceTrajectory to propagate back to the
1188// POCA to the beam line, adding a bit of energy at each step that would have
1189// been lost had the particle emerged from the target.
1190void DTrackTimeBased_factory::CorrectForELoss(DVector3 &position,DVector3 &momentum,double q,double my_mass){
1191 DReferenceTrajectory::swim_step_t dummy_step;
1192 DReferenceTrajectory rt(fitter->GetDMagneticFieldMap(),q,&dummy_step);
1193 rt.SetDGeometry(geom);
1194 rt.SetMass(my_mass);
1195 rt.SetPLossDirection(DReferenceTrajectory::kBackward);
1196 DVector3 last_pos,last_mom;
1197 DVector3 origin(0.,0.,65.);
1198 DVector3 dir(0.,0.,1.);
1199 rt.FastSwim(position,momentum,last_pos,last_mom,q,origin,dir,300.);
1200 position=last_pos;
1201 momentum=last_mom;
1202}
1203
1204// Fill in all missing hypotheses for a given track candidate
1205void DTrackTimeBased_factory::AddMissingTrackHypotheses(unsigned int mass_bits,
1206 vector<DTrackTimeBased*>&tracks_to_add,
1207 vector<DTrackTimeBased *>&myhypotheses,
1208 double q,
1209 bool flipped_charge,
1210 JEventLoop *loop){
1211
1212 unsigned int last_index=myhypotheses.size()-1;
1213 unsigned int index=0;
1214 if (q>0){
1215 if (flipped_charge){
1216 /*if ((mass_bits & (1<<AntiProton))==0){
1217 AddMissingTrackHypothesis(tracks_to_add,myhypotheses[last_index],
1218 ParticleMass(Proton),-1.,loop);
1219 }
1220 */
1221 for (unsigned int i=0;i<mass_hypotheses_negative.size();i++){
1222 if ((mass_bits & (1<<mass_hypotheses_negative[i]))==0){
1223 if (mass_hypotheses_negative[i]>13) index=last_index;
1224 else index=0;
1225 AddMissingTrackHypothesis(tracks_to_add,myhypotheses[index],
1226 ParticleMass(Particle_t(mass_hypotheses_negative[i])),
1227 -1.,loop);
1228 }
1229 }
1230 }
1231 /* if ((mass_bits & (1<<Proton))==0){
1232 AddMissingTrackHypothesis(tracks_to_add,myhypotheses[last_index],
1233 ParticleMass(Proton),+1.,loop);
1234 } */
1235 for (unsigned int i=0;i<mass_hypotheses_positive.size();i++){
1236 if ((mass_bits & (1<<mass_hypotheses_positive[i]))==0){
1237 if (mass_hypotheses_positive[i]>13) index=last_index;
1238 else index=0;
1239 AddMissingTrackHypothesis(tracks_to_add,myhypotheses[index],
1240 ParticleMass(Particle_t(mass_hypotheses_positive[i])),
1241 +1.,loop);
1242 }
1243 }
1244 }
1245 else{
1246 /*
1247 if ((mass_bits & (1<<AntiProton))==0){
1248 AddMissingTrackHypothesis(tracks_to_add,myhypotheses[last_index],
1249 ParticleMass(Proton),-1.,loop);
1250 } */
1251 for (unsigned int i=0;i<mass_hypotheses_negative.size();i++){
1252 if ((mass_bits & (1<<mass_hypotheses_negative[i]))==0){
1253 if (mass_hypotheses_negative[i]>13) index=last_index;
1254 else index=0;
1255 AddMissingTrackHypothesis(tracks_to_add,myhypotheses[index],
1256 ParticleMass(Particle_t(mass_hypotheses_negative[i])),
1257 -1.,loop);
1258 }
1259 }
1260 if (flipped_charge){
1261 /*if ((mass_bits & (1<<Proton))==0){
1262 AddMissingTrackHypothesis(tracks_to_add,myhypotheses[last_index],
1263 ParticleMass(Proton),+1.,loop);
1264 } */
1265 for (unsigned int i=0;i<mass_hypotheses_positive.size();i++){
1266 if ((mass_bits & (1<<mass_hypotheses_positive[i]))==0){
1267 if (mass_hypotheses_positive[i]>13) index=last_index;
1268 else index=0;
1269 AddMissingTrackHypothesis(tracks_to_add,myhypotheses[index],
1270 ParticleMass(Particle_t(mass_hypotheses_positive[i])),
1271 +1.,loop);
1272 }
1273 }
1274 }
1275 }
1276}

/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
3.1
'tag' is not equal to NULL
3.1
'tag' is not equal to NULL
3.1
'tag' is not equal to NULL
==NULL__null ? "":tag; // protection against NULL tags
4
'?' condition is false
291 if(strlen(mytag)==0 && allow_deftag
4.1
'allow_deftag' is true
4.1
'allow_deftag' is true
4.1
'allow_deftag' is true
){
5
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();
6
Assuming the condition is true
7
Taking true branch
8
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);
9
Assuming field 'record_call_stack' is false
10
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);
11
Passing value via 2nd parameter 'tag'
12
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
13
Assuming 'tag' is equal to NULL
14
'?' condition is true
380 if(strlen(mytag)==0 && allow_deftag
14.1
'allow_deftag' is true
14.1
'allow_deftag' is true
14.1
'allow_deftag' is true
){
15
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();
16
Assuming the condition is false
17
Taking false branch
383 }
384
385 for(; iter!=factories.end(); iter++){
18
Calling 'operator!=<jana::JFactory_base **, std::vector<jana::JFactory_base *>>'
21
Returning from 'operator!=<jana::JFactory_base **, std::vector<jana::JFactory_base *>>'
22
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);
23
Taking true branch
396 if(factory == NULL__null)continue;
24
Assuming 'factory' is not equal to NULL
25
Taking false branch
397 const char *factag = factory->Tag()==NULL__null ? "":factory->Tag();
26
Assuming the condition is true
27
'?' condition is true
398 if(!strcmp(factag, tag)){
28
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(); }
19
Assuming the condition is true
20
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