Documentation 6b54b78464
Loading...
Searching...
No Matches
special_vectorization.hpp
Go to the documentation of this file.
1/*!
2 * \file special_vectorization.hpp
3 * \brief Code generator header to create specializations of simd::Array.
4 * \author P. Gomes
5 * \version 8.5.0 "Harrier"
6 *
7 * SU2 Project Website: https://su2code.github.io
8 *
9 * The SU2 Project is maintained by the SU2 Foundation
10 * (http://su2foundation.org)
11 *
12 * Copyright 2012-2026, SU2 Contributors (cf. AUTHORS.md)
13 *
14 * SU2 is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU Lesser General Public
16 * License as published by the Free Software Foundation; either
17 * version 2.1 of the License, or (at your option) any later version.
18 *
19 * SU2 is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 * Lesser General Public License for more details.
23 *
24 * You should have received a copy of the GNU Lesser General Public
25 * License along with SU2. If not, see <http://www.gnu.org/licenses/>.
26 */
27
28// no #pragma once, header needs to be included once per specialization.
29
30/// \addtogroup SIMD
31/// @{
32
33/*!
34 * \brief Symbols that need to be defined before including this header:
35 * \param[in] ARRAY_T - The desired specialization of simd::Array.
36 * \param[in] SCALAR_T - Scalar type.
37 * \param[in] REGISTER_T - Intrinsic type.
38 * \param[in] SIZE_TAG - Dummy object associated with the simd size.
39 * \param[in] ARRAY_BOILERPLATE - Generates the general ctors, access, etc.
40 * \note On top of that, the intrinsic functions must be wrapped to
41 * strip their type / size characteristics, e.g. _mm256_add_pd -> add_p,
42 * overload resolution will do the rest. The first four symbols are
43 * undefined once we are done using them.
44 */
45template <>
46class ARRAY_T {
47#define FOREACH SU2_OMP_SIMD for (size_t k = 0; k < Size; ++k)
48 template <class F, class S>
49 FORCEINLINE static S second(F, S s) {
50 return s;
51 }
52
53 public:
56 enum : size_t { Align = alignof(Register) };
57 enum : size_t { Size = sizeof(Register) / sizeof(Scalar) };
58
59 /*--- The infamous union "hack", sue me. ---*/
60 union {
63 };
64
65 /*--- Same basic construction operations as the general case. ---*/
66
68
69 /*--- Special construction using the "register type" directly. ---*/
70
72 FORCEINLINE Array(const Array& other) noexcept { reg = other.reg; }
73
74 /*--- Specialized construction primitives. ---*/
75
76 FORCEINLINE void bcast(Scalar x) { reg = set1_p(SIZE_TAG, x); }
77 FORCEINLINE void load(const Scalar* ptr) { reg = loadu_p(SIZE_TAG, ptr); }
78 FORCEINLINE void loada(const Scalar* ptr) { reg = load_p(SIZE_TAG, ptr); }
79 FORCEINLINE void store(Scalar* ptr) const { storeu_p(ptr, reg); }
80 FORCEINLINE void storea(Scalar* ptr) const { store_p(ptr, reg); }
81 FORCEINLINE void stream(Scalar* ptr) const { stream_p(ptr, reg); }
82 template <class T>
83 FORCEINLINE void gather(const Scalar* begin, const T& offsets) {
84 FOREACH x_[k] = begin[offsets[k]];
85 }
86
87 /*--- Compound assignement operators. ---*/
88
89#define MAKE_COMPOUND(OP, IMPL) \
90 FORCEINLINE Array& operator OP(Scalar x) { \
91 reg = IMPL(reg, set1_p(SIZE_TAG, x)); \
92 return *this; \
93 } \
94 FORCEINLINE Array& operator OP(const Array& other) noexcept { \
95 reg = IMPL(reg, other.reg); \
96 return *this; \
97 }
98 MAKE_COMPOUND(=, second)
99 MAKE_COMPOUND(+=, add_p)
100 MAKE_COMPOUND(-=, sub_p)
101 MAKE_COMPOUND(*=, mul_p)
102 MAKE_COMPOUND(/=, div_p)
103#undef MAKE_COMPOUND
104
105#undef FOREACH
106};
107
108/*!
109 * SIMD overloads, NAME is the operator or function,
110 * IMPL the intrinsic function that implements it.
111 */
112#define MAKE_UNARY_FUN(NAME, IMPL) \
113 FORCEINLINE ARRAY_T NAME(const ARRAY_T& x) { return IMPL(x.reg); }
114
115MAKE_UNARY_FUN(operator-, neg_p)
119
120#undef MAKE_UNARY_FUN
121
122#define MAKE_BINARY_FUN(NAME, IMPL) \
123 FORCEINLINE ARRAY_T NAME(const ARRAY_T& a, const ARRAY_T& b) { return IMPL(a.reg, b.reg); } \
124 FORCEINLINE ARRAY_T NAME(const ARRAY_T& a, SCALAR_T b) { return IMPL(a.reg, set1_p(SIZE_TAG, b)); } \
125 FORCEINLINE ARRAY_T NAME(SCALAR_T b, const ARRAY_T& a) { return IMPL(set1_p(SIZE_TAG, b), a.reg); }
126
127MAKE_BINARY_FUN(operator+, add_p)
128MAKE_BINARY_FUN(operator-, sub_p)
129MAKE_BINARY_FUN(operator*, mul_p)
130MAKE_BINARY_FUN(operator/, div_p)
131MAKE_BINARY_FUN(operator<, lt_p)
132MAKE_BINARY_FUN(operator>, gt_p)
133MAKE_BINARY_FUN(operator==, eq_p)
134MAKE_BINARY_FUN(operator!=, ne_p)
135MAKE_BINARY_FUN(operator<=, le_p)
136MAKE_BINARY_FUN(operator>=, ge_p)
137MAKE_BINARY_FUN(fmax, max_p)
138MAKE_BINARY_FUN(fmin, min_p)
139
140#undef MAKE_BINARY_FUN
141
142/*!
143 * Compatibility mode overloads, element-wise implementation.
144 */
145#define FOREACH SU2_OMP_SIMD for (size_t k = 0; k < ARRAY_T::Size; ++k)
146
147/*--- Functions of one (array) argument. ---*/
148
149#define MAKE_UNARY_FUN(NAME, IMPL) \
150 FORCEINLINE ARRAY_T NAME(const ARRAY_T& x) { \
151 ARRAY_T res; \
152 FOREACH { res[k] = IMPL(x[k]); } \
153 return res; \
154 }
155
157
158#undef MAKE_UNARY_FUN
159
160/*--- Functions of two arguments, with arrays and scalars. ---*/
161
162#define MAKE_BINARY_FUN(NAME, IMPL) \
163 FORCEINLINE ARRAY_T NAME(const ARRAY_T& a, const ARRAY_T& b) { \
164 ARRAY_T res; \
165 FOREACH { res[k] = IMPL(a[k], b[k]); } \
166 return res; \
167 } \
168 FORCEINLINE ARRAY_T NAME(const ARRAY_T& a, SCALAR_T b) { \
169 ARRAY_T res; \
170 FOREACH { res[k] = IMPL(a[k], b); } \
171 return res; \
172 } \
173 FORCEINLINE ARRAY_T NAME(SCALAR_T b, const ARRAY_T& a) { \
174 ARRAY_T res; \
175 FOREACH { res[k] = IMPL(b, a[k]); } \
176 return res; \
177 }
178
180
181#undef MAKE_BINARY_FUN
182
183#undef FOREACH
184
185#undef ARRAY_T
186#undef SCALAR_T
187#undef REGISTER_T
188#undef SIZE_TAG
189
190/// @}
#define MAKE_COMPOUND(OP, ASSIGN_OP)
Compound assignement operations with scalars and expressions.
Definition CSysVector.hpp:488
Symbols that need to be defined before including this header:
Definition special_vectorization.hpp:46
SCALAR_T Scalar
Definition special_vectorization.hpp:54
@ Size
Definition special_vectorization.hpp:57
ARRAY_BOILERPLATE FORCEINLINE Array(Register y)
Definition special_vectorization.hpp:71
Scalar x_[Size]
Definition special_vectorization.hpp:62
FORCEINLINE void bcast(Scalar x)
Definition special_vectorization.hpp:76
FORCEINLINE void gather(const Scalar *begin, const T &offsets)
Definition special_vectorization.hpp:83
FORCEINLINE void stream(Scalar *ptr) const
Definition special_vectorization.hpp:81
Register reg
Definition special_vectorization.hpp:61
FORCEINLINE void loada(const Scalar *ptr)
Definition special_vectorization.hpp:78
FORCEINLINE Array(const Array &other) noexcept
Definition special_vectorization.hpp:72
@ Align
Definition special_vectorization.hpp:56
FORCEINLINE void load(const Scalar *ptr)
Definition special_vectorization.hpp:77
REGISTER_T Register
Definition special_vectorization.hpp:55
FORCEINLINE void storea(Scalar *ptr) const
Definition special_vectorization.hpp:80
FORCEINLINE void store(Scalar *ptr) const
Definition special_vectorization.hpp:79
#define FORCEINLINE
Definition code_config.hpp:44
#define SIZE_TAG
Definition vectorization.hpp:219
FORCEINLINE ARRAY_T exp(const ARRAY_T &x)
Definition special_vectorization.hpp:156
FORCEINLINE ARRAY_T sqrt(const ARRAY_T &x)
Definition special_vectorization.hpp:116
#define MAKE_UNARY_FUN(NAME, IMPL)
Definition special_vectorization.hpp:112
#define FOREACH
Definition special_vectorization.hpp:47
FORCEINLINE ARRAY_T pow(const ARRAY_T &a, const ARRAY_T &b)
Definition special_vectorization.hpp:179
#define MAKE_BINARY_FUN(NAME, IMPL)
Definition special_vectorization.hpp:122
#define SCALAR_T
Definition vectorization.hpp:217
FORCEINLINE ARRAY_T sign(const ARRAY_T &x)
Definition special_vectorization.hpp:118
#define REGISTER_T
Definition vectorization.hpp:218
FORCEINLINE ARRAY_T abs(const ARRAY_T &x)
Definition special_vectorization.hpp:117
#define ARRAY_BOILERPLATE
Definition vectorization.hpp:103