QDP++
sse_blas_local_vcdot_real_double.cc
Go to the documentation of this file.
1
6
7#include <qdp.h>
8#include <xmmintrin.h>
10#include <iostream>
11
12namespace QDP {
13
14 typedef union {
15 double c[2];
16 __m128d vec;
17 } VDU;
18
19 // Re < y^\dag , x >
20 // = sum ( y.re x.re + y.im x.im )
21 // = sum ( y.re x.re ) + sum( y.im x.im )
22 //
23 // Load in [ x.re | x.im ]
24 // [ y.re | y.im ]
25 // Make [ x.re y.re | x.im y.im ]
26 // accumulate sum
27 //
28 // At the end do a single crossing:
29 //
30 // [ sum (x.re y.re) | sum(x.im y.im) ]
31 // + [ sum (x.im y.im) | sum(x.re y.re) ]
32 // = [ innerProdReal | innerProdReal ]
33 //
34 void local_vcdot_real4(REAL64 *sum, REAL64 *y, REAL64* x,int n_4spin)
35{
36 __m128d sum1 = _mm_setzero_pd();
37 __m128d sum2 = _mm_setzero_pd();
38 __m128d sum3 = _mm_setzero_pd();
39 __m128d sum4 = _mm_setzero_pd();
40
41 __m128d tmp1;
42 __m128d tmp2;
43 __m128d tmp3;
44 __m128d tmp4;
45 __m128d tmp5;
46 __m128d tmp6;
47 __m128d tmp7;
48 __m128d tmp8;
49 __m128d tmp9;
50 __m128d tmp10;
51 __m128d tmp11;
52 __m128d tmp12;
53
54 double *x_p=x;
55 double *y_p=y;
56
57 for(int i=0; i < n_4spin; i++) {
58
59 tmp1 = _mm_load_pd(x_p);
60 tmp2 = _mm_load_pd(y_p);
61 tmp3 = _mm_mul_pd(tmp1,tmp2);
62 sum1 = _mm_add_pd(sum1,tmp3);
63
64
65 tmp4 = _mm_load_pd(x_p+2);
66 tmp5 = _mm_load_pd(y_p+2);
67 tmp6 = _mm_mul_pd(tmp4,tmp5);
68 sum2 = _mm_add_pd(sum2,tmp6);
69
70 tmp7 = _mm_load_pd(x_p+4);
71 tmp8 = _mm_load_pd(y_p+4);
72 tmp9 = _mm_mul_pd(tmp7,tmp8);
73 sum3 = _mm_add_pd(sum3,tmp9);
74
75 tmp10 = _mm_load_pd(x_p+6);
76 tmp11 = _mm_load_pd(y_p+6);
77 tmp12 = _mm_mul_pd(tmp10,tmp11);
78 sum4 = _mm_add_pd(sum4,tmp12);
79
80
81
82 tmp1 = _mm_load_pd(x_p+8);
83 tmp2 = _mm_load_pd(y_p+8);
84 tmp3 = _mm_mul_pd(tmp1,tmp2);
85 sum1 = _mm_add_pd(sum1,tmp3);
86
87 tmp4 = _mm_load_pd(x_p+10);
88 tmp5 = _mm_load_pd(y_p+10);
89 tmp6 = _mm_mul_pd(tmp4,tmp5);
90 sum2 = _mm_add_pd(sum2,tmp6);
91
92 tmp7 = _mm_load_pd(x_p+12);
93 tmp8 = _mm_load_pd(y_p+12);
94 tmp9 = _mm_mul_pd(tmp7,tmp8);
95 sum3 = _mm_add_pd(sum3,tmp9);
96
97 tmp10 = _mm_load_pd(x_p+14);
98 tmp11 = _mm_load_pd(y_p+14);
99 tmp12 = _mm_mul_pd(tmp10,tmp11);
100 sum4 = _mm_add_pd(sum4,tmp12);
101
102
103
104 tmp1 = _mm_load_pd(x_p+16);
105 tmp2 = _mm_load_pd(y_p+16);
106 tmp3 = _mm_mul_pd(tmp1,tmp2);
107 sum1 = _mm_add_pd(sum1,tmp3);
108
109 tmp4 = _mm_load_pd(x_p+18);
110 tmp5 = _mm_load_pd(y_p+18);
111 tmp6 = _mm_mul_pd(tmp4,tmp5);
112 sum2 = _mm_add_pd(sum2,tmp6);
113
114 tmp7 = _mm_load_pd(x_p+20);
115 tmp8 = _mm_load_pd(y_p+20);
116 tmp9 = _mm_mul_pd(tmp7,tmp8);
117 sum3 = _mm_add_pd(sum3,tmp9);
118
119 tmp10 = _mm_load_pd(x_p+22);
120 tmp11 = _mm_load_pd(y_p+22);
121 tmp12 = _mm_mul_pd(tmp10,tmp11);
122 sum4 = _mm_add_pd(sum4,tmp12);
123
124 x_p += 24; y_p+=24;
125
126 }
127
128 // Accumulate into 2 vecs
129 sum1 = _mm_add_pd(sum1,sum2);
130 sum3 = _mm_add_pd(sum3,sum4);
131
132 // Accumulate into 1 vec
133 sum1 = _mm_add_pd(sum1,sum3);
134
135 // Cross the vector and add
136 tmp1 = _mm_shuffle_pd(sum1, sum1, 0x1);
137 sum1 = _mm_add_pd(tmp1,sum1);
138
139 // Store either half
140 _mm_storeh_pd(sum,sum1);
141
142}
143
144
145
146} // namespace QDP;
147
double REAL64
UnaryReturn< C, FnSum >::Type_t sum(const QDPType< T, C > &s1)
OScalar = sum(source).
Yet another random number generator.
void local_vcdot_real4(REAL64 *sum, REAL64 *y, REAL64 *x, int n_4spin)
Primary include file for QDP.
Generic Scalar VAXPY routine.