QUDA  v1.1.0
A library for QCD on GPUs
color_spinor.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include <complex_quda.h>
4 #include <quda_matrix.h>
5 
15 namespace quda {
16 
17  template<typename Float, typename T> struct colorspinor_wrapper;
18  template<typename Float, typename T> struct colorspinor_ghost_wrapper;
19 
23  template <typename Float, int Nc, int Ns>
24  struct ColorSpinor {
25 
26  static constexpr int size = Nc * Ns;
28 
29  __device__ __host__ inline ColorSpinor<Float, Nc, Ns>()
30  {
31 #pragma unroll
32  for (int i = 0; i < size; i++) { data[i] = 0; }
33  }
34 
35  __device__ __host__ inline ColorSpinor<Float, Nc, Ns>(const ColorSpinor<Float, Nc, Ns> &a) {
36 #pragma unroll
37  for (int i = 0; i < size; i++) { data[i] = a.data[i]; }
38  }
39 
40  __device__ __host__ inline ColorSpinor<Float, Nc, Ns>& operator=(const ColorSpinor<Float, Nc, Ns> &a) {
41  if (this != &a) {
42 #pragma unroll
43  for (int i = 0; i < size; i++) { data[i] = a.data[i]; }
44  }
45  return *this;
46  }
47 
48  __device__ __host__ inline ColorSpinor<Float, Nc, Ns> operator-() const
49  {
51 #pragma unroll
52  for (int i = 0; i < size; i++) { a.data[i] = -data[i]; }
53  return a;
54  }
55 
56  __device__ __host__ inline ColorSpinor<Float, Nc, Ns>& operator+=(const ColorSpinor<Float, Nc, Ns> &a) {
57 #pragma unroll
58  for (int i = 0; i < size; i++) { data[i] += a.data[i]; }
59  return *this;
60  }
61 
62  template <typename T> __device__ __host__ inline ColorSpinor<Float, Nc, Ns> &operator*=(const T &a)
63  {
64 #pragma unroll
65  for (int i = 0; i < size; i++) { data[i] *= a; }
66  return *this;
67  }
68 
70  {
71  if (this != &a) {
72 #pragma unroll
73  for (int i = 0; i < Nc * Ns; i++) { data[i] -= a.data[i]; }
74  }
75  return *this;
76  }
77 
78  template<typename S>
79  __device__ __host__ inline ColorSpinor<Float, Nc, Ns>(const colorspinor_wrapper<Float, S> &s);
80 
81  template<typename S>
82  __device__ __host__ inline void operator=(const colorspinor_wrapper<Float, S> &s);
83 
84  template<typename S>
86 
87  template<typename S>
88  __device__ __host__ inline void operator=(const colorspinor_ghost_wrapper<Float, S> &s);
89 
96  __device__ __host__ inline complex<Float>& operator()(int s, int c) { return data[s*Nc + c]; }
97 
104  __device__ __host__ inline const complex<Float>& operator()(int s, int c) const { return data[s*Nc + c]; }
105 
111  __device__ __host__ inline complex<Float>& operator()(int idx) { return data[idx]; }
112 
118  __device__ __host__ inline const complex<Float>& operator()(int idx) const { return data[idx]; }
119 
123  __device__ __host__ void print() const
124  {
125  for (int s=0; s<Ns; s++) {
126  for (int c=0; c<Nc; c++) {
127  printf("s=%d c=%d %e %e\n", s, c, data[s*Nc+c].real(), data[s*Nc+c].imag());
128  }
129  }
130  }
131  };
132 
137  template <typename Float, int Nc> struct ColorSpinor<Float, Nc, 4> {
138  static constexpr int Ns = 4;
139  static constexpr int size = Nc * Ns;
141 
142  __device__ __host__ inline ColorSpinor<Float, Nc, 4>()
143  {
144 #pragma unroll
145  for (int i = 0; i < size; i++) { data[i] = 0; }
146  }
147 
148  __device__ __host__ inline ColorSpinor<Float, Nc, 4>(const ColorSpinor<Float, Nc, 4> &a) {
149 #pragma unroll
150  for (int i = 0; i < size; i++) { data[i] = a.data[i]; }
151  }
152 
153  __device__ __host__ inline ColorSpinor<Float, Nc, 4>& operator=(const ColorSpinor<Float, Nc, 4> &a) {
154  if (this != &a) {
155 #pragma unroll
156  for (int i = 0; i < size; i++) { data[i] = a.data[i]; }
157  }
158  return *this;
159  }
160 
161  __device__ __host__ inline ColorSpinor<Float, Nc, 4>& operator+=(const ColorSpinor<Float, Nc, 4> &a) {
162 #pragma unroll
163  for (int i = 0; i < size; i++) { data[i] += a.data[i]; }
164  return *this;
165  }
166 
167  template <typename T> __device__ __host__ inline ColorSpinor<Float, Nc, 4> &operator*=(const T &a)
168  {
169 #pragma unroll
170  for (int i = 0; i < size; i++) { data[i] *= a; }
171  return *this;
172  }
173 
179  __device__ __host__ inline ColorSpinor<Float,Nc,4> gamma(int dim) {
181  const auto &t = *this;
182 
183  switch (dim) {
184  case 0: // x dimension
185 #pragma unroll
186  for (int i=0; i<Nc; i++) {
187  a(0, i) = i_(t(3, i));
188  a(1, i) = i_(t(2, i));
189  a(2, i) = -i_(t(1, i));
190  a(3, i) = -i_(t(0, i));
191  }
192  break;
193  case 1: // y dimension
194 #pragma unroll
195  for (int i=0; i<Nc; i++) {
196  a(0, i) = t(3, i);
197  a(1, i) = -t(2, i);
198  a(2, i) = -t(1, i);
199  a(3, i) = t(0, i);
200  }
201  break;
202  case 2: // z dimension
203 #pragma unroll
204  for (int i=0; i<Nc; i++) {
205  a(0, i) = i_(t(2, i));
206  a(1, i) = -i_(t(3, i));
207  a(2, i) = -i_(t(0, i));
208  a(3, i) = i_(t(1, i));
209  }
210  break;
211  case 3: // t dimension
212 #pragma unroll
213  for (int i=0; i<Nc; i++) {
214  a(0, i) = t(0, i);
215  a(1, i) = t(1, i);
216  a(2, i) = -t(2, i);
217  a(3, i) = -t(3, i);
218  }
219  break;
220  case 4: // gamma_5
221 #pragma unroll
222  for (int i=0; i<Nc; i++) {
223  a(0, i) = t(2, i);
224  a(1, i) = t(3, i);
225  a(2, i) = t(0, i);
226  a(3, i) = t(1, i);
227  }
228  break;
229  }
230 
231  return a;
232  }
233 
239  __device__ __host__ inline ColorSpinor<Float,Nc,4> igamma(int dim) {
241  const auto &t = *this;
242 
243  switch (dim) {
244  case 0: // x dimension
245 #pragma unroll
246  for (int i=0; i<Nc; i++) {
247  a(0, i) = -t(3, i);
248  a(1, i) = -t(2, i);
249  a(2, i) = t(1, i);
250  a(3, i) = t(0, i);
251  }
252  break;
253  case 1: // y dimension
254 #pragma unroll
255  for (int i=0; i<Nc; i++) {
256  a(0, i) = i_(t(3, i));
257  a(1, i) = -i_(t(2, i));
258  a(2, i) = -i_(t(1, i));
259  a(3, i) = i_(t(0, i));
260  }
261  break;
262  case 2: // z dimension
263 #pragma unroll
264  for (int i=0; i<Nc; i++) {
265  a(0, i) = -t(2, i);
266  a(1, i) = t(3, i);
267  a(2, i) = t(0, i);
268  a(3, i) = -t(1, i);
269  }
270  break;
271  case 3: // t dimension
272 #pragma unroll
273  for (int i=0; i<Nc; i++) {
274  a(0, i) = i_(t(0, i));
275  a(1, i) = i_(t(1, i));
276  a(2, i) = -i_(t(2, i));
277  a(3, i) = -i_(t(3, i));
278  }
279  break;
280  case 4: // gamma_5
281 #pragma unroll
282  for (int i=0; i<Nc; i++) {
283  a(0, i) = i_(t(2, i));
284  a(1, i) = i_(t(3, i));
285  a(2, i) = i_(t(0, i));
286  a(3, i) = i_(t(1, i));
287  }
288  break;
289  }
290 
291  return a;
292  }
293 
298  __device__ __host__ inline ColorSpinor<Float,Nc,2> chiral_project(int chirality) const {
300 #pragma unroll
301  for (int s=0; s<Ns/2; s++) {
302 #pragma unroll
303  for (int c=0; c<Nc; c++) {
304  proj(s,c) = (*this)(chirality*Ns/2+s,c);
305  }
306  }
307  return proj;
308  }
309 
316  __device__ __host__ inline ColorSpinor<Float, Nc, 2> project(int dim, int sign) const
317  {
319  const auto &t = *this;
320  switch (dim) {
321  case 0: // x dimension
322  switch (sign) {
323  case 1: // positive projector
324 #pragma unroll
325  for (int i=0; i<Nc; i++) {
326  proj(0, i) = t(0, i) + i_(t(3, i));
327  proj(1, i) = t(1, i) + i_(t(2, i));
328  }
329  break;
330  case -1: // negative projector
331 #pragma unroll
332  for (int i=0; i<Nc; i++) {
333  proj(0, i) = t(0, i) - i_(t(3, i));
334  proj(1, i) = t(1, i) - i_(t(2, i));
335  }
336  break;
337  }
338  break;
339  case 1: // y dimension
340  switch (sign) {
341  case 1: // positive projector
342 #pragma unroll
343  for (int i=0; i<Nc; i++) {
344  proj(0, i) = t(0, i) + t(3, i);
345  proj(1, i) = t(1, i) - t(2, i);
346  }
347  break;
348  case -1: // negative projector
349 #pragma unroll
350  for (int i=0; i<Nc; i++) {
351  proj(0, i) = t(0, i) - t(3, i);
352  proj(1, i) = t(1, i) + t(2, i);
353  }
354  break;
355  }
356  break;
357  case 2: // z dimension
358  switch (sign) {
359  case 1: // positive projector
360 #pragma unroll
361  for (int i=0; i<Nc; i++) {
362  proj(0, i) = t(0, i) + i_(t(2, i));
363  proj(1, i) = t(1, i) - i_(t(3, i));
364  }
365  break;
366  case -1: // negative projector
367 #pragma unroll
368  for (int i=0; i<Nc; i++) {
369  proj(0, i) = t(0, i) - i_(t(2, i));
370  proj(1, i) = t(1, i) + i_(t(3, i));
371  }
372  break;
373  }
374  break;
375  case 3: // t dimension
376  switch (sign) {
377  case 1: // positive projector
378 #pragma unroll
379  for (int i=0; i<Nc; i++) {
380  proj(0, i) = 2 * t(0, i);
381  proj(1, i) = 2 * t(1, i);
382  }
383  break;
384  case -1: // negative projector
385 #pragma unroll
386  for (int i=0; i<Nc; i++) {
387  proj(0, i) = 2 * t(2, i);
388  proj(1, i) = 2 * t(3, i);
389  }
390  break;
391  }
392  break;
393  case 4:
394  switch (sign) {
395  case 1: // positive projector
396 #pragma unroll
397  for (int i = 0; i < Nc; i++) {
398  proj(0, i) = t(0, i) + t(2, i);
399  proj(1, i) = t(1, i) + t(3, i);
400  }
401  break;
402  case -1: // negative projector
403 #pragma unroll
404  for (int i = 0; i < Nc; i++) {
405  proj(0, i) = t(0, i) - t(2, i);
406  proj(1, i) = t(1, i) - t(3, i);
407  }
408  break;
409  }
410  break;
411  }
412 
413  return proj;
414  }
415 
451  __device__ __host__ inline ColorSpinor<Float,Nc,4> sigma(int mu, int nu) {
453  ColorSpinor<Float,Nc,4> &b = *this;
454  complex<Float> j(0.0,1.0);
455 
456  switch(mu) {
457  case 0:
458  switch(nu) {
459  case 1:
460 #pragma unroll
461  for (int i=0; i<Nc; i++) {
462  a(0,i) = j*b(0,i);
463  a(1,i) = -j*b(1,i);
464  a(2,i) = j*b(2,i);
465  a(3,i) = -j*b(3,i);
466  }
467  break;
468  case 2:
469 #pragma unroll
470  for (int i=0; i<Nc; i++) {
471  a(0,i) = -b(1,i);
472  a(1,i) = b(0,i);
473  a(2,i) = -b(3,i);
474  a(3,i) = b(2,i);
475  }
476  break;
477  case 3:
478 #pragma unroll
479  for (int i=0; i<Nc; i++) {
480  a(0,i) = -j*b(3,i);
481  a(1,i) = -j*b(2,i);
482  a(2,i) = -j*b(1,i);
483  a(3,i) = -j*b(0,i);
484  }
485  break;
486  }
487  break;
488  case 1:
489  switch(nu) {
490  case 0:
491 #pragma unroll
492  for (int i=0; i<Nc; i++) {
493  a(0,i) = -j*b(0,i);
494  a(1,i) = j*b(1,i);
495  a(2,i) = -j*b(2,i);
496  a(3,i) = j*b(3,i);
497  }
498  break;
499  case 2:
500 #pragma unroll
501  for (int i=0; i<Nc; i++) {
502  a(0,i) = j*b(1,i);
503  a(1,i) = j*b(0,i);
504  a(2,i) = j*b(3,i);
505  a(3,i) = j*b(2,i);
506  }
507  break;
508  case 3:
509 #pragma unroll
510  for (int i=0; i<Nc; i++) {
511  a(0,i) = -b(3,i);
512  a(1,i) = b(2,i);
513  a(2,i) = -b(1,i);
514  a(3,i) = b(0,i);
515  }
516  break;
517  }
518  break;
519  case 2:
520  switch(nu) {
521  case 0:
522 #pragma unroll
523  for (int i=0; i<Nc; i++) {
524  a(0,i) = b(1,i);
525  a(1,i) = -b(0,i);
526  a(2,i) = b(3,i);
527  a(3,i) = -b(2,i);
528  }
529  break;
530  case 1:
531 #pragma unroll
532  for (int i=0; i<Nc; i++) {
533  a(0,i) = -j*b(1,i);
534  a(1,i) = -j*b(0,i);
535  a(2,i) = -j*b(3,i);
536  a(3,i) = -j*b(2,i);
537  }
538  break;
539  case 3:
540 #pragma unroll
541  for (int i=0; i<Nc; i++) {
542  a(0,i) = -j*b(2,i);
543  a(1,i) = j*b(3,i);
544  a(2,i) = -j*b(0,i);
545  a(3,i) = j*b(1,i);
546  }
547  break;
548  }
549  break;
550  case 3:
551  switch(nu) {
552  case 0:
553 #pragma unroll
554  for (int i=0; i<Nc; i++) {
555  a(0,i) = j*b(3,i);
556  a(1,i) = j*b(2,i);
557  a(2,i) = j*b(1,i);
558  a(3,i) = j*b(0,i);
559  }
560  break;
561  case 1:
562 #pragma unroll
563  for (int i=0; i<Nc; i++) {
564  a(0,i) = b(3,i);
565  a(1,i) = -b(2,i);
566  a(2,i) = b(1,i);
567  a(3,i) = -b(0,i);
568  }
569  break;
570  case 2:
571 #pragma unroll
572  for (int i=0; i<Nc; i++) {
573  a(0,i) = j*b(2,i);
574  a(1,i) = -j*b(3,i);
575  a(2,i) = j*b(0,i);
576  a(3,i) = -j*b(1,i);
577  }
578  break;
579  }
580  break;
581  }
582  return a;
583  }
584 
585 
592  __device__ __host__ inline complex<Float>& operator()(int s, int c) { return data[s*Nc + c]; }
593 
600  __device__ __host__ inline const complex<Float>& operator()(int s, int c) const { return data[s*Nc + c]; }
601 
607  __device__ __host__ inline complex<Float>& operator()(int idx) { return data[idx]; }
608 
614  __device__ __host__ inline const complex<Float>& operator()(int idx) const { return data[idx]; }
615 
616  template<typename S>
617  __device__ __host__ inline ColorSpinor<Float, Nc, Ns>(const colorspinor_wrapper<Float, S> &s);
618 
619  template<typename S>
620  __device__ __host__ inline void operator=(const colorspinor_wrapper<Float, S> &s);
621 
622  template<typename S>
624 
625  template<typename S>
626  __device__ __host__ inline void operator=(const colorspinor_ghost_wrapper<Float, S> &s);
627 
632  __device__ __host__ inline void toNonRel() {
634 #pragma unroll
635  for (int c=0; c<Nc; c++) {
636  a(0,c) = (*this)(1,c)+(*this)(3,c);
637  a(1,c) = -(*this)(2,c)-(*this)(0,c);
638  a(2,c) = -(*this)(3,c)+(*this)(1,c);
639  a(3,c) = -(*this)(0,c)+(*this)(2,c);
640  }
641  *this = a;
642  }
643 
647  __device__ __host__ inline void toRel() {
649 #pragma unroll
650  for (int c=0; c<Nc; c++) {
651  a(0,c) = -(*this)(1,c)-(*this)(3,c);
652  a(1,c) = (*this)(2,c)+(*this)(0,c);
653  a(2,c) = (*this)(3,c)-(*this)(1,c);
654  a(3,c) = (*this)(0,c)-(*this)(2,c);
655  }
656  *this = a;
657  }
658 
659  __device__ __host__ void print() const
660  {
661  for (int s=0; s<Ns; s++) {
662  for (int c=0; c<Nc; c++) {
663  printf("s=%d c=%d %e %e\n", s, c, data[s*Nc+c].real(), data[s*Nc+c].imag());
664  }
665  }
666  }
667  };
668 
673  template <typename Float, int Nc>
674  struct ColorSpinor<Float, Nc, 2> {
675  static constexpr int Ns = 2;
676  static constexpr int size = Ns * Nc;
678 
679  __device__ __host__ inline ColorSpinor<Float, Nc, 2>() {
680 #pragma unroll
681  for (int i = 0; i < size; i++) { data[i] = 0; }
682  }
683 
684  __device__ __host__ inline ColorSpinor<Float, Nc, 2>(const ColorSpinor<Float, Nc, 2> &a) {
685 #pragma unroll
686  for (int i = 0; i < size; i++) { data[i] = a.data[i]; }
687  }
688 
689 
690  __device__ __host__ inline ColorSpinor<Float, Nc, 2>& operator=(const ColorSpinor<Float, Nc, 2> &a) {
691  if (this != &a) {
692 #pragma unroll
693  for (int i = 0; i < size; i++) { data[i] = a.data[i]; }
694  }
695  return *this;
696  }
697 
698  __device__ __host__ inline ColorSpinor<Float, Nc, 2>& operator+=(const ColorSpinor<Float, Nc, 2> &a) {
699 #pragma unroll
700  for (int i = 0; i < size; i++) { data[i] += a.data[i]; }
701  return *this;
702  }
703 
704  template <typename T> __device__ __host__ inline ColorSpinor<Float, Nc, 2> &operator*=(const T &a)
705  {
706 #pragma unroll
707  for (int i = 0; i < size; i++) { data[i] *= a; }
708  return *this;
709  }
710 
715  __device__ __host__ inline ColorSpinor<Float,Nc,4> chiral_reconstruct(int chirality) const {
717 #pragma unroll
718  for (int s=0; s<Ns; s++) {
719 #pragma unroll
720  for (int c=0; c<Nc; c++) {
721  recon(chirality*Ns+s,c) = (*this)(s,c);
722  }
723  }
724  return recon;
725  }
726 
733  __device__ __host__ inline ColorSpinor<Float, Nc, 4> reconstruct(int dim, int sign) const
734  {
736  const auto t = *this;
737 
738  switch (dim) {
739  case 0: // x dimension
740  switch (sign) {
741  case 1: // positive projector
742 #pragma unroll
743  for (int i=0; i<Nc; i++) {
744  recon(0, i) = t(0, i);
745  recon(1, i) = t(1, i);
746  recon(2, i) = -i_(t(1, i));
747  recon(3, i) = -i_(t(0, i));
748  }
749  break;
750  case -1: // negative projector
751 #pragma unroll
752  for (int i=0; i<Nc; i++) {
753  recon(0, i) = t(0, i);
754  recon(1, i) = t(1, i);
755  recon(2, i) = i_(t(1, i));
756  recon(3, i) = i_(t(0, i));
757  }
758  break;
759  }
760  break;
761  case 1: // y dimension
762  switch (sign) {
763  case 1: // positive projector
764 #pragma unroll
765  for (int i=0; i<Nc; i++) {
766  recon(0, i) = t(0, i);
767  recon(1, i) = t(1, i);
768  recon(2, i) = -t(1, i);
769  recon(3, i) = t(0, i);
770  }
771  break;
772  case -1: // negative projector
773 #pragma unroll
774  for (int i=0; i<Nc; i++) {
775  recon(0, i) = t(0, i);
776  recon(1, i) = t(1, i);
777  recon(2, i) = t(1, i);
778  recon(3, i) = -t(0, i);
779  }
780  break;
781  }
782  break;
783  case 2: // z dimension
784  switch (sign) {
785  case 1: // positive projector
786 #pragma unroll
787  for (int i=0; i<Nc; i++) {
788  recon(0, i) = t(0, i);
789  recon(1, i) = t(1, i);
790  recon(2, i) = -i_(t(0, i));
791  recon(3, i) = i_(t(1, i));
792  }
793  break;
794  case -1: // negative projector
795 #pragma unroll
796  for (int i=0; i<Nc; i++) {
797  recon(0, i) = t(0, i);
798  recon(1, i) = t(1, i);
799  recon(2, i) = i_(t(0, i));
800  recon(3, i) = -i_(t(1, i));
801  }
802  break;
803  }
804  break;
805  case 3: // t dimension
806  switch (sign) {
807  case 1: // positive projector
808 #pragma unroll
809  for (int i=0; i<Nc; i++) {
810  recon(0, i) = t(0, i);
811  recon(1, i) = t(1, i);
812  recon(2, i) = 0;
813  recon(3,i) = 0;
814  }
815  break;
816  case -1: // negative projector
817 #pragma unroll
818  for (int i=0; i<Nc; i++) {
819  recon(0,i) = 0;
820  recon(1,i) = 0;
821  recon(2, i) = t(0, i);
822  recon(3, i) = t(1, i);
823  }
824  break;
825  }
826  break;
827  case 4:
828  switch (sign) {
829  case 1: // positive projector
830 #pragma unroll
831  for (int i = 0; i < Nc; i++) {
832  recon(0, i) = t(0, i);
833  recon(1, i) = t(1, i);
834  recon(2, i) = t(0, i);
835  recon(3, i) = t(1, i);
836  }
837  break;
838  case -1: // negative projector
839 #pragma unroll
840  for (int i = 0; i < Nc; i++) {
841  recon(0, i) = t(0, i);
842  recon(1, i) = t(1, i);
843  recon(2, i) = -t(0, i);
844  recon(3, i) = -t(1, i);
845  }
846  break;
847  }
848  break;
849  }
850  return recon;
851  }
852 
859  __device__ __host__ inline complex<Float>& operator()(int s, int c) { return data[s*Nc + c]; }
860 
867  __device__ __host__ inline const complex<Float>& operator()(int s, int c) const { return data[s*Nc + c]; }
868 
874  __device__ __host__ inline complex<Float>& operator()(int idx) { return data[idx]; }
875 
881  __device__ __host__ inline const complex<Float>& operator()(int idx) const { return data[idx]; }
882 
883  template<typename S>
884  __device__ __host__ inline ColorSpinor<Float, Nc, Ns>(const colorspinor_wrapper<Float, S> &s);
885 
886  template<typename S>
887  __device__ __host__ inline void operator=(const colorspinor_wrapper<Float, S> &s);
888 
889  template<typename S>
891 
892  template<typename S>
893  __device__ __host__ inline void operator=(const colorspinor_ghost_wrapper<Float, S> &s);
894 
895  __device__ __host__ void print() const
896  {
897  for (int s=0; s<Ns; s++) {
898  for (int c=0; c<Nc; c++) {
899  printf("s=%d c=%d %e %e\n", s, c, data[s*Nc+c].real(), data[s*Nc+c].imag());
900  }
901  }
902  }
903  };
904 
912  template <typename Float, int Nc, int Ns>
913  __device__ __host__ inline complex<Float> innerProduct(const ColorSpinor<Float, Nc, Ns> &a,
915  {
916  complex<Float> dot = 0;
917 #pragma unroll
918  for (int s = 0; s < Ns; s++) { dot += innerProduct(a, b, s, s); }
919  return dot;
920  }
921 
929  template <typename Float, int Nc, int Ns>
930  __device__ __host__ inline complex<Float> colorContract(const ColorSpinor<Float, Nc, Ns> &a,
931  const ColorSpinor<Float, Nc, Ns> &b, int sa, int sb)
932  {
933  complex<Float> dot = 0;
934  for (int c = 0; c < Nc; c++) {
935  dot.real(dot.real() + a(sa, c).real() * b(sb, c).real());
936  dot.real(dot.real() - a(sa, c).imag() * b(sb, c).imag());
937  dot.imag(dot.imag() + a(sa, c).real() * b(sb, c).imag());
938  dot.imag(dot.imag() + a(sa, c).imag() * b(sb, c).real());
939  }
940 
941  return dot;
942  }
943 
952  template <typename Float, int Nc, int Ns>
953  __device__ __host__ inline complex<Float> innerProduct(const ColorSpinor<Float, Nc, Ns> &a,
954  const ColorSpinor<Float, Nc, Ns> &b, int s)
955  {
956  return innerProduct(a, b, s, s);
957  }
958 
968  template <typename Float, int Nc, int Ns>
969  __device__ __host__ inline complex<Float> innerProduct(const ColorSpinor<Float, Nc, Ns> &a,
970  const ColorSpinor<Float, Nc, Ns> &b, int sa, int sb)
971  {
972  complex<Float> dot = 0;
973 #pragma unroll
974  for (int c = 0; c < Nc; c++) {
975  dot.real(dot.real() + a(sa, c).real() * b(sb, c).real());
976  dot.real(dot.real() + a(sa, c).imag() * b(sb, c).imag());
977  dot.imag(dot.imag() + a(sa, c).real() * b(sb, c).imag());
978  dot.imag(dot.imag() - a(sa, c).imag() * b(sb, c).real());
979  }
980  return dot;
981  }
982 
991  template <typename Float, int Nc, int Nsa, int Nsb>
992  __device__ __host__ inline complex<Float> innerProduct(const ColorSpinor<Float, Nc, Nsa> &a,
993  const ColorSpinor<Float, Nc, Nsb> &b, int sa, int sb)
994  {
995  complex<Float> dot = 0;
996 #pragma unroll
997  for (int c = 0; c < Nc; c++) {
998  dot.real(dot.real() + a(sa, c).real() * b(sb, c).real());
999  dot.real(dot.real() + a(sa, c).imag() * b(sb, c).imag());
1000  dot.imag(dot.imag() + a(sa, c).real() * b(sb, c).imag());
1001  dot.imag(dot.imag() - a(sa, c).imag() * b(sb, c).real());
1002  }
1003  return dot;
1004  }
1005 
1016  template <typename Float, int Ns>
1018  const ColorSpinor<Float, 3, Ns> &b, int sa, int sb)
1019  {
1021  res(0, 0) = a(sa, 1) * b(sb, 2) - a(sa, 2) * b(sb, 1);
1022  res(0, 1) = a(sa, 2) * b(sb, 0) - a(sa, 0) * b(sb, 2);
1023  res(0, 2) = a(sa, 0) * b(sb, 1) - a(sa, 1) * b(sb, 0);
1024  return res;
1025  }
1026 
1034  template <typename Float, int Nc, int Ns>
1035  __device__ __host__ inline Matrix<complex<Float>, Nc> outerProdSpinTrace(const ColorSpinor<Float, Nc, Ns> &a,
1036  const ColorSpinor<Float, Nc, Ns> &b)
1037  {
1038  Matrix<complex<Float>, Nc> out;
1039 
1040  // outer product over color
1041 #pragma unroll
1042  for (int i = 0; i < Nc; i++) {
1043 #pragma unroll
1044  for (int j = 0; j < Nc; j++) {
1045  // trace over spin (manual unroll for perf)
1046  out(j, i).real(a(0, j).real() * b(0, i).real());
1047  out(j, i).real(out(j, i).real() + a(0, j).imag() * b(0, i).imag());
1048  out(j, i).imag(a(0, j).imag() * b(0, i).real());
1049  out(j, i).imag(out(j, i).imag() - a(0, j).real() * b(0, i).imag());
1050  // out(j,i) = a(0,j) * conj(b(0,i));
1051 
1052 #pragma unroll
1053  for (int s=1; s<Ns; s++) {
1054  out(j,i).real( out(j,i).real() + a(s,j).real() * b(s,i).real() );
1055  out(j,i).real( out(j,i).real() + a(s,j).imag() * b(s,i).imag() );
1056  out(j,i).imag( out(j,i).imag() + a(s,j).imag() * b(s,i).real() );
1057  out(j,i).imag( out(j,i).imag() - a(s,j).real() * b(s,i).imag() );
1058  // out(j,i) += a(s,j) * conj(b(s,i));
1059  }
1060  }
1061  }
1062  return out;
1063  }
1064 
1072  template <typename Float, int Nc>
1073  __device__ __host__ inline Matrix<complex<Float>, Nc> outerProduct(const ColorSpinor<Float, Nc, 1> &a,
1074  const ColorSpinor<Float, Nc, 1> &b)
1075  {
1076  Matrix<complex<Float>, Nc> out;
1077 
1078  // outer product over color
1079 #pragma unroll
1080  for (int i = 0; i < Nc; i++) {
1081 #pragma unroll
1082  for (int j = 0; j < Nc; j++) {
1083  // trace over spin (manual unroll for perf)
1084  out(j, i).real(a(0, j).real() * b(0, i).real());
1085  out(j, i).real(out(j, i).real() + a(0, j).imag() * b(0, i).imag());
1086  out(j, i).imag(a(0, j).imag() * b(0, i).real());
1087  out(j, i).imag(out(j, i).imag() - a(0, j).real() * b(0, i).imag());
1088  // out(j,i) = a(0,j) * conj(b(0,i));
1089  }
1090  }
1091  return out;
1092  }
1093 
1100  template<typename Float, int Nc, int Ns> __device__ __host__ inline
1102 
1104 
1105 #pragma unroll
1106  for (int i=0; i<Nc; i++) {
1107 #pragma unroll
1108  for (int s=0; s<Ns; s++) {
1109  z.data[s*Nc + i] = x.data[s*Nc + i] + y.data[s*Nc + i];
1110  }
1111  }
1112 
1113  return z;
1114  }
1115 
1122  template<typename Float, int Nc, int Ns> __device__ __host__ inline
1124 
1126 
1127 #pragma unroll
1128  for (int i=0; i<Nc; i++) {
1129 #pragma unroll
1130  for (int s=0; s<Ns; s++) {
1131  z.data[s*Nc + i] = x.data[s*Nc + i] - y.data[s*Nc + i];
1132  }
1133  }
1134 
1135  return z;
1136  }
1137 
1144  template<typename Float, int Nc, int Ns, typename S> __device__ __host__ inline
1146 
1148 
1149 #pragma unroll
1150  for (int i=0; i<Nc; i++) {
1151 #pragma unroll
1152  for (int s=0; s<Ns; s++) {
1153  y.data[s*Nc + i] = a * x.data[s*Nc + i];
1154  }
1155  }
1156 
1157  return y;
1158  }
1159 
1166  template<typename Float, int Nc, int Ns> __device__ __host__ inline
1168 
1170 
1171 #pragma unroll
1172  for (int i=0; i<Nc; i++) {
1173 #pragma unroll
1174  for (int s=0; s<Ns; s++) {
1175  y.data[s*Nc + i].x = A(i,0).real() * x.data[s*Nc + 0].real();
1176  y.data[s*Nc + i].x -= A(i,0).imag() * x.data[s*Nc + 0].imag();
1177  y.data[s*Nc + i].y = A(i,0).real() * x.data[s*Nc + 0].imag();
1178  y.data[s*Nc + i].y += A(i,0).imag() * x.data[s*Nc + 0].real();
1179  }
1180 #pragma unroll
1181  for (int j=1; j<Nc; j++) {
1182 #pragma unroll
1183  for (int s=0; s<Ns; s++) {
1184  y.data[s*Nc + i].x += A(i,j).real() * x.data[s*Nc + j].real();
1185  y.data[s*Nc + i].x -= A(i,j).imag() * x.data[s*Nc + j].imag();
1186  y.data[s*Nc + i].y += A(i,j).real() * x.data[s*Nc + j].imag();
1187  y.data[s*Nc + i].y += A(i,j).imag() * x.data[s*Nc + j].real();
1188  }
1189  }
1190  }
1191 
1192  return y;
1193  }
1194 
1202  template<typename Float, int Nc, int Ns> __device__ __host__ inline
1204  {
1206 
1207 #pragma unroll
1208  for (int i=0; i<Nc; i++) {
1209 #pragma unroll
1210  for (int s=0; s<Ns; s++) {
1211  z.data[s*Nc + i].x = y.data[s*Nc + i].real() + A(i,0).real() * x.data[s*Nc + 0].real();
1212  z.data[s*Nc + i].x -= A(i,0).imag() * x.data[s*Nc + 0].imag();
1213  z.data[s*Nc + i].y = y.data[s*Nc + i].imag() + A(i,0).real() * x.data[s*Nc + 0].imag();
1214  z.data[s*Nc + i].y += A(i,0).imag() * x.data[s*Nc + 0].real();
1215  }
1216 #pragma unroll
1217  for (int j=1; j<Nc; j++) {
1218 #pragma unroll
1219  for (int s=0; s<Ns; s++) {
1220  z.data[s*Nc + i].x += A(i,j).real() * x.data[s*Nc + j].real();
1221  z.data[s*Nc + i].x -= A(i,j).imag() * x.data[s*Nc + j].imag();
1222  z.data[s*Nc + i].y += A(i,j).real() * x.data[s*Nc + j].imag();
1223  z.data[s*Nc + i].y += A(i,j).imag() * x.data[s*Nc + j].real();
1224  }
1225  }
1226  }
1227 
1228  return z;
1229  }
1230 
1237  template<typename Float, int Nc, int Ns> __device__ __host__ inline
1239 
1241  constexpr int N = Ns * Nc;
1242 
1243 #pragma unroll
1244  for (int i=0; i<N; i++) {
1245  if (i==0) {
1246  y.data[i].x = A(i,0).real() * x.data[0].real();
1247  y.data[i].y = A(i,0).real() * x.data[0].imag();
1248  } else {
1249  y.data[i].x = A(i,0).real() * x.data[0].real();
1250  y.data[i].x -= A(i,0).imag() * x.data[0].imag();
1251  y.data[i].y = A(i,0).real() * x.data[0].imag();
1252  y.data[i].y += A(i,0).imag() * x.data[0].real();
1253  }
1254 #pragma unroll
1255  for (int j=1; j<N; j++) {
1256  if (i==j) {
1257  y.data[i].x += A(i,j).real() * x.data[j].real();
1258  y.data[i].y += A(i,j).real() * x.data[j].imag();
1259  } else {
1260  y.data[i].x += A(i,j).real() * x.data[j].real();
1261  y.data[i].x -= A(i,j).imag() * x.data[j].imag();
1262  y.data[i].y += A(i,j).real() * x.data[j].imag();
1263  y.data[i].y += A(i,j).imag() * x.data[j].real();
1264  }
1265  }
1266  }
1267 
1268  return y;
1269  }
1270 
1271 } // namespace quda
Specialized container for Hermitian matrices (e.g., used for wrapping clover matrices)
Definition: quda_matrix.h:282
std::array< int, 4 > dim
double mu
__device__ __host__ Matrix< complex< Float >, Nc > outerProduct(const ColorSpinor< Float, Nc, 1 > &a, const ColorSpinor< Float, Nc, 1 > &b)
__device__ __host__ ColorSpinor< Float, Nc, Ns > operator*(const S &a, const ColorSpinor< Float, Nc, Ns > &x)
Compute the scalar-vector product y = a * x.
__device__ __host__ ColorSpinor< Float, Nc, Ns > mv_add(const Matrix< complex< Float >, Nc > &A, const ColorSpinor< Float, Nc, Ns > &x, const ColorSpinor< Float, Nc, Ns > &y)
Compute the matrix-vector product z = A * x + y.
__device__ __host__ complex< Float > innerProduct(const ColorSpinor< Float, Nc, Ns > &a, const ColorSpinor< Float, Nc, Ns > &b)
Compute the inner product over color and spin dot = \sum_s,c conj(a(s,c)) * b(s,c)
Definition: color_spinor.h:913
__device__ __host__ complex< Float > colorContract(const ColorSpinor< Float, Nc, Ns > &a, const ColorSpinor< Float, Nc, Ns > &b, int sa, int sb)
Compute the color contraction over color at spin s dot = \sum_s,c a(s,c) * b(s,c)
Definition: color_spinor.h:930
__device__ __host__ ColorSpinor< Float, Nc, Ns > operator+(const ColorSpinor< Float, Nc, Ns > &x, const ColorSpinor< Float, Nc, Ns > &y)
ColorSpinor addition operator.
__device__ __host__ ColorSpinor< Float, 3, 1 > crossProduct(const ColorSpinor< Float, 3, Ns > &a, const ColorSpinor< Float, 3, Ns > &b, int sa, int sb)
__host__ __device__ complex< real > i_(const complex< real > &a)
__device__ __host__ Matrix< complex< Float >, Nc > outerProdSpinTrace(const ColorSpinor< Float, Nc, Ns > &a, const ColorSpinor< Float, Nc, Ns > &b)
__device__ __host__ ColorSpinor< Float, Nc, Ns > operator-(const ColorSpinor< Float, Nc, Ns > &x, const ColorSpinor< Float, Nc, Ns > &y)
ColorSpinor subtraction operator.
FloatingPoint< float > Float
__device__ __host__ complex< Float > & operator()(int idx)
1-d accessor functor
Definition: color_spinor.h:874
__device__ __host__ const complex< Float > & operator()(int s, int c) const
2-d accessor functor
Definition: color_spinor.h:867
__device__ __host__ void print() const
Definition: color_spinor.h:895
__device__ __host__ void operator=(const colorspinor_ghost_wrapper< Float, S > &s)
__device__ __host__ ColorSpinor< Float, Nc, 2 > & operator+=(const ColorSpinor< Float, Nc, 2 > &a)
Definition: color_spinor.h:698
__device__ __host__ void operator=(const colorspinor_wrapper< Float, S > &s)
__device__ __host__ const complex< Float > & operator()(int idx) const
1-d accessor functor
Definition: color_spinor.h:881
__device__ __host__ ColorSpinor< Float, Nc, 4 > chiral_reconstruct(int chirality) const
Reconstruct two-component spinor to a four-component spinor.
Definition: color_spinor.h:715
__device__ __host__ ColorSpinor< Float, Nc, 2 > & operator*=(const T &a)
Definition: color_spinor.h:704
__device__ __host__ ColorSpinor< Float, Nc, 4 > reconstruct(int dim, int sign) const
Spin reconstruct the full Spinor from the projected spinor.
Definition: color_spinor.h:733
__device__ __host__ ColorSpinor< Float, Nc, 2 > & operator=(const ColorSpinor< Float, Nc, 2 > &a)
Definition: color_spinor.h:690
__device__ __host__ complex< Float > & operator()(int s, int c)
2-d accessor functor
Definition: color_spinor.h:859
complex< Float > data[size]
Definition: color_spinor.h:677
__device__ __host__ ColorSpinor< Float, Nc, 4 > igamma(int dim)
Definition: color_spinor.h:239
__device__ __host__ void operator=(const colorspinor_ghost_wrapper< Float, S > &s)
__device__ __host__ ColorSpinor< Float, Nc, 4 > & operator+=(const ColorSpinor< Float, Nc, 4 > &a)
Definition: color_spinor.h:161
complex< Float > data[size]
Definition: color_spinor.h:140
__device__ __host__ void toRel()
Transform from non-relativistic into relavisitic basis.
Definition: color_spinor.h:647
__device__ __host__ complex< Float > & operator()(int s, int c)
2-d accessor functor
Definition: color_spinor.h:592
__device__ __host__ const complex< Float > & operator()(int s, int c) const
2-d accessor functor
Definition: color_spinor.h:600
__device__ __host__ ColorSpinor< Float, Nc, 4 > sigma(int mu, int nu)
Definition: color_spinor.h:451
__device__ __host__ ColorSpinor< Float, Nc, 4 > & operator=(const ColorSpinor< Float, Nc, 4 > &a)
Definition: color_spinor.h:153
__device__ __host__ ColorSpinor< Float, Nc, 2 > chiral_project(int chirality) const
Project four-component spinor to either chirality.
Definition: color_spinor.h:298
__device__ __host__ void operator=(const colorspinor_wrapper< Float, S > &s)
__device__ __host__ const complex< Float > & operator()(int idx) const
1-d accessor functor
Definition: color_spinor.h:614
__device__ __host__ void toNonRel()
Transform from relativistic into non-relavisitic basis Required normalization factor of 1/2 included ...
Definition: color_spinor.h:632
__device__ __host__ ColorSpinor< Float, Nc, 2 > project(int dim, int sign) const
Definition: color_spinor.h:316
__device__ __host__ ColorSpinor< Float, Nc, 4 > gamma(int dim)
Definition: color_spinor.h:179
__device__ __host__ complex< Float > & operator()(int idx)
1-d accessor functor
Definition: color_spinor.h:607
__device__ __host__ void print() const
Definition: color_spinor.h:659
__device__ __host__ ColorSpinor< Float, Nc, 4 > & operator*=(const T &a)
Definition: color_spinor.h:167
__device__ __host__ void operator=(const colorspinor_wrapper< Float, S > &s)
__device__ __host__ ColorSpinor< Float, Nc, Ns > & operator=(const ColorSpinor< Float, Nc, Ns > &a)
Definition: color_spinor.h:40
__device__ __host__ const complex< Float > & operator()(int s, int c) const
2-d accessor functor
Definition: color_spinor.h:104
__device__ __host__ complex< Float > & operator()(int idx)
1-d accessor functor
Definition: color_spinor.h:111
__device__ __host__ ColorSpinor< Float, Nc, Ns > & operator+=(const ColorSpinor< Float, Nc, Ns > &a)
Definition: color_spinor.h:56
__device__ __host__ const complex< Float > & operator()(int idx) const
1-d accessor functor
Definition: color_spinor.h:118
__device__ __host__ void operator=(const colorspinor_ghost_wrapper< Float, S > &s)
complex< Float > data[size]
Definition: color_spinor.h:27
__device__ __host__ ColorSpinor< Float, Nc, Ns > & operator-=(const ColorSpinor< Float, Nc, Ns > &a)
Definition: color_spinor.h:69
__device__ __host__ ColorSpinor< Float, Nc, Ns > & operator*=(const T &a)
Definition: color_spinor.h:62
__device__ __host__ complex< Float > & operator()(int s, int c)
2-d accessor functor
Definition: color_spinor.h:96
__device__ __host__ void print() const
Prints the NsxNc complex elements of the color spinor.
Definition: color_spinor.h:123
__device__ __host__ ColorSpinor< Float, Nc, Ns > operator-() const
Definition: color_spinor.h:48
static constexpr int size
Definition: color_spinor.h:26
colorspinor_ghost_wrapper is an internal class that is used to wrap instances of colorspinor accessor...
colorspinor_wrapper is an internal class that is used to wrap instances of colorspinor accessors,...
__host__ __device__ ValueType imag() const volatile
__host__ __device__ ValueType real() const volatile