StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
StThreeVector.hh
1 /***************************************************************************
2  *
3  * $Id: StThreeVector.hh,v 1.23 2010/10/18 21:55:11 fisyak Exp $
4  *
5  * Author: Brian Lasiuk, Thomas Ullrich, April 1998
6  ***************************************************************************
7  *
8  * Description:
9  *
10  * Remarks: Since not all compilers support member templates
11  * we have to specialize the templated member on these
12  * platforms. If member templates are not supported the
13  * ST_NO_MEMBER_TEMPLATES flag has to be set. tu.
14  *
15  ***************************************************************************
16  *
17  * $Log: StThreeVector.hh,v $
18  * Revision 1.23 2010/10/18 21:55:11 fisyak
19  * Warn off for gcc4.5.1 64bits
20  *
21  * Revision 1.22 2009/09/22 16:43:29 fine
22  * Introdcue the dedicated default ctor for StThreeVector #1612
23  *
24  * Revision 1.21 2008/10/29 19:16:13 perev
25  * set(x,y,z) added
26  *
27  * Revision 1.20 2007/02/23 22:41:42 ullrich
28  * Also add non-const version of xyz().
29  *
30  * Revision 1.19 2007/02/23 17:36:19 ullrich
31  * Added xyz() method.
32  *
33  * Revision 1.18 2006/02/14 17:57:31 perev
34  * x(),y(),z() return references now
35  *
36  * Revision 1.17 2006/01/09 23:47:27 fisyak
37  * Add missing methods (found by Zhangbu) to Cint dictionary
38  *
39  * Revision 1.16 2005/12/07 20:47:21 perev
40  * uint<0 redundand. WarnOff
41  *
42  * Revision 1.15 2005/09/22 20:09:20 fisyak
43  * Make StLorentzVector persistent
44  *
45  * Revision 1.14 2005/07/19 22:27:11 perev
46  * Cleanup
47  *
48  * Revision 1.13 2005/07/06 18:49:57 fisyak
49  * Replace StHelixD, StLorentzVectorD,StLorentzVectorF,StMatrixD,StMatrixF,StPhysicalHelixD,StThreeVectorD,StThreeVectorF by templated version
50  *
51  * Revision 1.12 2005/03/28 06:03:41 perev
52  * Defence FPE added
53  *
54  * Revision 1.11 2004/12/02 20:07:32 fine
55  * define the valid method for both flavor of StThreeVector
56  *
57  * Revision 1.10 2003/10/30 20:06:46 perev
58  * Check of quality added
59  *
60  * Revision 1.9 2003/09/02 17:59:35 perev
61  * gcc 3.2 updates + WarnOff
62  *
63  * Revision 1.8 2002/06/21 17:47:37 genevb
64  * Added pseudoProduct
65  *
66  * Revision 1.7 2000/01/04 19:56:05 ullrich
67  * Added cpp macro for CINT.
68  *
69  * Revision 1.6 1999/12/21 15:14:31 ullrich
70  * Modified to cope with new compiler version on Sun (CC5.0).
71  *
72  * Revision 1.5 1999/10/15 15:46:54 ullrich
73  * Changed output format in operator<<
74  *
75  * Revision 1.4 1999/06/04 18:00:05 ullrich
76  * Added new constructor which takes C-style array as argument.
77  * New operators operator() and operator[] which can be used
78  * as lvalues.
79  *
80  * Revision 1.3 1999/02/17 11:42:19 ullrich
81  * Removed specialization for 'long double'.
82  *
83  * Revision 1.2 1999/02/14 23:11:48 fisyak
84  * Fixes for Rootcint
85  *
86  * Revision 1.1 1999/01/30 03:59:05 fisyak
87  * Root Version of StarClassLibrary
88  *
89  * Revision 1.1 1999/01/23 00:28:04 ullrich
90  * Initial Revision
91  *
92  **************************************************************************/
93 #ifndef ST_THREE_VECTOR_HH
94 #define ST_THREE_VECTOR_HH
95 #ifdef __ROOT__
96 #include "Rtypes.h"
97 #endif
98 #ifndef __CINT__
99 #include <Stiostream.h>
100 #include <math.h>
101 #ifdef GNU_GCC
102 # include <stddef.h>
103 #endif
104 #if defined (__SUNPRO_CC) && __SUNPRO_CC < 0x500
105 # include <stdcomp.h>
106 #endif
107 #ifndef ST_NO_EXCEPTIONS
108 # include <stdexcept>
109 # if !defined(ST_NO_NAMESPACES)
110 using std::out_of_range;
111 # endif
112 #endif
113 #endif // __CINT__
114 
115 template<class T> class StThreeVector {
116 public:
117  StThreeVector();
118  StThreeVector(T, T, T);
119  // ROOT_VERSION(5,03,01)
120 #if ROOT_VERSION_CODE >= 328449
121  StThreeVector(TRootIOCtor*) : mX1(0), mX2(0), mX3(0) {}
122 #endif
123  virtual ~StThreeVector();
124 
125 #if !defined(ST_NO_MEMBER_TEMPLATES) && !defined(__CINT__)
126  template<class X> StThreeVector(const StThreeVector<X>&);
127  template<class X> StThreeVector(const X*);
128  template<class X> StThreeVector<T>& operator=(const StThreeVector<X>&);
129  // StThreeVector(const StThreeVector<T>&); use default
130  // StThreeVector<T>& operator=(const StThreeVector<T>&); use default
131 #else
134 
135  StThreeVector(const float*);
136  StThreeVector(const double*);
137 
138  StThreeVector<T>& operator=(const StThreeVector<float>&);
139  StThreeVector<T>& operator=(const StThreeVector<double>&);
140 #endif
141 
142  void setX(T);
143  void setY(T);
144  void setZ(T);
145  void set(T X,T Y, T Z) {mX1=X;mX2=Y;mX3=Z;}
146 
147  void setPhi(T);
148  void setTheta(T);
149  void setMag(T);
150  void setMagnitude(T);
151 
152  const T& x() const;
153  const T& y() const;
154  const T& z() const;
155  const T* xyz() const;
156  T* xyz();
157  T theta() const;
158  T cosTheta() const;
159  T phi() const;
160  T perp() const;
161  T perp2() const;
162  T magnitude() const;
163  T mag() const;
164  T mag2() const;
165  T pseudoRapidity() const;
166  T operator() (size_t) const;
167  T operator[] (size_t) const;
168 
169  T& operator() (size_t);
170  T& operator[] (size_t);
171 
172  T massHypothesis(T mass) const;
173 
174  StThreeVector<T> unit() const;
175  StThreeVector<T> orthogonal() const;
176 
177  void rotateX(T);
178  void rotateY(T);
179  void rotateZ(T);
180 
181  StThreeVector<T> operator- ();
182  StThreeVector<T> operator+ ();
183  StThreeVector<T>& operator*= (double);
184  StThreeVector<T>& operator/= (double);
185  StThreeVector<T> pseudoProduct(double,double,double) const;
186 
187 #if !defined(ST_NO_MEMBER_TEMPLATES) && !defined(__CINT__)
188  template<class X> T angle(const StThreeVector<X>&) const;
189  template<class X> StThreeVector<T> cross(const StThreeVector<X>&) const;
190  template<class X> T dot (const StThreeVector<X>&) const;
191  template<class X> StThreeVector<T> pseudoProduct(const StThreeVector<X>&) const;
192 
193  template<class X> bool operator == (const StThreeVector<X>& v) const;
194  template<class X> bool operator != (const StThreeVector<X>& v) const;
195 
196  template<class X> StThreeVector<T>& operator+= (const StThreeVector<X>&);
197  template<class X> StThreeVector<T>& operator-= (const StThreeVector<X>&);
198 #else
199  T angle(const StThreeVector<float>&) const;
200  StThreeVector<T> cross(const StThreeVector<float>&) const;
201  T dot (const StThreeVector<float>&) const;
202  StThreeVector<T> pseudoProduct(const StThreeVector<float>&) const;
203 
204  T angle(const StThreeVector<double>&) const;
205  T dot (const StThreeVector<double>&) const;
206  StThreeVector<T> cross(const StThreeVector<double>&) const;
207  StThreeVector<T> pseudoProduct(const StThreeVector<double>&) const;
208 
209  bool operator == (const StThreeVector<float>& v) const;
210  bool operator != (const StThreeVector<float>& v) const;
211  StThreeVector<T>& operator+= (const StThreeVector<float>&);
212  StThreeVector<T>& operator-= (const StThreeVector<float>&);
213 
214  bool operator == (const StThreeVector<double>& v) const;
215  bool operator != (const StThreeVector<double>& v) const;
216  StThreeVector<T>& operator+= (const StThreeVector<double>&);
217  StThreeVector<T>& operator-= (const StThreeVector<double>&);
218 #endif
219  int valid(double world = 1.e+5) const;
220  int bad(double world = 1.e+5) const;
221 protected:
222  T mX1, mX2, mX3;
223 #ifdef __ROOT__
224  ClassDef(StThreeVector,3)
225 #endif /* __ROOT__ */
226 };
227 
228 //
229 // Implementation of member functions
230 //
231 template<class T>
233  : mX1(0), mX2(0), mX3(0) {/* nop */}
234 
235 template<class T>
236 inline StThreeVector<T>::StThreeVector(T X, T Y, T Z)
237  : mX1(X), mX2(Y), mX3(Z) {/* nop */}
238 template<class T>
239 inline StThreeVector<T>::~StThreeVector() {/* nop */}
240 
241 template<class T>
242 inline void StThreeVector<T>::setX(T X) {mX1 = X;}
243 
244 template<class T>
245 inline void StThreeVector<T>::setY(T Y) {mX2 = Y;}
246 
247 template<class T>
248 inline void StThreeVector<T>::setZ(T Z) {mX3 = Z;}
249 
250 template<class T>
251 void StThreeVector<T>::setPhi(T Angle)
252 {
253  double r = magnitude();
254  double th = theta();
255 
256  mX1 = r*sin(th)*cos(Angle);
257  mX2 = r*sin(th)*sin(Angle);
258 }
259 
260 template <class T>
261 void StThreeVector<T>::setTheta(T Angle)
262 {
263  double r = magnitude();
264  double ph = phi();
265 
266  mX1 = r*sin(Angle)*cos(ph);
267  mX2 = r*sin(Angle)*sin(ph);
268  mX3 = r*cos(Angle);
269 }
270 
271 template <class T>
273 {
274  double th = theta();
275  double ph = phi();
276 
277  mX1 = r*sin(th)*cos(ph);
278  mX2 = r*sin(th)*sin(ph);
279  mX3 = r*cos(th);
280 }
281 
282 template <class T>
283 void StThreeVector<T>::setMag(T Mag)
284 {
285  setMagnitude(Mag);
286 }
287 
288 template<class T>
289 inline const T& StThreeVector<T>::x() const {return mX1;}
290 
291 template<class T>
292 inline const T& StThreeVector<T>::y() const {return mX2;}
293 
294 template<class T>
295 inline const T& StThreeVector<T>::z() const {return mX3;}
296 
297 template<class T>
298 inline const T* StThreeVector<T>::xyz() const {return &mX1;}
299 
300 template<class T>
301 inline T* StThreeVector<T>::xyz() {return &mX1;}
302 
303 template<class T>
304 inline T StThreeVector<T>::theta() const
305 {
306  return acos(cosTheta());
307 }
308 
309 template<class T>
310 inline T StThreeVector<T>::cosTheta() const
311 {
312  return mX3/(mag()+1e-20);
313 }
314 
315 template<class T>
316 inline T StThreeVector<T>::phi() const
317 {
318  return atan2(mX2,mX1);
319 }
320 
321 template<class T>
322 inline T StThreeVector<T>::pseudoRapidity() const
323 {
324  //
325  // change code to more optimal:
326  // double m = mag();
327  // return 0.5*::log( (m+z())/(m-z()) );
328  double tmp = tan(theta()/2.); if (tmp <=0.) return 1e20;
329  return -::log(tmp);
330 }
331 
332 template<class T>
334 {
335  double tmp = mag(); if (tmp<=0.) tmp = 1e-20;
336  return *this/tmp;
337 }
338 
339 template <class T>
340 T StThreeVector<T>::massHypothesis(T mass) const
341 {
342  return ::sqrt((*this)*(*this) + mass*mass);
343 }
344 
345 template <class T>
347 {
348  // Direct copy from CLHEP--it is probably better to
349  // use your own dot/cross product code...
350  double X = (mX1 < 0.0) ? -mX1 : mX1;
351  double Y = (mX2 < 0.0) ? -mX2 : mX2;
352  double Z = (mX3 < 0.0) ? -mX3 : mX3;
353 
354  if(X<Y)
355  return X < Z ? StThreeVector<T>(0,mX3,-mX2) : StThreeVector<T>(mX2,-mX1,0);
356  else
357  return mX2 < mX3 ? StThreeVector<T>(-mX3,0,mX1) : StThreeVector<T>(mX2,-mX1,0);
358 }
359 
360 template <class T>
361 void StThreeVector<T>::rotateX(T Angle)
362 {
363  // may in the future make use of the StRotation class!
364  double yPrime = cos(Angle)*mX2 - sin(Angle)*mX3;
365  double zPrime = sin(Angle)*mX2 + cos(Angle)*mX3;
366 
367  mX2 = yPrime;
368  mX3 = zPrime;
369 }
370 
371 template <class T>
372 void StThreeVector<T>::rotateY(T Angle)
373 {
374  // may in the future make use of the StRotation class!
375  double zPrime = cos(Angle)*mX3 - sin(Angle)*mX1;
376  double xPrime = sin(Angle)*mX3 + cos(Angle)*mX1;
377 
378  mX1 = xPrime;
379  mX3 = zPrime;
380 }
381 
382 template <class T>
383 void StThreeVector<T>::rotateZ(T Angle)
384 {
385  // may in the future make use of the StRotation class!
386  double xPrime = cos(Angle)*mX1 - sin(Angle)*mX2;
387  double yPrime = sin(Angle)*mX1 + cos(Angle)*mX2;
388 
389  mX1 = xPrime;
390  mX2 = yPrime;
391 }
392 
393 template<class T>
394 inline T StThreeVector<T>::perp() const
395 {
396  return ::sqrt(mX1*mX1+mX2*mX2);
397 }
398 
399 template<class T>
400 inline T StThreeVector<T>::perp2() const
401 {
402  return mX1*mX1+mX2*mX2;
403 }
404 
405 template<class T>
406 inline T StThreeVector<T>::magnitude() const
407 {
408  return mag();
409 }
410 
411 template<class T>
412 inline T StThreeVector<T>::mag() const
413 {
414  return ::sqrt(mX1*mX1+mX2*mX2+mX3*mX3);
415 }
416 
417 template<class T>
418 inline T StThreeVector<T>::mag2() const
419 {
420  return mX1*mX1+mX2*mX2+mX3*mX3;
421 }
422 
423 template<class T>
424 inline T StThreeVector<T>::operator() (size_t i) const
425 {
426  if (i <= 2) return (&mX1)[i];
427 #ifndef ST_NO_EXCEPTIONS
428  throw out_of_range("StThreeVector<T>::operator(): bad index");
429 #else
430  cerr << "StThreeVector<T>::operator(): bad index" << endl;
431 #endif
432  return 0;
433 }
434 
435 template<class T>
436 inline T& StThreeVector<T>::operator() (size_t i)
437 {
438  if (i <= 2) return (&mX1)[i];
439 #ifndef ST_NO_EXCEPTIONS
440  throw out_of_range("StThreeVector<T>::operator(): bad index");
441 #else
442  cerr << "StThreeVector<T>::operator(): bad index" << endl;
443 #endif
444  return mX1;
445 }
446 
447 template<class T>
448 inline T StThreeVector<T>::operator[] (size_t i) const
449 {
450  if (i <= 2) return (&mX1)[i];
451 #ifndef ST_NO_EXCEPTIONS
452  throw out_of_range("StThreeVector<T>::operator[]: bad index");
453 #else
454  cerr << "StThreeVector<T>::operator[]: bad index" << endl;
455 #endif
456  return 0;
457 }
458 
459 template<class T>
460 inline T &StThreeVector<T>::operator[] (size_t i)
461 {
462  if (i <= 2) return (&mX1)[i];
463 #ifndef ST_NO_EXCEPTIONS
464  throw out_of_range("StThreeVector<T>::operator[]: bad index");
465 #else
466  cerr << "StThreeVector<T>::operator[]: bad index" << endl;
467 #endif
468  return mX1;
469 }
470 #ifndef __CINT__
471 template<class T>
473 {
474  mX1 *= c; mX2 *= c; mX3 *= c;
475  return *this;
476 }
477 #else
480 #endif
481 template<class T>
483 {
484  mX1 /= c; mX2 /= c; mX3 /= c;
485  return *this;
486 }
487 
488 template<class T>
489 inline StThreeVector<T>
490 StThreeVector<T>::pseudoProduct(double X,double Y,double Z) const
491 {
492  return StThreeVector<T>(mX1*X,mX2*Y,mX3*Z);
493 }
494 
495 template<class T>
497 {
498  return StThreeVector<T>(-mX1, -mX2, -mX3);
499 }
500 
501 template<class T>
503 {
504  return *this;
505 }
506 
507 #if !defined(ST_NO_MEMBER_TEMPLATES) && !defined(__CINT__)
508 
509 template<class T>
510 template<class X>
512  : mX1(v.x()), mX2(v.y()), mX3(v.z()) {/* nop */}
513 
514 template<class T>
515 template<class X>
516 inline StThreeVector<T>::StThreeVector(const X *a)
517 {
518  mX1 = a[0];
519  mX2 = a[1];
520  mX3 = a[2];
521 }
522 
523 template<class T>
524 template<class X>
525 inline StThreeVector<T>&
527 {
528  mX1 = v.x(); mX2 = v.y(); mX3 = v.z();
529  return *this;
530 }
531 
532 template<class T>
533 template<class X>
534 inline bool StThreeVector<T>::operator== (const StThreeVector<X>& v) const
535 {
536  return mX1 == v.x() && mX2 == v.y() && mX3 == v.z();
537 }
538 
539 template<class T>
540 template<class X>
541 inline bool StThreeVector<T>::operator!= (const StThreeVector<X>& v) const
542 {
543  return !(*this == v);
544 }
545 
546 template<class T>
547 template<class X>
548 inline StThreeVector<T>&
550 {
551  mX1 += v.x(); mX2 += v.y(); mX3 += v.z();
552  return *this;
553 }
554 
555 template<class T>
556 template<class X>
557 inline StThreeVector<T>&
559 {
560  mX1 -= v.x(); mX2 -= v.y(); mX3 -= v.z();
561  return *this;
562 }
563 
564 template<class T>
565 template<class X>
566 inline T StThreeVector<T>::dot(const StThreeVector<X>& v) const
567 {
568  return mX1*v.x() + mX2*v.y() + mX3*v.z();
569 }
570 
571 template<class T>
572 template<class X>
573 inline StThreeVector<T>
575 {
576  return StThreeVector<T>(mX2*v.z() - mX3*v.y(),
577  mX3*v.x() - mX1*v.z(),
578  mX1*v.y() - mX2*v.x());
579 }
580 
581 template<class T>
582 template<class X>
583 inline T StThreeVector<T>::angle(const StThreeVector<X>& vec) const
584 {
585  double norm = this->mag2()*vec.mag2();
586 
587  return norm > 0 ? acos(this->dot(vec)/(::sqrt(norm))) : 0;
588 }
589 
590 template<class T>
591 template<class X>
592 inline StThreeVector<T>
594 {
595  return this->pseudoProduct(v.x(),v.y(),v.z());
596 }
597 
598 #else
599 
600 template<class T>
602  : mX1(v.x()), mX2(v.y()), mX3(v.z()) {/* nop */}
603 
604 template<class T>
606  : mX1(v.x()), mX2(v.y()), mX3(v.z()) {/* nop */}
607 
608 template<class T>
609 inline StThreeVector<T>::StThreeVector(const float *a)
610 {
611  mX1 = a[0];
612  mX2 = a[1];
613  mX3 = a[2];
614 }
615 
616 template<class T>
617 inline StThreeVector<T>::StThreeVector(const double *a)
618 {
619  mX1 = a[0];
620  mX2 = a[1];
621  mX3 = a[2];
622 }
623 
624 template<class T>
625 inline StThreeVector<T>&
627 {
628  mX1 = v.x(); mX2 = v.y(); mX3 = v.z();
629  return *this;
630 }
631 
632 template<class T>
633 inline StThreeVector<T>&
635 {
636  mX1 = v.x(); mX2 = v.y(); mX3 = v.z();
637  return *this;
638 }
639 
640 template<class T>
641 inline bool
643 {
644  return mX1 == v.x() && mX2 == v.y() && mX3 == v.z();
645 }
646 
647 template<class T>
648 inline bool
650 {
651  return mX1 == v.x() && mX2 == v.y() && mX3 == v.z();
652 }
653 
654 template<class T>
655 inline bool
657 {
658  return !(*this == v);
659 }
660 
661 template<class T>
662 inline bool
664 {
665  return !(*this == v);
666 }
667 
668 template<class T>
669 inline StThreeVector<T>&
671 {
672  mX1 += v.x(); mX2 += v.y(); mX3 += v.z();
673  return *this;
674 }
675 
676 template<class T>
677 inline StThreeVector<T>&
679 {
680  mX1 += v.x(); mX2 += v.y(); mX3 += v.z();
681  return *this;
682 }
683 
684 template<class T>
685 inline StThreeVector<T>&
687 {
688  mX1 -= v.x(); mX2 -= v.y(); mX3 -= v.z();
689  return *this;
690 }
691 
692 template<class T>
693 inline StThreeVector<T>&
695 {
696  mX1 -= v.x(); mX2 -= v.y(); mX3 -= v.z();
697  return *this;
698 }
699 
700 template<class T>
701 inline T StThreeVector<T>::dot(const StThreeVector<float>& v) const
702 {
703  return mX1*v.x() + mX2*v.y() + mX3*v.z();
704 }
705 
706 template<class T>
707 inline T StThreeVector<T>::dot(const StThreeVector<double>& v) const
708 {
709  return mX1*v.x() + mX2*v.y() + mX3*v.z();
710 }
711 
712 template<class T>
713 inline StThreeVector<T>
715 {
716  return StThreeVector<T>(mX2*v.z() - mX3*v.y(),
717  mX3*v.x() - mX1*v.z(),
718  mX1*v.y() - mX2*v.x());
719 }
720 
721 template<class T>
722 inline StThreeVector<T>
724 {
725  return StThreeVector<T>(mX2*v.z() - mX3*v.y(),
726  mX3*v.x() - mX1*v.z(),
727  mX1*v.y() - mX2*v.x());
728 }
729 
730 template<class T>
731 inline T StThreeVector<T>::angle(const StThreeVector<float>& v) const
732 {
733  double tmp = mag()*v.mag(); if (tmp <=0) tmp = 1e-20;
734  return acos(this->dot(v)/tmp);
735 }
736 
737 template<class T>
738 inline T StThreeVector<T>::angle(const StThreeVector<double>& v) const
739 {
740  double tmp = mag()*v.mag(); if (tmp <=0) tmp = 1e-20;
741  return acos(this->dot(v)/tmp);
742 }
743 
744 template<class T>
745 inline StThreeVector<T>
747 {
748  return this->pseudoProduct(v.x(),v.y(),v.z());
749 }
750 
751 template<class T>
752 inline StThreeVector<T>
754 {
755  return this->pseudoProduct(v.x(),v.y(),v.z());
756 }
757 #endif // ST_NO_MEMBER_TEMPLATES
758 template<class T>
759 inline int
760 StThreeVector<T>::valid(double world) const {return !bad(world);}
761 
762 template<class T>
763 inline int
764 StThreeVector<T>::bad(double world) const
765 {
766  for (int i=0;i<3;i++) {
767  if (!::finite((&mX1)[i]) ) return 10+i;
768  if ( ::fabs ((&mX1)[i])>world) return 20+i;
769  }
770  return 0;
771 }
772 //
773 // Non-member functions
774 //
775 #if !defined(ST_NO_MEMBER_TEMPLATES) && !defined(__CINT__)
776 template<class T>
777 inline T abs(const StThreeVector<T>& v) {return v.mag();}
778 template<class T, class X>
779 inline StThreeVector<T>
780 cross_product(const StThreeVector<T>& v1, const StThreeVector<X>& v2)
781 {
782  return v1.cross(v2);
783 }
784 template<class T, class X>
785 inline StThreeVector<T>
786 operator+ (const StThreeVector<T>& v1, const StThreeVector<X>& v2)
787 {
788  return StThreeVector<T>(v1) += v2;
789 }
790 
791 template<class T, class X>
792 inline StThreeVector<T>
793 operator- (const StThreeVector<T>& v1, const StThreeVector<X>& v2)
794 {
795  return StThreeVector<T>(v1) -= v2;
796 }
797 
798 template<class T, class X>
799 inline T operator* (const StThreeVector<T>& v1, const StThreeVector<X>& v2)
800 {
801  return StThreeVector<T>(v1).dot(v2);
802 }
803 #else
804 template<>
805 inline double abs(const StThreeVector<double>& v) {return v.mag();}
806 
807 template<>
808 inline float abs(const StThreeVector<float>& v) {return v.mag();}
809 
810 template<class T>
811 inline StThreeVector<T>
812 cross_product(const StThreeVector<T>& v1, const StThreeVector<double>& v2)
813 {
814  return v1.cross(v2);
815 }
816 template<class T>
817 inline StThreeVector<T>
818 cross_product(const StThreeVector<T>& v1, const StThreeVector<float>& v2)
819 {
820  return v1.cross(v2);
821 }
822 
823 
824 //
825 // Non-member operators
826 //
827 template<class T>
828 inline StThreeVector<T>
829 operator+ (const StThreeVector<T>& v1, const StThreeVector<double>& v2)
830 {
831  return StThreeVector<T>(v1) += v2;
832 }
833 
834 template<class T>
835 inline StThreeVector<T>
836 operator- (const StThreeVector<T>& v1, const StThreeVector<double>& v2)
837 {
838  return StThreeVector<T>(v1) -= v2;
839 }
840 #ifndef __CINT__
841 template<class T>
842 inline T operator* (const StThreeVector<T>& v1, const StThreeVector<double>& v2)
843 {
844  return StThreeVector<T>(v1).dot(v2);
845 }
846 template<class T>
847 inline T operator* (const StThreeVector<T>& v1, const StThreeVector<float>& v2)
848 {
849  return StThreeVector<T>(v1).dot(v2);
850 }
851 #else
852 template<> double operator* (const StThreeVector<double>& v1, const StThreeVector<double>& v2);
853 template<> double operator* (const StThreeVector<double>& v1, const StThreeVector<float>& v2);
854 template<> double operator* (const StThreeVector<float>& v1, const StThreeVector<double>& v2);
855 template<> float operator* (const StThreeVector<float>& v1, const StThreeVector<float>& v2);
856 #endif
857 template<class T>
858 inline StThreeVector<T>
859 operator+ (const StThreeVector<T>& v1, const StThreeVector<float>& v2)
860 {
861  return StThreeVector<T>(v1) += v2;
862 }
863 
864 template<class T>
865 inline StThreeVector<T>
866 operator- (const StThreeVector<T>& v1, const StThreeVector<float>& v2)
867 {
868  return StThreeVector<T>(v1) -= v2;
869 }
870 
871 #endif
872 template<class T>
873 inline StThreeVector<T> operator* (const StThreeVector<T>& v, double c)
874 {
875  return StThreeVector<T>(v) *= c;
876 }
877 
878 template<class T>
879 inline StThreeVector<T> operator* (double c, const StThreeVector<T>& v)
880 {
881  return StThreeVector<T>(v) *= c;
882 }
883 
884 template<class T>
885 inline StThreeVector<T> operator/ (const StThreeVector<T>& v,double c)
886 {
887  return StThreeVector<T>(v) /= c;
888 }
889 #ifndef __CINT__
890 template<class T>
891 ostream& operator<<(ostream& os, const StThreeVector<T>& v)
892 {
893  return os << v.x() << '\t' << v.y() << '\t' << v.z();
894 }
895 #else
896 template<> ostream& operator<<(ostream& os, const StThreeVector<double>& v);
897 template<> ostream& operator<<(ostream& os, const StThreeVector<float>& v);
898 #endif
899 template<class T>
900 istream& operator>>(istream& is, StThreeVector<T>& v)
901 {
902  T x, y, z;
903  is >> x >> y >> z;
904  v.setX(x);
905  v.setY(y);
906  v.setZ(z);
907  return is;
908 }
909 #endif