LIBINT  2.1.0-stable
vector_ppc.h
1 /*
2  * This file is a part of Libint.
3  * Copyright (C) 2004-2014 Edward F. Valeev
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU Library General Public License, version 2,
7  * as published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public License
15  * along with this program. If not, see http://www.gnu.org/licenses/.
16  *
17  */
18 
19 #ifndef _libint2_src_lib_libint_vectorppc_h_
20 #define _libint2_src_lib_libint_vectorppc_h_
21 
22 #include <libint2/type_traits.h>
23 
24 // clang on BG/Q defines __VECTOR4DOUBLE__ and intrinsics in this header file
25 #if defined(__clang__) && defined(__bgq__)
26 # include <qpxintrin.h>
27 #endif
28 
29 #ifdef __VECTOR4DOUBLE__
30 
31 namespace libint2 { namespace simd {
32 
37  struct VectorQPXDouble {
38 
39  typedef double T;
40  vector4double d;
41 
46 
51  d = vec_splats(a);
52  }
53 
57  VectorQPXDouble(T (&a)[4]) {
58  d = vec_ld(0, &a[0]);
59  }
60 
64  VectorQPXDouble(T a0, T a1, T a2, T a3) {
65  T a[4]; a[0] = a0; a[1] = a1; a[2] = a2; a[3] = a3;
66  d = vec_ld(0, &a[0]);
67  }
68 
69  VectorQPXDouble& operator=(T a) {
70  d = vec_splats(a);
71  return *this;
72  }
73 
74  VectorQPXDouble& operator+=(VectorQPXDouble a) {
75  d = vec_add(d, a.d);
76  return *this;
77  }
78 
79  VectorQPXDouble& operator-=(VectorQPXDouble a) {
80  d = vec_sub(d, a.d);
81  return *this;
82  }
83 
84  operator double() const {
85  double d0 = vec_extract(d, 0);
86  return d0;
87  }
88 
89  void convert(double(&a)[4]) const {
90  vec_st(d, 0, &a[0]);
91  }
92 
93  };
94 
96  inline VectorQPXDouble operator*(double a, VectorQPXDouble b) {
98  VectorQPXDouble _a(a);
99  c.d = vec_mul(_a.d, b.d);
100  return c;
101  }
102 
103  inline VectorQPXDouble operator*(VectorQPXDouble a, double b) {
104  VectorQPXDouble c;
105  VectorQPXDouble _b(b);
106  c.d = vec_mul(a.d, _b.d);
107  return c;
108  }
109 
110  inline VectorQPXDouble operator*(int a, VectorQPXDouble b) {
111  if (a == 1)
112  return b;
113  else {
114  VectorQPXDouble c;
115  VectorQPXDouble _a((double)a);
116  c.d = vec_mul(_a.d, b.d);
117  return c;
118  }
119  }
120 
121  inline VectorQPXDouble operator*(VectorQPXDouble a, int b) {
122  if (b == 1)
123  return a;
124  else {
125  VectorQPXDouble c;
126  VectorQPXDouble _b((double)b);
127  c.d = vec_mul(a.d, _b.d);
128  return c;
129  }
130  }
131 
133  VectorQPXDouble c;
134  c.d = vec_mul(a.d, b.d);
135  return c;
136  }
137 
138  inline VectorQPXDouble operator+(VectorQPXDouble a, VectorQPXDouble b) {
139  VectorQPXDouble c;
140  c.d = vec_add(a.d, b.d);
141  return c;
142  }
143 
144  inline VectorQPXDouble operator-(VectorQPXDouble a, VectorQPXDouble b) {
145  VectorQPXDouble c;
146  c.d = vec_sub(a.d, b.d);
147  return c;
148  }
149 
150  inline VectorQPXDouble operator/(VectorQPXDouble a, VectorQPXDouble b) {
151  VectorQPXDouble c;
152  c.d = vec_swdiv(a.d, b.d);
153  return c;
154  }
155 
157  VectorQPXDouble d;
158  d.d = vec_madd(a.d, b.d, c.d);
159  return d;
160  }
162  VectorQPXDouble d;
163  d.d = vec_msub(a.d, b.d, c.d);
164  return d;
165  }
166 
168 
169 };}; // namespace libint2::simd
170 
171 namespace libint2 {
172 
174 
175  template <>
176  struct is_vector<simd::VectorQPXDouble> {
177  static const bool value = true;
178  };
179 
180  template <>
182  typedef double value_type;
183  static const size_t extent = 4;
184  };
185 
187 
188 } // namespace libint2
189 
190 #endif // QPX-only
191 
192 // only xlC on BG/L and BG/P supports FP2 (Double Hummer)instructions, not sure how to check if they are enabled
193 #if (defined(__xlC__) || defined(__clang__)) && (defined(__bgp__) || defined(__blrts__))
194 
195 #if defined(__xlC__)
196 # include <builtins.h>
197 #endif
198 #if defined(__clang__)
199 # include <fp2intrin.h>
200 #endif
201 
202 namespace libint2 { namespace simd {
203 
209 
210  typedef double T;
211  double _Complex d; //< represents 2 doubles
212 
217 
222  T a01[2]; a01[0] = a; a01[1] = a;
223  d = __lfpd(&a01[0]);
224  }
225 
229  VectorFP2Double(T (&a)[2]) {
230  d = __lfpd(&a[0]);
231  }
232 
236  VectorFP2Double(T a0, T a1) {
237  T a[2]; a[0] = a0; a[1] = a1;
238  d = __lfpd(&a[0]);
239  }
240 
241  VectorFP2Double& operator=(T a) {
242  T a01[2]; a01[0] = a; a01[1] = a;
243  d = __lfpd(&a01[0]);
244  return *this;
245  }
246 
247  VectorFP2Double& operator+=(VectorFP2Double a) {
248  d = __fpadd(d, a.d);
249  return *this;
250  }
251 
252  VectorFP2Double& operator-=(VectorFP2Double a) {
253  d = __fpsub(d, a.d);
254  return *this;
255  }
256 
257  operator double() const {
258  double d0 = __creal(d);
259  return d0;
260  }
261 
262  void convert(double(&a)[2]) const {
263  __stfpd(&a[0], d);
264  }
265  };
266 
268  inline VectorFP2Double operator*(double a, VectorFP2Double b) {
269  VectorFP2Double c;
270  c.d = __fxpmul(b.d, a);
271  return c;
272  }
273 
274  inline VectorFP2Double operator*(VectorFP2Double a, double b) {
275  VectorFP2Double c;
276  c.d = __fxpmul(a.d, b);
277  return c;
278  }
279 
280  inline VectorFP2Double operator*(int a, VectorFP2Double b) {
281  if (a == 1)
282  return b;
283  else {
284  VectorFP2Double c;
285  c.d = __fxpmul(b.d, (double)a);
286  return c;
287  }
288  }
289 
290  inline VectorFP2Double operator*(VectorFP2Double a, int b) {
291  if (b == 1)
292  return a;
293  else {
294  VectorFP2Double c;
295  c.d = __fxpmul(a.d, (double)b);
296  return c;
297  }
298  }
299 
301  VectorFP2Double c;
302  c.d = __fpmul(a.d, b.d);
303  return c;
304  }
305 
306  inline VectorFP2Double operator+(VectorFP2Double a, VectorFP2Double b) {
307  VectorFP2Double c;
308  c.d = __fpadd(a.d, b.d);
309  return c;
310  }
311 
312  inline VectorFP2Double operator-(VectorFP2Double a, VectorFP2Double b) {
313  VectorFP2Double c;
314  c.d = __fpsub(a.d, b.d);
315  return c;
316  }
317 
318  /* there's no division DH instruction that I can see
319  inline VectorFP2Double operator/(VectorFP2Double a, VectorFP2Double b) {
320  VectorFP2Double c;
321  }
322  */
323 
325  VectorFP2Double d;
326  d.d = __fpmadd(a.d, b.d, c.d);
327  return d;
328  }
330  VectorFP2Double d;
331  d.d = __fpmsub(a.d, b.d, c.d);
332  return d;
333  }
334 
336 
337 };}; // namespace libint2::simd
338 
339 namespace libint2 {
340 
342 
343  template <>
344  struct is_vector<simd::VectorFP2Double> {
345  static const bool value = true;
346  };
347 
348  template <>
349  struct vector_traits<simd::VectorFP2Double> {
350  typedef double value_type;
351  static const size_t extent = 2;
352  };
353 
355 
356 } // namespace libint2
357 
358 #endif // FP2-only
359 
360 #endif // header guard
361 
Z fma_minus(X x, Y y, Z z)
Definition: intrinsic_operations.h:36
VectorFP2Double(T(&a)[2])
creates a vector of values initialized by an ordinary static-sized array
Definition: vector_ppc.h:229
Definition: type_traits.h:30
Defaults definitions for various parameters assumed by Libint.
Definition: algebra.cc:23
VectorQPXDouble(T a)
Initializes all elements to the same value.
Definition: vector_ppc.h:50
SafePtr< CTimeEntity< typename ProductType< T, U >::result > > operator*(const SafePtr< CTimeEntity< T > > &A, const SafePtr< CTimeEntity< U > > &B)
Creates product A*B.
Definition: entity.h:277
VectorFP2Double()
creates a vector of default-initialized values.
Definition: vector_ppc.h:216
Z fma_plus(X x, Y y, Z z)
Definition: intrinsic_operations.h:30
VectorQPXDouble(T a0, T a1, T a2, T a3)
creates a vector of values initialized by an ordinary static-sized array
Definition: vector_ppc.h:64
VectorQPXDouble(T(&a)[4])
creates a vector of values initialized by an ordinary static-sized array
Definition: vector_ppc.h:57
SIMD vector of 4 double-precision floating-point real numbers, operations on which use QPX instructio...
Definition: vector_ppc.h:37
VectorQPXDouble()
creates a vector of default-initialized values.
Definition: vector_ppc.h:45
SIMD vector of 2 double-precision floating-point real numbers, operations on which use FP2 (Double Hu...
Definition: vector_ppc.h:208
Definition: type_traits.h:25
VectorFP2Double(T a)
Initializes all elements to the same value.
Definition: vector_ppc.h:221
VectorFP2Double(T a0, T a1)
creates a vector of values initialized by an ordinary static-sized array
Definition: vector_ppc.h:236