#ifndef GRID_QCD_DIRAC_H #define GRID_QCD_DIRAC_H namespace Grid{ namespace QCD { class Gamma { public: const int Ns=4; enum GammaMatrix { Identity, GammaX, GammaY, GammaZ, GammaT, Gamma5, MinusIdentity, MinusGammaX, MinusGammaY, MinusGammaZ, MinusGammaT, MinusGamma5 // GammaXGamma5, // Rest are composite (willing to take hit for two calls sequentially) // GammaYGamma5, // as they are less commonly used. // GammaZGamma5, // GammaTGamma5, // SigmaXY, // SigmaXZ, // SigmaYZ, // SigmaXT, // SigmaYT, // SigmaZT, // MinusGammaXGamma5, easiest to form by composition // MinusGammaYGamma5, as performance is not critical for these // MinusGammaZGamma5, // MinusGammaTGamma5, // MinusSigmaXY, // MinusSigmaXZ, // MinusSigmaYZ, // MinusSigmaXT, // MinusSigmaYT, // MinusSigmaZT }; static GammaMatrix GammaMatrices[]; static const char *GammaMatrixNames[]; Gamma (GammaMatrix g) { _g=g; } GammaMatrix _g; }; /* Gx * 0 0 0 i * 0 0 i 0 * 0 -i 0 0 * -i 0 0 0 */ // right multiplication makes sense for matrix args, not for vector since there is // no concept of row versus columnar indices template inline void rmultMinusGammaX(iMatrix &ret,const iMatrix &rhs){ for(int i=0;i inline void rmultGammaX(iMatrix &ret, const iMatrix &rhs){ for(int i=0;i inline void multGammaX(iMatrix &ret, const iMatrix &rhs){ for(int i=0;i inline void multMinusGammaX(iMatrix &ret, const iMatrix &rhs){ for(int i=0;i inline void multGammaX(iVector &ret, const iVector &rhs){ ret._internal[0] = timesI(rhs._internal[3]); ret._internal[1] = timesI(rhs._internal[2]); ret._internal[2] = timesMinusI(rhs._internal[1]); ret._internal[3] = timesMinusI(rhs._internal[0]); }; template inline void multMinusGammaX(iVector &ret, const iVector &rhs){ ret(0) = timesMinusI(rhs(3)); ret(1) = timesMinusI(rhs(2)); ret(2) = timesI(rhs(1)); ret(3) = timesI(rhs(0)); }; /*Gy * 0 0 0 -1 [0] -+ [3] * 0 0 1 0 [1] +- [2] * 0 1 0 0 * -1 0 0 0 */ template inline void rmultGammaY(iMatrix &ret, const iMatrix &rhs){ for(int i=0;i inline void rmultMinusGammaY(iMatrix &ret, const iMatrix &rhs){ for(int i=0;i inline void multGammaY(iMatrix &ret, const iMatrix &rhs){ for(int i=0;i inline void multMinusGammaY(iMatrix &ret, const iMatrix &rhs){ for(int i=0;i inline void multGammaY(iVector &ret, const iVector &rhs){ ret(0) = -rhs(3); ret(1) = rhs(2); ret(2) = rhs(1); ret(3) = -rhs(0); }; template inline void multMinusGammaY(iVector &ret, const iVector &rhs){ ret(0) = rhs(3); ret(1) = -rhs(2); ret(2) = -rhs(1); ret(3) = rhs(0); }; /*Gz * 0 0 i 0 [0]+-i[2] * 0 0 0 -i [1]-+i[3] * -i 0 0 0 * 0 i 0 0 */ template inline void rmultGammaZ(iMatrix &ret, const iMatrix &rhs){ for(int i=0;i inline void rmultMinusGammaZ(iMatrix &ret, const iMatrix &rhs){ for(int i=0;i inline void multGammaZ(iMatrix &ret, const iMatrix &rhs){ for(int i=0;i inline void multMinusGammaZ(iMatrix &ret, const iMatrix &rhs){ for(int i=0;i inline void multGammaZ(iVector &ret, const iVector &rhs){ ret(0) = timesI(rhs(2)); ret(1) =timesMinusI(rhs(3)); ret(2) =timesMinusI(rhs(0)); ret(3) = timesI(rhs(1)); }; template inline void multMinusGammaZ(iVector &ret, const iVector &rhs){ ret(0) = timesMinusI(rhs(2)); ret(1) = timesI(rhs(3)); ret(2) = timesI(rhs(0)); ret(3) = timesMinusI(rhs(1)); }; /*Gt * 0 0 1 0 [0]+-[2] * 0 0 0 1 [1]+-[3] * 1 0 0 0 * 0 1 0 0 */ template inline void rmultGammaT(iMatrix &ret, const iMatrix &rhs){ for(int i=0;i inline void rmultMinusGammaT(iMatrix &ret, const iMatrix &rhs){ for(int i=0;i inline void multGammaT(iMatrix &ret, const iMatrix &rhs){ for(int i=0;i inline void multMinusGammaT(iMatrix &ret, const iMatrix &rhs){ for(int i=0;i inline void multGammaT(iVector &ret, const iVector &rhs){ ret(0) = rhs(2); ret(1) = rhs(3); ret(2) = rhs(0); ret(3) = rhs(1); }; template inline void multMinusGammaT(iVector &ret, const iVector &rhs){ ret(0) =-rhs(2); ret(1) =-rhs(3); ret(2) =-rhs(0); ret(3) =-rhs(1); }; /*G5 * 1 0 0 0 [0]+-[2] * 0 1 0 0 [1]+-[3] * 0 0 -1 0 * 0 0 0 -1 */ template inline void rmultGamma5(iMatrix &ret, const iMatrix &rhs){ for(int i=0;i inline void rmultMinusGamma5(iMatrix &ret, const iMatrix &rhs){ for(int i=0;i inline void multGamma5(iMatrix &ret, const iMatrix &rhs){ for(int i=0;i inline void multMinusGamma5(iMatrix &ret, const iMatrix &rhs){ for(int i=0;i inline void multGamma5(iVector &ret, const iVector &rhs){ ret(0) = rhs(0); ret(1) = rhs(1); ret(2) =-rhs(2); ret(3) =-rhs(3); }; template inline void multMinusGamma5(iVector &ret, const iVector &rhs){ ret(0) =-rhs(0); ret(1) =-rhs(1); ret(2) = rhs(2); ret(3) = rhs(3); }; #ifdef GRID_WARN_SUBOPTIMAL #warning "Optimisation alert switch over to multGammaX early " #endif /////////////////////////////////////////////////////////////////////////////////////////////////// // Operator * : first case this is not a spin index, so recurse /////////////////////////////////////////////////////////////////////////////////////////////////// // FIXME // // Optimisation; switch over to a "multGammaX(ret._internal,arg._internal)" style early and // note that doing so from the lattice operator will avoid copy back and case switch overhead, as // was done for the tensor math operator to remove operator * notation early // //left multiply template inline auto operator * ( const Gamma &G,const iScalar &arg) -> typename std::enable_if,SpinorIndex>::notvalue,iScalar >::type { iScalar ret; ret._internal=G*arg._internal; return ret; } template inline auto operator * ( const Gamma &G,const iVector &arg) -> typename std::enable_if,SpinorIndex>::notvalue,iVector >::type { iVector ret; ret._internal=G*arg._internal; return ret; } template inline auto operator * ( const Gamma &G,const iMatrix &arg) -> typename std::enable_if,SpinorIndex>::notvalue,iMatrix >::type { iMatrix ret; ret._internal=G*arg._internal; return ret; } //right multiply template inline auto operator * (const iScalar &arg, const Gamma &G) -> typename std::enable_if,SpinorIndex>::notvalue,iScalar >::type { iScalar ret; ret._internal=arg._internal*G; return ret; } template inline auto operator * (const iVector &arg, const Gamma &G) -> typename std::enable_if,SpinorIndex>::notvalue,iVector >::type { iVector ret; ret._internal=arg._internal*G; return ret; } template inline auto operator * (const iMatrix &arg, const Gamma &G) -> typename std::enable_if,SpinorIndex>::notvalue,iMatrix >::type { iMatrix ret; ret._internal=arg._internal*G; return ret; } //////////////////////////////////////////////////////// // When we hit the spin index this matches and we stop //////////////////////////////////////////////////////// template inline auto operator * ( const Gamma &G,const iMatrix &arg) -> typename std::enable_if,SpinorIndex>::value,iMatrix >::type { iMatrix ret; switch (G._g) { case Gamma::Identity: ret = arg; break; case Gamma::MinusIdentity: ret = -arg; break; case Gamma::GammaX: multGammaX(ret,arg); break; case Gamma::MinusGammaX: multMinusGammaX(ret,arg); break; case Gamma::GammaY: multGammaY(ret,arg); break; case Gamma::MinusGammaY: multMinusGammaY(ret,arg); break; case Gamma::GammaZ: multGammaZ(ret,arg); break; case Gamma::MinusGammaZ: multMinusGammaZ(ret,arg); break; case Gamma::GammaT: multGammaT(ret,arg); break; case Gamma::MinusGammaT: multMinusGammaT(ret,arg); break; case Gamma::Gamma5: multGamma5(ret,arg); break; case Gamma::MinusGamma5: multMinusGamma5(ret,arg); break; default: assert(0); break; } return ret; } // Could have used type trait for Matrix/vector and then an enable if to share code template inline auto operator * ( const Gamma &G,const iVector &arg) -> typename std::enable_if,SpinorIndex>::value,iVector >::type { iVector ret; switch (G._g) { case Gamma::Identity: ret = arg; break; case Gamma::MinusIdentity: ret = -arg; break; case Gamma::GammaX: multGammaX(ret,arg); break; case Gamma::MinusGammaX: multMinusGammaX(ret,arg); break; case Gamma::GammaY: multGammaY(ret,arg); break; case Gamma::MinusGammaY: multMinusGammaY(ret,arg); break; case Gamma::GammaZ: multGammaZ(ret,arg); break; case Gamma::MinusGammaZ: multMinusGammaZ(ret,arg); break; case Gamma::GammaT: multGammaT(ret,arg); break; case Gamma::MinusGammaT: multMinusGammaT(ret,arg); break; case Gamma::Gamma5: multGamma5(ret,arg); break; case Gamma::MinusGamma5: multMinusGamma5(ret,arg); break; default: assert(0); break; } return ret; } template inline auto operator * (const iMatrix &arg, const Gamma &G) -> typename std::enable_if,SpinorIndex>::value,iMatrix >::type { iMatrix ret; switch (G._g) { case Gamma::Identity: ret = arg; break; case Gamma::MinusIdentity: ret = -arg; break; case Gamma::GammaX: rmultGammaX(ret,arg); break; case Gamma::MinusGammaX: rmultMinusGammaX(ret,arg); break; case Gamma::GammaY: rmultGammaY(ret,arg); break; case Gamma::MinusGammaY: rmultMinusGammaY(ret,arg); break; case Gamma::GammaZ: rmultGammaZ(ret,arg); break; case Gamma::MinusGammaZ: rmultMinusGammaZ(ret,arg); break; case Gamma::GammaT: rmultGammaT(ret,arg); break; case Gamma::MinusGammaT: rmultMinusGammaT(ret,arg); break; case Gamma::Gamma5: rmultGamma5(ret,arg); break; case Gamma::MinusGamma5: rmultMinusGamma5(ret,arg); break; default: assert(0); break; } return ret; } /* Output from test ./Grid_gamma Identity((1,0),(0,0),(0,0),(0,0)) ((0,0),(1,0),(0,0),(0,0)) ((0,0),(0,0),(1,0),(0,0)) ((0,0),(0,0),(0,0),(1,0)) OK GammaX ((0,0),(0,0),(0,0),(0,1)) ((0,0),(0,0),(0,1),(0,0)) ((0,0),(0,-1),(0,0),(0,0)) ((0,-1),(0,0),(0,0),(0,0)) OK * Gx * 0 0 0 i * 0 0 i 0 * 0 -i 0 0 * -i 0 0 0 GammaY ((-0,-0),(-0,-0),(-0,-0),(-1,-0)) ((0,0),(0,0),(1,0),(0,0)) ((0,0),(1,0),(0,0),(0,0)) OK ((-1,-0),(-0,-0),(-0,-0),(-0,-0)) *Gy * 0 0 0 -1 [0] -+ [3] * 0 0 1 0 [1] +- [2] * 0 1 0 0 * -1 0 0 0 GammaZ ((0,0),(0,0),(0,1),(0,0)) ((0,0),(0,0),(0,0),(0,-1)) ((0,-1),(0,0),(0,0),(0,0)) ((0,0),(0,1),(0,0),(0,0)) OK * 0 0 i 0 [0]+-i[2] * 0 0 0 -i [1]-+i[3] * -i 0 0 0 * 0 i 0 0 GammaT ((0,0),(0,0),(1,0),(0,0)) ((0,0),(0,0),(0,0),(1,0)) OK ((1,0),(0,0),(0,0),(0,0)) ((0,0),(1,0),(0,0),(0,0)) * 0 0 1 0 [0]+-[2] * 0 0 0 1 [1]+-[3] * 1 0 0 0 * 0 1 0 0 Gamma5 ((1,0),(0,0),(0,0),(0,0)) ((0,0),(1,0),(0,0),(0,0)) ((-0,-0),(-0,-0),(-1,-0),(-0,-0)) ((-0,-0),(-0,-0),(-0,-0),(-1,-0)) * 1 0 0 0 [0]+-[2] * 0 1 0 0 [1]+-[3] OK * 0 0 -1 0 * 0 0 0 -1 */ } //namespace QCD } // Grid #endif