Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-08-06 09:38:25

0001 // -*- C++ -*-
0002 //
0003 // LorentzSpinor.h is a part of ThePEG - Toolkit for HEP Event Generation
0004 // Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad
0005 //
0006 // ThePEG is licenced under version 3 of the GPL, see COPYING for details.
0007 // Please respect the MCnet academic guidelines, see GUIDELINES for details.
0008 //
0009 #ifndef ThePEG_LorentzSpinor_H
0010 #define ThePEG_LorentzSpinor_H
0011 // This is the declaration of the LorentzSpinor class.
0012 #include "ThePEG/Config/ThePEG.h"
0013 #include "ThePEG/Vectors/LorentzRotation.h"
0014 #include "ThePEG/Vectors/ThreeVector.h"
0015 #include "HelicityDefinitions.h"
0016 #include "LorentzSpinor.fh"
0017 #include "LorentzSpinorBar.h"
0018 #include "LorentzPolarizationVector.h"
0019 #include "LorentzTensor.h"
0020 #include <array>
0021 
0022 namespace ThePEG{
0023 namespace Helicity{
0024 
0025 /**
0026  *  The LorentzSpinor class is designed to store a spinor. In addition
0027  *  to storing the components of the spinor, information is stored on
0028  *  the representation of the type of spinor, for example u or v type.
0029  *
0030  *  At the moment only one choice of the Dirac matrix representation
0031  *  is supported. For high-energy calculations the choice made by the
0032  *  HELAS collaboration is more efficient for numerical
0033  *  calculations. In this representation
0034  *
0035  *  \f[
0036  * \gamma_{i=1,2,3}=\left(\begin{array}{cc}
0037  *                          0 & \sigma_i \\
0038  *                          -\sigma_i & 0
0039  *                        \end{array}\right)
0040  *          \quad
0041  * \gamma_0=\left(\begin{array}{cc}
0042  *                  0 & 1 \\
0043  *                  1 & 0
0044  *                \end{array}\right)
0045  *          \quad
0046  * \gamma_5=\left(\begin{array}{cc}
0047  *                  -1 & 0 \\
0048  *                  0 & 1
0049  *                \end{array}\right)
0050  * \f]
0051  *
0052  *  The type of the spinor is also stored using the SpinorType
0053  *  enumeration.  There are three types supported SpinorType::u,
0054  *  SpinorType::v, SpinorType::unknown.  This information is intended
0055  *  mainly for use in the case of Majorana particles where matrix
0056  *  elements can be calculated with either u or v type spinors and
0057  *  knowledge of which was used will be needed in order to give the
0058  *  correct correlations. The SpinorType::unknowne is intended for
0059  *  cases where either the spinor for an off-shell line in a matrix
0060  *  element calculation or the information is genuinely unknown.
0061  *
0062  *  The LorentzSpinorBar class is also provided to store the barred
0063  *  spinor.
0064  *
0065  * @see LorentzSpinorBar
0066  *
0067  * @author Peter Richardson
0068  *
0069  */
0070 template<typename Value>
0071 class LorentzSpinor {
0072 public:
0073 
0074   /** @name Standard constructors. */
0075   //@{
0076   /**
0077    * Default zero constructor, optionally specifying \a t, the type.
0078    */
0079   LorentzSpinor(SpinorType t = SpinorType::unknown) : _type(t), _spin() {}
0080 
0081   /**
0082    * Constructor with complex numbers specifying the components,
0083    * optionally specifying \a s, the type.
0084    */
0085   LorentzSpinor(complex<Value> a,complex<Value> b,
0086         complex<Value> c,complex<Value> d,
0087         SpinorType s = SpinorType::unknown) : _type(s), _spin{{a,b,c,d}} {}
0088   //@}
0089 
0090   template <typename U>
0091   LorentzSpinor(const LorentzSpinor<U> & other)
0092     : _type(other._type), _spin(other._spin) {}
0093 
0094   /** @name Access the components. */
0095   //@{
0096   /**
0097    * Subscript operator to return spinor components
0098    */
0099   complex<Value> operator[](int i) const  {
0100     assert( i >= 0 && i <= 3 );
0101     return _spin[i];
0102   }
0103 
0104   /**
0105    * Subscript operator to return spinor components
0106    */
0107   complex<Value> operator()(int i) const  {
0108     assert( i >= 0 && i <= 3 );
0109     return _spin[i];
0110   }
0111   
0112   /**
0113    * Set components by index.
0114    */
0115   complex<Value> & operator()(int i) {
0116     assert( i >= 0 && i <= 3 );
0117     return _spin[i];
0118   }
0119   
0120   /**
0121    * Set components by index.
0122    */
0123   complex<Value> & operator[](int i) {
0124     assert( i >= 0 && i <= 3 );
0125     return _spin[i];
0126   }
0127   
0128   /**
0129    * Get first component.
0130    */
0131   complex<Value> s1() const {return _spin[0];}
0132 
0133   /**
0134    * Get second component.
0135    */
0136   complex<Value> s2() const {return _spin[1];}
0137 
0138   /**
0139    * Get third component.
0140    */
0141   complex<Value> s3() const {return _spin[2];}
0142 
0143   /**
0144    * Get fourth component.
0145    */
0146   complex<Value> s4() const {return _spin[3];}
0147 
0148   /**
0149    * Set first component.
0150    */
0151   void setS1(complex<Value> in) {_spin[0]=in;}
0152 
0153   /**
0154    * Set second component.
0155    */
0156   void setS2(complex<Value> in) {_spin[1]=in;}
0157 
0158   /**
0159    * Set third component.
0160    */
0161   void setS3(complex<Value> in) {_spin[2]=in;}
0162 
0163   /**
0164    * Set fourth component.
0165    */
0166   void setS4(complex<Value> in) {_spin[3]=in;}
0167   //@}
0168 
0169   /// @name Mathematical assignment operators.
0170   //@{
0171   template <typename ValueB>
0172   LorentzSpinor<Value> & operator+=(const LorentzSpinor<ValueB> & a) {
0173     for(unsigned int ix=0;ix<4;++ix) _spin[ix] += a._spin[ix];
0174     return *this;
0175   }
0176   
0177   template <typename ValueB>
0178   LorentzSpinor<Value> & operator-=(const LorentzSpinor<ValueB> & a) {
0179     for(unsigned int ix=0;ix<4;++ix) _spin[ix] -= a._spin[ix];
0180     return *this;
0181   }
0182   
0183   LorentzSpinor<Value> & operator*=(double a) {
0184     for(unsigned int ix=0;ix<4;++ix) _spin[ix] *=a;
0185     return *this;
0186   }
0187 
0188   LorentzSpinor<Value> & operator/=(double a) {
0189     for(unsigned int ix=0;ix<4;++ix) _spin[ix] /=a;
0190     return *this;
0191   }
0192   //@}
0193   
0194   /** @name Transformations. */
0195   //@{
0196   /**
0197    * Return the barred spinor
0198    */
0199   LorentzSpinorBar<Value> bar() const;
0200 
0201   /**
0202    * Return the conjugated spinor \f$u_c=C\bar{u}^T\f$. This operation
0203    * transforms u-spinors to v-spinors and vice-versa and is required when
0204    * dealing with majorana particles.
0205    */
0206   LorentzSpinor conjugate() const;
0207 
0208   /**
0209    * Standard Lorentz boost specifying the components of the beta vector.
0210    */
0211   LorentzSpinor & boost(double,double,double);
0212 
0213   /**
0214    * Standard Lorentz boost specifying the beta vector.
0215    */
0216   LorentzSpinor & boost(const Boost &);
0217 
0218   /**
0219    * General Lorentz transformation
0220    */
0221   LorentzSpinor & transform(const SpinHalfLorentzRotation & );
0222 
0223   /**
0224    * General Lorentz transformation
0225    */
0226   LorentzSpinor & transform(const LorentzRotation & r) {
0227     transform(r.half());
0228     return *this;
0229   }
0230   //@}
0231 
0232   /** @name Functions related to type. */
0233   //@{
0234   /**
0235    * Return the type of the spinor.
0236    */
0237   SpinorType Type() const {return _type;}
0238   //@}
0239 
0240   /**
0241    *  @name Functions to apply the projection operator
0242    */
0243   //@{
0244   /**
0245    *   Apply \f$p\!\!\!\!\!\not\,\,\,+m\f$
0246    */
0247   template<typename ValueB> 
0248   auto projectionOperator(const LorentzVector<ValueB> & p, 
0249                           const ValueB & m) const 
0250   -> LorentzSpinor<decltype(m*Value())>
0251   {
0252     LorentzSpinor<decltype(m*Value())> spin;
0253     static const Complex ii(0.,1.);
0254     complex<ValueB> p0pp3=p.t()+p.z();
0255     complex<ValueB> p0mp3=p.t()-p.z();
0256     complex<ValueB> p1pp2=p.x()+ii*p.y();
0257     complex<ValueB> p1mp2=p.x()-ii*p.y();
0258     spin.setS1(m*s1()+p0mp3*s3()-p1mp2*s4());
0259     spin.setS2(m*s2()+p0pp3*s4()-p1pp2*s3());
0260     spin.setS3(m*s3()+p0pp3*s1()+p1mp2*s2());
0261     spin.setS4(m*s4()+p0mp3*s2()+p1pp2*s1());
0262     return spin;
0263   }
0264 
0265   /**
0266    *  Apply \f$g^LP_L+g^RP_R\f$
0267    */
0268   LorentzSpinor
0269   helicityProjectionOperator(const Complex & gL, const Complex & gR) const {
0270     LorentzSpinor spin;
0271     spin.setS1(gL*s1());
0272     spin.setS2(gL*s2());
0273     spin.setS3(gR*s3());
0274     spin.setS4(gR*s4());
0275     return spin;
0276   }
0277   //@}
0278 
0279 
0280   /** @name Functions to calculate certain currents. */
0281   //@{
0282   /**
0283    *   Apply \f$p\!\!\!\!\!\not\f$
0284    */
0285   template<typename ValueB> 
0286   auto slash(const LorentzVector<ValueB> & p) const 
0287   -> LorentzSpinor<decltype(p.t()*Value())>
0288   {
0289     LorentzSpinor<decltype(p.t()*Value())> spin;
0290     static const Complex ii(0.,1.);
0291     complex<ValueB> p0pp3=p.t()+p.z();
0292     complex<ValueB> p0mp3=p.t()-p.z();
0293     complex<ValueB> p1pp2=p.x()+ii*p.y();
0294     complex<ValueB> p1mp2=p.x()-ii*p.y();
0295     spin.setS1(p0mp3*s3()-p1mp2*s4());
0296     spin.setS2(p0pp3*s4()-p1pp2*s3());
0297     spin.setS3(p0pp3*s1()+p1mp2*s2());
0298     spin.setS4(p0mp3*s2()+p1pp2*s1());
0299     return spin;
0300   }
0301 
0302   /**
0303    *   Apply \f$p\!\!\!\!\!\not\f$
0304    */
0305   template<typename ValueB> 
0306   auto slash(const LorentzVector<complex<ValueB> > & p) const 
0307   -> LorentzSpinor<decltype(ValueB()*Value())>
0308   {
0309     LorentzSpinor<decltype(ValueB()*Value())> spin;
0310     static const Complex ii(0.,1.);
0311     complex<ValueB> p0pp3=p.t()+p.z();
0312     complex<ValueB> p0mp3=p.t()-p.z();
0313     complex<ValueB> p1pp2=p.x()+ii*p.y();
0314     complex<ValueB> p1mp2=p.x()-ii*p.y();
0315     spin.setS1(p0mp3*s3()-p1mp2*s4());
0316     spin.setS2(p0pp3*s4()-p1pp2*s3());
0317     spin.setS3(p0pp3*s1()+p1mp2*s2());
0318     spin.setS4(p0mp3*s2()+p1pp2*s1());
0319     return spin;
0320   }
0321 
0322   /**
0323    *  Calculate the left-handed current \f$\bar{f}\gamma^\mu P_Lf\f$.
0324    * @param fb The barred spinor.
0325    */
0326   template<typename ValueB>
0327   auto leftCurrent(const LorentzSpinorBar<ValueB>& fb) const 
0328   -> LorentzVector<decltype(fb.s3()*this->s2())>
0329   {
0330     typedef decltype(fb.s3()*s2()) ResultT;
0331     LorentzVector<ResultT> vec;
0332     Complex ii(0.,1.);
0333     ResultT p1(fb.s3()*s2()),p2(fb.s4()*s1());
0334     vec.setX(   -(p1+p2) );
0335     vec.setY( ii*(p1-p2) );
0336     p1 = fb.s3()*s1();p2 = fb.s4()*s2();
0337     vec.setZ(   -(p1-p2) );
0338     vec.setT(    (p1+p2) );
0339     return vec;
0340   }
0341 
0342   /**
0343    *  Calculate the right-handed current \f$\bar{f}\gamma^\mu P_Rf\f$.
0344    * @param fb The barred spinor.
0345    */
0346   template<typename ValueB>
0347   auto rightCurrent(const LorentzSpinorBar<ValueB>& fb) const 
0348   -> LorentzVector<decltype(fb.s1()*this->s4())>
0349   {
0350     typedef decltype(fb.s1()*s4()) ResultT;
0351     LorentzVector<ResultT> vec;
0352     Complex ii(0.,1.);
0353     ResultT p1(fb.s1()*s4()),p2(fb.s2()*s3());
0354     vec.setX(     (p1+p2));
0355     vec.setY( -ii*(p1-p2));
0356     p1 = fb.s1()*s3();p2 = fb.s2()*s4();
0357     vec.setZ(     (p1-p2));
0358     vec.setT(     (p1+p2));
0359     return vec;
0360   }
0361 
0362   /**
0363    *  Calculate the vector current \f$\bar{f}\gamma^\mu f\f$
0364    * @param fb The barred spinor.
0365    */
0366   template<typename ValueB>
0367   auto vectorCurrent(const LorentzSpinorBar<ValueB>& fb) const 
0368   -> LorentzVector<decltype(fb.s1()*this->s4())>
0369   {
0370     typedef decltype(fb.s1()*this->s4()) ResultT;
0371     LorentzVector<ResultT> vec;
0372     Complex ii(0.,1.);
0373     ResultT s1s4(fb.s1()*s4()),s2s3(fb.s2()*s3()),
0374       s3s2(fb.s3()*s2()),s4s1(fb.s4()*s1()),
0375       s1s3(fb.s1()*s3()),s2s4(fb.s2()*s4()),
0376       s3s1(fb.s3()*s1()),s4s2(fb.s4()*s2());
0377     vec.setX(      s1s4+s2s3-s3s2-s4s1 );
0378     vec.setY( -ii*(s1s4-s2s3-s3s2+s4s1));
0379     vec.setZ(      s1s3-s2s4-s3s1+s4s2 );
0380     vec.setT(      s1s3+s2s4+s3s1+s4s2);
0381     return vec;
0382   }
0383 
0384   /**
0385    * Calculate a general current with arbitary left and right couplings,
0386    * i.e. \f$\bar{f}\gamma^\mu(c_lP_L+c_RP_R)f\f$
0387    * @param fb The barred spinor.
0388    * @param left The left coupling, \f$c_L\f$.
0389    * @param right The right coupling, \f$c_R\f$.
0390    */
0391   template<typename ValueB>
0392   auto generalCurrent(const LorentzSpinorBar<ValueB>& fb,
0393               Complex left, Complex right) const
0394   -> LorentzVector<decltype(fb.s3()*this->s2())>
0395   {
0396     typedef decltype(fb.s3()*this->s2()) ResultT;
0397     LorentzVector<ResultT> vec;
0398     Complex ii(0.,1.);
0399     ResultT p1(fb.s3()*s2()),p2(fb.s4()*s1());
0400     vec.setX(   -left*(p1+p2));
0401     vec.setY( ii*left*(p1-p2));
0402     p1 = fb.s3()*s1();p2 = fb.s4()*s2();
0403     vec.setZ(   -left*(p1-p2));
0404     vec.setT(    left*(p1+p2));
0405     p1=fb.s1()*s4();p2=fb.s2()*s3();
0406     vec.setX(vec.x()+right*(p1+p2));
0407     vec.setY(vec.y()-ii*right*(p1-p2));
0408     p1 = fb.s1()*s3();p2 = fb.s2()*s4();
0409     vec.setZ(vec.z()+right*(p1-p2));
0410     vec.setT(vec.t()+right*(p1+p2));
0411     return vec;
0412   }
0413   //@}
0414 
0415   /** @name Functions to calculate certain scalars. */
0416   //@{
0417   /**
0418    * Calculate the left-handed scalar \f$\bar{f}P_Lf\f$.
0419    * @param fb The barred spinor.
0420    */
0421   template<typename ValueB>
0422   auto leftScalar(const LorentzSpinorBar<ValueB>& fb) const  
0423   -> decltype(fb.s1()*this->s1())
0424   {
0425     return fb.s1()*s1()+fb.s2()*s2();
0426   }
0427 
0428   /**
0429    * Calculate the right-handed scalar \f$\bar{f}P_Rf\f$.
0430    * @param fb The barred spinor.
0431    */
0432   template<typename ValueB>
0433   auto rightScalar(const LorentzSpinorBar<ValueB>& fb) const 
0434   -> decltype(fb.s3()*this->s3())
0435   {
0436     return fb.s3()*s3()+fb.s4()*s4();
0437   }
0438   
0439   /**
0440    *  Calculate the scalar \f$\bar{f}f\f$.
0441    * @param fb The barred spinor.
0442    */
0443   template<typename ValueB>
0444   auto scalar(const LorentzSpinorBar<ValueB>& fb) const 
0445   -> decltype(fb.s1()*this->s1())
0446   {
0447     return fb.s1()*s1()+fb.s2()*s2()
0448           +fb.s3()*s3()+fb.s4()*s4();
0449   }
0450 
0451   /**
0452    *  Calculate the pseudoscalar \f$\bar{f}\gamma_5f\f$.
0453    * @param fb The barred spinor.
0454    */
0455   template<typename ValueB>
0456   auto pseudoScalar(const LorentzSpinorBar<ValueB>& fb) const 
0457   -> decltype(fb.s1()*this->s1())
0458   {
0459     return -fb.s1()*s1()-fb.s2()*s2()
0460            +fb.s3()*s3()+fb.s4()*s4();
0461   }
0462 
0463   /**
0464    * Calculate a general scalar product with arbitary left and right couplings,
0465    * i.e. \f$\bar{f}c_lP_L+c_RP_Rf\f$
0466    * @param fb The barred spinor.
0467    * @param left The left coupling, \f$c_L\f$.
0468    * @param right The right coupling, \f$c_R\f$.
0469    */
0470   template<typename ValueB>
0471   auto generalScalar(const LorentzSpinorBar<ValueB>& fb,
0472                          Complex left, Complex right) const 
0473   -> decltype(left*fb.s1()*this->s1())
0474   {
0475     return  left*(fb.s1()*s1()+fb.s2()*s2())
0476          + right*(fb.s3()*s3()+fb.s4()*s4());
0477   }
0478   //@}
0479 
0480   /**
0481    *  Calculate the product with \f$\sigma^{\mu\nu}\f$, i.e.
0482    *  \f$\bar{f}\sigma^{\mu\nu}f\f$
0483    */
0484   template<typename ValueB>
0485   auto sigma(const LorentzSpinorBar<ValueB>& fb) const 
0486     -> LorentzTensor<decltype(ValueB()*Value())> {
0487     typedef decltype(ValueB()*Value()) ResultT;
0488     LorentzTensor<ResultT> output;
0489     complex<ResultT> s11(fb.s1()*s1()),s22(fb.s2()*s2()),
0490       s33(fb.s3()*s3()),s44(fb.s4()*s4()),
0491       s12(fb.s1()*s2()),s21(fb.s2()*s1()),
0492       s34(fb.s3()*s4()),s43(fb.s4()*s3());
0493     Complex ii(0.,1.);
0494     ResultT zero;
0495     zero = ZERO;
0496     output.setTT(         zero         );
0497     output.setTX(-ii*( s12+s21-s34-s43));
0498     output.setTY(     -s12+s21+s34-s43 );
0499     output.setTZ(-ii*( s11-s22-s33+s44));
0500     output.setXT(      -output.tx()    );
0501     output.setXX(         zero         );
0502     output.setXY(      s11-s22+s33-s44 );
0503     output.setXZ(-ii*(-s12+s21-s34+s43));
0504     output.setYT(     -output.ty()     );
0505     output.setYX(     -output.xy()     );
0506     output.setYY(         zero         );
0507     output.setYZ(      s12+s21+s34+s43 );
0508     output.setZT(     -output.tz()     );
0509     output.setZX(     -output.xz()     );
0510     output.setZY(     -output.yz()     );
0511     output.setZZ(         zero         );
0512     return output;
0513   }
0514 
0515 private:
0516   /**
0517    * Type of spinor
0518    */
0519   SpinorType _type;
0520 
0521   /**
0522    * Storage of the components.
0523    */
0524   std::array<complex<Value>,4> _spin;
0525 };
0526 
0527 /// @name Basic mathematical operations
0528 //@{
0529 template <typename Value>
0530 inline LorentzSpinor<double>
0531 operator/(const LorentzSpinor<Value> & v, Value a) {
0532   return LorentzSpinor<double>(v.s1()/a, v.s2()/a, v.s3()/a, v.s4()/a,v.Type());
0533 }
0534 
0535 inline LorentzSpinor<double>
0536 operator/(const LorentzSpinor<double> & v, Complex a) {
0537   return LorentzSpinor<double>(v.s1()/a, v.s2()/a, v.s3()/a, v.s4()/a,v.Type());
0538 }
0539 
0540 template <typename Value>
0541 inline LorentzSpinor<Value> operator-(const LorentzSpinor<Value> & v) {
0542   return LorentzSpinor<Value>(-v.s1(),-v.s2(),-v.s3(),-v.s4(),v.Type());
0543 }
0544 
0545 template <typename ValueA, typename ValueB>
0546 inline LorentzSpinor<ValueA>
0547 operator+(LorentzSpinor<ValueA> a, const LorentzSpinor<ValueB> & b) {
0548   return a += b;
0549 }
0550 
0551 template <typename ValueA, typename ValueB>
0552 inline LorentzSpinor<ValueA>
0553 operator-(LorentzSpinor<ValueA> a, const LorentzSpinor<ValueB> & b) {
0554   return a -= b;
0555 }
0556 
0557 template <typename Value>
0558 inline LorentzSpinor<Value>
0559 operator*(const LorentzSpinor<Value> & a, double b) {
0560   return LorentzSpinor<Value>(a.s1()*b, a.s2()*b, a.s3()*b, a.s4()*b,a.Type());
0561 }
0562 
0563 template <typename Value>
0564 inline LorentzSpinor<Value>
0565 operator*(double b, LorentzSpinor<Value> a) {
0566   return a *= b;
0567 }
0568   
0569 template <typename Value>
0570 inline LorentzSpinor<Value>
0571 operator*(const LorentzSpinor<Value> & a, Complex b) {
0572   return LorentzSpinor<Value>(a.s1()*b, a.s2()*b, a.s3()*b, a.s4()*b,a.Type());
0573 }
0574 
0575 template <typename ValueA, typename ValueB>
0576 inline auto operator*(complex<ValueB> a, const LorentzSpinor<ValueA> & v) 
0577   -> LorentzSpinor<decltype(a.real()*v.s1().real())>
0578 {
0579   return {a*v.s1(), a*v.s2(), a*v.s3(), a*v.s4(),v.Type()};
0580 }
0581 
0582 template <typename ValueA, typename ValueB>
0583 inline auto operator*(const LorentzSpinor<ValueA> & v, complex<ValueB> b) 
0584   -> LorentzSpinor<decltype(b.real()*v.s1().real())>
0585 {
0586   return b*v;
0587 }
0588 
0589 template <typename ValueA, typename ValueB>
0590 inline auto operator/(const LorentzSpinor<ValueA> & v, complex<ValueB> b) 
0591   -> LorentzSpinor<decltype(v.s1().real()/b.real())>
0592 {
0593   return {v.s1()/b, v.s2()/b, v.s3()/b, v.s4()/b,v.Type()};
0594 }
0595   
0596 template <typename ValueA, typename ValueB>
0597 inline auto operator*(ValueB a, const LorentzSpinor<ValueA> & v) 
0598   -> LorentzSpinor<decltype(a*v.s1().real())>
0599 {
0600   return {a*v.s1(), a*v.s2(), a*v.s3(), a*v.s4(),v.Type()};
0601 }
0602 
0603 template <typename ValueA, typename ValueB>
0604 inline auto operator*(const LorentzSpinor<ValueA> & v, ValueB b) 
0605   -> LorentzSpinor<decltype(b*v.s1().real())>
0606 {
0607   return b*v;
0608 }
0609 
0610 template <typename ValueA, typename ValueB>
0611 inline auto operator/(const LorentzSpinor<ValueA> & v, ValueB b) 
0612   -> LorentzSpinor<decltype(v.s1().real()/b)>
0613 {
0614   return {v.s1()/b, v.s2()/b, v.s3()/b, v.s4()/b,v.Type()};
0615 }
0616 
0617 }
0618 }
0619 
0620 #ifndef ThePEG_TEMPLATES_IN_CC_FILE
0621 #include "LorentzSpinor.tcc"
0622 #endif 
0623 
0624 #endif
0625