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