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 DTrackFitterStraightTrack.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/DTrackFitterStraightTrack.cc

libraries/TRACKING/DTrackFitterStraightTrack.cc

1// $Id$
2//
3// File: DTrackFitterStraightTrack.cc
4// Created: Tue Mar 12 10:22:32 EDT 2019
5// Creator: staylor (on Linux ifarm1402.jlab.org 3.10.0-327.el7.x86_64 x86_64)
6//
7
8#include "DTrackFitterStraightTrack.h"
9
10//---------------------------------
11// DTrackFitterStraightTrack (Constructor)
12//---------------------------------
13DTrackFitterStraightTrack::DTrackFitterStraightTrack(JEventLoop *loop):DTrackFitter(loop){
14 int runnumber=(loop->GetJEvent()).GetRunNumber();
15 DApplication* dapp = dynamic_cast<DApplication*>(loop->GetJApplication());
16 JCalibration *jcalib = dapp->GetJCalibration(runnumber);
17 const DGeometry *geom = dapp->GetDGeometry(runnumber);
18
19 // Get pointer to TrackFinder object
20 vector<const DTrackFinder *> finders;
21 loop->Get(finders);
1
Calling 'JEventLoop::Get'
22
23 // Drop the const qualifier from the DTrackFinder pointer
24 finder = const_cast<DTrackFinder*>(finders[0]);
25
26 // Resource pool for matrices
27 dResourcePool_TMatrixFSym = std::make_shared<DResourcePool<TMatrixFSym>>
28 ();
29 dResourcePool_TMatrixFSym->Set_ControlParams(20, 20, 50);
30
31 //****************
32 // FDC parameters
33 //****************
34
35 map<string,double>drift_res_parms;
36 jcalib->Get("FDC/drift_resolution_parms",drift_res_parms);
37 DRIFT_RES_PARMS[0]=drift_res_parms["p0"];
38 DRIFT_RES_PARMS[1]=drift_res_parms["p1"];
39 DRIFT_RES_PARMS[2]=drift_res_parms["p2"];
40
41 // Time-to-distance function parameters for FDC
42 map<string,double>drift_func_parms;
43 jcalib->Get("FDC/drift_function_parms",drift_func_parms);
44 DRIFT_FUNC_PARMS[0]=drift_func_parms["p0"];
45 DRIFT_FUNC_PARMS[1]=drift_func_parms["p1"];
46 DRIFT_FUNC_PARMS[2]=drift_func_parms["p2"];
47 DRIFT_FUNC_PARMS[3]=drift_func_parms["p3"];
48 DRIFT_FUNC_PARMS[4]=1000.;
49 DRIFT_FUNC_PARMS[5]=0.;
50 map<string,double>drift_func_ext;
51 if (jcalib->Get("FDC/drift_function_ext",drift_func_ext)==false){
52 DRIFT_FUNC_PARMS[4]=drift_func_ext["p4"];
53 DRIFT_FUNC_PARMS[5]=drift_func_ext["p5"];
54 }
55
56 PLANE_TO_SKIP=0;
57 gPARMS->SetDefaultParameter("TRKFIT:PLANE_TO_SKIP",PLANE_TO_SKIP);
58
59 //****************
60 // CDC parameters
61 //****************
62 RING_TO_SKIP=0;
63 gPARMS->SetDefaultParameter("TRKFIT:RING_TO_SKIP",RING_TO_SKIP);
64
65 map<string, double> cdc_res_parms;
66 jcalib->Get("CDC/cdc_resolution_parms_v2", cdc_res_parms);
67 CDC_RES_PAR1 = cdc_res_parms["res_par1"];
68 CDC_RES_PAR2 = cdc_res_parms["res_par2"];
69 CDC_RES_PAR3 = cdc_res_parms["res_par3"];
70
71 vector< map<string, double> > tvals;
72 cdc_drift_table.clear();
73 if (jcalib->Get("CDC/cdc_drift_table", tvals)==false){
74 for(unsigned int i=0; i<tvals.size(); i++){
75 map<string, double> &row = tvals[i];
76 cdc_drift_table.push_back(1000.*row["t"]);
77 }
78 }
79 else{
80 jerr << " CDC time-to-distance table not available... bailing..." << endl;
81 exit(0);
82 }
83
84 if (jcalib->Get("CDC/drift_parameters", tvals)==false){
85 map<string, double> &row = tvals[0]; //long drift side
86 long_drift_func[0][0]=row["a1"];
87 long_drift_func[0][1]=row["a2"];
88 long_drift_func[0][2]=row["a3"];
89 long_drift_func[1][0]=row["b1"];
90 long_drift_func[1][1]=row["b2"];
91 long_drift_func[1][2]=row["b3"];
92 long_drift_func[2][0]=row["c1"];
93 long_drift_func[2][1]=row["c2"];
94 long_drift_func[2][2]=row["c3"];
95
96 row = tvals[1]; // short drift side
97 short_drift_func[0][0]=row["a1"];
98 short_drift_func[0][1]=row["a2"];
99 short_drift_func[0][2]=row["a3"];
100 short_drift_func[1][0]=row["b1"];
101 short_drift_func[1][1]=row["b2"];
102 short_drift_func[1][2]=row["b3"];
103 short_drift_func[2][0]=row["c1"];
104 short_drift_func[2][1]=row["c2"];
105 short_drift_func[2][2]=row["c3"];
106 }
107
108 // Get the straw sag parameters from the database
109 max_sag.clear();
110 sag_phi_offset.clear();
111 unsigned int numstraws[28]={42,42,54,54,66,66,80,80,93,93,106,106,123,123,
112 135,135,146,146,158,158,170,170,182,182,197,197,209,209};
113 unsigned int straw_count=0,ring_count=0;
114 if (jcalib->Get("CDC/sag_parameters", tvals)==false){
115 vector<double>temp,temp2;
116 for(unsigned int i=0; i<tvals.size(); i++){
117 map<string, double> &row = tvals[i];
118
119 temp.push_back(row["offset"]);
120 temp2.push_back(row["phi"]);
121
122 straw_count++;
123 if (straw_count==numstraws[ring_count]){
124 max_sag.push_back(temp);
125 sag_phi_offset.push_back(temp2);
126 temp.clear();
127 temp2.clear();
128 straw_count=0;
129 ring_count++;
130 }
131 }
132 }
133
134 // CDC Geometry
135 vector<double>cdc_origin;
136 vector<double>cdc_center;
137 vector<double>cdc_upstream_endplate_pos;
138 vector<double>cdc_endplate_dim;
139 geom->Get("//posXYZ[@volume='CentralDC'/@X_Y_Z",cdc_origin);
140 geom->Get("//posXYZ[@volume='centralDC']/@X_Y_Z",cdc_center);
141 geom->Get("//posXYZ[@volume='CDPU']/@X_Y_Z",cdc_upstream_endplate_pos);
142 geom->Get("//tubs[@name='CDPU']/@Rio_Z",cdc_endplate_dim);
143 cdc_origin[2]+=cdc_center[2]+cdc_upstream_endplate_pos[2]
144 +0.5*cdc_endplate_dim[2];
145 upstreamEndplate=cdc_origin[2];
146
147 double endplate_dz=0.;
148 geom->GetCDCEndplate(downstreamEndplate,endplate_dz,cdc_endplate_rmin,
149 cdc_endplate_rmax);
150 downstreamEndplate-=0.5*endplate_dz;
151
152 // Outer detector geometry parameters
153 if (geom->GetDIRCZ(dDIRCz)==false) dDIRCz=1000.;
154 geom->GetFCALZ(dFCALz);
155 vector<double>tof_face;
156 geom->Get("//section/composition/posXYZ[@volume='ForwardTOF']/@X_Y_Z",
157 tof_face);
158 vector<double>tof_plane;
159 geom->Get("//composition[@name='ForwardTOF']/posXYZ[@volume='forwardTOF']/@X_Y_Z/plane[@value='0']", tof_plane);
160 dTOFz=tof_face[2]+tof_plane[2];
161 geom->Get("//composition[@name='ForwardTOF']/posXYZ[@volume='forwardTOF']/@X_Y_Z/plane[@value='1']", tof_plane);
162 dTOFz+=tof_face[2]+tof_plane[2];
163 dTOFz*=0.5; // mid plane between tof planes
164 geom->GetTRDZ(dTRDz_vec); // TRD planes
165
166 // Get start counter geometry;
167 if (geom->GetStartCounterGeom(sc_pos,sc_norm)){
168 // Create vector of direction vectors in scintillator planes
169 for (int i=0;i<30;i++){
170 vector<DVector3>temp;
171 for (unsigned int j=0;j<sc_pos[i].size()-1;j++){
172 double dx=sc_pos[i][j+1].x()-sc_pos[i][j].x();
173 double dy=sc_pos[i][j+1].y()-sc_pos[i][j].y();
174 double dz=sc_pos[i][j+1].z()-sc_pos[i][j].z();
175 temp.push_back(DVector3(dx/dz,dy/dz,1.));
176 }
177 sc_dir.push_back(temp);
178 }
179 SC_END_NOSE_Z=sc_pos[0][12].z();
180 SC_BARREL_R=sc_pos[0][0].Perp();
181 SC_PHI_SECTOR1=sc_pos[0][0].Phi();
182 }
183
184
185 //*************************
186 // Command-line parameters
187 //*************************
188 VERBOSE=0;
189 gPARMS->SetDefaultParameter("TRKFIT:VERBOSE",VERBOSE);
190 COSMICS=false;
191 gPARMS->SetDefaultParameter("TRKFIND:COSMICS",COSMICS);
192 CHI2CUT = 15.0;
193 gPARMS->SetDefaultParameter("TRKFIT:CHI2CUT",CHI2CUT);
194 DO_PRUNING = true;
195 gPARMS->SetDefaultParameter("TRKFIT:DO_PRUNING",DO_PRUNING);
196}
197
198//---------------------------------
199// ~DTrackFitterStraightTrack (Destructor)
200//---------------------------------
201DTrackFitterStraightTrack::~DTrackFitterStraightTrack()
202{
203
204}
205
206//----------------------------------------------------
207// Comparison routines for sorting
208//----------------------------------------------------
209bool DTrackFitterStraightTrack_cdc_hit_cmp(const DCDCTrackHit *a,
210 const DCDCTrackHit *b){
211
212 return(a->wire->origin.Y()>b->wire->origin.Y());
213}
214
215bool DTrackFitterStraightTrack_cdc_hit_reverse_cmp(const DCDCTrackHit *a,
216 const DCDCTrackHit *b){
217
218 return(a->wire->origin.Y()<b->wire->origin.Y());
219}
220
221bool DTrackFitterStraightTrack_cdc_hit_radius_cmp(const DCDCTrackHit *a,
222 const DCDCTrackHit *b){
223 if (a==NULL__null || b==NULL__null){
224 cout << "Null pointer in CDC hit list??" << endl;
225 return false;
226 }
227 const DCDCWire *wire_a= a->wire;
228 const DCDCWire *wire_b= b->wire;
229 if(wire_a->ring == wire_b->ring){
230 return wire_a->straw < wire_b->straw;
231 }
232
233 return (wire_a->ring<wire_b->ring);
234}
235
236bool DTrackFitterStraightTrack_fdc_hit_cmp(const DFDCPseudo *a,
237 const DFDCPseudo *b){
238
239 return(a->wire->origin.z()<b->wire->origin.z());
240}
241
242//----------------------------------------------------
243// CDC fitting routines
244//----------------------------------------------------
245
246// Smearing function derived from fitting residuals
247inline double DTrackFitterStraightTrack::CDCDriftVariance(double t) const {
248 if (t<0.) t=0.;
249 double sigma=CDC_RES_PAR1/(t+1.)+CDC_RES_PAR2 + CDC_RES_PAR3*t;
250 return sigma*sigma;
251}
252
253// Convert time to distance for the cdc. Also returns the variance in d.
254void DTrackFitterStraightTrack::CDCDriftParameters(double dphi,double delta,
255 double t, double &d,
256 double &V) const{
257
258// NSJ 26 May 2020 included long side a3, b3 and short side c1, c2, c3
259// Previously these parameters were not used (0 in ccdb) for production runs
260// except intensity scan run 72312 by accident 5 May 2020, superseded 8 May.
261// They were used in 2015 for runs 0-3050.
262
263d=0.;
264 double dd_dt=0;
265 if (t>0){
266 double f_0=0.;
267 double f_delta=0.;
268
269 if (delta>0){
270 double a1=long_drift_func[0][0];
271 double a2=long_drift_func[0][1];
272 double a3=long_drift_func[0][2];
273 double b1=long_drift_func[1][0];
274 double b2=long_drift_func[1][1];
275 double b3=long_drift_func[1][2];
276 double c1=long_drift_func[2][0];
277 double c2=long_drift_func[2][1];
278 double c3=long_drift_func[2][2];
279
280 // use "long side" functional form
281 double my_t=0.001*t;
282 double sqrt_t=sqrt(my_t);
283 double t3=my_t*my_t*my_t;
284 double delta_mag=fabs(delta);
285
286 double delta_sq=delta*delta;
287 double a=a1+a2*delta_mag+a3*delta_sq;
288 double b=b1+b2*delta_mag+b3*delta_sq;
289 double c=c1+c2*delta_mag+c3*delta_sq;
290
291 f_delta=a*sqrt_t+b*my_t+c*t3;
292 f_0=a1*sqrt_t+b1*my_t+c1*t3;
293
294 dd_dt=0.001*(0.5*a/sqrt_t+b+3.*c*my_t*my_t);
295
296 }
297 else{
298 double my_t=0.001*t;
299 double sqrt_t=sqrt(my_t);
300 double t3=my_t*my_t*my_t;
301 double delta_mag=fabs(delta);
302
303 // use "short side" functional form
304 double a1=short_drift_func[0][0];
305 double a2=short_drift_func[0][1];
306 double a3=short_drift_func[0][2];
307 double b1=short_drift_func[1][0];
308 double b2=short_drift_func[1][1];
309 double b3=short_drift_func[1][2];
310 double c1=short_drift_func[2][0];
311 double c2=short_drift_func[2][1];
312 double c3=short_drift_func[2][2];
313
314 double delta_sq=delta*delta;
315 double a=a1+a2*delta_mag+a3*delta_sq;
316 double b=b1+b2*delta_mag+b3*delta_sq;
317 double c=c1+c2*delta_mag+c3*delta_sq;
318
319 f_delta=a*sqrt_t+b*my_t+c*t3;
320 f_0=a1*sqrt_t+b1*my_t+c1*t3;
321
322 dd_dt=0.001*(0.5*a/sqrt_t+b+3.*c*my_t*my_t);
323
324 }
325
326 unsigned int max_index=cdc_drift_table.size()-1;
327 if (t>cdc_drift_table[max_index]){
328 //_DBG_ << "t: " << t <<" d " << f_delta <<endl;
329 d=f_delta;
330 }
331
332 // Drift time is within range of table -- interpolate...
333 unsigned int index=0;
334 index=Locate(cdc_drift_table,t);
335 double dt=cdc_drift_table[index+1]-cdc_drift_table[index];
336 double frac=(t-cdc_drift_table[index])/dt;
337 double d_0=0.01*(double(index)+frac);
338
339 double P=0.;
340 double tcut=250.0; // ns
341 if (t<tcut) {
342 P=(tcut-t)/tcut;
343 }
344 d=f_delta*(d_0/f_0*P+1.-P);
345 }
346 double VarMs=0.001; // kludge for material effects
347 V=CDCDriftVariance(t)+mVarT0*dd_dt*dd_dt+VarMs;
348}
349
350// Perform the Kalman Filter for the current set of cdc hits
351jerror_t DTrackFitterStraightTrack::KalmanFilter(DMatrix4x1 &S,DMatrix4x4 &C,
352 vector<int>&used_hits,
353 vector<cdc_update_t>&updates,
354 double &chi2,
355 int &ndof,
356 unsigned int iter){
357 DMatrix1x4 H; // Track projection matrix
358 DMatrix4x1 H_T; // Transpose of track projection matrix
359 DMatrix4x1 K; // Kalman gain matrix
360 DMatrix4x4 J; // Jacobian matrix
361 DMatrix4x1 S0; // State vector from reference trajectory
362 double V=1.15*(0.78*0.78/12.); // sigma=cell_size/sqrt(12.)*scale_factor
363
364 const double d_EPS=1e-8;
365
366 // Zero out the vector of used hit flags
367 for (unsigned int i=0;i<used_hits.size();i++) used_hits[i]=0;
368
369 //Initialize chi2 and ndof
370 chi2=0.;
371 ndof=0;
372
373 //Save the starting values for C and S
374 trajectory[0].Skk=S;
375 trajectory[0].Ckk=C;
376
377 double doca2=0.;
378
379 // CDC index and wire position variables
380 unsigned int cdc_index=cdchits.size()-1;
381 bool more_hits=true;
382 const DCDCWire *wire=cdchits[cdc_index]->wire;
383 DVector3 origin=wire->origin;
384 double z0=origin.z();
385 double vz=wire->udir.z();
386 if (VERBOSE) jout << " Starting in Ring " << wire->ring << endl;
387 DVector3 wdir=(1./vz)*wire->udir;
388 DVector3 wirepos=origin+(trajectory[0].z-z0)*wdir;
389
390 /// compute initial doca^2 to first wire
391 double dx=S(state_x)-wirepos.X();
392 double dy=S(state_y)-wirepos.Y();
393 double old_doca2=dx*dx+dy*dy;
394
395 // Loop over all steps in the trajectory
396 S0=trajectory[0].S;
397 J=trajectory[0].J;
398 for (unsigned int k=1;k<trajectory.size();k++){
399 if (!C.IsPosDef()) return UNRECOVERABLE_ERROR;
400
401 // Propagate the state and covariance matrix forward in z
402 S=trajectory[k].S+J*(S-S0);
403 C=J*C*J.Transpose();
404
405 // Save the current state and covariance matrix in the deque
406 trajectory[k].Skk=S;
407 trajectory[k].Ckk=C;
408
409 // Save S and J for the next step
410 S0=trajectory[k].S;
411 J=trajectory[k].J;
412
413 // Position along wire
414 wirepos=origin+(trajectory[k].z-z0)*wdir;
415
416 // New doca^2
417 dx=S(state_x)-wirepos.X();
418 dy=S(state_y)-wirepos.Y();
419 doca2=dx*dx+dy*dy;
420 if (VERBOSE > 10) jout<< "At Position " << S(state_x) << " " << S(state_y) << " " << trajectory[k].z << " doca2 " << doca2 << endl;
421
422 if (doca2>old_doca2 && more_hits){
423
424 // zero-position and direction of line describing particle trajectory
425 double tx=S(state_tx),ty=S(state_ty);
426 DVector3 pos0(S(state_x),S(state_y),trajectory[k].z);
427 DVector3 tdir(tx,ty,1.);
428
429 // Find the true doca to the wire
430 DVector3 diff=pos0-origin;
431 double dx0=diff.x(),dy0=diff.y();
432 double wdir_dot_diff=diff.Dot(wdir);
433 double tdir_dot_diff=diff.Dot(tdir);
434 double tdir_dot_wdir=tdir.Dot(wdir);
435 double tdir2=tdir.Mag2();
436 double wdir2=wdir.Mag2();
437 double D=tdir2*wdir2-tdir_dot_wdir*tdir_dot_wdir;
438 double N=tdir_dot_wdir*wdir_dot_diff-wdir2*tdir_dot_diff;
439 double N1=tdir2*wdir_dot_diff-tdir_dot_wdir*tdir_dot_diff;
440 double scale=1./D;
441 double s=scale*N;
442 double t=scale*N1;
443 diff+=s*tdir-t*wdir;
444 double d=diff.Mag()+d_EPS; // prevent division by zero
445
446 // The next measurement
447 double dmeas=0.39,delta=0.;
448 double tdrift=cdchits[cdc_index]->tdrift-trajectory[k].t;
449 if (fit_type==kTimeBased){
450 double phi_d=diff.Phi();
451 double dphi=phi_d-origin.Phi();
452 while (dphi>M_PI3.14159265358979323846) dphi-=2*M_PI3.14159265358979323846;
453 while (dphi<-M_PI3.14159265358979323846) dphi+=2*M_PI3.14159265358979323846;
454
455 int ring_index=cdchits[cdc_index]->wire->ring-1;
456 int straw_index=cdchits[cdc_index]->wire->straw-1;
457 double dz=t*wdir.z();
458 double delta=max_sag[ring_index][straw_index]*(1.-dz*dz/5625.)
459 *cos(phi_d+sag_phi_offset[ring_index][straw_index]);
460 CDCDriftParameters(dphi,delta,tdrift,dmeas,V);
461 }
462
463 // residual
464 double res=dmeas-d;
465 if (VERBOSE>5) jout << " Residual " << res << endl;
466
467 // Track projection
468
469 double one_over_d=1./d;
470 double diffx=diff.x(),diffy=diff.y(),diffz=diff.z();
471 double wx=wdir.x(),wy=wdir.y();
472
473 double dN1dtx=2.*tx*wdir_dot_diff-wx*tdir_dot_diff-tdir_dot_wdir*dx0;
474 double dDdtx=2.*tx*wdir2-2.*tdir_dot_wdir*wx;
475 double dtdtx=scale*(dN1dtx-t*dDdtx);
476
477 double dN1dty=2.*ty*wdir_dot_diff-wy*tdir_dot_diff-tdir_dot_wdir*dy0;
478 double dDdty=2.*ty*wdir2-2.*tdir_dot_wdir*wy;
479 double dtdty=scale*(dN1dty-t*dDdty);
480
481 double dNdtx=wx*wdir_dot_diff-wdir2*dx0;
482 double dsdtx=scale*(dNdtx-s*dDdtx);
483
484 double dNdty=wy*wdir_dot_diff-wdir2*dy0;
485 double dsdty=scale*(dNdty-s*dDdty);
486
487 H(state_tx)=H_T(state_tx)
488 =one_over_d*(diffx*(s+tx*dsdtx-wx*dtdtx)+diffy*(ty*dsdtx-wy*dtdtx)
489 +diffz*(dsdtx-dtdtx));
490 H(state_ty)=H_T(state_ty)
491 =one_over_d*(diffx*(tx*dsdty-wx*dtdty)+diffy*(s+ty*dsdty-wy*dtdty)
492 +diffz*(dsdty-dtdty));
493
494 double dsdx=scale*(tdir_dot_wdir*wx-wdir2*tx);
495 double dtdx=scale*(tdir2*wx-tdir_dot_wdir*tx);
496 double dsdy=scale*(tdir_dot_wdir*wy-wdir2*ty);
497 double dtdy=scale*(tdir2*wy-tdir_dot_wdir*ty);
498
499 H(state_x)=H_T(state_x)
500 =one_over_d*(diffx*(1.+dsdx*tx-dtdx*wx)+diffy*(dsdx*ty-dtdx*wy)
501 +diffz*(dsdx-dtdx));
502 H(state_y)=H_T(state_y)
503 =one_over_d*(diffx*(dsdy*tx-dtdy*wx)+diffy*(1.+dsdy*ty-dtdy*wy)
504 +diffz*(dsdy-dtdy));
505
506 double InvV=1./(V+H*C*H_T);
507
508 // Check how far this hit is from the projection
509 double chi2check=res*res*InvV;
510 if (chi2check < CHI2CUT || DO_PRUNING == 0 || (COSMICS && iter == 0)){
511 if (VERBOSE>5) jout << "Hit Added to track " << endl;
512 if (cdchits[cdc_index]->wire->ring!=RING_TO_SKIP){
513
514 // Compute Kalman gain matrix
515 K=InvV*(C*H_T);
516
517 // Update state vector covariance matrix
518 DMatrix4x4 Ctest=C-K*(H*C);
519
520 //C.Print();
521 //K.Print();
522 //Ctest.Print();
523
524 // Check that Ctest is positive definite
525 if (!Ctest.IsPosDef()) return VALUE_OUT_OF_RANGE;
526 C=Ctest;
527 if(VERBOSE>10) C.Print();
528 // Update the state vector
529 //S=S+res*K;
530 S+=res*K;
531 if(VERBOSE>10) S.Print();
532
533 // Compute new residual
534 //d=finder->FindDoca(trajectory[k].z,S,wdir,origin);
535 res=res-H*K*res;
536
537 // Update chi2
538 double fit_V=V-H*C*H_T;
539 chi2+=res*res/fit_V;
540 ndof++;
541
542 // fill pull vector entry
543 updates[cdc_index].V=fit_V;
544 }
545 else {
546 updates[cdc_index].V=V;
547 }
548
549 // Flag that we used this hit
550 used_hits[cdc_index]=1;
551
552 // fill updates
553 updates[cdc_index].resi=res;
554 updates[cdc_index].d=d;
555 updates[cdc_index].delta=delta;
556 updates[cdc_index].S=S;
557 updates[cdc_index].C=C;
558 updates[cdc_index].tdrift=tdrift;
559 updates[cdc_index].ddrift=dmeas;
560 updates[cdc_index].s=29.98*trajectory[k].t; // assume beta=1
561 trajectory[k].id=cdc_index+1;
562 }
563 // move to next cdc hit
564 if (cdc_index>0){
565 cdc_index--;
566
567 //New wire position
568 wire=cdchits[cdc_index]->wire;
569 if (VERBOSE>5) {
570 jout << " Next Wire ring " << wire->ring << " straw " << wire->straw << " origin udir" << endl;
571 wire->origin.Print(); wire->udir.Print();
572 }
573 origin=wire->origin;
574 z0=origin.z();
575 vz=wire->udir.z();
576 wdir=(1./vz)*wire->udir;
577 wirepos=origin+((trajectory[k].z-z0))*wdir;
578
579 // New doca^2
580 dx=S(state_x)-wirepos.x();
581 dy=S(state_y)-wirepos.y();
582 doca2=dx*dx+dy*dy;
583
584 }
585 else more_hits=false;
586 }
587
588 old_doca2=doca2;
589 }
590 if (ndof<=4) return VALUE_OUT_OF_RANGE;
591
592 ndof-=4;
593
594 return NOERROR;
595}
596
597// Smooth the CDC only tracks
598jerror_t DTrackFitterStraightTrack::Smooth(vector<cdc_update_t>&cdc_updates){
599 unsigned int max=best_trajectory.size()-1;
600 DMatrix4x1 S=(best_trajectory[max].Skk);
601 DMatrix4x4 C=(best_trajectory[max].Ckk);
602 DMatrix4x4 JT=best_trajectory[max].J.Transpose();
603 DMatrix4x1 Ss=S;
604 DMatrix4x4 Cs=C;
605 DMatrix4x4 A,dC;
606 DMatrix1x4 H; // Track projection matrix
607 DMatrix4x1 H_T; // Transpose of track projection matrix
608
609 const double d_EPS=1e-8;
610
611 for (unsigned int m=max-1;m>0;m--){
612 if (best_trajectory[m].id>0){
613 unsigned int id=best_trajectory[m].id-1;
614 A=cdc_updates[id].C*JT*C.Invert();
615 Ss=cdc_updates[id].S+A*(Ss-S);
616
617 dC=A*(Cs-C)*A.Transpose();
618 Cs=cdc_updates[id].C+dC;
619 if (VERBOSE > 10) {
620 jout << " In Smoothing Step Using ID " << id << "/" << cdc_updates.size() << " for ring " << cdchits[id]->wire->ring << endl;
621 jout << " A cdc_updates[id].C Ss Cs " << endl;
622 A.Print(); cdc_updates[id].C.Print(); Ss.Print(); Cs.Print();
623 }
624 if(!Cs.IsPosDef()) {
625 if (VERBOSE) jout << "Cs is not PosDef!" << endl;
626 return VALUE_OUT_OF_RANGE;
627 }
628
629 const DCDCWire *wire=cdchits[id]->wire;
630 DVector3 origin=wire->origin;
631 double z0=origin.z();
632 double vz=wire->udir.z();
633 DVector3 wdir=(1./vz)*wire->udir;
634 DVector3 wirepos=origin+(best_trajectory[m].z-z0)*wdir;
635 // Position and direction from state vector
636 double x=Ss(state_x);
637 double y=Ss(state_y);
638 double tx=Ss(state_tx);
639 double ty=Ss(state_ty);
640
641 DVector3 pos0(x,y,best_trajectory[m].z);
642 DVector3 tdir(tx,ty,1.);
643
644 // Find the true doca to the wire
645 DVector3 diff=pos0-origin;
646 double dx0=diff.x(),dy0=diff.y();
647 double wdir_dot_diff=diff.Dot(wdir);
648 double tdir_dot_diff=diff.Dot(tdir);
649 double tdir_dot_wdir=tdir.Dot(wdir);
650 double tdir2=tdir.Mag2();
651 double wdir2=wdir.Mag2();
652 double D=tdir2*wdir2-tdir_dot_wdir*tdir_dot_wdir;
653 double N=tdir_dot_wdir*wdir_dot_diff-wdir2*tdir_dot_diff;
654 double N1=tdir2*wdir_dot_diff-tdir_dot_wdir*tdir_dot_diff;
655 double scale=1./D;
656 double s=scale*N;
657 double t=scale*N1;
658 diff+=s*tdir-t*wdir;
659 double d=diff.Mag()+d_EPS; // prevent division by zero
660 double ddrift = cdc_updates[id].ddrift;
661
662 double resi = ddrift - d;
663 // Track projection
664
665 {
666 double one_over_d=1./d;
667 double diffx=diff.x(),diffy=diff.y(),diffz=diff.z();
668 double wx=wdir.x(),wy=wdir.y();
669
670 double dN1dtx=2.*tx*wdir_dot_diff-wx*tdir_dot_diff-tdir_dot_wdir*dx0;
671 double dDdtx=2.*tx*wdir2-2.*tdir_dot_wdir*wx;
672 double dtdtx=scale*(dN1dtx-t*dDdtx);
673
674 double dN1dty=2.*ty*wdir_dot_diff-wy*tdir_dot_diff-tdir_dot_wdir*dy0;
675 double dDdty=2.*ty*wdir2-2.*tdir_dot_wdir*wy;
676 double dtdty=scale*(dN1dty-t*dDdty);
677
678 double dNdtx=wx*wdir_dot_diff-wdir2*dx0;
679 double dsdtx=scale*(dNdtx-s*dDdtx);
680
681 double dNdty=wy*wdir_dot_diff-wdir2*dy0;
682 double dsdty=scale*(dNdty-s*dDdty);
683
684 H(state_tx)=H_T(state_tx)
685 =one_over_d*(diffx*(s+tx*dsdtx-wx*dtdtx)+diffy*(ty*dsdtx-wy*dtdtx)
686 +diffz*(dsdtx-dtdtx));
687 H(state_ty)=H_T(state_ty)
688 =one_over_d*(diffx*(tx*dsdty-wx*dtdty)+diffy*(s+ty*dsdty-wy*dtdty)
689 +diffz*(dsdty-dtdty));
690
691 double dsdx=scale*(tdir_dot_wdir*wx-wdir2*tx);
692 double dtdx=scale*(tdir2*wx-tdir_dot_wdir*tx);
693 double dsdy=scale*(tdir_dot_wdir*wy-wdir2*ty);
694 double dtdy=scale*(tdir2*wy-tdir_dot_wdir*ty);
695
696 H(state_x)=H_T(state_x)
697 =one_over_d*(diffx*(1.+dsdx*tx-dtdx*wx)+diffy*(dsdx*ty-dtdx*wy)
698 +diffz*(dsdx-dtdx));
699 H(state_y)=H_T(state_y)
700 =one_over_d*(diffx*(dsdy*tx-dtdy*wx)+diffy*(1.+dsdy*ty-dtdy*wy)
701 +diffz*(dsdy-dtdy));
702 }
703 double V=cdc_updates[id].V;
704
705 if (VERBOSE > 10) jout << " d " << d << " H*S " << H*S << endl;
706 if (cdchits[id]->wire->ring==RING_TO_SKIP){
707 V=V+H*Cs*H_T;
708 }
709 else{
710 V=V-H*Cs*H_T;
711 }
712 if (V<0) return VALUE_OUT_OF_RANGE;
713
714 // Add the pull
715 double myscale=1./sqrt(1.+tx*tx+ty*ty);
716 double cosThetaRel=wire->udir.Dot(DVector3(myscale*tx,myscale*ty,myscale));
717 pull_t thisPull(resi,sqrt(V),
718 best_trajectory[m].t*SPEED_OF_LIGHT29.9792458,
719 cdc_updates[id].tdrift,
720 d,cdchits[id], NULL__null,
721 diff.Phi(), //docaphi
722 best_trajectory[m].z,cosThetaRel,
723 cdc_updates[id].tdrift);
724
725 // Derivatives for alignment
726 double wtx=wire->udir.X(), wty=wire->udir.Y(), wtz=wire->udir.Z();
727 double wx=wire->origin.X(), wy=wire->origin.Y(), wz=wire->origin.Z();
728
729 double z=best_trajectory[m].z;
730 double tx2=tx*tx, ty2=ty*ty;
731 double wtx2=wtx*wtx, wty2=wty*wty, wtz2=wtz*wtz;
732 double denom=(1 + ty2)*wtx2 + (1 + tx2)*wty2 - 2*ty*wty*wtz + (tx2 + ty2)*wtz2 - 2*tx*wtx*(ty*wty + wtz) +d_EPS;
733 double denom2=denom*denom;
734 double c1=-(wtx - tx*wtz)*(wy - y);
735 double c2=wty*(wx - tx*wz - x + tx*z);
736 double c3=ty*(-(wtz*wx) + wtx*wz + wtz*x - wtx*z);
737 double dscale=0.5*(1./d);
738
739 vector<double> derivatives(11);
740
741 derivatives[CDCTrackD::dDOCAdOriginX]=dscale*(2*(wty - ty*wtz)*(c1 + c2 + c3))/denom;
742
743 derivatives[CDCTrackD::dDOCAdOriginY]=dscale*(2*(-wtx + tx*wtz)*(c1 + c2 + c3))/denom;
744
745 derivatives[CDCTrackD::dDOCAdOriginZ]=dscale*(2*(ty*wtx - tx*wty)*(c1 + c2 + c3))/denom;
746
747 derivatives[CDCTrackD::dDOCAdDirX]=dscale*(2*(wty - ty*wtz)*(c1 + c2 + c3)*
748 (tx*(ty*wty + wtz)*(wx - x) + (wty - ty*wtz)*(-wy + y + ty*(wz - z)) +
749 wtx*(-((1 + ty2)*wx) + (1 + ty2)*x + tx*(ty*wy + wz - ty*y - z)) + tx2*(wty*(-wy + y) + wtz*(-wz + z))))/denom2;
750
751 derivatives[CDCTrackD::dDOCAdDirY]=dscale*(-2*(wtx - tx*wtz)*(c1 + c2 + c3)*
752 (tx*(ty*wty + wtz)*(wx - x) + (wty - ty*wtz)*(-wy + y + ty*(wz - z)) +
753 wtx*(-((1 + ty2)*wx) + (1 + ty2)*x + tx*(ty*wy + wz - ty*y - z)) + tx2*(wty*(-wy + y) + wtz*(-wz + z))))/denom2;
754
755 derivatives[CDCTrackD::dDOCAdDirZ]=dscale*(-2*(ty*wtx - tx*wty)*(c1 + c2 + c3)*
756 (-(tx*(ty*wty + wtz)*(wx - x)) + tx2*(wty*(wy - y) + wtz*(wz - z)) + (wty - ty*wtz)*(wy - y + ty*(-wz + z)) +
757 wtx*((1 + ty2)*wx - (1 + ty2)*x + tx*(-(ty*wy) - wz + ty*y + z))))/denom2;
758
759 derivatives[CDCTrackD::dDOCAdS0]=-derivatives[CDCTrackD::dDOCAdOriginX];
760
761 derivatives[CDCTrackD::dDOCAdS1]=-derivatives[CDCTrackD::dDOCAdOriginY];
762
763 derivatives[CDCTrackD::dDOCAdS2]=dscale*(2*(wty - ty*wtz)*(-c1 - c2 - c3)*
764 (-(wtx*wtz*wx) - wty*wtz*wy + wtx2*wz + wty2*wz + wtx*wtz*x + wty*wtz*y - wtx2*z - wty2*z +
765 tx*(wty2*(wx - x) + wtx*wty*(-wy + y) + wtz*(wtz*wx - wtx*wz - wtz*x + wtx*z)) +
766 ty*(wtx*wty*(-wx + x) + wtx2*(wy - y) + wtz*(wtz*wy - wty*wz - wtz*y + wty*z))))/denom2;
767
768 derivatives[CDCTrackD::dDOCAdS3]=dscale*(2*(wtx - tx*wtz)*(c1 + c2 + c3)*
769 (-(wtx*wtz*wx) - wty*wtz*wy + wtx2*wz + wty2*wz + wtx*wtz*x + wty*wtz*y - wtx2*z - wty2*z +
770 tx*(wty2*(wx - x) + wtx*wty*(-wy + y) + wtz*(wtz*wx - wtx*wz - wtz*x + wtx*z)) +
771 ty*(wtx*wty*(-wx + x) + wtx2*(wy - y) + wtz*(wtz*wy - wty*wz - wtz*y + wty*z))))/denom2;
772
773 thisPull.AddTrackDerivatives(derivatives);
774 pulls.push_back(thisPull);
775 }
776 else{
777 A=best_trajectory[m].Ckk*JT*C.Invert();
778 Ss=best_trajectory[m].Skk+A*(Ss-S);
779 Cs=best_trajectory[m].Ckk+A*(Cs-C)*A.Transpose();
780 }
781
782 S=best_trajectory[m].Skk;
783 C=best_trajectory[m].Ckk;
784 JT=best_trajectory[m].J.Transpose();
785 }
786
787 return NOERROR;
788}
789
790//Reference trajectory for the track for cdc tracks
791jerror_t DTrackFitterStraightTrack::SetReferenceTrajectory(double t0,double z,
792 DMatrix4x1 &S,
793 const DCDCTrackHit *last_cdc,
794 double &dzsign){
795 DMatrix4x4 J(1.,0.,1.,0., 0.,1.,0.,1., 0.,0.,1.,0., 0.,0.,0.,1.);
796
797 double ds=0.5;
798 double t=t0;
799
800 // last y position of hit (approximate, using center of wire)
801 double last_y=last_cdc->wire->origin.y();
802 double last_r2=last_cdc->wire->origin.Perp2();
803 // Check that track points towards last wire, otherwise swap deltaz
804 DVector3 dir(S(state_tx),S(state_ty),dzsign);
805 if (fabs(dir.Theta() - M_PI_21.57079632679489661923) < 0.2) ds = 0.1;
806
807 //jout << "dPhi " << dphi << " theta " << dir.Theta() << endl;
808 double dz=dzsign*ds/sqrt(1.+S(state_tx)*S(state_tx)+S(state_ty)*S(state_ty));
809
810 if (VERBOSE) {
811 if (COSMICS) jout << " Swimming Reference Trajectory last CDC y " << last_y << " dz "<< dz << endl;
812 else jout << " Swimming Reference Trajectory last CDC r2 " << last_r2 << " dz "<< dz << endl;
813 jout << " S" << endl; S.Print(); jout << "z= "<< z << endl;
814 jout << " Last CDC ring " << last_cdc->wire->ring << " straw " << last_cdc->wire->straw << endl;
815 }
816 unsigned int numsteps=0;
817 const unsigned int MAX_STEPS=5000;
818 bool done=false;
819 do{
820 numsteps++;
821 z+=dz;
822 J(state_x,state_tx)=-dz;
823 J(state_y,state_ty)=-dz;
824 // Flight time: assume particle is moving at the speed of light
825 t+=ds/29.98;
826 //propagate the state to the next z position
827 S(state_x)+=S(state_tx)*dz;
828 S(state_y)+=S(state_ty)*dz;
829
830 if (z > downstreamEndplate && dz < 0) continue;
831 if (z < upstreamEndplate && dz > 0) continue;
832 trajectory.push_front(trajectory_t(z,t,S,J,DMatrix4x1(),DMatrix4x4()));
833
834 done=((z>downstreamEndplate) || (z<upstreamEndplate));
835 if (COSMICS==false){
836 double r2=S(state_x)*S(state_x)+S(state_y)*S(state_y);
837 done |= (r2>last_r2);
838 }
839 }while (!done && numsteps<MAX_STEPS);
840
841 if (VERBOSE)
842 {
843 if (VERBOSE > 10){
844 printf("Trajectory:\n");
845 for (unsigned int i=0;i<trajectory.size();i++){
846 printf(" x %f y %f z %f\n",trajectory[i].S(state_x),
847 trajectory[i].S(state_y),trajectory[i].z);
848 }
849 }
850 else{
851 printf("%i step trajectory Begin/End:\n", numsteps);
852 printf(" x %f y %f z %f\n",trajectory[0].S(state_x), trajectory[0].S(state_y), trajectory[0].z);
853 if (trajectory.size() > 1) printf(" x %f y %f z %f\n",trajectory[trajectory.size()-1].S(state_x),
854 trajectory[trajectory.size()-1].S(state_y),trajectory[trajectory.size()-1].z);
855 }
856 }
857 if (trajectory.size()<2) return UNRECOVERABLE_ERROR;
858 return NOERROR;
859}
860
861// Routine for steering the fit of the track
862DTrackFitter::fit_status_t DTrackFitterStraightTrack::FitTrack(void){
863 DTrackFitter::fit_status_t status=DTrackFitter::kFitNotDone;
864 if (cdchits.size()+fdchits.size() < 4) return status;
865
866 // Initial guess for state vector
867 DVector3 input_pos=input_params.position();
868 DVector3 input_mom=input_params.momentum();
869 double pz=input_mom.z();
870 DMatrix4x1 S(input_pos.x(),input_pos.y(),input_mom.x()/pz,input_mom.y()/pz);
871
872 // Initial guess for covariance matrix
873 DMatrix4x4 C;
874 if (fit_type==kWireBased){
875 C(state_x,state_x)=C(state_y,state_y)=4.0;
876 C(state_tx,state_tx)=C(state_ty,state_ty)=1.0;
877 }
878 else{
879 C(state_x,state_x)=C(state_y,state_y)=1.;
880 C(state_tx,state_tx)=C(state_ty,state_ty)=0.01;
881 }
882
883 // Starting z-position and time
884 double z=input_pos.z();
885 double t0=input_params.t0();
886 // Variance in start time
887 switch(input_params.t0_detector()){
888 case SYS_TOF:
889 mVarT0=0.01;
890 break;
891 case SYS_CDC:
892 mVarT0=25.;
893 break;
894 case SYS_FDC:
895 mVarT0=25.;
896 break;
897 case SYS_BCAL:
898 mVarT0=0.25;
899 break;
900 case SYS_START:
901 mVarT0=0.09;
902 break;
903 default:
904 mVarT0=0.;
905 break;
906 }
907
908 // Chisq and ndof
909 chisq=1e16;
910 Ndof=0;
911
912 // Sort the CDC hits by radius or y (for cosmics)
913 if (cdchits.size()>0){
914 if (COSMICS){
915 stable_sort(cdchits.begin(),cdchits.end(),DTrackFitterStraightTrack_cdc_hit_cmp);
916 }
917 else{
918 stable_sort(cdchits.begin(),cdchits.end(),DTrackFitterStraightTrack_cdc_hit_radius_cmp);
919 }
920 }
921
922 if (fdchits.size()>0){
923 // Sort FDC hits by z
924 stable_sort(fdchits.begin(),fdchits.end(),DTrackFitterStraightTrack_fdc_hit_cmp);
925 status=FitForwardTrack(t0,z,S,C,chisq,Ndof);
926 }
927 else if (cdchits.size()>0){
928 double dzsign=(pz>0)?1.:-1.;
929 status=FitCentralTrack(z,t0,dzsign,S,C,chisq,Ndof);
930 }
931
932 if (status==DTrackFitter::kFitSuccess){
933 // Output fit results
934 double tx=S(state_tx),ty=S(state_ty);
935 double phi=atan2(ty,tx);
936 double tanl=1./sqrt(tx*tx+ty*ty);
937 // Check for tracks heading upstream
938 if (cdchits_used_in_fit.size()>0){
939 double phi_diff=phi-cdchits_used_in_fit[0]->wire->origin.Phi()-M_PI3.14159265358979323846;
940 if (phi_diff<-M_PI3.14159265358979323846) phi_diff+=2.*M_PI3.14159265358979323846;
941 if (phi_diff> M_PI3.14159265358979323846) phi_diff-=2.*M_PI3.14159265358979323846;
942 if (fabs(phi_diff)<M_PI_21.57079632679489661923){
943 tanl*=-1;
944 phi+=M_PI3.14159265358979323846;
945 }
946 }
947 double pt=5.0*cos(atan(tanl)); // arbitrary magnitude...
948 DVector3 mom(pt*cos(phi),pt*sin(phi),pt*tanl);
949
950 // Convert 4x4 covariance matrix to a TMatrixFSym for output
951 TMatrixFSym errMatrix(5);
952 for(unsigned int loc_i = 0; loc_i < 4; ++loc_i){
953 for(unsigned int loc_j = 0; loc_j < 4; ++loc_j){
954 errMatrix(loc_i, loc_j) = C(loc_i, loc_j);
955 }
956 }
957 errMatrix(4,4)=1.;
958
959 // Add 7x7 covariance matrix to output
960 double sign=(mom.Theta()>M_PI_21.57079632679489661923)?-1.:1.;
961 fit_params.setErrorMatrix(Get7x7ErrorMatrix(errMatrix,S,sign));
962
963 DVector3 pos;
964 if (COSMICS==false){
965 DVector3 beamdir(0.,0.,1.);
966 DVector3 beampos(0.,0.,65.);
967 finder->FindDoca(z,S,beamdir,beampos,&pos);
968
969 // Jacobian matrix
970 double dz=pos.z()-z;
971 DMatrix4x4 J(1.,0.,1.,0., 0.,1.,0.,1., 0.,0.,1.,0., 0.,0.,0.,1.);
972 J(state_x,state_tx)=dz;
973 J(state_y,state_ty)=dz;
974 // Transform the matrix to the position of the doca
975 C=J*C*J.Transpose();
976 }
977 else{
978 pos.SetXYZ(S(state_x),S(state_y),z);
979 }
980
981 fit_params.setForwardParmFlag(true);
982
983 fit_params.setPosition(pos);
984 fit_params.setMomentum(mom);
985
986 // Add tracking covariance matrix to output
987 auto locTrackingCovarianceMatrix = dResourcePool_TMatrixFSym->Get_SharedResource();
988 locTrackingCovarianceMatrix->ResizeTo(5, 5);
989 locTrackingCovarianceMatrix->Zero();
990 for(unsigned int loc_i = 0; loc_i < 4; ++loc_i){
991 for(unsigned int loc_j = 0; loc_j < 4; ++loc_j){
992 (*locTrackingCovarianceMatrix)(loc_i, loc_j) = C(loc_i, loc_j);
993 }
994 }
995 (*locTrackingCovarianceMatrix)(4,4)=1.;
996 fit_params.setTrackingErrorMatrix(locTrackingCovarianceMatrix);
997
998 // Get extrapolations to other detectors
999 GetExtrapolations(pos,mom);
1000
1001 }
1002
1003 return status;
1004}
1005
1006// Locate a position in vector xx given x
1007unsigned int DTrackFitterStraightTrack::Locate(const vector<double>&xx,double x) const{
1008 int n=xx.size();
1009 if (x==xx[0]) return 0;
1010 else if (x==xx[n-1]) return n-2;
1011
1012 int jl=-1;
1013 int ju=n;
1014 int ascnd=(xx[n-1]>=xx[0]);
1015 while(ju-jl>1){
1016 int jm=(ju+jl)>>1;
1017 if ( (x>=xx[jm])==ascnd)
1018 jl=jm;
1019 else
1020 ju=jm;
1021 }
1022 return jl;
1023}
1024
1025// Steering routine for fitting CDC-only tracks
1026DTrackFitter::fit_status_t DTrackFitterStraightTrack::FitCentralTrack(double &z0,double t0,
1027 double dzsign,
1028 DMatrix4x1 &Sbest,
1029 DMatrix4x4 &Cbest,
1030 double &chi2_best,
1031 int &ndof_best){
1032 // State vector and covariance matrix
1033 DMatrix4x1 S(Sbest);
1034 DMatrix4x4 C(Cbest),C0(Cbest);
1035
1036 double chi2=chi2_best;
1037 int ndof=ndof_best;
1038
1039 unsigned int numhits=cdchits.size();
1040 unsigned int maxindex=numhits-1;
1041
1042 // vectors of indexes to cdc hits used in the fit
1043 vector<int> used_cdc_hits(numhits);
1044 vector<int> used_cdc_hits_best_fit(numhits);
1045
1046 // vectors of residual information
1047 vector<cdc_update_t>updates(numhits);
1048 vector<cdc_update_t>best_updates(numhits);
1049
1050 // Rest deque for "best" trajectory
1051 best_trajectory.clear();
1052
1053 // Perform the fit
1054 int iter=0;
1055 for(iter=0;iter<20;iter++){
1056 if (VERBOSE) jout << " Performing Pass iter " << iter << endl;
1057
1058 trajectory.clear();
1059 if (SetReferenceTrajectory(t0,z0,S,cdchits[maxindex],dzsign)
1060 !=NOERROR) break;
1061
1062 if (VERBOSE) jout << " Reference Trajectory Set " << endl;
1063 C=C0;
1064 if (KalmanFilter(S,C,used_cdc_hits,updates,chi2,ndof,iter)!=NOERROR) break;
1065 if (VERBOSE) jout << " Filter returns NOERROR" << endl;
1066 if (iter>0 && (fabs(chi2_best-chi2)<0.1 || chi2>chi2_best)) break;
1067
1068 // Save the current state and covariance matrixes
1069 Cbest=C;
1070 Sbest=S;
1071
1072 // Save the current used hit and trajectory information
1073 best_trajectory.assign(trajectory.begin(),trajectory.end());
1074 used_cdc_hits_best_fit.assign(used_cdc_hits.begin(),used_cdc_hits.end());
1075 best_updates.assign(updates.begin(),updates.end());
1076
1077 chi2_best=chi2;
1078 ndof_best=ndof;
1079 }
1080 if (iter==0) return DTrackFitter::kFitFailed;
1081
1082 //Final z position (closest to beam line)
1083 z0=best_trajectory[best_trajectory.size()-1].z;
1084
1085 //Run the smoother
1086 if (Smooth(best_updates) == NOERROR) IsSmoothed=true;
1087
1088 // output list of cdc hits used in the fit
1089 cdchits_used_in_fit.clear();
1090 for (unsigned int m=0;m<used_cdc_hits_best_fit.size();m++){
1091 if (used_cdc_hits_best_fit[m]){
1092 cdchits_used_in_fit.push_back(cdchits[m]);
1093 }
1094 }
1095
1096 return DTrackFitter::kFitSuccess;
1097}
1098
1099
1100//----------------------------------------------------
1101// FDC fitting routines
1102//----------------------------------------------------
1103
1104// parametrization of time-to-distance for FDC
1105double DTrackFitterStraightTrack::fdc_drift_distance(double time) const {
1106 if (time<0.) return 0.;
1107 double d=0.;
1108 double tsq=time*time;
1109 double t_high=DRIFT_FUNC_PARMS[4];
1110
1111 if (time<t_high){
1112 d=DRIFT_FUNC_PARMS[0]*sqrt(time)+DRIFT_FUNC_PARMS[1]*time
1113 +DRIFT_FUNC_PARMS[2]*tsq+DRIFT_FUNC_PARMS[3]*tsq*time;
1114 }
1115 else{
1116 double t_high_sq=t_high*t_high;
1117 d=DRIFT_FUNC_PARMS[0]*sqrt(t_high)+DRIFT_FUNC_PARMS[1]*t_high
1118 +DRIFT_FUNC_PARMS[2]*t_high_sq+DRIFT_FUNC_PARMS[3]*t_high_sq*t_high;
1119 d+=DRIFT_FUNC_PARMS[5]*(time-t_high);
1120 }
1121
1122 return d;
1123
1124}
1125
1126// Crude approximation for the variance in drift distance due to smearing
1127double DTrackFitterStraightTrack::fdc_drift_variance(double t) const{
1128 //return FDC_ANODE_VARIANCE;
1129 if (t<5.) t=5.;
1130 double sigma=DRIFT_RES_PARMS[0]/(t+1.)+DRIFT_RES_PARMS[1]+DRIFT_RES_PARMS[2]*t*t;
1131
1132 return sigma*sigma;
1133}
1134
1135// Steering routine for the kalman filter
1136DTrackFitter::fit_status_t
1137DTrackFitterStraightTrack::FitForwardTrack(double t0,double &start_z,
1138 DMatrix4x1 &Sbest,DMatrix4x4 &Cbest,double &chi2_best,int &ndof_best){
1139 // State vector and covariance matrix
1140 DMatrix4x1 S(Sbest);
1141 DMatrix4x4 C(Cbest),C0(Cbest);
1142
1143 // vectors of indexes to fdc hits used in the fit
1144 unsigned int numfdchits=fdchits.size();
1145 vector<int> used_fdc_hits(numfdchits);
1146 vector<int> used_fdc_hits_best_fit(numfdchits);
1147 // vectors of indexes to cdc hits used in the fit
1148 unsigned int numcdchits=cdchits.size();
1149 vector<int> used_cdc_hits(numcdchits);
1150 vector<int> used_cdc_hits_best_fit(numcdchits);
1151
1152 // vectors of residual information
1153 vector<fdc_update_t>updates(numfdchits);
1154 vector<fdc_update_t>best_updates(numfdchits);
1155 vector<cdc_update_t>cdc_updates(numcdchits);
1156 vector<cdc_update_t>best_cdc_updates(numcdchits);
1157
1158 vector<const DCDCTrackHit *> matchedCDCHits;
1159
1160 // Chi-squared and degrees of freedom
1161 double chi2=chi2_best;
1162 int ndof=ndof_best;
1163
1164 // Rest deque for "best" trajectory
1165 best_trajectory.clear();
1166
1167 unsigned iter=0;
1168 // First pass
1169 for(iter=0;iter<20;iter++){
1170 trajectory.clear();
1171 if (SetReferenceTrajectory(t0,start_z,S)!=NOERROR) break;
1172
1173 C=C0;
1174 if (KalmanFilter(S,C,used_fdc_hits,used_cdc_hits,updates,cdc_updates,
1175 chi2,ndof)!=NOERROR) break;
1176
1177 // printf(" == iter %d =====chi2 %f ndof %d \n",iter,chi2,ndof);
1178 if (iter>0 && (chi2>chi2_best || fabs(chi2_best-chi2)<0.1)) break;
1179
1180 // Save the current state and covariance matrixes
1181 Cbest=C;
1182 Sbest=S;
1183
1184 // Save the current used hit and trajectory information
1185 best_trajectory.assign(trajectory.begin(),trajectory.end());
1186 used_cdc_hits_best_fit.assign(used_cdc_hits.begin(),used_cdc_hits.end());
1187 used_fdc_hits_best_fit.assign(used_fdc_hits.begin(),used_fdc_hits.end());
1188 best_updates.assign(updates.begin(),updates.end());
1189 best_cdc_updates.assign(cdc_updates.begin(),cdc_updates.end());
1190
1191 chi2_best=chi2;
1192 ndof_best=ndof;
1193 }
1194 if (iter==0) return DTrackFitter::kFitFailed;
1195
1196 //Final z position (closest to beam line)
1197 start_z=best_trajectory[best_trajectory.size()-1].z;
1198
1199 //Run the smoother
1200 if (Smooth(best_updates,best_cdc_updates) == NOERROR) IsSmoothed=true;
1201
1202 // output list of hits used in the fit
1203 cdchits_used_in_fit.clear();
1204 for (unsigned int m=0;m<used_cdc_hits_best_fit.size();m++){
1205 if (used_cdc_hits_best_fit[m]){
1206 cdchits_used_in_fit.push_back(cdchits[m]);
1207 }
1208 }
1209 fdchits_used_in_fit.clear();
1210 for (unsigned int m=0;m<used_fdc_hits_best_fit.size();m++){
1211 if (used_fdc_hits_best_fit[m]){
1212 fdchits_used_in_fit.push_back(fdchits[m]);
1213 }
1214 }
1215
1216
1217 return DTrackFitter::kFitSuccess;
1218}
1219
1220
1221// Reference trajectory for the track
1222jerror_t
1223DTrackFitterStraightTrack::SetReferenceTrajectory(double t0,double z,
1224 DMatrix4x1 &S){
1225 const double EPS=1e-3;
1226
1227 // Jacobian matrix
1228 DMatrix4x4 J(1.,0.,1.,0., 0.,1.,0.,1., 0.,0.,1.,0., 0.,0.,0.,1.);
1229
1230 double dz=1.1;
1231 double t=t0;
1232 trajectory.push_front(trajectory_t(z,t,S,J,DMatrix4x1(),DMatrix4x4()));
1233
1234 double zhit=z;
1235 double old_zhit=z;
1236 for (unsigned int i=0;i<fdchits.size();i++){
1237 zhit=fdchits[i]->wire->origin.z();
1238 dz=1.1;
1239
1240 if (fabs(zhit-old_zhit)<EPS && i>0){
1241 trajectory[0].numhits++;
1242 continue;
1243 }
1244 // propagate until we would step beyond the FDC hit plane
1245 bool done=false;
1246 while (!done){
1247 double new_z=z+dz;
1248
1249 if (new_z>zhit){
1250 dz=zhit-z;
1251 new_z=zhit;
1252 done=true;
1253 }
1254 J(state_x,state_tx)=-dz;
1255 J(state_y,state_ty)=-dz;
1256 // Flight time: assume particle is moving at the speed of light
1257 t+=dz*sqrt(1+S(state_tx)*S(state_tx)+S(state_ty)*S(state_ty))/29.98;
1258 //propagate the state to the next z position
1259 S(state_x)+=S(state_tx)*dz;
1260 S(state_y)+=S(state_ty)*dz;
1261
1262 trajectory.push_front(trajectory_t(new_z,t,S,J,DMatrix4x1(),
1263 DMatrix4x4()));
1264 if (done){
1265 trajectory[0].id=i+1;
1266 trajectory[0].numhits=1;
1267 }
1268
1269 z=new_z;
1270 }
1271 old_zhit=zhit;
1272 }
1273 // One last step
1274 dz=1.1;
1275 J(state_x,state_tx)=-dz;
1276 J(state_y,state_ty)=-dz;
1277
1278 // Flight time: assume particle is moving at the speed of light
1279 t+=dz*sqrt(1+S(state_tx)*S(state_tx)+S(state_ty)*S(state_ty))/29.98;
1280
1281 //propagate the state to the next z position
1282 S(state_x)+=S(state_tx)*dz;
1283 S(state_y)+=S(state_ty)*dz;
1284 trajectory.push_front(trajectory_t(z+dz,t,S,J,DMatrix4x1(),DMatrix4x4()));
1285
1286 if (false)
1287 {
1288 printf("Trajectory:\n");
1289 for (unsigned int i=0;i<trajectory.size();i++){
1290 printf(" x %f y %f z %f first hit %d num in layer %d\n",trajectory[i].S(state_x),
1291 trajectory[i].S(state_y),trajectory[i].z,trajectory[i].id,
1292 trajectory[i].numhits);
1293 }
1294 }
1295
1296 return NOERROR;
1297}
1298
1299// Perform Kalman Filter for the current trajectory
1300jerror_t DTrackFitterStraightTrack::KalmanFilter(DMatrix4x1 &S,DMatrix4x4 &C,
1301 vector<int>&used_fdc_hits,
1302 vector<int>&used_cdc_hits,
1303 vector<fdc_update_t>&updates,
1304 vector<cdc_update_t>&cdc_updates,
1305 double &chi2,int &ndof){
1306 DMatrix2x4 H; // Track projection matrix
1307 DMatrix4x2 H_T; // Transpose of track projection matrix
1308 DMatrix4x2 K; // Kalman gain matrix
1309 double VarMs=0.001; // kludge for material
1310 DMatrix2x2 V(0.0833,0.,0.,0.000256+VarMs); // Measurement variance
1311 DMatrix2x2 Vtemp,InvV;
1312 DMatrix2x1 Mdiff;
1313 DMatrix4x4 I; // identity matrix
1314 DMatrix4x4 J; // Jacobian matrix
1315 DMatrix4x1 S0; // State vector from reference trajectory
1316
1317 DMatrix1x4 H_CDC; // Track projection matrix
1318 DMatrix4x1 H_T_CDC; // Transpose of track projection matrix
1319 DMatrix4x1 K_CDC; // Kalman gain matrix
1320 double V_CDC;
1321
1322 const double d_EPS=1e-8;
1323
1324 // Zero out the vectors of used hit flags
1325 for (unsigned int i=0;i<used_fdc_hits.size();i++) used_fdc_hits[i]=0;
1326 for (unsigned int i=0;i<used_cdc_hits.size();i++) used_cdc_hits[i]=0;
1327
1328 //Initialize chi2 and ndof
1329 chi2=0.;
1330 ndof=0;
1331
1332 // Save the starting values for C and S in the deque
1333 trajectory[0].Skk=S;
1334 trajectory[0].Ckk=C;
1335
1336 // Loop over all steps in the trajectory
1337 S0=trajectory[0].S;
1338 J=trajectory[0].J;
1339
1340 // CDC index and wire position variables
1341 bool more_hits = cdchits.size() == 0 ? false: true;
1342 bool firstCDCStep=true;
1343 unsigned int cdc_index=0;
1344 const DCDCWire *wire;
1345 DVector3 origin,wdir,wirepos;
1346 double doca2=0.0, old_doca2=0.0;
1347 if(more_hits){
1348 cdc_index=cdchits.size()-1;
1349 wire=cdchits[cdc_index]->wire;
1350 origin=wire->origin;
1351 double vz=wire->udir.z();
1352 if (VERBOSE) jout << " Additional CDC Hits in FDC track Starting in Ring " << wire->ring << endl;
1353 wdir=(1./vz)*wire->udir;
1354 }
1355
1356 for (unsigned int k=1;k<trajectory.size();k++){
1357 if (C(0,0)<=0. || C(1,1)<=0. || C(2,2)<=0. || C(3,3)<=0.)
1358 return UNRECOVERABLE_ERROR;
1359
1360 // Propagate the state and covariance matrix forward in z
1361 S=trajectory[k].S+J*(S-S0);
1362 C=J*C*J.Transpose();
1363
1364 // Save the current state and covariance matrix in the deque
1365 trajectory[k].Skk=S;
1366 trajectory[k].Ckk=C;
1367
1368 // Save S and J for the next step
1369 S0=trajectory[k].S;
1370 J=trajectory[k].J;
1371
1372 // Correct S and C for the hit
1373 if (trajectory[k].id>0){
1374 unsigned int id=trajectory[k].id-1;
1375
1376 double cospsi=cos(fdchits[id]->wire->angle);
1377 double sinpsi=sin(fdchits[id]->wire->angle);
1378
1379 // Small angle alignment correction
1380 double x = S(state_x) + fdchits[id]->wire->angles.Z()*S(state_y);
1381 double y = S(state_y) - fdchits[id]->wire->angles.Z()*S(state_x);
1382 //tz = 1. + my_fdchits[id]->phiY*tx - my_fdchits[id]->phiX*ty;
1383 double tx = (S(state_tx) + fdchits[id]->wire->angles.Z()*S(state_ty) - fdchits[id]->wire->angles.Y());
1384 double ty = (S(state_ty) - fdchits[id]->wire->angles.Z()*S(state_tx) + fdchits[id]->wire->angles.X());
1385
1386 if (std::isnan(x) || std::isnan(y)) return UNRECOVERABLE_ERROR;
1387
1388 // x,y and tx,ty in local coordinate system
1389 // To transform from (x,y) to (u,v), need to do a rotation:
1390 // u = x*cos(psi)-y*sin(psi)
1391 // v = y*cos(psi)+x*sin(psi)
1392 // (without alignment offsets)
1393 double vpred_wire_plane=y*cospsi+x*sinpsi;
1394 double upred_wire_plane=x*cospsi-y*sinpsi;
1395 double tu=tx*cospsi-ty*sinpsi;
1396 double tv=tx*sinpsi+ty*cospsi;
1397
1398 // Variables for angle of incidence with respect to the z-direction in
1399 // the u-z plane
1400 double alpha=atan(tu);
1401 double cosalpha=cos(alpha);
1402 double cos2_alpha=cosalpha*cosalpha;
1403 double sinalpha=sin(alpha);
1404 double sin2_alpha=sinalpha*sinalpha;
1405 double cos2_alpha_minus_sin2_alpha=cos2_alpha-sin2_alpha;
1406
1407 // Difference between measurement and projection
1408 for (int m=trajectory[k].numhits-1;m>=0;m--){
1409 unsigned int my_id=id+m;
1410 double uwire=fdchits[my_id]->w;
1411 // (signed) distance of closest approach to wire
1412 double du=upred_wire_plane-uwire;
1413 double doca=du*cosalpha;
1414
1415 // Predicted avalanche position along the wire
1416 double vpred=vpred_wire_plane;
1417
1418 // Measured position of hit along wire
1419 double v=fdchits[my_id]->s;
1420
1421 // Difference between measurements and predictions
1422 double drift=0.; // assume hit at wire position
1423 if (fit_type==kTimeBased){
1424 double drift_time=fdchits[my_id]->time-trajectory[k].t;
1425 drift=(du>0.0?1.:-1.)*fdc_drift_distance(drift_time);
1426 V(0,0)=fdc_drift_variance(drift_time)+VarMs;
1427 }
1428 Mdiff(0)=drift-doca;
1429 Mdiff(1)=v-vpred;
1430
1431 // Matrix for transforming from state-vector space to measurement space
1432 H_T(state_x,0)=cospsi*cosalpha;
1433 H_T(state_y,0)=-sinpsi*cosalpha;
1434 double temp=-du*sinalpha*cos2_alpha;
1435 H_T(state_tx,0)=cospsi*temp;
1436 H_T(state_ty,0)=-sinpsi*temp;
1437 double temp2=cosalpha*sinalpha*tv;
1438 H_T(state_x,1)=sinpsi-temp2*cospsi;
1439 H_T(state_y,1)=cospsi+temp2*sinpsi;
1440 double temp4=sinalpha*doca;
1441 double temp5=tv*cos2_alpha*du*cos2_alpha_minus_sin2_alpha;
1442 H_T(state_tx,1)=-sinpsi*temp4-cospsi*temp5;
1443 H_T(state_ty,1)=-cospsi*temp4+sinpsi*temp5;
1444
1445 // Matrix transpose H_T -> H
1446 H(0,state_x)=H_T(state_x,0);
1447 H(0,state_y)=H_T(state_y,0);
1448 H(0,state_tx)=H_T(state_tx,0);
1449 H(0,state_ty)=H_T(state_ty,0);
1450 H(1,state_x)=H_T(state_x,1);
1451 H(1,state_y)=H_T(state_y,1);
1452 H(1,state_tx)=H_T(state_tx,1);
1453 H(1,state_ty)=H_T(state_ty,1);
1454
1455 // Variance for this hit
1456 InvV=(V+H*C*H_T).Invert();
1457
1458 // Compute Kalman gain matrix
1459 K=(C*H_T)*InvV;
1460
1461 if (fdchits[my_id]->wire->layer!=PLANE_TO_SKIP){
1462 /*
1463 if(DEBUG_HISTS){
1464 hFDCOccTrkFit->Fill(fdchits[my_id]->wire->layer);
1465 }
1466 */
1467 // Update the state vector
1468 S+=K*Mdiff;
1469 if(VERBOSE) S.Print();
1470 // Update state vector covariance matrix
1471 C=C-K*(H*C);
1472
1473 // Update the filtered measurement covariane matrix and put results in
1474 // update vector
1475 DMatrix2x2 RC=V-H*C*H_T;
1476 DMatrix2x1 res=Mdiff-H*K*Mdiff;
1477
1478 chi2+=RC.Chi2(res);
1479 ndof+=2;
1480
1481 // fill pull vector entries
1482 updates[my_id].V=RC;
1483 }
1484 else{
1485 updates[my_id].V=V;
1486 }
1487
1488 used_fdc_hits[my_id]=1;
1489
1490 // fill pull vector
1491 updates[my_id].d=doca;
1492 updates[my_id].S=S;
1493 updates[my_id].C=C;
1494 updates[my_id].tdrift=fdchits[my_id]->time-trajectory[k].t;
1495 updates[my_id].s=29.98*trajectory[k].t; // assume beta=1
1496 }
1497 }
1498
1499 if (more_hits && trajectory[k].z < downstreamEndplate){
1500 // Position along wire
1501 double z0=origin.Z();
1502 wirepos=origin+(trajectory[k].z-z0)*wdir;
1503
1504 // New doca^2
1505 double dx=S(state_x)-wirepos.X();
1506 double dy=S(state_y)-wirepos.Y();
1507 doca2=dx*dx+dy*dy;
1508 if (VERBOSE > 10) jout<< "At Position " << S(state_x) << " " << S(state_y) << " " << trajectory[k].z << " doca2 " << doca2 << endl;
1509
1510 if (doca2>old_doca2 && more_hits && !firstCDCStep){
1511
1512 // zero-position and direction of line describing particle trajectory
1513 double tx=S(state_tx),ty=S(state_ty);
1514 DVector3 pos0(S(state_x),S(state_y),trajectory[k].z);
1515 DVector3 tdir(tx,ty,1.);
1516
1517 // Find the true doca to the wire
1518 DVector3 diff=pos0-origin;
1519 double dx0=diff.x(),dy0=diff.y();
1520 double wdir_dot_diff=diff.Dot(wdir);
1521 double tdir_dot_diff=diff.Dot(tdir);
1522 double tdir_dot_wdir=tdir.Dot(wdir);
1523 double tdir2=tdir.Mag2();
1524 double wdir2=wdir.Mag2();
1525 double D=tdir2*wdir2-tdir_dot_wdir*tdir_dot_wdir;
1526 double N=tdir_dot_wdir*wdir_dot_diff-wdir2*tdir_dot_diff;
1527 double N1=tdir2*wdir_dot_diff-tdir_dot_wdir*tdir_dot_diff;
1528 double scale=1./D;
1529 double s=scale*N;
1530 double t=scale*N1;
1531 diff+=s*tdir-t*wdir;
1532 double d=diff.Mag()+d_EPS; // prevent division by zero
1533
1534 // The next measurement
1535 double dmeas=0.39,delta=0.;
1536 double tdrift=cdchits[cdc_index]->tdrift-trajectory[k].t;
1537 if (fit_type==kTimeBased){
1538 double phi_d=diff.Phi();
1539 double dphi=phi_d-origin.Phi();
1540 while (dphi>M_PI3.14159265358979323846) dphi-=2*M_PI3.14159265358979323846;
1541 while (dphi<-M_PI3.14159265358979323846) dphi+=2*M_PI3.14159265358979323846;
1542
1543 int ring_index=cdchits[cdc_index]->wire->ring-1;
1544 int straw_index=cdchits[cdc_index]->wire->straw-1;
1545 double dz=t*wdir.z();
1546 double delta=max_sag[ring_index][straw_index]*(1.-dz*dz/5625.)
1547 *cos(phi_d+sag_phi_offset[ring_index][straw_index]);
1548 CDCDriftParameters(dphi,delta,tdrift,dmeas,V_CDC);
1549 }
1550
1551 // residual
1552 double res=dmeas-d;
1553 if (VERBOSE>5) jout << " Residual " << res << endl;
1554 // Track projection
1555 double one_over_d=1./d;
1556 double diffx=diff.x(),diffy=diff.y(),diffz=diff.z();
1557 double wx=wdir.x(),wy=wdir.y();
1558
1559 double dN1dtx=2.*tx*wdir_dot_diff-wx*tdir_dot_diff-tdir_dot_wdir*dx0;
1560 double dDdtx=2.*tx*wdir2-2.*tdir_dot_wdir*wx;
1561 double dtdtx=scale*(dN1dtx-t*dDdtx);
1562
1563 double dN1dty=2.*ty*wdir_dot_diff-wy*tdir_dot_diff-tdir_dot_wdir*dy0;
1564 double dDdty=2.*ty*wdir2-2.*tdir_dot_wdir*wy;
1565 double dtdty=scale*(dN1dty-t*dDdty);
1566
1567 double dNdtx=wx*wdir_dot_diff-wdir2*dx0;
1568 double dsdtx=scale*(dNdtx-s*dDdtx);
1569
1570 double dNdty=wy*wdir_dot_diff-wdir2*dy0;
1571 double dsdty=scale*(dNdty-s*dDdty);
1572
1573 H_CDC(state_tx)=H_T_CDC(state_tx)
1574 =one_over_d*(diffx*(s+tx*dsdtx-wx*dtdtx)+diffy*(ty*dsdtx-wy*dtdtx)
1575 +diffz*(dsdtx-dtdtx));
1576 H_CDC(state_ty)=H_T_CDC(state_ty)
1577 =one_over_d*(diffx*(tx*dsdty-wx*dtdty)+diffy*(s+ty*dsdty-wy*dtdty)
1578 +diffz*(dsdty-dtdty));
1579
1580 double dsdx=scale*(tdir_dot_wdir*wx-wdir2*tx);
1581 double dtdx=scale*(tdir2*wx-tdir_dot_wdir*tx);
1582 double dsdy=scale*(tdir_dot_wdir*wy-wdir2*ty);
1583 double dtdy=scale*(tdir2*wy-tdir_dot_wdir*ty);
1584
1585 H_CDC(state_x)=H_T_CDC(state_x)
1586 =one_over_d*(diffx*(1.+dsdx*tx-dtdx*wx)+diffy*(dsdx*ty-dtdx*wy)
1587 +diffz*(dsdx-dtdx));
1588 H_CDC(state_y)=H_T_CDC(state_y)
1589 =one_over_d*(diffx*(dsdy*tx-dtdy*wx)+diffy*(1.+dsdy*ty-dtdy*wy)
1590 +diffz*(dsdy-dtdy));
1591
1592 double InvV=1./(V_CDC+H_CDC*C*H_T_CDC);
1593
1594 // Check how far this hit is from the projection
1595 double chi2check=res*res*InvV;
1596 if (chi2check < CHI2CUT || DO_PRUNING == 0){
1597 if (VERBOSE) jout << "CDC Hit Added to FDC track " << endl;
1598 if (cdchits[cdc_index]->wire->ring!=RING_TO_SKIP){
1599
1600 // Compute Kalman gain matrix
1601 K_CDC=InvV*(C*H_T_CDC);
1602 // Update state vector covariance matrix
1603 DMatrix4x4 Ctest=C-K_CDC*(H_CDC*C);
1604
1605 //C.Print();
1606 //K.Print();
1607 //Ctest.Print();
1608
1609 // Check that Ctest is positive definite
1610 if (!Ctest.IsPosDef()) return VALUE_OUT_OF_RANGE;
1611 C=Ctest;
1612 if(VERBOSE>10) C.Print();
1613 // Update the state vector
1614 //S=S+res*K;
1615 S+=res*K_CDC;
1616 if(VERBOSE) {jout << "traj[z]=" << trajectory[k].z<< endl; S.Print();}
1617
1618 // Compute new residual
1619 //d=finder->FindDoca(trajectory[k].z,S,wdir,origin);
1620 res=res-H_CDC*K_CDC*res;
1621
1622 // Update chi2
1623 double fit_V=V_CDC-H_CDC*C*H_T_CDC;
1624 chi2+=res*res/fit_V;
1625 ndof++;
1626
1627 // fill pull vector entry
1628 cdc_updates[cdc_index].V=fit_V;
1629 }
1630 else {
1631 cdc_updates[cdc_index].V=V_CDC;
1632 }
1633
1634 // fill updates
1635 cdc_updates[cdc_index].resi=res;
1636 cdc_updates[cdc_index].d=d;
1637 cdc_updates[cdc_index].delta=delta;
1638 cdc_updates[cdc_index].S=S;
1639 cdc_updates[cdc_index].C=C;
1640 cdc_updates[cdc_index].tdrift=tdrift;
1641 cdc_updates[cdc_index].ddrift=dmeas;
1642 cdc_updates[cdc_index].s=29.98*trajectory[k].t; // assume beta=1
1643 trajectory[k].id=cdc_index+1000;
1644
1645 used_cdc_hits[cdc_index]=1;
1646 }
1647 // move to next cdc hit
1648 if (cdc_index>0){
1649 cdc_index--;
1650
1651 //New wire position
1652 wire=cdchits[cdc_index]->wire;
1653 if (VERBOSE>5) jout << " Next Wire ring " << wire->ring << endl;
1654 origin=wire->origin;
1655 double vz=wire->udir.z();
1656 wdir=(1./vz)*wire->udir;
1657 wirepos=origin+((trajectory[k].z-z0))*wdir;
1658
1659 // New doca^2
1660 dx=S(state_x)-wirepos.x();
1661 dy=S(state_y)-wirepos.y();
1662 doca2=dx*dx+dy*dy;
1663
1664 }
1665 else more_hits=false;
1666 }
1667 firstCDCStep=false;
1668 old_doca2=doca2;
1669 }
1670 }
1671
1672 ndof-=4;
1673
1674 return NOERROR;
1675}
1676
1677
1678// Smoothing algorithm for the forward trajectory. Updates the state vector
1679// at each step (going in the reverse direction to the filter) based on the
1680// information from all the steps and outputs the state vector at the
1681// outermost step.
1682
1683jerror_t
1684DTrackFitterStraightTrack::Smooth(vector<fdc_update_t>&fdc_updates,
1685 vector<cdc_update_t>&cdc_updates){
1686 unsigned int max=best_trajectory.size()-1;
1687 DMatrix4x1 S=(best_trajectory[max].Skk);
1688 DMatrix4x4 C=(best_trajectory[max].Ckk);
1689 DMatrix4x4 JT=best_trajectory[max].J.Transpose();
1690 DMatrix4x1 Ss=S;
1691 DMatrix4x4 Cs=C;
1692 DMatrix4x4 A,dC;
1693
1694 const double d_EPS=1e-8;
1695
1696 for (unsigned int m=max-1;m>0;m--){
1697 if (best_trajectory[m].id>0 && best_trajectory[m].id<1000){ // FDC Hit
1698 unsigned int id=best_trajectory[m].id-1;
1699 A=fdc_updates[id].C*JT*C.Invert();
1700 Ss=fdc_updates[id].S+A*(Ss-S);
1701
1702 dC=A*(Cs-C)*A.Transpose();
1703 Cs=fdc_updates[id].C+dC;
1704
1705 double cosa=cos(fdchits[id]->wire->angle);
1706 double cos2a=cos(2*fdchits[id]->wire->angle);
1707 double sina=sin(fdchits[id]->wire->angle);
1708 double u=fdchits[id]->w;
1709 double v=fdchits[id]->s;
1710
1711 // Small angle alignment correction
1712 double x = Ss(state_x) + fdchits[id]->wire->angles.Z() * Ss(state_y);
1713 double y = Ss(state_y) - fdchits[id]->wire->angles.Z() * Ss(state_x);
1714 // tz = 1.0 + my_fdchits[id]->phiY * tx - my_fdchits[id]->phiX * ty;
1715 double tx = Ss(state_tx) + fdchits[id]->wire->angles.Z() * Ss(state_ty) - fdchits[id]->wire->angles.Y();
1716 double ty = Ss(state_ty) - fdchits[id]->wire->angles.Z() * Ss(state_tx) + fdchits[id]->wire->angles.X();
1717
1718 // Projected position along the wire
1719 double vpred=x*sina+y*cosa;
1720
1721 // Projected position in the plane of the wires transverse to the wires
1722 double upred=x*cosa-y*sina;
1723
1724 // Direction tangent in the u-z plane
1725 double tu=tx*cosa-ty*sina;
1726 double alpha=atan(tu);
1727 double cosalpha=cos(alpha);
1728 //double cosalpha2=cosalpha*cosalpha;
1729 double sinalpha=sin(alpha);
1730
1731 // (signed) distance of closest approach to wire
1732 double du=upred-u;
1733 double doca=du*cosalpha;
1734 // Difference between measurement and projection for the cathodes
1735 double tv=tx*sina+ty*cosa;
1736 double resi_c=v-vpred;
1737
1738 // Difference between measurement and projection perpendicular to the wire
1739 double drift = 0.0; // assume hit at wire position
1740 int left_right = -999;
1741 double drift_time = fdc_updates[id].tdrift;
1742 if (fit_type == kTimeBased) {
1743 drift = (du > 0.0 ? 1.0 : -1.0) * fdc_drift_distance(drift_time);
1744 left_right = (du > 0.0 ? +1 : -1);
1745 }
1746 double resi_a = drift - doca;
1747
1748 // Variance from filter step
1749 DMatrix2x2 V=fdc_updates[id].V;
1750 // Compute projection matrix and find the variance for the residual
1751 DMatrix4x2 H_T;
1752 double temp2=-tv*sinalpha;
1753 H_T(state_x,1)=sina+cosa*cosalpha*temp2;
1754 H_T(state_y,1)=cosa-sina*cosalpha*temp2;
1755
1756 double cos2_minus_sin2=cosalpha*cosalpha-sinalpha*sinalpha;
1757 double doca_cosalpha=doca*cosalpha;
1758 H_T(state_tx,1)=-doca_cosalpha*(tu*sina+tv*cosa*cos2_minus_sin2);
1759 H_T(state_ty,1)=-doca_cosalpha*(tu*cosa-tv*sina*cos2_minus_sin2);
1760
1761 H_T(state_x,0)=cosa*cosalpha;
1762 H_T(state_y,0)=-sina*cosalpha;
1763 double one_plus_tu2=1.+tu*tu;
1764 double factor=du*tu/sqrt(one_plus_tu2)/one_plus_tu2;
1765 H_T(state_ty,0)=sina*factor;
1766 H_T(state_tx,0)=-cosa*factor;
1767
1768 // Matrix transpose H_T -> H
1769 DMatrix2x4 H;
1770 H(0,state_x)=H_T(state_x,0);
1771 H(0,state_y)=H_T(state_y,0);
1772 H(0,state_tx)=H_T(state_tx,0);
1773 H(0,state_ty)=H_T(state_ty,0);
1774 H(1,state_x)=H_T(state_x,1);
1775 H(1,state_y)=H_T(state_y,1);
1776 H(1,state_tx)=H_T(state_tx,1);
1777 H(1,state_ty)=H_T(state_ty,1);
1778
1779 if (fdchits[id]->wire->layer == PLANE_TO_SKIP) {
1780 // V += Cs.SandwichMultiply(H_T);
1781 V = V + H * Cs * H_T;
1782 } else {
1783 // V -= dC.SandwichMultiply(H_T);
1784
1785 // R. Fruehwirth, Nucl. Instrum. Methods Phys. Res. A 262, 444 (1987).
1786 // Eq. (9)
1787 // The following V (lhs) corresponds to R^n_k in the paper.
1788 // dC corresponds to 'A_k * (C^n_{k+1} - C^k_{k+1}) * A_k^T' in the paper.
1789 V = V - H * dC * H_T;
1790 }
1791
1792 /*
1793 if(DEBUG_HISTS){
1794 hFDCOccTrkSmooth->Fill(fdchits[id]->wire->layer);
1795 }
1796 */
1797 // Implement derivatives wrt track parameters needed for millepede alignment
1798 // Add the pull
1799 double scale=1./sqrt(1.+tx*tx+ty*ty);
1800 double cosThetaRel=fdchits[id]->wire->udir.Dot(DVector3(scale*tx,scale*ty,scale));
1801 DTrackFitter::pull_t thisPull(resi_a,sqrt(V(0,0)),
1802 best_trajectory[m].t*SPEED_OF_LIGHT29.9792458,
1803 fdc_updates[id].tdrift,
1804 fdc_updates[id].d,
1805 NULL__null,fdchits[id],
1806 0.0, //docaphi
1807 best_trajectory[m].z,cosThetaRel,
1808 0.0, //tcorr
1809 resi_c, sqrt(V(1,1))
1810 );
1811 thisPull.left_right = left_right;
1812
1813 if (fdchits[id]->wire->layer!=PLANE_TO_SKIP){
1814 vector<double> derivatives;
1815 derivatives.resize(FDCTrackD::size);
1816
1817 //dDOCAW/dDeltaX
1818 derivatives[FDCTrackD::dDOCAW_dDeltaX] = -(1/sqrt(1 + pow(tx*cosa - ty*sina,2)));
1819
1820 //dDOCAW/dDeltaZ
1821 derivatives[FDCTrackD::dDOCAW_dDeltaZ] = (tx*cosa - ty*sina)/sqrt(1 + pow(tx*cosa - ty*sina,2));
1822
1823 //dDOCAW/ddeltaPhiX
1824 derivatives[FDCTrackD::dDOCAW_dDeltaPhiX] = (sina*(-(tx*cosa) + ty*sina)*(u - x*cosa + y*sina))/pow(1 + pow(tx*cosa - ty*sina,2),1.5);
1825
1826 //dDOCAW/ddeltaphiY
1827 derivatives[FDCTrackD::dDOCAW_dDeltaPhiY] = (cosa*(tx*cosa - ty*sina)*(-u + x*cosa - y*sina))/pow(1 + pow(tx*cosa - ty*sina,2),1.5);
1828
1829 //dDOCAW/ddeltaphiZ
1830 derivatives[FDCTrackD::dDOCAW_dDeltaPhiZ] = (tx*ty*u*cos2a + (x + pow(ty,2)*x - tx*ty*y)*sina +
1831 cosa*(-(tx*ty*x) + y + pow(tx,2)*y + (pow(tx,2) - pow(ty,2))*u*sina))/
1832 pow(1 + pow(tx*cosa - ty*sina,2),1.5);
1833
1834 // dDOCAW/dx
1835 derivatives[FDCTrackD::dDOCAW_dx] = cosa/sqrt(1 + pow(tx*cosa - ty*sina,2));
1836
1837 // dDOCAW/dy
1838 derivatives[FDCTrackD::dDOCAW_dy] = -(sina/sqrt(1 + pow(tx*cosa - ty*sina,2)));
1839
1840 // dDOCAW/dtx
1841 derivatives[FDCTrackD::dDOCAW_dtx] = -((cosa*(tx*cosa - ty*sina)*(-u + x*cosa - y*sina))/pow(1 + pow(tx*cosa - ty*sina,2),1.5));
1842
1843 // dDOCAW/dty
1844 derivatives[FDCTrackD::dDOCAW_dty] = (sina*(-(tx*cosa) + ty*sina)*(u - x*cosa + y*sina))/pow(1 + pow(tx*cosa - ty*sina,2),1.5);
1845
1846 // dDOCAW/dt0
1847 double t0shift = 4.0; // ns
1848 double drift_shift = 0.0;
1849 if (drift_time < 0.0) {
1850 drift_shift = drift;
1851 } else {
1852 drift_shift =
1853 (du > 0.0 ? 1.0 : -1.0) *
1854 fdc_drift_distance(drift_time + t0shift);
1855 }
1856 derivatives[FDCTrackD::dW_dt0] = (drift_shift - drift) / t0shift;
1857
1858 // And the cathodes
1859 //dDOCAW/ddeltax
1860 derivatives[FDCTrackD::dDOCAC_dDeltaX] = 0.;
1861
1862 //dDOCAW/ddeltax
1863 derivatives[FDCTrackD::dDOCAC_dDeltaZ] = ty*cosa + tx*sina;
1864
1865 //dDOCAW/ddeltaPhiX
1866 derivatives[FDCTrackD::dDOCAC_dDeltaPhiX] = 0.;
1867
1868 //dDOCAW/ddeltaPhiX
1869 derivatives[FDCTrackD::dDOCAC_dDeltaPhiY] = 0.;
1870
1871 //dDOCAW/ddeltaPhiX
1872 derivatives[FDCTrackD::dDOCAC_dDeltaPhiZ] = -(x*cosa) + y*sina;
1873
1874 // dDOCAW/dx
1875 derivatives[FDCTrackD::dDOCAC_dx] = sina;
1876
1877 // dDOCAW/dy
1878 derivatives[FDCTrackD::dDOCAW_dy] = cosa;
1879
1880 // dDOCAW/dtx
1881 derivatives[FDCTrackD::dDOCAW_dtx] = 0.;
1882
1883 // dDOCAW/dty
1884 derivatives[FDCTrackD::dDOCAW_dty] = 0.;
1885
1886 thisPull.AddTrackDerivatives(derivatives);
1887 }
1888 pulls.push_back(thisPull);
1889 }
1890 else if (best_trajectory[m].id>=1000){ // CDC Hit
1891 unsigned int id=best_trajectory[m].id-1000;
1892 A=cdc_updates[id].C*JT*C.Invert();
1893 Ss=cdc_updates[id].S+A*(Ss-S);
1894
1895 dC=A*(Cs-C)*A.Transpose();
1896 Cs=cdc_updates[id].C+dC;
1897 if (VERBOSE > 10) {
1898 jout << " In Smoothing Step Using ID " << id << "/" << cdc_updates.size() << " for ring " << cdchits[id]->wire->ring << endl;
1899 jout << " A cdc_updates[id].C Ss Cs " << endl;
1900 A.Print(); cdc_updates[id].C.Print(); Ss.Print(); Cs.Print();
1901 }
1902 if(!Cs.IsPosDef()) {
1903 if (VERBOSE) jout << "Cs is not PosDef!" << endl;
1904 return VALUE_OUT_OF_RANGE;
1905 }
1906
1907 const DCDCWire *wire=cdchits[id]->wire;
1908 DVector3 origin=wire->origin;
1909 double z0=origin.z();
1910 double vz=wire->udir.z();
1911 DVector3 wdir=(1./vz)*wire->udir;
1912 DVector3 wirepos=origin+(best_trajectory[m].z-z0)*wdir;
1913 // Position and direction from state vector
1914 double x=Ss(state_x);
1915 double y=Ss(state_y);
1916 double tx=Ss(state_tx);
1917 double ty=Ss(state_ty);
1918
1919 DVector3 pos0(x,y,best_trajectory[m].z);
1920 DVector3 tdir(tx,ty,1.);
1921
1922 // Find the true doca to the wire
1923 DVector3 diff=pos0-origin;
1924 double dx0=diff.x(),dy0=diff.y();
1925 double wdir_dot_diff=diff.Dot(wdir);
1926 double tdir_dot_diff=diff.Dot(tdir);
1927 double tdir_dot_wdir=tdir.Dot(wdir);
1928 double tdir2=tdir.Mag2();
1929 double wdir2=wdir.Mag2();
1930 double D=tdir2*wdir2-tdir_dot_wdir*tdir_dot_wdir;
1931 double N=tdir_dot_wdir*wdir_dot_diff-wdir2*tdir_dot_diff;
1932 double N1=tdir2*wdir_dot_diff-tdir_dot_wdir*tdir_dot_diff;
1933 double scale=1./D;
1934 double s=scale*N;
1935 double t=scale*N1;
1936 diff+=s*tdir-t*wdir;
1937 double d=diff.Mag()+d_EPS; // prevent division by zero
1938 double ddrift = cdc_updates[id].ddrift;
1939
1940 double resi = ddrift - d;
1941
1942
1943 // Track projection
1944 DMatrix1x4 H; DMatrix4x1 H_T;
1945 {
1946 double one_over_d=1./d;
1947 double diffx=diff.x(),diffy=diff.y(),diffz=diff.z();
1948 double wx=wdir.x(),wy=wdir.y();
1949
1950 double dN1dtx=2.*tx*wdir_dot_diff-wx*tdir_dot_diff-tdir_dot_wdir*dx0;
1951 double dDdtx=2.*tx*wdir2-2.*tdir_dot_wdir*wx;
1952 double dtdtx=scale*(dN1dtx-t*dDdtx);
1953
1954 double dN1dty=2.*ty*wdir_dot_diff-wy*tdir_dot_diff-tdir_dot_wdir*dy0;
1955 double dDdty=2.*ty*wdir2-2.*tdir_dot_wdir*wy;
1956 double dtdty=scale*(dN1dty-t*dDdty);
1957
1958 double dNdtx=wx*wdir_dot_diff-wdir2*dx0;
1959 double dsdtx=scale*(dNdtx-s*dDdtx);
1960
1961 double dNdty=wy*wdir_dot_diff-wdir2*dy0;
1962 double dsdty=scale*(dNdty-s*dDdty);
1963
1964 H(state_tx)=H_T(state_tx)
1965 =one_over_d*(diffx*(s+tx*dsdtx-wx*dtdtx)+diffy*(ty*dsdtx-wy*dtdtx)
1966 +diffz*(dsdtx-dtdtx));
1967 H(state_ty)=H_T(state_ty)
1968 =one_over_d*(diffx*(tx*dsdty-wx*dtdty)+diffy*(s+ty*dsdty-wy*dtdty)
1969 +diffz*(dsdty-dtdty));
1970
1971 double dsdx=scale*(tdir_dot_wdir*wx-wdir2*tx);
1972 double dtdx=scale*(tdir2*wx-tdir_dot_wdir*tx);
1973 double dsdy=scale*(tdir_dot_wdir*wy-wdir2*ty);
1974 double dtdy=scale*(tdir2*wy-tdir_dot_wdir*ty);
1975
1976 H(state_x)=H_T(state_x)
1977 =one_over_d*(diffx*(1.+dsdx*tx-dtdx*wx)+diffy*(dsdx*ty-dtdx*wy)
1978 +diffz*(dsdx-dtdx));
1979 H(state_y)=H_T(state_y)
1980 =one_over_d*(diffx*(dsdy*tx-dtdy*wx)+diffy*(1.+dsdy*ty-dtdy*wy)
1981 +diffz*(dsdy-dtdy));
1982 }
1983 double V=cdc_updates[id].V;
1984
1985 if (VERBOSE > 10) jout << " d " << d << " H*S " << H*S << endl;
1986 if (cdchits[id]->wire->ring==RING_TO_SKIP){
1987 V=V+H*Cs*H_T;
1988 }
1989 else{
1990 V=V-H*Cs*H_T;
1991 }
1992 if (V<0) return VALUE_OUT_OF_RANGE;
1993
1994 // Add the pull
1995 double myscale=1./sqrt(1.+tx*tx+ty*ty);
1996 double cosThetaRel=wire->udir.Dot(DVector3(myscale*tx,myscale*ty,myscale));
1997 DTrackFitter::pull_t thisPull(resi,sqrt(V),
1998 best_trajectory[m].t*SPEED_OF_LIGHT29.9792458,
1999 cdc_updates[id].tdrift,
2000 d,cdchits[id], NULL__null,
2001 diff.Phi(), //docaphi
2002 best_trajectory[m].z,cosThetaRel,
2003 cdc_updates[id].tdrift);
2004
2005 // Derivatives for alignment
2006 double wtx=wire->udir.X(), wty=wire->udir.Y(), wtz=wire->udir.Z();
2007 double wx=wire->origin.X(), wy=wire->origin.Y(), wz=wire->origin.Z();
2008
2009 double z=best_trajectory[m].z;
2010 double tx2=tx*tx, ty2=ty*ty;
2011 double wtx2=wtx*wtx, wty2=wty*wty, wtz2=wtz*wtz;
2012 double denom=(1 + ty2)*wtx2 + (1 + tx2)*wty2 - 2*ty*wty*wtz + (tx2 + ty2)*wtz2 - 2*tx*wtx*(ty*wty + wtz)+d_EPS;
2013 double denom2=denom*denom;
2014 double c1=-(wtx - tx*wtz)*(wy - y);
2015 double c2=wty*(wx - tx*wz - x + tx*z);
2016 double c3=ty*(-(wtz*wx) + wtx*wz + wtz*x - wtx*z);
2017 double dscale=0.5*(1/d);
2018
2019 vector<double> derivatives(11);
2020
2021 derivatives[CDCTrackD::dDOCAdOriginX]=dscale*(2*(wty - ty*wtz)*(c1 + c2 + c3))/denom;
2022
2023 derivatives[CDCTrackD::dDOCAdOriginY]=dscale*(2*(-wtx + tx*wtz)*(c1 + c2 + c3))/denom;
2024
2025 derivatives[CDCTrackD::dDOCAdOriginZ]=dscale*(2*(ty*wtx - tx*wty)*(c1 + c2 + c3))/denom;
2026
2027 derivatives[CDCTrackD::dDOCAdDirX]=dscale*(2*(wty - ty*wtz)*(c1 + c2 + c3)*
2028 (tx*(ty*wty + wtz)*(wx - x) + (wty - ty*wtz)*(-wy + y + ty*(wz - z)) +
2029 wtx*(-((1 + ty2)*wx) + (1 + ty2)*x + tx*(ty*wy + wz - ty*y - z)) + tx2*(wty*(-wy + y) + wtz*(-wz + z))))/denom2;
2030
2031 derivatives[CDCTrackD::dDOCAdDirY]=dscale*(-2*(wtx - tx*wtz)*(c1 + c2 + c3)*
2032 (tx*(ty*wty + wtz)*(wx - x) + (wty - ty*wtz)*(-wy + y + ty*(wz - z)) +
2033 wtx*(-((1 + ty2)*wx) + (1 + ty2)*x + tx*(ty*wy + wz - ty*y - z)) + tx2*(wty*(-wy + y) + wtz*(-wz + z))))/denom2;
2034
2035 derivatives[CDCTrackD::dDOCAdDirZ]=dscale*(-2*(ty*wtx - tx*wty)*(c1 + c2 + c3)*
2036 (-(tx*(ty*wty + wtz)*(wx - x)) + tx2*(wty*(wy - y) + wtz*(wz - z)) + (wty - ty*wtz)*(wy - y + ty*(-wz + z)) +
2037 wtx*((1 + ty2)*wx - (1 + ty2)*x + tx*(-(ty*wy) - wz + ty*y + z))))/denom2;
2038
2039 derivatives[CDCTrackD::dDOCAdS0]=-derivatives[CDCTrackD::dDOCAdOriginX];
2040
2041 derivatives[CDCTrackD::dDOCAdS1]=-derivatives[CDCTrackD::dDOCAdOriginY];
2042
2043 derivatives[CDCTrackD::dDOCAdS2]=dscale*(2*(wty - ty*wtz)*(-c1 - c2 - c3)*
2044 (-(wtx*wtz*wx) - wty*wtz*wy + wtx2*wz + wty2*wz + wtx*wtz*x + wty*wtz*y - wtx2*z - wty2*z +
2045 tx*(wty2*(wx - x) + wtx*wty*(-wy + y) + wtz*(wtz*wx - wtx*wz - wtz*x + wtx*z)) +
2046 ty*(wtx*wty*(-wx + x) + wtx2*(wy - y) + wtz*(wtz*wy - wty*wz - wtz*y + wty*z))))/denom2;
2047
2048 derivatives[CDCTrackD::dDOCAdS3]=dscale*(2*(wtx - tx*wtz)*(c1 + c2 + c3)*
2049 (-(wtx*wtz*wx) - wty*wtz*wy + wtx2*wz + wty2*wz + wtx*wtz*x + wty*wtz*y - wtx2*z - wty2*z +
2050 tx*(wty2*(wx - x) + wtx*wty*(-wy + y) + wtz*(wtz*wx - wtx*wz - wtz*x + wtx*z)) +
2051 ty*(wtx*wty*(-wx + x) + wtx2*(wy - y) + wtz*(wtz*wy - wty*wz - wtz*y + wty*z))))/denom2;
2052
2053 thisPull.AddTrackDerivatives(derivatives);
2054
2055 pulls.push_back(thisPull);
2056 }
2057 else{
2058 A=best_trajectory[m].Ckk*JT*C.Invert();
2059 Ss=best_trajectory[m].Skk+A*(Ss-S);
2060 Cs=best_trajectory[m].Ckk+A*(Cs-C)*A.Transpose();
2061 }
2062
2063 S=best_trajectory[m].Skk;
2064 C=best_trajectory[m].Ckk;
2065 JT=best_trajectory[m].J.Transpose();
2066 }
2067
2068 return NOERROR;
2069}
2070
2071shared_ptr<TMatrixFSym>
2072DTrackFitterStraightTrack::Get7x7ErrorMatrix(TMatrixFSym C,DMatrix4x1 &S,double sign){
2073 auto C7x7 = dResourcePool_TMatrixFSym->Get_SharedResource();
2074 C7x7->ResizeTo(7, 7);
2075 DMatrix J(7,5);
2076
2077 double p=5.; // fixed: cannot measure
2078 double tx_=S(state_tx);
2079 double ty_=S(state_ty);
2080 double x_=S(state_x);
2081 double y_=S(state_y);
2082 double tanl=sign/sqrt(tx_*tx_+ty_*ty_);
2083 double tanl2=tanl*tanl;
2084 double lambda=atan(tanl);
2085 double sinl=sin(lambda);
2086 double sinl3=sinl*sinl*sinl;
2087
2088 J(state_X,state_x)=J(state_Y,state_y)=1.;
2089 J(state_Pz,state_ty)=-p*ty_*sinl3;
2090 J(state_Pz,state_tx)=-p*tx_*sinl3;
2091 J(state_Px,state_ty)=J(state_Py,state_tx)=-p*tx_*ty_*sinl3;
2092 J(state_Px,state_tx)=p*(1.+ty_*ty_)*sinl3;
2093 J(state_Py,state_ty)=p*(1.+tx_*tx_)*sinl3;
2094 J(state_Pz,4)=-p*p*sinl;
2095 J(state_Px,4)=tx_*J(state_Pz,4);
2096 J(state_Py,4)=ty_*J(state_Pz,4);
2097 J(state_Z,state_x)=-tx_*tanl2;
2098 J(state_Z,state_y)=-ty_*tanl2;
2099 double diff=tx_*tx_-ty_*ty_;
2100 double frac=tanl2*tanl2;
2101 J(state_Z,state_tx)=(x_*diff+2.*tx_*ty_*y_)*frac;
2102 J(state_Z,state_ty)=(2.*tx_*ty_*x_-y_*diff)*frac;
2103
2104 // C'= JCJ^T
2105 *C7x7=C.Similarity(J);
2106
2107 return C7x7;
2108}
2109
2110// Routine to get extrapolations to other detectors
2111void DTrackFitterStraightTrack::GetExtrapolations(const DVector3 &pos0,
2112 const DVector3 &dir){
2113 double x0=pos0.x(),y0=pos0.y(),z0=pos0.z();
2114 double s=0.,t=0.;
2115 DVector3 pos(0,0,0);
2116 DVector3 diff(0,0,0);
2117 ClearExtrapolations();
2118
2119 double z=z0;
2120 double dz=0.1;
2121 double uz=dir.z();
2122 double ux=dir.x()/uz,ux2=ux*ux;
2123 double uy=dir.y()/uz,uy2=uy*uy;
2124
2125 // Extrapolate to start counter
2126 double Rd=SC_BARREL_R;
2127 double A=ux*x0 + uy*y0;
2128 double B=uy2*(Rd - x0)*(Rd + x0) + 2*ux*uy*x0*y0 + ux2*(Rd - y0)*(Rd + y0);
2129 double C=ux2 + uy2;
2130 if (sc_pos.empty()==false && z<SC_END_NOSE_Z && B>0){
2131 dz=-(A-sqrt(B))/C;
2132 pos=pos0+(dz/uz)*dir;
2133 z=pos.z();
2134 bool done=(z<sc_pos[0][0].z()||z>SC_END_NOSE_Z);
2135 while(!done){
2136 double d_old=1000.,d=1000.;
2137 unsigned int index=0;
2138
2139 for (unsigned int m=0;m<12;m++){
2140 double dphi=pos.Phi()-SC_PHI_SECTOR1;
2141 if (dphi<0) dphi+=2.*M_PI3.14159265358979323846;
2142 index=int(floor(dphi/(2.*M_PI3.14159265358979323846/30.)));
2143 if (index>29) index=0;
2144 d=sc_norm[index][m].Dot(pos-sc_pos[index][m]);
2145 if (d*d_old<0){ // break if we cross the current plane
2146 pos+=d*dir;
2147 s=(pos-pos0).Mag();
2148 t=s/29.98;
2149 extrapolations[SYS_START].push_back(DTrackFitter::Extrapolation_t(pos,dir,t,s));
2150 done=true;
2151 break;
2152 }
2153 d_old=d;
2154 }
2155 pos-=(0.1/uz)*dir;
2156 z=pos.z();
2157 }
2158 }
2159 // Extrapolate to BCAL
2160 Rd=65.; // approximate BCAL inner radius
2161 B=uy2*(Rd - x0)*(Rd + x0) + 2*ux*uy*x0*y0 + ux2*(Rd - y0)*(Rd + y0);
2162 if (B>0){
2163 diff=-(A-sqrt(B))/(C*uz)*dir;
2164 s=diff.Mag();
2165 t=s/29.98;
2166 pos=pos0+diff;
2167 extrapolations[SYS_BCAL].push_back(DTrackFitter::Extrapolation_t(pos,dir,t,s));
2168 Rd=89.; // approximate BCAL outer radius
2169 B=uy2*(Rd - x0)*(Rd + x0) + 2*ux*uy*x0*y0 + ux2*(Rd - y0)*(Rd + y0);
2170 if (B>0){
2171 diff=-(A-sqrt(B))/(C*uz)*dir;
2172 s=diff.Mag();
2173 t=s/29.98;
2174 pos=pos0+diff;
2175 extrapolations[SYS_BCAL].push_back(DTrackFitter::Extrapolation_t(pos,dir,t,s));
2176 }
2177 }
2178
2179 // Extrapolate to TRD
2180 for (unsigned int i=0;i<dTRDz_vec.size();i++){
2181 diff=((dTRDz_vec[i]-z0)/uz)*dir;
2182 pos=pos0+diff;
2183 if (fabs(pos.x())<130. && fabs(pos.y())<130.){
2184 s=diff.Mag();
2185 t=s/29.98;
2186 extrapolations[SYS_TRD].push_back(DTrackFitter::Extrapolation_t(pos,dir,t,s));
2187 }
2188 }
2189
2190 // Extrapolate to DIRC
2191 diff=((dDIRCz-z0)/uz)*dir;
2192 pos=pos0+diff;
2193 if (fabs(pos.x())<130. && fabs(pos.y())<130.){
2194 s=diff.Mag();
2195 t=s/29.98;
2196 extrapolations[SYS_DIRC].push_back(DTrackFitter::Extrapolation_t(pos,dir,t,s));
2197 }
2198
2199 // Extrapolate to TOF
2200 diff=((dTOFz-z0)/uz)*dir;
2201 pos=pos0+diff;
2202 if (fabs(pos.x())<130. && fabs(pos.y())<130.){
2203 double s=diff.Mag();
2204 double t=s/29.98;
2205 s=diff.Mag();
2206 t=s/29.98;
2207 extrapolations[SYS_TOF].push_back(DTrackFitter::Extrapolation_t(pos,dir,t,s));
2208 }
2209
2210 // Extrapolate to FCAL
2211 diff=((dFCALz-z0)/uz)*dir;
2212 pos=pos0+diff;
2213 if (fabs(pos.x())<130. && fabs(pos.y())<130.){
2214 s=diff.Mag();
2215 t=s/29.98;
2216 extrapolations[SYS_FCAL].push_back(DTrackFitter::Extrapolation_t(pos,dir,t,s));
2217
2218 // extrapolate to exit of FCAL
2219 diff=((dFCALz+45.-z0)/uz)*dir;
2220 pos=pos0+diff;
2221 s=diff.Mag();
2222 t=s/29.98;
2223 extrapolations[SYS_FCAL].push_back(DTrackFitter::Extrapolation_t(pos,dir,t,s));
2224 }
2225}

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

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

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

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