QDP++
qdp_scalar_specific.h
Go to the documentation of this file.
1// -*- C++ -*-
2//
3// QDP data parallel interface
4//
5// Outer lattice routines specific to a scalar platform
6
7#ifndef QDP_SCALAR_SPECIFIC_H
8#define QDP_SCALAR_SPECIFIC_H
9
10namespace QDP {
11
12// Use separate defs here. This will cause subroutine calls under g++
13
14//-----------------------------------------------------------------------------
15// Layout stuff specific to a scalar architecture
16namespace Layout
17{
20}
21
22
23//-----------------------------------------------------------------------------
24// Internal ops designed to look like those in parscalar
25// These dummy routines exist just to make code more portable
26namespace QDPInternal
27{
29 template<class T>
30 inline void globalSumArray(T* dest, int n) {}
31
33 template<class T>
34 inline void globalSumArray(multi1d<T>& dest) {}
35
37 template<class T>
38 inline void globalSumArray(multi2d<T>& dest) {}
39
41 template<class T>
42 inline void globalSum(T& dest) {}
43
45 inline void globalAnd(bool& in) {}
46
48 inline void globalOr(bool& in) {}
49
51 template<class T>
52 inline void broadcast(T& dest) {}
53
55 template<>
56 inline void broadcast(std::string& dest) {}
57
59 inline void broadcast_str(std::string& dest) {}
60
62 inline void broadcast(void* dest, size_t nbytes) {}
63}
64
66// Threading evaluate with openmp and qmt implementation
67//
68// by Xu Guo, EPCC, 16 June 2008
70
72// "OLattice Op Scalar(Expression(source)) under an Subset"
73//
74template<class T, class T1, class Op, class RHS>
75struct u_arg{
76 OLattice<T>& d;
77 const QDPExpr<RHS,OScalar<T1> >& r;
78 const Op& op;
79 const int *tab;
81 const QDPExpr<RHS, OScalar<T1> >& r_,
82 const Op& op_,
83 const int *tab_ ) : d(d_), r(r_), op(op_), tab(tab_) {}
84 };
85
87// "OLattice Op Scalar(Expression(source)) under an Subset"
88//
89template<class T, class T1, class Op, class RHS>
90void ev_userfunc(int lo, int hi, int myId, u_arg<T,T1,Op,RHS> *a)
91{
92 OLattice<T>& dest = a->d;
93 const QDPExpr<RHS,OScalar<T1> >&rhs = a->r;
94 const int* tab = a->tab;
95 const Op& op= a->op;
96
97
98 for(int j=lo; j < hi; ++j)
99 {
100 int i = tab[j];
101 op(dest.elem(i), forEach(rhs, EvalLeaf1(0), OpCombine()));
102 }
103}
104
105
107// "OLattice Op OLattice(Expression(source)) under an Subset"
108//
109template<class T, class T1, class Op, class RHS>
110struct user_arg{
111 OLattice<T>& d;
112 const QDPExpr<RHS,OLattice<T1> >& r;
113 const Op& op;
114 const int *tab;
116 const QDPExpr<RHS,OLattice<T1> >& r_,
117 const Op& op_,
118 const int *tab_) : d(d_), r(r_), op(op_), tab(tab_) {}
119
120 };
121
123// "OLattice Op OLattice(Expression(source)) under an Subset"
124//
125template<class T, class T1, class Op, class RHS>
126void evaluate_userfunc(int lo, int hi, int myId, user_arg<T,T1,Op,RHS> *a)
127{
128
129 OLattice<T>& dest = a->d;
130 const QDPExpr<RHS,OLattice<T1> >&rhs = a->r;
131 const int* tab = a->tab;
132 const Op& op= a->op;
133
134
135 for(int j=lo; j < hi; ++j)
136 {
137 int i = tab[j];
138 op(dest.elem(i), forEach(rhs, EvalLeaf1(i), OpCombine()));
139 }
140}
141
143#include "qdp_dispatch.h"
144
145//-----------------------------------------------------------------------------
147
151template<class T, class T1, class Op, class RHS>
152//inline
153void evaluate(OLattice<T>& dest, const Op& op, const QDPExpr<RHS,OScalar<T1> >& rhs,
154 const Subset& s)
155{
156// cerr << "In evaluateUnorderedSubet(olattice,oscalar)\n";
157
158#if defined(QDP_USE_PROFILING)
159 static QDPProfile_t prof(dest, op, rhs);
160 prof.time -= getClockTime();
161#endif
162
163 int numSiteTable = s.numSiteTable();
164
165 u_arg<T,T1,Op,RHS> a(dest, rhs, op, s.siteTable().slice());
166
168
170 // Original code
172 //const int *tab = s.siteTable().slice();
173 //for(int j=0; j < s.numSiteTable(); ++j)
174 //{
175 //int i = tab[j];
176// fprintf(stderr,"eval(olattice,oscalar): site %d\n",i);
177// op(dest.elem(i), forEach(rhs, ElemLeaf(), OpCombine()));
178 //op(dest.elem(i), forEach(rhs, EvalLeaf1(0), OpCombine()));
179 //}
180
181#if defined(QDP_USE_PROFILING)
182 prof.time += getClockTime();
183 prof.count++;
184 prof.print();
185#endif
186}
187
188
189
191
195template<class T, class T1, class Op, class RHS>
196//inline
197void evaluate(OLattice<T>& dest, const Op& op, const QDPExpr<RHS,OLattice<T1> >& rhs,
198 const Subset& s)
199{
200// cerr << "In evaluateSubset(olattice,olattice)" << endl;
201
202#if defined(QDP_USE_PROFILING)
203 static QDPProfile_t prof(dest, op, rhs);
204 prof.time -= getClockTime();
205#endif
206
207 int numSiteTable = s.numSiteTable();
208
209 user_arg<T,T1,Op,RHS> a(dest, rhs, op, s.siteTable().slice());
210
212
214 // Original code
216
217 // General form of loop structure
218 //const int *tab = s.siteTable().slice();
219 //for(int j=0; j < s.numSiteTable(); ++j)
220 //{
221 //int i = tab[j];
222// fprintf(stderr,"eval(olattice,olattice): site %d\n",i);
223 //op(dest.elem(i), forEach(rhs, EvalLeaf1(i), OpCombine()));
224 //}
225
226#if defined(QDP_USE_PROFILING)
227 prof.time += getClockTime();
228 prof.count++;
229 prof.print();
230#endif
231}
232
233
234
235//-----------------------------------------------------------------------------
236template<class T, class T1, class Op, class RHS>
237//inline
238void evaluate_F(T* dest, const Op& op, const QDPExpr<RHS,OLattice<T1> >& rhs,
239 const Subset& s)
240{
241 //cerr << "In evaluate_F(olattice,olattice)" << endl;
242
243#if defined(QDP_USE_PROFILING)
244 static QDPProfile_t prof(dest, op, rhs);
245 prof.time -= getClockTime();
246#endif
247
248 // int numSiteTable = s.numSiteTable();
249 // user_arg<T,T1,Op,RHS> a(dest, rhs, op, s.siteTable().slice());
250 // dispatch_to_threads< user_arg<T,T1,Op,RHS> >(numSiteTable, a, evaluate_userfunc);
251
253 // Original code
255
256 //QDP_info("eval_F %d sites",s.numSiteTable());
257
258 // General form of loop structure
259 const int *tab = s.siteTable().slice();
260
261#pragma omp parallel for
262 for(int j=0; j < s.numSiteTable(); ++j)
263 {
264 int i = tab[j];
265 //fprintf(stderr,"eval(olattice,olattice): site %d\n",i);
266 op( dest[j], forEach(rhs, EvalLeaf1(i), OpCombine()));
267 }
268
269#if defined(QDP_USE_PROFILING)
270 prof.time += getClockTime();
271 prof.count++;
272 prof.print();
273#endif
274}
275
276
277//-----------------------------------------------------------------------------
279template<class T1, class T2>
280void
281copymask(OSubLattice<T2> d, const OLattice<T1>& mask, const OLattice<T2>& s1)
282{
283 OLattice<T2>& dest = d.field();
284 const Subset& s = d.subset();
285
286 const int *tab = s.siteTable().slice();
287#pragma omp parallel for
288 for(int j=0; j < s.numSiteTable(); ++j)
289 {
290 int i = tab[j];
291 copymask(dest.elem(i), mask.elem(i), s1.elem(i));
292 }
293}
294
295
297template<class T1, class T2>
298void
299copymask(OLattice<T2>& dest, const OLattice<T1>& mask, const OLattice<T2>& s1)
300{
301 const int vvol = Layout::vol();
302
303#pragma omp parallel for
304 for(int i=0; i < vvol; ++i)
305 copymask(dest.elem(i), mask.elem(i), s1.elem(i));
306}
307
308
309
310//-----------------------------------------------------------------------------
311// Random numbers
312namespace RNG
313{
314 extern Seed ran_seed;
315 extern Seed ran_mult;
316 extern Seed ran_mult_n;
318}
319
320
322
323template<class T>
324void
326{
327 Seed seed = RNG::ran_seed;
328 Seed skewed_seed = RNG::ran_seed * RNG::ran_mult;
329
330 fill_random(d.elem(), seed, skewed_seed, RNG::ran_mult);
331
332 RNG::ran_seed = seed; // The seed from any site is the same as the new global seed
333}
334
335
337template<class T>
338void
339random(OLattice<T>& d, const Subset& s)
340{
341 // Grab table array
342 const int *tab = s.siteTable().slice();
343
344#pragma omp parallel
345 {
346 Seed seed;
347 Seed skewed_seed;
348
349#pragma omp for // need the barrier to avoid that RNG::ran_seed is changed too early
350 for(int j=0; j < s.numSiteTable(); ++j) {
351 int i = tab[j];
352 seed = RNG::ran_seed;
353 skewed_seed.elem() = RNG::ran_seed.elem() * RNG::lattice_ran_mult->elem(i);
354 fill_random(d.elem(i), seed, skewed_seed, RNG::ran_mult_n);
355 }
356
357#pragma omp critical (random)
358 {
359 RNG::ran_seed = seed; // The seed from any site is the same as the new global seed
360 }
361 }
362
363}
364
365
367template<class T>
368void random(OSubLattice<T> dd)
369{
370 OLattice<T>& d = dd.field();
371 const Subset& s = dd.subset();
372
373 random(d,s);
374}
375
376
378template<class T>
379void random(OLattice<T>& d)
380{
381 random(d,all);
382}
383
384
386template<class T>
387void gaussian(OLattice<T>& d, const Subset& s)
388{
389 OLattice<T> r1, r2;
390
391 random(r1,s);
392 random(r2,s);
393
394 const int *tab = s.siteTable().slice();
395
396#pragma omp parallel for
397 for(int j=0; j < s.numSiteTable(); ++j)
398 {
399 int i = tab[j];
400 fill_gaussian(d.elem(i), r1.elem(i), r2.elem(i));
401 }
402}
403
404
405
407template<class T>
409{
410 OLattice<T>& d = dd.field();
411 const Subset& s = dd.subset();
412
413 gaussian(d,s);
414}
415
416
418template<class T>
419void gaussian(OLattice<T>& d)
420{
421 gaussian(d,all);
422}
423
424
425
426//-----------------------------------------------------------------------------
427// Broadcast operations
429template<class T>
430void zero_rep(OLattice<T>& dest, const Subset& s)
431{
432 const int *tab = s.siteTable().slice();
433
434#pragma omp parallel for
435 for(int j=0; j < s.numSiteTable(); ++j)
436 {
437 int i = tab[j];
438 zero_rep(dest.elem(i));
439 }
440}
441
442
443#if 0
445template<class T, class S>
446void zero_rep(OSubLattice<T> dd)
447{
448 OLattice<T>& d = dd.field();
449 const Subset& s = dd.subset();
450
451 zero_rep(d,s);
452}
453#endif
454
456template<class T>
457void zero_rep(OLattice<T>& dest)
458{
459 const int vvol = Layout::vol();
460#pragma omp parallel for
461 for(int i=0; i < vvol; ++i)
462 zero_rep(dest.elem(i));
463}
464
465
466
467//-----------------------------------------------
468// Global sums
470
474template<class RHS, class T>
475typename UnaryReturn<OScalar<T>, FnSum>::Type_t
476sum(const QDPExpr<RHS,OScalar<T> >& s1, const Subset& s)
477{
478 typename UnaryReturn<OScalar<T>, FnSum>::Type_t d;
479
480#if defined(QDP_USE_PROFILING)
481 static QDPProfile_t prof(d, OpAssign(), FnSum(), s1);
482 prof.time -= getClockTime();
483#endif
484
485 evaluate(d,OpAssign(),s1,all); // since OScalar, no global sum needed
486
487#if defined(QDP_USE_PROFILING)
488 prof.time += getClockTime();
489 prof.count++;
490 prof.print();
491#endif
492
493 return d;
494}
495
496
498
502template<class RHS, class T>
503typename UnaryReturn<OScalar<T>, FnSum>::Type_t
504sum(const QDPExpr<RHS,OScalar<T> >& s1)
505{
506 typename UnaryReturn<OScalar<T>, FnSum>::Type_t d;
507
508#if defined(QDP_USE_PROFILING)
509 static QDPProfile_t prof(d, OpAssign(), FnSum(), s1);
510 prof.time -= getClockTime();
511#endif
512
513 evaluate(d,OpAssign(),s1,all);
514
515#if defined(QDP_USE_PROFILING)
516 prof.time += getClockTime();
517 prof.count++;
518 prof.print();
519#endif
520
521 return d;
522}
523
524
525
527
531template<class RHS, class T>
532typename UnaryReturn<OLattice<T>, FnSum>::Type_t
533sum(const QDPExpr<RHS,OLattice<T> >& s1, const Subset& s)
534{
535 typename UnaryReturn<OLattice<T>, FnSum>::Type_t d;
536
537#if defined(QDP_USE_PROFILING)
538 static QDPProfile_t prof(d, OpAssign(), FnSum(), s1);
539 prof.time -= getClockTime();
540#endif
541
542 // Must initialize to zero since we do not know if the loop will be entered
543 zero_rep(d.elem());
544
545 const int *tab = s.siteTable().slice();
546
547#pragma omp parallel
548 {
549 typename UnaryReturn<OLattice<T>, FnSum>::Type_t dthread;
550 zero_rep(dthread.elem());
551
552#pragma omp for nowait
553 for(int j=0; j < s.numSiteTable(); ++j) {
554
555 int i = tab[j];
556 dthread.elem() += forEach(s1, EvalLeaf1(i), OpCombine()); // SINGLE NODE VERSION FOR NOW
557 }
558
559#pragma omp critical
560 {
561 d.elem() += dthread.elem();
562 }
563
564 }
565
566#if defined(QDP_USE_PROFILING)
567 prof.time += getClockTime();
568 prof.count++;
569 prof.print();
570#endif
571
572 return d;
573}
574
575
577
581template<class RHS, class T>
582typename UnaryReturn<OLattice<T>, FnSum>::Type_t
583sum(const QDPExpr<RHS,OLattice<T> >& s1)
584{
585 typename UnaryReturn<OLattice<T>, FnSum>::Type_t d;
586
587#if defined(QDP_USE_PROFILING)
588 static QDPProfile_t prof(d, OpAssign(), FnSum(), s1);
589 prof.time -= getClockTime();
590#endif
591
592 // Loop always entered - could unroll
593 zero_rep(d.elem());
594
595 const int vvol = Layout::vol();
596
597#pragma omp parallel
598 {
599 typename UnaryReturn<OLattice<T>, FnSum>::Type_t dthread;
600 zero_rep(dthread.elem());
601
602#pragma omp for nowait
603 for(int i=0; i < vvol; ++i) {
604 dthread.elem() += forEach(s1, EvalLeaf1(i), OpCombine());
605 }
606
607#pragma omp critical
608 {
609 d.elem() += dthread.elem();
610 }
611 }
612
613#if defined(QDP_USE_PROFILING)
614 prof.time += getClockTime();
615 prof.count++;
616 prof.print();
617#endif
618
619 return d;
620}
621
622
623#if 0
625
629template<class RHS, class T>
630typename UnaryReturn<OLattice<T>, FnSum>::Type_t
631sum(const QDPExpr<RHS,OLattice<T> >& s1)
632{
633 typename UnaryReturn<OLattice<T>, FnSum>::Type_t d;
634
635#if defined(QDP_USE_PROFILING)
636 static QDPProfile_t prof(d, OpAssign(), FnSum(), s1);
637 prof.time -= getClockTime();
638#endif
639
640 // Loop always entered - could unroll
641 zero_rep(d.elem());
642 const int nodeSites = Layout::sitesOnNode();
643
644#pragma omp parallel
645 {
646 typename UnaryReturn<OLattice<T>, FnSum>::Type_t dthread;
647 zero_rep(dthread.elem());
648
649#pragma omp for nowait
650 for(int i=0; i < vvol; ++i) {
651 d.elem() += forEach(s1, EvalLeaf1(i), OpCombine()); // SINGLE NODE VERSION FOR NOW
652 }
653
654#pragma omp critical
655 {
656 d.elem() += dthread.elem();
657 }
658 }
659
660#if defined(QDP_USE_PROFILING)
661 prof.time += getClockTime();
662 prof.count++;
663 prof.print();
664#endif
665
666 return d;
667}
668#endif
669
670//-----------------------------------------------------------------------------
671// Multiple global sums
673
680template<class RHS, class T>
681typename UnaryReturn<OScalar<T>, FnSumMulti>::Type_t
682sumMulti(const QDPExpr<RHS,OScalar<T> >& s1, const Set& ss)
683{
684 typename UnaryReturn<OScalar<T>, FnSumMulti>::Type_t dest(ss.numSubsets());
685
686#if defined(QDP_USE_PROFILING)
687 static QDPProfile_t prof(dest[0], OpAssign(), FnSum(), s1);
688 prof.time -= getClockTime();
689#endif
690
691 // lazy - evaluate repeatedly
692 for(int i=0; i < ss.numSubsets(); ++i)
693 evaluate(dest[i],OpAssign(),s1,all);
694
695#if defined(QDP_USE_PROFILING)
696 prof.time += getClockTime();
697 prof.count++;
698 prof.print();
699#endif
700
701 return dest;
702}
703
704
706
714 template<class RHS, class T>
724
725 template<class RHS, class T>
726 void sumMultiKernel(int lo, int hi, int my_id, SumMultiOLatticeThreadArgs<RHS,T>* a)
727 {
728 const multi1d<int>& lat_color = a->lat_color;
729 const QDPExpr<RHS,OLattice<T> >& s=a->s;
731 for(int i=lo; i < hi; ++i) {
732 int j = lat_color[i];
733 (dest[my_id])[j].elem() += forEach(s, EvalLeaf1(i), OpCombine()); // SINGLE NODE VERSION FOR NOW
734 }
735 }
736
737template<class RHS, class T>
738typename UnaryReturn<OLattice<T>, FnSumMulti>::Type_t
739sumMulti(const QDPExpr<RHS,OLattice<T> >& s1, const Set& ss)
740{
741 typename UnaryReturn<OLattice<T>, FnSumMulti>::Type_t dest(ss.numSubsets());
742
743#if defined(QDP_USE_PROFILING)
744 static QDPProfile_t prof(dest[0], OpAssign(), FnSum(), s1);
745 prof.time -= getClockTime();
746#endif
747
748 multi1d< typename UnaryReturn<OLattice<T>, FnSumMulti>::Type_t > pdest(qdpNumThreads());
749
750 // Initialize result with zero
751 for(int thread=0; thread < qdpNumThreads(); ++thread) {
752 pdest[thread].resize(ss.numSubsets());
753
754 for(int k=0; k < ss.numSubsets(); ++k) {
755 zero_rep(pdest[thread][k]);
756 }
757 }
758
759 // Loop over all sites and accumulate based on the coloring
760 const multi1d<int>& lat_color = ss.latticeColoring();
761 SumMultiOLatticeThreadArgs<RHS,T> args(lat_color,s1,pdest);
762
763 const int vvol = Layout::vol();
765
766 for(int k=0; k< ss.numSubsets(); ++k) {
767 dest[k] = pdest[0][k];
768 }
769
770 for(int thread=1; thread < qdpNumThreads(); thread++) {
771 for(int k=0; k< ss.numSubsets(); ++k) {
772 dest[k] += pdest[thread][k];
773 }
774 }
775
776#if 0
777 for(int i=0; i < vvol; ++i)
778 {
779 int j = lat_color[i];
780 dest[j].elem() += forEach(s1, EvalLeaf1(i), OpCombine()); // SINGLE NODE VERSION FOR NOW
781 }
782#endif
783
784#if defined(QDP_USE_PROFILING)
785 prof.time += getClockTime();
786 prof.count++;
787 prof.print();
788#endif
789
790 return dest;
791}
792
793#if 0
794 // Original code
795template<class RHS, class T>
796typename UnaryReturn<OLattice<T>, FnSumMulti>::Type_t
797sumMulti(const QDPExpr<RHS,OLattice<T> >& s1, const Set& ss)
798{
799 typename UnaryReturn<OLattice<T>, FnSumMulti>::Type_t dest(ss.numSubsets());
800
801#if defined(QDP_USE_PROFILING)
802 static QDPProfile_t prof(dest[0], OpAssign(), FnSum(), s1);
803 prof.time -= getClockTime();
804#endif
805
806 // Initialize result with zero
807 for(int k=0; k < ss.numSubsets(); ++k)
808 zero_rep(dest[k]);
809
810 // Loop over all sites and accumulate based on the coloring
811 const multi1d<int>& lat_color = ss.latticeColoring();
812
813 const int vvol = Layout::vol();
814 for(int i=0; i < vvol; ++i)
815 {
816 int j = lat_color[i];
817 dest[j].elem() += forEach(s1, EvalLeaf1(i), OpCombine()); // SINGLE NODE VERSION FOR NOW
818 }
819
820#if defined(QDP_USE_PROFILING)
821 prof.time += getClockTime();
822 prof.count++;
823 prof.print();
824#endif
825
826 return dest;
827}
828#endif
829
830//-----------------------------------------------------------------------------
831// Multiple global sums
833
840template<class T>
842sumMulti(const multi1d< OScalar<T> >& s1, const Set& ss)
843{
845
846#if defined(QDP_USE_PROFILING)
847 static QDPProfile_t prof(dest(0,0), OpAssign(), FnSum(), s1);
848 prof.time -= getClockTime();
849#endif
850
851 // lazy - evaluate repeatedly
852 for(int i=0; i < dest.size1(); ++i)
853 for(int j=0; j < dest.size2(); ++j)
854 dest(j,i) = s1[j];
855
856#if defined(QDP_USE_PROFILING)
857 prof.time += getClockTime();
858 prof.count++;
859 prof.print();
860#endif
861
862 return dest;
863}
864
865
867
875template<class T>
876multi2d<typename UnaryReturn<OLattice<T>, FnSumMulti>::Type_t>
877sumMulti(const multi1d< OLattice<T> >& s1, const Set& ss)
878{
880
881#if defined(QDP_USE_PROFILING)
882 static QDPProfile_t prof(dest(0,0), OpAssign(), FnSum(), s1);
883 prof.time -= getClockTime();
884#endif
885
886 // Initialize result with zero
887 for(int i=0; i < dest.size1(); ++i)
888 for(int j=0; j < dest.size2(); ++j)
889 zero_rep(dest(j,i));
890
891 // Loop over all sites and accumulate based on the coloring
892 const multi1d<int>& lat_color = ss.latticeColoring();
893
894 const int vvol = Layout::vol();
895 for(int k=0; k < s1.size(); ++k)
896 {
897 const OLattice<T>& ss1 = s1[k];
898
899 for(int i=0; i < vvol; ++i)
900 {
901 int j = lat_color[i];
902 dest(k,j).elem() += ss1.elem(i);
903 }
904 }
905
906#if defined(QDP_USE_PROFILING)
907 prof.time += getClockTime();
908 prof.count++;
909 prof.print();
910#endif
911
912 return dest;
913}
914
915
916//-----------------------------------------------------------------------------
918
924template<class T>
925inline typename UnaryReturn<OScalar<T>, FnNorm2>::Type_t
926norm2(const multi1d< OScalar<T> >& s1)
927{
928 typename UnaryReturn<OScalar<T>, FnNorm2>::Type_t d;
929
930#if defined(QDP_USE_PROFILING)
931 static QDPProfile_t prof(d, OpAssign(), FnNorm2(), s1[0]);
932 prof.time -= getClockTime();
933#endif
934
935 // Possibly loop entered
936 zero_rep(d.elem());
937
938 for(int n=0; n < s1.size(); ++n)
939 {
940 OScalar<T>& ss1 = s1[n];
941 d.elem() += localNorm2(ss1.elem());
942 }
943
944#if defined(QDP_USE_PROFILING)
945 prof.time += getClockTime();
946 prof.count++;
947 prof.print();
948#endif
949
950 return d;
951}
952
954
955template<class T>
956inline typename UnaryReturn<OScalar<T>, FnNorm2>::Type_t
957norm2(const multi1d< OScalar<T> >& s1, const Subset& s)
958{
959 return norm2(s1);
960}
961
962
963
965
971template<class T>
972inline typename UnaryReturn<OLattice<T>, FnNorm2>::Type_t
973norm2(const multi1d< OLattice<T> >& s1, const Subset& s)
974{
975 typename UnaryReturn<OLattice<T>, FnNorm2>::Type_t d;
976
977#if defined(QDP_USE_PROFILING)
978 static QDPProfile_t prof(d, OpAssign(), FnNorm2(), s1[0]);
979 prof.time -= getClockTime();
980#endif
981
982 // Possibly loop entered
983 zero_rep(d.elem());
984
985 const int *tab = s.siteTable().slice();
986
987 for(int n=0; n < s1.size(); ++n) {
988
989 const OLattice<T>& ss1 = s1[n];
990
991#pragma omp parallel
992 {
993 typename UnaryReturn<OLattice<T>, FnNorm2>::Type_t dthread;
994 zero_rep(dthread.elem());
995
996#pragma omp for
997 for(int j=0; j < s.numSiteTable(); ++j) {
998
999 int i = tab[j];
1000 dthread.elem() += localNorm2(ss1.elem(i));
1001 }
1002
1003#pragma omp critical
1004 {
1005 d.elem() += dthread.elem();
1006 }
1007 }
1008 }
1009
1010
1011#if defined(QDP_USE_PROFILING)
1012 prof.time += getClockTime();
1013 prof.count++;
1014 prof.print();
1015#endif
1016
1017 return d;
1018}
1019
1020
1021
1023
1029template<class T>
1030inline typename UnaryReturn<OLattice<T>, FnNorm2>::Type_t
1031norm2(const multi1d< OLattice<T> >& s1)
1032{
1033 return norm2(s1,all);
1034}
1035
1036
1037
1038//-----------------------------------------------------------------------------
1040
1046template<class T1, class T2>
1047inline typename BinaryReturn<OScalar<T1>, OScalar<T2>, FnInnerProduct>::Type_t
1048innerProduct(const multi1d< OScalar<T1> >& s1, const multi1d< OScalar<T2> >& s2)
1049{
1051
1052#if defined(QDP_USE_PROFILING)
1053 static QDPProfile_t prof(d, OpAssign(), FnInnerProduct(), s1[0]);
1054 prof.time -= getClockTime();
1055#endif
1056
1057 // Possibly loop entered
1058 zero_rep(d.elem());
1059
1060 for(int n=0; n < s1.size(); ++n)
1061 {
1062 OScalar<T1>& ss1 = s1[n];
1063 OScalar<T2>& ss2 = s2[n];
1064 d.elem() += localInnerProduct(ss1.elem(),ss2.elem());
1065 }
1066
1067#if defined(QDP_USE_PROFILING)
1068 prof.time += getClockTime();
1069 prof.count++;
1070 prof.print();
1071#endif
1072
1073 return d;
1074}
1075
1077
1078template<class T1, class T2>
1079inline typename BinaryReturn<OScalar<T1>, OScalar<T2>, FnInnerProduct>::Type_t
1080innerProduct(const multi1d< OScalar<T1> >& s1, const multi1d< OScalar<T2> >& s2,
1081 const Subset& s)
1082{
1083 return innerProduct(s1,s2);
1084}
1085
1086
1088
1094template<class T1, class T2>
1095inline typename BinaryReturn<OLattice<T1>, OLattice<T2>, FnInnerProduct>::Type_t
1096innerProduct(const multi1d< OLattice<T1> >& s1, const multi1d< OLattice<T2> >& s2,
1097 const Subset& s)
1098{
1100
1101#if defined(QDP_USE_PROFILING)
1102 static QDPProfile_t prof(d, OpAssign(), FnInnerProduct(), s1[0]);
1103 prof.time -= getClockTime();
1104#endif
1105
1106 // Possibly loop entered
1107 zero_rep(d.elem());
1108
1109 const int *tab = s.siteTable().slice();
1110
1111 for(int n=0; n < s1.size(); ++n) {
1112 const OLattice<T1>& ss1 = s1[n];
1113 const OLattice<T2>& ss2 = s2[n];
1114
1115#pragma omp parallel
1116 {
1117 typename BinaryReturn<OLattice<T1>, OLattice<T2>, FnInnerProduct>::Type_t dthread;
1118 zero_rep(dthread.elem());
1119
1120#pragma omp for
1121 for(int j=0; j < s.numSiteTable(); ++j)
1122 {
1123 int i = tab[j];
1124 dthread.elem() += localInnerProduct(ss1.elem(i),ss2.elem(i));
1125 }
1126#pragma omp critical
1127 {
1128 d.elem() += dthread.elem();
1129 }
1130 }
1131 }
1132
1133#if defined(QDP_USE_PROFILING)
1134 prof.time += getClockTime();
1135 prof.count++;
1136 prof.print();
1137#endif
1138
1139 return d;
1140}
1141
1142
1144
1150template<class T1, class T2>
1151inline typename BinaryReturn<OLattice<T1>, OLattice<T2>, FnInnerProduct>::Type_t
1152innerProduct(const multi1d< OLattice<T1> >& s1, const multi1d< OLattice<T2> >& s2)
1153{
1154 return innerProduct(s1,s2,all);
1155}
1156
1157
1158
1159//-----------------------------------------------------------------------------
1161
1167template<class T1, class T2>
1169innerProductReal(const multi1d< OScalar<T1> >& s1, const multi1d< OScalar<T2> >& s2)
1170{
1172
1173#if defined(QDP_USE_PROFILING)
1174 static QDPProfile_t prof(d, OpAssign(), FnInnerProductReal(), s1[0]);
1175 prof.time -= getClockTime();
1176#endif
1177
1178 // Possibly loop entered
1179 zero_rep(d.elem());
1180
1181 for(int n=0; n < s1.size(); ++n)
1182 {
1183 OScalar<T1>& ss1 = s1[n];
1184 OScalar<T2>& ss2 = s2[n];
1185 d.elem() += localInnerProductReal(ss1.elem(),ss2.elem());
1186 }
1187
1188#if defined(QDP_USE_PROFILING)
1189 prof.time += getClockTime();
1190 prof.count++;
1191 prof.print();
1192#endif
1193
1194 return d;
1195}
1196
1198
1199template<class T1, class T2>
1201innerProductReal(const multi1d< OScalar<T1> >& s1, const multi1d< OScalar<T2> >& s2,
1202 const Subset& s)
1203{
1204 return innerProductReal(s1,s2);
1205}
1206
1207
1208
1210
1216template<class T1, class T2>
1218innerProductReal(const multi1d< OLattice<T1> >& s1, const multi1d< OLattice<T2> >& s2,
1219 const Subset& s)
1220{
1222
1223#if defined(QDP_USE_PROFILING)
1224 static QDPProfile_t prof(d, OpAssign(), FnInnerProductReal(), s1[0]);
1225 prof.time -= getClockTime();
1226#endif
1227
1228 // Possibly loop entered
1229 zero_rep(d.elem());
1230
1231 const int *tab = s.siteTable().slice();
1232
1233 for(int n=0; n < s1.size(); ++n) {
1234
1235 const OLattice<T1>& ss1 = s1[n];
1236 const OLattice<T2>& ss2 = s2[n];
1237
1238#pragma omp parallel
1239 {
1240 typename BinaryReturn<OLattice<T1>, OLattice<T2>, FnInnerProductReal>::Type_t dthread;
1241 zero_rep(dthread.elem());
1242
1243#pragma omp for
1244 for(int j=0; j < s.numSiteTable(); ++j)
1245 {
1246 int i = tab[j];
1247 dthread.elem() += localInnerProductReal(ss1.elem(i),ss2.elem(i));
1248 }
1249#pragma omp critical
1250 {
1251 d.elem() += dthread.elem();
1252 }
1253 }
1254 }
1255
1256#if defined(QDP_USE_PROFILING)
1257 prof.time += getClockTime();
1258 prof.count++;
1259 prof.print();
1260#endif
1261
1262 return d;
1263}
1264
1265
1267
1273template<class T1, class T2>
1275innerProductReal(const multi1d< OLattice<T1> >& s1, const multi1d< OLattice<T2> >& s2)
1276{
1277 return innerProductReal(s1,s2,all);
1278}
1279
1280
1281//-----------------------------------------------
1282// Global max and min
1283// NOTE: there are no subset version of these operations. It is very problematic
1284// and QMP does not support them.
1286
1289template<class RHS, class T>
1290typename UnaryReturn<OScalar<T>, FnGlobalMax>::Type_t
1291globalMax(const QDPExpr<RHS,OScalar<T> >& s1)
1292{
1293 typename UnaryReturn<OScalar<T>, FnGlobalMax>::Type_t d;
1294
1295#if defined(QDP_USE_PROFILING)
1296 static QDPProfile_t prof(d, OpAssign(), FnGlobalMax(), s1);
1297 prof.time -= getClockTime();
1298#endif
1299
1300 evaluate(d,OpAssign(),s1,all); // since OScalar, no global max needed
1301
1302#if defined(QDP_USE_PROFILING)
1303 prof.time += getClockTime();
1304 prof.count++;
1305 prof.print();
1306#endif
1307
1308 return d;
1309}
1310
1311
1312
1314
1317template<class RHS, class T>
1318typename UnaryReturn<OLattice<T>, FnGlobalMax>::Type_t
1319globalMax(const QDPExpr<RHS,OLattice<T> >& s1)
1320{
1321 typename UnaryReturn<OLattice<T>, FnGlobalMax>::Type_t d;
1322
1323#if defined(QDP_USE_PROFILING)
1324 static QDPProfile_t prof(d, OpAssign(), FnGlobalMax(), s1);
1325 prof.time -= getClockTime();
1326#endif
1327
1328 // Loop always entered so unroll
1329 d.elem() = forEach(s1, EvalLeaf1(0), OpCombine()); // SINGLE NODE VERSION FOR NOW
1330
1331 const int vvol = Layout::vol();
1332 for(int i=1; i < vvol; ++i)
1333 {
1335 forEach(s1, EvalLeaf1(i), OpCombine()); // SINGLE NODE VERSION FOR NOW
1336
1337 if (toBool(dd > d.elem()))
1338 d.elem() = dd;
1339 }
1340
1341#if defined(QDP_USE_PROFILING)
1342 prof.time += getClockTime();
1343 prof.count++;
1344 prof.print();
1345#endif
1346
1347 return d;
1348}
1349
1350
1352
1355template<class RHS, class T>
1356typename UnaryReturn<OScalar<T>, FnGlobalMin>::Type_t
1357globalMin(const QDPExpr<RHS,OScalar<T> >& s1)
1358{
1359 typename UnaryReturn<OScalar<T>, FnGlobalMin>::Type_t d;
1360
1361#if defined(QDP_USE_PROFILING)
1362 static QDPProfile_t prof(d, OpAssign(), FnGlobalMin(), s1);
1363 prof.time -= getClockTime();
1364#endif
1365
1366 evaluate(d,OpAssign(),s1,all); // since OScalar, no global min needed
1367
1368#if defined(QDP_USE_PROFILING)
1369 prof.time += getClockTime();
1370 prof.count++;
1371 prof.print();
1372#endif
1373
1374 return d;
1375}
1376
1377
1378
1380
1383template<class RHS, class T>
1384typename UnaryReturn<OLattice<T>, FnGlobalMin>::Type_t
1385globalMin(const QDPExpr<RHS,OLattice<T> >& s1)
1386{
1387 typename UnaryReturn<OLattice<T>, FnGlobalMin>::Type_t d;
1388
1389#if defined(QDP_USE_PROFILING)
1390 static QDPProfile_t prof(d, OpAssign(), FnGlobalMin(), s1);
1391 prof.time -= getClockTime();
1392#endif
1393
1394 // Loop always entered so unroll
1395 d.elem() = forEach(s1, EvalLeaf1(0), OpCombine()); // SINGLE NODE VERSION FOR NOW
1396
1397 const int vvol = Layout::vol();
1398 for(int i=1; i < vvol; ++i)
1399 {
1401 forEach(s1, EvalLeaf1(i), OpCombine()); // SINGLE NODE VERSION FOR NOW
1402
1403 if (toBool(dd < d.elem()))
1404 d.elem() = dd;
1405 }
1406
1407#if defined(QDP_USE_PROFILING)
1408 prof.time += getClockTime();
1409 prof.count++;
1410 prof.print();
1411#endif
1412
1413 return d;
1414}
1415
1416
1417//-----------------------------------------------
1418// Test badness/goodness of floating point numbers.
1419// These functions always return bool
1421
1424template<class T>
1425inline bool
1426isnan(const QDPType<T,OScalar<T> >& s1)
1427{
1428 return isnan(s1.elem());
1429}
1430
1431
1433
1436template<class T>
1437inline bool
1438isnan(const OLattice<T>& s1)
1439{
1440 bool d = false;
1441
1442#if defined(QDP_USE_PROFILING)
1443 static QDPProfile_t prof(d, OpAssign(), FnIsNan(), s1);
1444 prof.time -= getClockTime();
1445#endif
1446
1447 const int vvol = Layout::vol();
1448 for(int i=0; i < vvol; ++i)
1449 {
1450 d |= isnan(s1.elem(i));
1451 }
1452
1454
1455#if defined(QDP_USE_PROFILING)
1456 prof.time += getClockTime();
1457 prof.count++;
1458 prof.print();
1459#endif
1460
1461 return d;
1462}
1463
1464
1466
1469template<class T>
1470inline bool
1471isinf(const QDPType<T,OScalar<T> >& s1)
1472{
1473 return isinf(s1.elem());
1474}
1475
1476
1478
1481template<class T>
1482inline bool
1483isinf(const OLattice<T>& s1)
1484{
1485 bool d = false;
1486
1487#if defined(QDP_USE_PROFILING)
1488 static QDPProfile_t prof(d, OpAssign(), FnIsInf(), s1);
1489 prof.time -= getClockTime();
1490#endif
1491
1492 const int vvol = Layout::vol();
1493 for(int i=0; i < vvol; ++i)
1494 {
1495 d |= isinf(s1.elem(i));
1496 }
1497
1499
1500#if defined(QDP_USE_PROFILING)
1501 prof.time += getClockTime();
1502 prof.count++;
1503 prof.print();
1504#endif
1505
1506 return d;
1507}
1508
1509
1511
1514template<class T>
1515inline bool
1516isfinite(const QDPType<T,OScalar<T> >& s1)
1517{
1518 return isfinite(s1.elem());
1519}
1520
1521
1523
1526template<class T>
1527inline bool
1528isfinite(const OLattice<T>& s1)
1529{
1530 bool d = true;
1531
1532#if defined(QDP_USE_PROFILING)
1533 static QDPProfile_t prof(d, OpAssign(), FnIsFinite(), s1);
1534 prof.time -= getClockTime();
1535#endif
1536
1537 const int vvol = Layout::vol();
1538 for(int i=0; i < vvol; ++i)
1539 {
1540 d &= isfinite(s1.elem(i));
1541 }
1542
1544
1545#if defined(QDP_USE_PROFILING)
1546 prof.time += getClockTime();
1547 prof.count++;
1548 prof.print();
1549#endif
1550
1551 return d;
1552}
1553
1554
1556
1559template<class T>
1560inline bool
1561isnormal(const QDPType<T,OScalar<T> >& s1)
1562{
1563 return isnormal(s1.elem());
1564}
1565
1566
1568
1571template<class T>
1572inline bool
1573isnormal(const OLattice<T>& s1)
1574{
1575 bool d = true;
1576
1577#if defined(QDP_USE_PROFILING)
1578 static QDPProfile_t prof(d, OpAssign(), FnIsNormal(), s1);
1579 prof.time -= getClockTime();
1580#endif
1581
1582 const int vvol = Layout::vol();
1583 for(int i=0; i < vvol; ++i)
1584 {
1585 d &= isnormal(s1.elem(i));
1586 }
1587
1589
1590#if defined(QDP_USE_PROFILING)
1591 prof.time += getClockTime();
1592 prof.count++;
1593 prof.print();
1594#endif
1595
1596 return d;
1597}
1598
1599
1600//-----------------------------------------------------------------------------
1601// Peek and poke at individual sites. This is very architecture specific
1602// NOTE: these two routines assume there is no underlying inner grid
1603
1605
1611template<class T1>
1612inline OScalar<T1>
1613peekSite(const OScalar<T1>& l, const multi1d<int>& coord)
1614{
1615 return l;
1616}
1617
1619
1625template<class RHS, class T1>
1626inline OScalar<T1>
1627peekSite(const QDPExpr<RHS,OScalar<T1> > & l, const multi1d<int>& coord)
1628{
1629 // For now, simply evaluate the expression and then call the function
1630 typedef OScalar<T1> C1;
1631
1632 return peekSite(C1(l), coord);
1633}
1634
1635
1637
1643template<class T1>
1644inline OScalar<T1>
1645peekSite(const OLattice<T1>& l, const multi1d<int>& coord)
1646{
1647 OScalar<T1> dest;
1648
1649 dest.elem() = l.elem(Layout::linearSiteIndex(coord));
1650 return dest;
1651}
1652
1654
1660template<class RHS, class T1>
1661inline OScalar<T1>
1662peekSite(const QDPExpr<RHS,OLattice<T1> > & l, const multi1d<int>& coord)
1663{
1664 // For now, simply evaluate the expression and then call the function
1665 typedef OLattice<T1> C1;
1666
1667 return peekSite(C1(l), coord);
1668}
1669
1670
1672
1679template<class T1>
1680inline OLattice<T1>&
1682{
1683 l.elem(Layout::linearSiteIndex(coord)) = r.elem();
1684 return l;
1685}
1686
1687
1689
1695template<class T>
1696inline void
1697QDP_extract(multi1d<OScalar<T> >& dest, const OLattice<T>& src, const Subset& s)
1698{
1699 const int *tab = s.siteTable().slice();
1700
1701#pragma omp parallel for
1702 for(int j=0; j < s.numSiteTable(); ++j)
1703 {
1704 int i = tab[j];
1705 dest[i].elem() = src.elem(i);
1706 }
1707}
1708
1710
1716template<class T>
1717inline void
1718QDP_insert(OLattice<T>& dest, const multi1d<OScalar<T> >& src, const Subset& s)
1719{
1720 const int *tab = s.siteTable().slice();
1721
1722#pragma omp parallel for
1723 for(int j=0; j < s.numSiteTable(); ++j)
1724 {
1725 int i = tab[j];
1726 dest.elem(i) = src[i].elem();
1727 }
1728}
1729
1730
1731//-----------------------------------------------------------------------------
1732// This is the PETE version of a map, namely return an expression
1733struct FnMap
1734{
1736
1737 const int *goff;
1738 FnMap(const int *goffsets): goff(goffsets)
1739 {
1740// fprintf(stderr,"FnMap(): goff=0x%x\n",goff);
1741 }
1742
1743 template<class T>
1744 inline typename UnaryReturn<T, FnMap>::Type_t
1745 operator()(const T &a) const
1746 {
1747 return (a);
1748 }
1749};
1750
1751
1752#if defined(QDP_USE_PROFILING)
1753template <>
1754struct TagVisitor<FnMap, PrintTag> : public ParenPrinter<FnMap>
1755{
1756 static void visit(FnMap op, PrintTag t)
1757 { t.os_m << "shift"; }
1758};
1759#endif
1760
1761
1762// Specialization of ForEach deals with maps.
1763template<class A, class CTag>
1765{
1768 inline static
1770 const CTag &c)
1771 {
1772 EvalLeaf1 ff(expr.operation().goff[f.val1()]);
1773// fprintf(stderr,"ForEach<Unary<FnMap>>: site = %d, new = %d\n",f.val1(),ff.val1());
1774
1777 expr.operation(), c);
1778 }
1779};
1780
1781
1782
1783//-----------------------------------------------------------------------------
1785class Map
1786{
1787public:
1789 Map() {}
1790
1792 ~Map() {}
1793
1795 Map(const MapFunc& fn) {make(fn);}
1796
1798
1799 void make(const MapFunc& func);
1800
1802
1811 template<class T1,class C1>
1812 inline typename MakeReturn<UnaryNode<FnMap,
1813 typename CreateLeaf<QDPType<T1,C1> >::Leaf_t>, C1>::Expression_t
1815 {
1816 typedef UnaryNode<FnMap,
1817 typename CreateLeaf<QDPType<T1,C1> >::Leaf_t> Tree_t;
1818 return MakeReturn<Tree_t,C1>::make(Tree_t(FnMap(goffsets.slice()),
1820 }
1821
1822
1823 template<class T1,class C1>
1824 inline typename MakeReturn<UnaryNode<FnMap,
1825 typename CreateLeaf<QDPExpr<T1,C1> >::Leaf_t>, C1>::Expression_t
1827 {
1828 typedef UnaryNode<FnMap,
1829 typename CreateLeaf<QDPExpr<T1,C1> >::Leaf_t> Tree_t;
1830 return MakeReturn<Tree_t,C1>::make(Tree_t(FnMap(goffsets.slice()),
1832 }
1833
1834
1835public:
1837 const multi1d<int>& Offsets() const {return goffsets;}
1838
1839private:
1841 Map(const Map&) {}
1842
1844 void operator=(const Map&) {}
1845
1846private:
1848 multi1d<int> goffsets;
1849};
1850
1851
1852//-----------------------------------------------------------------------------
1854class ArrayMap
1855{
1856public:
1859
1862
1864 ArrayMap(const ArrayMapFunc& fn) {make(fn);}
1865
1867
1868 void make(const ArrayMapFunc& func);
1869
1871
1880 template<class T1,class C1>
1881 inline typename MakeReturn<UnaryNode<FnMap,
1882 typename CreateLeaf<QDPType<T1,C1> >::Leaf_t>, C1>::Expression_t
1883 operator()(const QDPType<T1,C1> & l, int dir)
1884 {
1885 typedef UnaryNode<FnMap,
1886 typename CreateLeaf<QDPType<T1,C1> >::Leaf_t> Tree_t;
1887 return MakeReturn<Tree_t,C1>::make(Tree_t(FnMap(mapsa[dir].Offsets().slice()),
1889 }
1890
1891
1892 template<class T1,class C1>
1893 inline typename MakeReturn<UnaryNode<FnMap,
1894 typename CreateLeaf<QDPExpr<T1,C1> >::Leaf_t>, C1>::Expression_t
1895 operator()(const QDPExpr<T1,C1> & l, int dir)
1896 {
1897 typedef UnaryNode<FnMap,
1898 typename CreateLeaf<QDPExpr<T1,C1> >::Leaf_t> Tree_t;
1899 return MakeReturn<Tree_t,C1>::make(Tree_t(FnMap(mapsa[dir].Offsets().slice()),
1901 }
1902
1903
1904private:
1906 ArrayMap(const ArrayMap&) {}
1907
1909 void operator=(const ArrayMap&) {}
1910
1911private:
1912 multi1d<Map> mapsa;
1913
1914};
1915
1916
1917//-----------------------------------------------------------------------------
1919class BiDirectionalMap
1920{
1921public:
1924
1927
1930
1932
1933 void make(const MapFunc& func);
1934
1936
1945 template<class T1,class C1>
1946 inline typename MakeReturn<UnaryNode<FnMap,
1947 typename CreateLeaf<QDPType<T1,C1> >::Leaf_t>, C1>::Expression_t
1948 operator()(const QDPType<T1,C1> & l, int isign)
1949 {
1950 typedef UnaryNode<FnMap,
1951 typename CreateLeaf<QDPType<T1,C1> >::Leaf_t> Tree_t;
1952 return MakeReturn<Tree_t,C1>::make(Tree_t(FnMap(bimaps[(isign+1)>>1].Offsets().slice()),
1954 }
1955
1956
1957 template<class T1,class C1>
1958 inline typename MakeReturn<UnaryNode<FnMap,
1959 typename CreateLeaf<QDPExpr<T1,C1> >::Leaf_t>, C1>::Expression_t
1960 operator()(const QDPExpr<T1,C1> & l, int isign)
1961 {
1962 typedef UnaryNode<FnMap,
1963 typename CreateLeaf<QDPExpr<T1,C1> >::Leaf_t> Tree_t;
1964 return MakeReturn<Tree_t,C1>::make(Tree_t(FnMap(bimaps[(isign+1)>>1].Offsets().slice()),
1966 }
1967
1968
1969private:
1972
1974 void operator=(const BiDirectionalMap&) {}
1975
1976private:
1977 multi1d<Map> bimaps;
1978
1979};
1980
1981
1982//-----------------------------------------------------------------------------
1985{
1986public:
1989
1992
1995
1997
1998 void make(const ArrayMapFunc& func);
1999
2001
2010 template<class T1,class C1>
2011 inline typename MakeReturn<UnaryNode<FnMap,
2012 typename CreateLeaf<QDPType<T1,C1> >::Leaf_t>, C1>::Expression_t
2013 operator()(const QDPType<T1,C1> & l, int isign, int dir)
2014 {
2015 typedef UnaryNode<FnMap,
2016 typename CreateLeaf<QDPType<T1,C1> >::Leaf_t> Tree_t;
2017 return MakeReturn<Tree_t,C1>::make(Tree_t(FnMap(bimapsa((isign+1)>>1,dir).Offsets().slice()),
2019 }
2020
2021
2022 template<class T1,class C1>
2023 inline typename MakeReturn<UnaryNode<FnMap,
2024 typename CreateLeaf<QDPExpr<T1,C1> >::Leaf_t>, C1>::Expression_t
2025 operator()(const QDPExpr<T1,C1> & l, int isign, int dir)
2026 {
2027 typedef UnaryNode<FnMap,
2028 typename CreateLeaf<QDPExpr<T1,C1> >::Leaf_t> Tree_t;
2029 return MakeReturn<Tree_t,C1>::make(Tree_t(FnMap(bimapsa((isign+1)>>1,dir).Offsets().slice()),
2031 }
2032
2033
2034private:
2037
2039 void operator=(const ArrayBiDirectionalMap&) {}
2040
2041private:
2042 multi2d<Map> bimapsa;
2043
2044};
2045
2046
2047//-----------------------------------------------------------------------------
2048// Input and output of various flavors that are architecture specific
2049
2051multi1d<int> crtesn(int ipos, const multi1d<int>& latt_size);
2052
2053#ifdef QDP_USE_LIBXML2
2055template<class T>
2057{
2058 xml.openTag("OLattice");
2059
2060 XMLWriterAPI::AttributeList alist;
2061
2062 const int vvol = Layout::vol();
2063 for(int site=0; site < vvol; ++site)
2064 {
2065 multi1d<int> coord = crtesn(site, Layout::lattSize());
2066 std::ostringstream os;
2067 os << coord[0];
2068 for(int i=1; i < coord.size(); ++i)
2069 os << " " << coord[i];
2070
2071 alist.clear();
2072 alist.push_back(XMLWriterAPI::Attribute("site", site));
2073 alist.push_back(XMLWriterAPI::Attribute("coord", os.str()));
2074
2075 xml.openTag("elem", alist);
2076 xml << d.elem(Layout::linearSiteIndex(site));
2077 xml.closeTag();
2078 }
2079
2080 xml.closeTag(); // OLattice
2081
2082 return xml;
2083}
2084#endif
2085
2086
2088
2089template<class T>
2090inline
2091void write(BinaryWriter& bin, const OScalar<T>& d)
2092{
2093 if (Layout::primaryNode())
2094 bin.writeArray((const char *)&(d.elem()),
2095 sizeof(typename WordType<T>::Type_t),
2096 sizeof(T) / sizeof(typename WordType<T>::Type_t));
2097}
2098
2100
2101template<class T>
2102void write(BinaryWriter& bin, const OLattice<T>& d)
2103{
2104 const int vvol = Layout::vol();
2105 for(int site=0; site < vvol; ++site)
2106 {
2107 int i = Layout::linearSiteIndex(site);
2108 bin.writeArray((const char*)&(d.elem(i)),
2109 sizeof(typename WordType<T>::Type_t),
2110 sizeof(T) / sizeof(typename WordType<T>::Type_t));
2111 }
2112}
2113
2115
2116template<class T>
2117void write(BinaryWriter& bin, OSubLattice<T> dd)
2118{
2119 // Single node code
2120 const Subset& sub = dd.subset();
2121 const Set& set = sub.getSet();
2122
2123 const OLattice<T>& d = dd.field();
2124
2125 const multi1d<int>& lat_color = set.latticeColoring();
2126 const int color = sub.color();
2127
2128 // Choose only this color within a lexicographic loop
2129 const int vvol = Layout::vol();
2130 for(int site=0; site < vvol; ++site)
2131 {
2132 int i = Layout::linearSiteIndex(site);
2133 if (lat_color[i] == color)
2134 {
2135 bin.writeArray((const char*)&(d.elem(i)),
2136 sizeof(typename WordType<T>::Type_t),
2137 sizeof(T) / sizeof(typename WordType<T>::Type_t));
2138 }
2139 }
2140}
2141
2143
2144template<class T>
2145void write(BinaryWriter& bin, const OLattice<T>& d, const multi1d<int>& coord)
2146{
2147 int i = Layout::linearSiteIndex(coord);
2148 bin.writeArray((const char*)&(d.elem(i)),
2149 sizeof(typename WordType<T>::Type_t),
2150 sizeof(T) / sizeof(typename WordType<T>::Type_t));
2151}
2152
2154
2155template<class T>
2156void read(BinaryReader& bin, OScalar<T>& d)
2157{
2158 bin.readArray((char*)&(d.elem()),
2159 sizeof(typename WordType<T>::Type_t),
2160 sizeof(T) / sizeof(typename WordType<T>::Type_t));
2161}
2162
2164
2165template<class T>
2166void read(BinaryReader& bin, OLattice<T>& d)
2167{
2168 const int vvol = Layout::vol();
2169 for(int site=0; site < vvol; ++site)
2170 {
2171 int i = Layout::linearSiteIndex(site);
2172 bin.readArray((char*)&(d.elem(i)),
2173 sizeof(typename WordType<T>::Type_t),
2174 sizeof(T) / sizeof(typename WordType<T>::Type_t));
2175 }
2176}
2177
2179
2180template<class T>
2181void read(BinaryReader& bin, OLattice<T>& d, const multi1d<int>& coord)
2182{
2183 int i = Layout::linearSiteIndex(coord);
2184 bin.readArray((char*)&(d.elem(i)),
2185 sizeof(typename WordType<T>::Type_t),
2186 sizeof(T) / sizeof(typename WordType<T>::Type_t));
2187}
2188
2190
2191template<class T>
2192void read(BinaryReader& bin, OSubLattice<T> dd)
2193{
2194 // Single node code
2195 const Subset& sub = dd.subset();
2196 const Set& set = sub.getSet();
2197
2198 OLattice<T>& d = dd.field();
2199
2200 const multi1d<int>& lat_color = set.latticeColoring();
2201 const int color = sub.color();
2202
2203 // Choose only this color within a lexicographic loop
2204 const int vvol = Layout::vol();
2205 for(int site=0; site < vvol; ++site)
2206 {
2207 int i = Layout::linearSiteIndex(site);
2208 if (lat_color[i] == color)
2209 {
2210 bin.readArray((char*)&(d.elem(i)),
2211 sizeof(typename WordType<T>::Type_t),
2212 sizeof(T) / sizeof(typename WordType<T>::Type_t));
2213 }
2214 }
2215}
2216
2217// **************************************************************
2218// Special support for slices of a lattice
2219namespace LatticeTimeSliceIO
2220{
2221 template<class T>
2222 void readSlice(BinaryReader& bin, OLattice<T>& data,
2223 int start_lexico, int stop_lexico)
2224 {
2225 for(int site=start_lexico; site < stop_lexico; ++site)
2226 {
2227 int i = Layout::linearSiteIndex(site);
2228 bin.readArray((char*)&(data.elem(i)),
2229 sizeof(typename WordType<T>::Type_t),
2230 sizeof(T) / sizeof(typename WordType<T>::Type_t));
2231 }
2232 }
2233
2234 template<class T>
2236 int start_lexico, int stop_lexico)
2237 {
2238 for(int site=start_lexico; site < stop_lexico; ++site)
2239 {
2240 int i = Layout::linearSiteIndex(site);
2241 bin.writeArray((const char*)&(data.elem(i)),
2242 sizeof(typename WordType<T>::Type_t),
2243 sizeof(T) / sizeof(typename WordType<T>::Type_t));
2244 }
2245 }
2246
2247} // namespace LatticeTimeSliceIO
2248} // namespace QDP
2249
2250#endif
ForEach< Expr, FTag, CTag >::Type_t forEach(const Expr &e, const FTag &f, const CTag &c)
Definition ForEach.h:87
#define PETE_EMPTY_CONSTRUCTORS(CLASS)
Definition PETE.h:58
ArrayBiDirectional of general permutation map class for communications.
void make(const ArrayMapFunc &func)
Actual constructor from a function object.
Definition qdp_map.cc:153
ArrayBiDirectionalMap(const ArrayMapFunc &fn)
Constructor from a function object.
MakeReturn< UnaryNode< FnMap, typenameCreateLeaf< QDPType< T1, C1 > >::Leaf_t >, C1 >::Expression_t operator()(const QDPType< T1, C1 > &l, int isign, int dir)
Function call operator for a shift.
ArrayBiDirectionalMap()
Constructor - does nothing really.
MakeReturn< UnaryNode< FnMap, typenameCreateLeaf< QDPExpr< T1, C1 > >::Leaf_t >, C1 >::Expression_t operator()(const QDPExpr< T1, C1 > &l, int isign, int dir)
ArrayMapFunc.
Definition qdp_map.h:45
Array of general permutation map class for communications.
ArrayMap()
Constructor - does nothing really.
ArrayMap(const ArrayMapFunc &fn)
Constructor from a function object.
MakeReturn< UnaryNode< FnMap, typenameCreateLeaf< QDPType< T1, C1 > >::Leaf_t >, C1 >::Expression_t operator()(const QDPType< T1, C1 > &l, int dir)
Function call operator for a shift.
MakeReturn< UnaryNode< FnMap, typenameCreateLeaf< QDPExpr< T1, C1 > >::Leaf_t >, C1 >::Expression_t operator()(const QDPExpr< T1, C1 > &l, int dir)
void make(const ArrayMapFunc &func)
Actual constructor from a function object.
Definition qdp_map.cc:74
BiDirectional of general permutation map class for communications.
MakeReturn< UnaryNode< FnMap, typenameCreateLeaf< QDPType< T1, C1 > >::Leaf_t >, C1 >::Expression_t operator()(const QDPType< T1, C1 > &l, int isign)
Function call operator for a shift.
void make(const MapFunc &func)
Actual constructor from a function object.
Definition qdp_map.cc:114
MakeReturn< UnaryNode< FnMap, typenameCreateLeaf< QDPExpr< T1, C1 > >::Leaf_t >, C1 >::Expression_t operator()(const QDPExpr< T1, C1 > &l, int isign)
BiDirectionalMap(const MapFunc &fn)
Constructor from a function object.
BiDirectionalMap()
Constructor - does nothing really.
Binary input base class.
Definition qdp_io.h:372
Binary writer base class.
Definition qdp_io.h:1010
virtual void writeArray(const char *output, size_t nbytes, size_t nmemb)
Write data from the primary node.
Definition qdp_io.cc:1182
MapFunc.
Definition qdp_map.h:32
General permutation map class for communications.
Map(const MapFunc &fn)
Constructor from a function object.
~Map()
Destructor.
MakeReturn< UnaryNode< FnMap, typenameCreateLeaf< QDPType< T1, C1 > >::Leaf_t >, C1 >::Expression_t operator()(const QDPType< T1, C1 > &l)
Function call operator for a shift.
Map()
Constructor - does nothing really.
void make(const MapFunc &func)
Actual constructor from a function object.
const multi1d< int > & Offsets() const
Accessor to offsets.
MakeReturn< UnaryNode< FnMap, typenameCreateLeaf< QDPExpr< T1, C1 > >::Leaf_t >, C1 >::Expression_t operator()(const QDPExpr< T1, C1 > &l)
Outer grid Lattice type.
Definition qdp_outer.h:264
T & elem(int i)
Definition qdp_outer.h:400
Outer grid Scalar class *‍/.
Definition qdp_outer.h:37
OLattice class narrowed to a subset.
Expression class for QDP.
Definition qdp_qdpexpr.h:16
QDPType - major type class/container for all QDP objects.
Definition qdp_qdptype.h:29
void QDP_extract(multi1d< OScalar< T > > &dest, const OLattice< T > &src, const Subset &s)
Copy data values from field src to array dest.
OLattice< T1 > & pokeSite(OLattice< T1 > &l, const OScalar< T1 > &r, const multi1d< int > &coord)
Insert site element.
OScalar< T1 > peekSite(const QDPExpr< RHS, OScalar< T1 > > &l, const multi1d< int > &coord)
Extract site element.
void QDP_insert(OLattice< T > &dest, const multi1d< OScalar< T > > &src, const Subset &s)
Inserts data values from site array src.
OScalar< T1 > peekSite(const OScalar< T1 > &l, const multi1d< int > &coord)
Extract site element.
OScalar< T1 > peekSite(const OLattice< T1 > &l, const multi1d< int > &coord)
Extract site element.
OScalar< T1 > peekSite(const QDPExpr< RHS, OLattice< T1 > > &l, const multi1d< int > &coord)
Extract site element.
Set - collection of subsets controlling which sites are involved in an operation.
Definition qdp_subset.h:96
int numSubsets() const
Return number of subsets.
Definition qdp_subset.h:111
const multi1d< int > & latticeColoring() const
The coloring of the lattice sites.
Definition qdp_subset.h:131
Subsets - controls how lattices are looped.
Definition qdp_subset.h:39
const multi1d< int > & siteTable() const
Definition qdp_subset.h:83
int numSiteTable() const
Definition qdp_subset.h:84
const Op & operation() const
Definition qdp.h:148
DeReference< Child >::Return_t child() const
Definition qdp.h:152
Metadata output class.
Definition qdp_xmlio.h:506
Container for a multi-dimensional 1D array.
Definition qdp_multi.h:25
const T * slice() const
Return ref to a column slice.
Definition qdp_multi.h:225
Container for a multi-dimensional 2D array.
Definition qdp_multi.h:640
int size1() const
Size of array.
Definition qdp_multi.h:673
int size2() const
Definition qdp_multi.h:674
OLattice< PScalar< PSeed< RScalar< INTEGER32 > > > > LatticeSeed
OScalar< PScalar< PSeed< RScalar< INTEGER32 > > > > Seed
OLattice< PScalar< PScalar< RScalar< INTEGER32 > > > > LatticeInteger
OScalar< T1 > peekSite(const OScalar< T1 > &l, const multi1d< int > &coord)
Extract site element.
BinaryReturn< C1, C2, FnInnerProductReal >::Type_t innerProductReal(const QDPType< T1, C1 > &s1, const QDPType< T2, C2 > &s2)
OScalar = innerProductReal(adj(source1)*source2).
UnaryReturn< C, FnGlobalMin >::Type_t globalMin(const QDPType< T, C > &s1)
OScalar = globalMin(source).
UnaryReturn< C, FnNorm2 >::Type_t norm2(const QDPType< T, C > &s1)
OScalar = norm2(trace(adj(source)*source)).
bool isnan(const QDPExpr< T, C > &s1)
bool = isnan(source)
bool isfinite(const QDPExpr< T, C > &s1)
bool = isfinite(source)
BinaryReturn< C1, C2, FnInnerProduct >::Type_t innerProduct(const QDPType< T1, C1 > &s1, const QDPType< T2, C2 > &s2)
OScalar = innerProduct(adj(source1)*source2).
bool isnormal(const QDPExpr< T, C > &s1)
bool = isnormal(source)
bool isinf(const QDPExpr< T, C > &s1)
bool = isinf(source)
UnaryReturn< C, FnGlobalMax >::Type_t globalMax(const QDPType< T, C > &s1)
OScalar = globalMax(source).
UnaryReturn< C, FnSumMulti >::Type_t sumMulti(const QDPType< T, C > &s1, const Set &ss)
dest = sumMulti(source1,Set)
UnaryReturn< C, FnSum >::Type_t sum(const QDPType< T, C > &s1)
OScalar = sum(source).
TextWriter & operator<<(TextWriter &txt, const std::string &output)
Definition qdp_io.cc:283
void write(BinaryWriter &bin, const std::string &output)
Definition qdp_io.cc:1204
void read(BinaryReader &bin, std::string &input, size_t maxBytes)
Definition qdp_io.cc:778
void fill_gaussian(IScalar< T > &d, IScalar< T > &r1, IScalar< T > &r2)
dest = gaussian
Definition qdp_inner.h:1861
void zero_rep(IScalar< T > &dest)
dest = 0
Definition qdp_inner.h:1841
void copymask(IScalar< T > &d, const IScalar< T1 > &mask, const IScalar< T > &s1)
dest = (mask) ? s1 : dest
Definition qdp_inner.h:1656
bool toBool(const IScalar< T > &s)
QDP Boolean to bool primitive in conversion routine.
Definition qdp_inner.h:1639
void evaluate(OLattice< DCol > &d, const OpAssign &op, const QDPExpr< BinaryNode< OpMultiply, Reference< QDPType< DCol, OLattice< DCol > > >, Reference< QDPType< DCol, OLattice< DCol > > > >, OLattice< DCol > > &rhs, const Subset &s)
void gaussian(OSubScalar< T > &d)
dest = gaussian
Definition qdp_outer.h:1462
void random(OScalar< T > &d)
dest = random
Subset all
Default all subset.
Definition qdp_subset.cc:16
void readSlice(BinaryReader &bin, OLattice< T > &data, int start_lexico, int stop_lexico)
void writeSlice(BinaryWriter &bin, const OLattice< T > &data, int start_lexico, int stop_lexico)
Layout namespace holding info on problem size and machine info.
Definition qdp_layout.cc:16
int linearSiteIndex(int site)
The linearized site index for the corresponding lexicographic site.
int sitesOnNode()
Subgrid lattice volume.
const multi1d< int > & lattSize()
Virtual grid (problem grid) lattice size.
LatticeInteger latticeCoordinate(int mu)
coord[mu] <- mu : fill with lattice coord in mu direction
int vol()
Total lattice volume.
bool primaryNode()
Returns whether this is the primary node.
void globalOr(bool &dest)
Wrapper to get a functional global Or.
void broadcast(T &dest)
Broadcast from primary node to all other nodes.
void globalSum(T &dest)
Sum across all nodes.
void globalAnd(bool &dest)
Wrapper to get a functional global And.
void broadcast_str(std::string &result)
Broadcast a string from primary node to all other nodes.
void globalSumArray(unsigned int *dest, int len)
Wrapper to get a functional unsigned global sum.
Random number generator namespace.
Definition qdp_random.cc:18
Seed ran_mult_n
RNG multiplier raised to the volume+1.
Definition qdp_random.cc:24
Seed ran_mult
RNG multiplier.
Definition qdp_random.cc:22
LatticeSeed * lattice_ran_mult
The lattice of skewed RNG multipliers.
Definition qdp_random.cc:26
Seed ran_seed
Global (current) seed.
Definition qdp_random.cc:20
Yet another random number generator.
void dispatch_to_threads(int numSiteTable, Arg a, void(*func)(int, int, int, Arg *))
ForEach< Expr, FTag, CTag >::Type_t forEach(const Expr &e, const FTag &f, const CTag &c)
Definition qdp.h:88
void sumMultiKernel(int lo, int hi, int my_id, SumMultiOLatticeThreadArgs< RHS, T > *a)
void evaluate_userfunc(int lo, int hi, int myId, user_arg< T, T1, Op, RHS > *a)
user function for the evaluate function:
MakeReturn< BinaryNode< FnLocalInnerProductReal, typenameCreateLeaf< QDPType< T1, C1 > >::Leaf_t, typenameCreateLeaf< QDPExpr< T2, C2 > >::Leaf_t >, typenameBinaryReturn< C1, C2, FnLocalInnerProductReal >::Type_t >::Expression_t localInnerProductReal(const QDPType< T1, C1 > &l, const QDPExpr< T2, C2 > &r)
Definition qdp.h:2428
QDPTime_t getClockTime()
Get the wallclock time.
void evaluate_F(T *dest, const Op &op, const QDPExpr< RHS, OScalar< T1 > > &rhs, const Subset &s)
Definition qdp_outer.h:242
MakeReturn< BinaryNode< FnLocalInnerProduct, typenameCreateLeaf< QDPType< T1, C1 > >::Leaf_t, typenameCreateLeaf< QDPExpr< T2, C2 > >::Leaf_t >, typenameBinaryReturn< C1, C2, FnLocalInnerProduct >::Type_t >::Expression_t localInnerProduct(const QDPType< T1, C1 > &l, const QDPExpr< T2, C2 > &r)
Definition qdp.h:2412
void ev_userfunc(int lo, int hi, int myId, u_arg< T, T1, Op, RHS > *a)
user function for the evaluate function:
multi1d< int > crtesn(int ipos, const multi1d< int > &latt_size)
Decompose a lexicographic site into coordinates.
void fill_random(float &d, T1 &seed, T2 &skewed_seed, const T1 &seed_mult)
dest = random
Definition qdp_random.h:54
int qdpNumThreads()
MakeReturn< UnaryNode< FnLocalNorm2, typenameCreateLeaf< QDPExpr< T1, C1 > >::Leaf_t >, typenameUnaryReturn< C1, FnLocalNorm2 >::Type_t >::Expression_t localNorm2(const QDPExpr< T1, C1 > &l)
Definition qdp.h:4998
static Type_t combine(const A &a, const Op &, const Tag &)
Definition qdp.h:89
int val1() const
Definition qdp.h:97
UnaryReturn< T, FnMap >::Type_t operator()(const T &a) const
FnMap(const int *goffsets)
static Type_t apply(const UnaryNode< FnMap, A > &expr, const EvalLeaf1 &f, const CTag &c)
static Type_t apply(const Expr &expr, const FTag &f, const CTag &)
Definition qdp.h:80
LeafFunctor< Expr, FTag >::Type_t Type_t
Definition qdp.h:78
static Expression_t make(const T &a)
Definition qdp_qdpexpr.h:66
multi1d<OScalar> dest = sumMulti(OLattice,Set)
multi1d< typename UnaryReturn< OLattice< T >, FnSumMulti >::Type_t > & dest
SumMultiOLatticeThreadArgs(const multi1d< int > &lat_color_, const QDPExpr< RHS, OLattice< T > > &s_, multi1d< typename UnaryReturn< OLattice< T >, FnSumMulti >::Type_t > &dest_)
const QDPExpr< RHS, OLattice< T > > & s
user argument for the evaluate function:
u_arg(OLattice< T > &d_, const QDPExpr< RHS, OScalar< T1 > > &r_, const Op &op_, const int *tab_)
const QDPExpr< RHS, OScalar< T1 > > & r
OLattice< T > & d
user argument for the evaluate function:
user_arg(OLattice< T > &d_, const QDPExpr< RHS, OLattice< T1 > > &r_, const Op &op_, const int *tab_)
const QDPExpr< RHS, OLattice< T1 > > & r