Hall-D Software  alpha
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DVector3.h
Go to the documentation of this file.
1 // $Id$
2 //
3 // File: DVector3.h
4 //
5 // This header file is a replacement of TVector3 using sse2 SIMD instructions
6 //
7 
8 #ifndef _DVector3_
9 #define _DVector3_
10 
11 #ifndef USE_SSE2
12 
13 #include <TVector3.h>
14 typedef TVector3 DVector3;
15 
16 #else
17 #include <math.h>
18 #include <emmintrin.h>
19 #include <iostream>
20 #include <iomanip>
21 #include <align_16.h>
22 #define RAD2DEG 180./M_PI
23 using namespace std;
24 
25 class DVector3{
26  public:
27  DVector3()
28  : xy( ALIGNED_16_BLOCK_PTR(union dvec, 1, xy) )
29  , zx(xy + 1)
30  {
31  xy->v=_mm_setzero_pd();
32  zx->v=_mm_setzero_pd();
33  };
34  DVector3(double x, double y, double z)
35  : xy( ALIGNED_16_BLOCK_PTR(union dvec, 1, xy) )
36  , zx(xy + 1)
37  {
38  xy->v=_mm_setr_pd(x,y);
39  zx->v=_mm_setr_pd(z,x);
40  };
41  DVector3(__m128d v1, __m128d v2)
42  : xy( ALIGNED_16_BLOCK_PTR(union dvec, 1, xy) )
43  , zx(xy + 1)
44  {
45  xy->v=v1;
46  zx->v=v2;
47  }
48  // Copy constructor
49  DVector3(const DVector3 &v1): xy( ALIGNED_16_BLOCK_PTR(union dvec, 1, xy) )
50  , zx(xy + 1){
51  xy->v=v1.GetVxy();
52  zx->v=v1.GetVzx();
53  }
54 
55  ~DVector3(){};
56 
57  // Routines to set the components of the vector
58  void SetXY(double x, double y){
59  xy->v=_mm_setr_pd(x,y);
60  }
61  void SetXYZ(double x, double y, double z){
62  xy->v=_mm_setr_pd(x,y);
63  zx->v=_mm_setr_pd(z,x);
64  }
65  void SetMagThetaPhi(double p, double theta, double phi){
66  double my_p=fabs(p);
67  double pt=my_p*sin(theta);
68  xy->d[0]=zx->d[1]=pt*cos(phi);
69  xy->d[1]=pt*sin(phi);
70  zx->d[0]=my_p*cos(theta);
71  }
72  // Set phi keeping theta and magnitude fixed
73  void SetPhi(double phi){
74  double pt=Perp();
75  xy->d[0]=zx->d[1]=pt*cos(phi);
76  xy->d[1]=pt*sin(phi);
77  }
78  void SetX(double x){
79  xy->d[0]=zx->d[1]=x;
80  }
81  void SetY(double y){
82  xy->d[1]=y;
83  }
84  void SetZ(double z){
85  zx->d[0]=z;
86  }
87 
88  // Get component by index
89  double operator () (int ind) const {
90  switch (ind){
91  case 0:
92  return x();
93  break;
94  case 1:
95  return y();
96  break;
97  case 2:
98  return z();
99  default:
100  // cerr << "Invalid index." <<endl;
101  break;
102  }
103  return 0.;
104  }
105 
106  double x() const {return xy->d[0];};
107  double y() const {return xy->d[1];};
108  double z() const {return zx->d[0];};
109  double X() const {return xy->d[0];};
110  double Y() const {return xy->d[1];};
111  double Z() const {return zx->d[0];};
112  double Px() const {return xy->d[0];};
113  double Py() const {return xy->d[1];};
114  double Pz() const {return zx->d[0];};
115 
116  double CosTheta() const{
117  double r=Mag();
118  return r == 0.0 ? 1.0 : z()/r;
119  }
120  double Theta() const{
121  return acos(CosTheta());
122  }
123  double Phi() const{
124  return atan2(y(),x());
125  }
126 
127  double Perp2() const{
128  return (xy->d[0]*xy->d[0]+xy->d[1]*xy->d[1]);
129  }
130 
131  double Perp() const{
132  return (sqrt(Perp2()));
133  }
134  double Pt() const{ return Perp();};
135 
136  double Mag2() const{
137  return(xy->d[0]*xy->d[0]+xy->d[1]*xy->d[1]+zx->d[0]*zx->d[0]);
138  }
139 
140  double Mag() const{
141  return (sqrt(Mag2()));
142  };
143 
144  // Cross product of "this"=(x,y,z) and v1
145  // |x'| |y*vz-z*vy|
146  // |y'|=|z*vx-x*vz|
147  // |z'| |x*vy-y*vx|
148  DVector3 Cross(const DVector3 &v1) const {
149  struct dvec1{
150  __m128d v[2];
151  };
152  ALIGNED_16_BLOCK_WITH_PTR(struct dvec1, 1, p)
153  struct dvec1 &yz=p[0];
154  yz.v[0]=_mm_setr_pd(y(),z());
155  yz.v[1]=_mm_setr_pd(v1.y(),v1.z());
156  return DVector3(_mm_sub_pd(_mm_mul_pd(yz.v[0],v1.zx->v),
157  _mm_mul_pd(zx->v,yz.v[1])),
158  _mm_sub_pd(_mm_mul_pd(xy->v,yz.v[1]),
159  _mm_mul_pd(yz.v[0],v1.xy->v))
160  );
161  }
162 
163  // Create a vector orthogonal to "this"
164  DVector3 Orthogonal() const{
165  double xx= x()<0.0 ? -x() : x();
166  double yy= y()<0.0 ? -y() : y();
167  double zz= z()<0.0 ? -z() : z();
168  if (xx < yy) {
169  return xx < zz ? DVector3(0.,z(),-y()) : DVector3(y(),-x(),0.);
170  } else {
171  return yy < zz ? DVector3(-z(),0.,x()) : DVector3(y(),-x(),0.);
172  }
173  };
174 
175  // Set the magnitude of the vector to c
176  DVector3 SetMag(double c){
177  ALIGNED_16_BLOCK_WITH_PTR(__m128d, 1, p)
178  __m128d &scale=p[0];
179  scale=_mm_set1_pd(c/Mag());
180  xy->v=_mm_mul_pd(xy->v,scale);
181  zx->v=_mm_mul_pd(zx->v,scale);
182  return *this;
183  }
184 
185  // Check for equality
186  bool operator==(const DVector3 &v1) const {
187  return ((x()==v1.x() && y()==v1.y() && z()==v1.z())? true : false);
188  }
189  // Check for inequality
190  bool operator!=(const DVector3 &v1) const{
191  return ((x()!=v1.x() || y()!=v1.y() || z()!=v1.z())? true : false);
192  }
193 
194 
195  // Assignment operator
196  DVector3 &operator=(const DVector3 &v1){
197  xy->v=v1.xy->v;
198  zx->v=v1.zx->v;
199  return *this;
200  };
201 
202  // Addition
203  DVector3 &operator+=(const DVector3 &v1){
204  xy->v=_mm_add_pd(xy->v,v1.xy->v);
205  zx->v=_mm_add_pd(zx->v,v1.zx->v);
206  return *this;
207  };
208 
209  // Subtraction
210  DVector3 &operator-=(const DVector3 &v1){
211  xy->v=_mm_sub_pd(xy->v,v1.xy->v);
212  zx->v=_mm_sub_pd(zx->v,v1.zx->v);
213  return *this;
214  };
215 
216  // Add two vectors
217  DVector3 operator+(const DVector3 &v2) const{
218  return DVector3(_mm_add_pd(GetVxy(),v2.GetVxy()),
219  _mm_add_pd(GetVzx(),v2.GetVzx()));
220  };
221  // Subtract two vectors
222  DVector3 operator-(const DVector3 &v2) const{
223  return DVector3(_mm_sub_pd(GetVxy(),v2.GetVxy()),
224  _mm_sub_pd(GetVzx(),v2.GetVzx()));
225  };
226 
227 
228 
229  // Scaling
230  DVector3 &operator*=(double c){
231  ALIGNED_16_BLOCK_WITH_PTR(__m128d, 1, p)
232  __m128d &scale=p[0];
233  scale=_mm_set1_pd(c);
234  xy->v=_mm_mul_pd(GetVxy(),scale);
235  zx->v=_mm_mul_pd(GetVzx(),scale);
236  return *this;
237  }
238 
239  // Unary minus
240  DVector3 operator-() const{
241  ALIGNED_16_BLOCK_WITH_PTR(__m128d, 1, p)
242  __m128d &zero=p[0];
243  zero=_mm_set1_pd(0.);
244  return DVector3(_mm_sub_pd(zero,xy->v),_mm_sub_pd(zero,zx->v));
245  }
246 
247  // Rotate by angle a about the z-axis
248  DVector3 RotateZ(double a){
249  ALIGNED_16_BLOCK_WITH_PTR(__m128d, 2, p)
250  __m128d &ca=p[0];
251  __m128d &sa=p[1];
252  sa=_mm_set1_pd(sin(a));
253  ca=_mm_set1_pd(cos(a));
254  xy->v=_mm_add_pd(_mm_mul_pd(ca,xy->v),
255  _mm_mul_pd(sa,_mm_setr_pd(-y(),x())));
256  zx->d[1]=x();
257  return *this;
258  }
259 
260  // Rotate by angle a about the x-axis
261  DVector3 RotateX(double a){
262  ALIGNED_16_BLOCK_WITH_PTR(__m128d, 2, p)
263  __m128d &sa=p[0];
264  __m128d &ca=p[1];
265  sa=_mm_set1_pd(sin(a));
266  ca=_mm_set1_pd(cos(a));
267  union dvec2{
268  __m128d v;
269  double d[2];
270  };
271  ALIGNED_16_BLOCK_WITH_PTR(union dvec2, 1, yz)
272  yz->v=_mm_add_pd(_mm_mul_pd(ca,_mm_setr_pd(y(),z())),
273  _mm_mul_pd(sa,_mm_setr_pd(-z(),y())));
274  xy->d[1]=yz->d[0];
275  zx->d[0]=yz->d[1];
276  return *this;
277  }
278 
279  // Rotate by angle a about the y-axis
280  DVector3 RotateY(double a){
281  ALIGNED_16_BLOCK_WITH_PTR(__m128d, 2, p)
282  __m128d &sa=p[0];
283  __m128d &ca=p[1];
284  sa=_mm_set1_pd(sin(a));
285  ca=_mm_set1_pd(cos(a));
286  zx->v=_mm_add_pd(_mm_mul_pd(ca,zx->v),
287  _mm_mul_pd(sa,_mm_setr_pd(-x(),z())));
288  xy->d[0]=zx->d[1];
289  return *this;
290  }
291 
292 // Rotate by angle a about the axis specified by v. The following ugly mess
293 // of SIMD instructions does the following:
294 // sa = sin(a), ca= cos(a)
295 // dx=vx/|v|, dy=vy/|v|, dz=vz/|v|
296 // |x'| |ca+(1-ca)*dx*dx (1-ca)*dx*dy-sa*dz (1-ca)*dx*dz+sa*dy||x|
297 // |y'|=| (1-ca)*dy*dx+sa*dz ca+(1-ca)*dy*dy (1-ca)*dy*dz-sa*dx||y|
298 // |z'| | (1-ca)*dz*dx-sa*dy (1-ca)*dz*dy+sa*dx ca+(1-ca)*dz*dz ||z|
299 //
300  DVector3 Rotate(double a,const DVector3 &v){
301  if (a!=0){
302  double vmag=v.Mag();
303  if (vmag==0.0){
304  //cerr << "axis vector has zero magnitude." <<endl;
305  }
306  else{
307  double sa=sin(a);
308  double ca=cos(a);
309  ALIGNED_16_BLOCK_WITH_PTR(__m128d, 20, p)
310  __m128d &xx=p[0];
311  __m128d &yy=p[1];
312  __m128d &zz=p[2];
313  __m128d &one_minus_ca=p[3];
314  __m128d &sa_zero=p[4];
315  __m128d &ca_zero=p[5];
316  __m128d &zero_sa=p[6];
317  __m128d &zero_ca=p[7];
318  __m128d &scale=p[8];
319  __m128d &dxdy=p[9];
320  __m128d &dzdx=p[10];
321  __m128d &dxdx=p[11];
322  __m128d &dydy=p[12];
323  __m128d &dzdz=p[13];
324  __m128d &AD=p[14];
325  __m128d &BE=p[15];
326  __m128d &CF=p[16];
327  __m128d &IA=p[17];
328  __m128d &JB=p[18];
329  __m128d &KC=p[19];
330  xx=_mm_set1_pd(x());
331  yy=_mm_set1_pd(y());
332  zz=_mm_set1_pd(z());
333  one_minus_ca=_mm_set1_pd(1.-ca);
334  sa_zero=_mm_setr_pd(sa,0.);
335  ca_zero=_mm_setr_pd(ca,0.);
336  zero_sa=_mm_setr_pd(0.,sa);
337  zero_ca=_mm_setr_pd(0.,ca);
338  scale=_mm_set1_pd(1./vmag);
339  dxdy=_mm_mul_pd(scale,v.GetVxy());
340  dzdx=_mm_mul_pd(scale,v.GetVzx());
341  dxdx=_mm_mul_pd(scale,_mm_set1_pd(v.x()));
342  dydy=_mm_mul_pd(scale,_mm_set1_pd(v.y()));
343  dzdz=_mm_mul_pd(scale,_mm_set1_pd(v.z()));
344  AD=_mm_add_pd(_mm_add_pd(ca_zero,
345  _mm_mul_pd(one_minus_ca,
346  _mm_mul_pd(dxdy,dxdx))),
347  _mm_mul_pd(zero_sa,dzdz));
348  BE=_mm_sub_pd(_mm_add_pd(zero_ca,
349  _mm_mul_pd(one_minus_ca,
350  _mm_mul_pd(dxdy,dydy))),
351  _mm_mul_pd(sa_zero,dzdz));
352  CF=_mm_sub_pd(_mm_add_pd(_mm_mul_pd(one_minus_ca,
353  _mm_mul_pd(dxdy,dzdz)),
354  _mm_mul_pd(sa_zero,dydy)),
355  _mm_mul_pd(zero_sa,dxdx));
356  IA=_mm_sub_pd(_mm_add_pd(zero_ca,
357  _mm_mul_pd(one_minus_ca,
358  _mm_mul_pd(dzdx,dxdx))),
359  _mm_mul_pd(sa_zero,dydy));
360  JB=_mm_sub_pd(_mm_add_pd(_mm_mul_pd(sa_zero,dxdx),
361  _mm_mul_pd(one_minus_ca,
362  _mm_mul_pd(dzdx,dydy))),
363  _mm_mul_pd(zero_sa,dzdz));
364  KC=_mm_add_pd(_mm_add_pd(ca_zero,
365  _mm_mul_pd(one_minus_ca,
366  _mm_mul_pd(dzdx,dzdz))),
367  _mm_mul_pd(zero_sa,dydy));
368 
369  xy->v=_mm_add_pd(_mm_add_pd(_mm_mul_pd(AD,xx),
370  _mm_mul_pd(BE,yy)), _mm_mul_pd(CF,zz));
371  zx->v=_mm_add_pd(_mm_add_pd(_mm_mul_pd(IA,xx),
372  _mm_mul_pd(JB,yy)), _mm_mul_pd(KC,zz));
373  }
374  }
375  return *this;
376  }
377 
378  // Take the dot product of "this" with the vector v.
379  double Dot(const DVector3 &v) const{
380  return (x()*v.x()+y()*v.y()+z()*v.z());
381  };
382 
383  // Angle between two vectors
384  double Angle(const DVector3 &v) const{
385  double v1mag=Mag();
386  double v2mag=v.Mag();
387  if (v2mag>0. && v1mag > 0.){
388  double costheta=Dot(v)/v1mag/v2mag;
389  // Due to round-off errors, costheta could be epsilon greater than 1...
390  if (costheta>1.) return 0.;
391  if (costheta<-1.) return M_PI;
392  return acos(costheta);
393  }
394  return 0.;
395  }
396 
397  // Print the components to the screen
398  void Print() const{
399  cout << "DVector3 (x,y,z)=("<<setprecision(5)<<x() << ","
400  << setprecision(5) << y() << ","<<setprecision(5) << z() << "), "
401  <<"(rho,theta,phi)=("<<setprecision(5) << Mag() << ","
402  << setprecision(5) <<RAD2DEG*Theta() << ","
403  << setprecision(5) << RAD2DEG*Phi() << ")"
404  <<endl;
405  };
406 
407 
408  // Routines to get the SIMD __mm128d vectors.
409  __m128d GetVxy() const {return xy->v;};
410  __m128d GetVzx() const {return zx->v;};
411 
412  private:
413  union dvec{
414  __m128d v;
415  double d[2];
416  };
417  ALIGNED_16_BLOCK(union dvec, 2, xy)
418  union dvec* const zx;
419 };
420 
421 // Scale a vector by c
422 inline DVector3 operator*(const DVector3 &v1, double c){
423  ALIGNED_16_BLOCK_WITH_PTR(__m128d, 1, p)
424  __m128d &scale=p[0];
425  scale=_mm_set1_pd(c);
426  return DVector3(_mm_mul_pd(v1.GetVxy(),scale),
427  _mm_mul_pd(v1.GetVzx(),scale));
428 }
429 // Scale a vector by c
430 inline DVector3 operator*(double c,const DVector3 &v1){
431  ALIGNED_16_BLOCK_WITH_PTR(__m128d, 1, p)
432  __m128d &scale=p[0];
433  scale=_mm_set1_pd(c);
434  return DVector3(_mm_mul_pd(v1.GetVxy(),scale),
435  _mm_mul_pd(v1.GetVzx(),scale));
436 }
437 
438 
439 #endif // USE_SSE2
440 #endif // _DVector3_
441 
DMatrix2x1 operator*(const double c, const DMatrix2x1 &M)
Definition: DMatrix2x1.h:58
#define ALIGNED_16_BLOCK_PTR(TYPE, NUM, PTR)
Definition: align_16.h:24
TVector3 DVector3
Definition: DVector3.h:14
DVector2S operator+(const DVector2S &vec1, const DVector2S &vec2)
Definition: DVector2S.h:54
Double_t x[NCHANNELS]
Definition: st_tw_resols.C:39
locHist_ADCmulti Print()
#define c
#define y
#define ALIGNED_16_BLOCK_WITH_PTR(TYPE, NUM, PTR)
Definition: align_16.h:27
#define X(str)
Definition: hddm-c.cpp:83
const double RAD2DEG
double sqrt(double)
double sin(double)
DVector2S operator-(const DVector2S &vec1, const DVector2S &vec2)
Definition: DVector2S.h:59
#define ALIGNED_16_BLOCK(TYPE, NUM, PTR)
Definition: align_16.h:19