3#ifndef DUNE_COMMON_SIMD_LOOP_HH
4#define DUNE_COMMON_SIMD_LOOP_HH
25# pragma GCC diagnostic push
26# pragma GCC diagnostic ignored "-Wbool-operation"
27# pragma GCC diagnostic ignored "-Wint-in-bool-context"
28# define GCC_WARNING_DISABLED
36#if __has_warning("-Wbitwise-instead-of-logical")
37# pragma clang diagnostic push
38# pragma clang diagnostic ignored "-Wbitwise-instead-of-logical"
39# define CLANG_WARNING_DISABLED
47 #define DUNE_PRAGMA_OMP_SIMD _Pragma("omp simd")
49 #define DUNE_PRAGMA_OMP_SIMD
64 template<
class T, std::
size_t S, std::
size_t A = 0>
65 class alignas(A==0?alignof(T):A)
LoopSIMD :
public std::array<T,S> {
71 assert(
reinterpret_cast<uintptr_t
>(
this) % std::min(
alignof(
LoopSIMD<T,S,A>),
alignof(std::max_align_t)) == 0);
79 template<std::
size_t OA>
81 :
std::array<T,S>(other)
83 assert(
reinterpret_cast<uintptr_t
>(
this) % std::min(
alignof(
LoopSIMD<T,S,A>),
alignof(std::max_align_t)) == 0);
91#define DUNE_SIMD_LOOP_PREFIX_OP(SYMBOL) \
92 auto operator SYMBOL() { \
93 DUNE_PRAGMA_OMP_SIMD \
94 for(std::size_t i=0; i<S; i++){ \
99 static_assert(true, "expecting ;")
103#undef DUNE_SIMD_LOOP_PREFIX_OP
106#define DUNE_SIMD_LOOP_UNARY_OP(SYMBOL) \
107 auto operator SYMBOL() const { \
108 LoopSIMD<T,S,A> out; \
109 DUNE_PRAGMA_OMP_SIMD \
110 for(std::size_t i=0; i<S; i++){ \
111 out[i] = SYMBOL((*this)[i]); \
115 static_assert(true, "expecting ;")
124 for(std::size_t i=0; i<S; i++){
125 out[i] = !((*this)[i]);
129#undef DUNE_SIMD_LOOP_UNARY_OP
132#define DUNE_SIMD_LOOP_POSTFIX_OP(SYMBOL) \
133 auto operator SYMBOL(int){ \
134 LoopSIMD<T,S,A> out = *this; \
138 static_assert(true, "expecting ;")
142#undef DUNE_SIMD_LOOP_POSTFIX_OP
145#define DUNE_SIMD_LOOP_ASSIGNMENT_OP(SYMBOL) \
146 auto operator SYMBOL(const Simd::Scalar<T> s) { \
147 DUNE_PRAGMA_OMP_SIMD \
148 for(std::size_t i=0; i<S; i++){ \
149 (*this)[i] SYMBOL s; \
154 auto operator SYMBOL(const LoopSIMD<T,S,A> &v) { \
155 DUNE_PRAGMA_OMP_SIMD \
156 for(std::size_t i=0; i<S; i++){ \
157 (*this)[i] SYMBOL v[i]; \
161 static_assert(true, "expecting ;")
173#undef DUNE_SIMD_LOOP_ASSIGNMENT_OP
177#define DUNE_SIMD_LOOP_BINARY_OP(SYMBOL) \
178 template<class T, std::size_t S, std::size_t A> \
179 auto operator SYMBOL(const LoopSIMD<T,S,A> &v, const Simd::Scalar<T> s) { \
180 LoopSIMD<T,S,A> out; \
181 DUNE_PRAGMA_OMP_SIMD \
182 for(std::size_t i=0; i<S; i++){ \
183 out[i] = v[i] SYMBOL s; \
187 template<class T, std::size_t S, std::size_t A> \
188 auto operator SYMBOL(const Simd::Scalar<T> s, const LoopSIMD<T,S,A> &v) { \
189 LoopSIMD<T,S,A> out; \
190 DUNE_PRAGMA_OMP_SIMD \
191 for(std::size_t i=0; i<S; i++){ \
192 out[i] = s SYMBOL v[i]; \
196 template<class T, std::size_t S, std::size_t A> \
197 auto operator SYMBOL(const LoopSIMD<T,S,A> &v, \
198 const LoopSIMD<T,S,A> &w) { \
199 LoopSIMD<T,S,A> out; \
200 DUNE_PRAGMA_OMP_SIMD \
201 for(std::size_t i=0; i<S; i++){ \
202 out[i] = v[i] SYMBOL w[i]; \
206 static_assert(true, "expecting ;")
218#undef DUNE_SIMD_LOOP_BINARY_OP
221#define DUNE_SIMD_LOOP_BITSHIFT_OP(SYMBOL) \
222 template<class T, std::size_t S, std::size_t A, class U> \
223 auto operator SYMBOL(const LoopSIMD<T,S,A> &v, const U s) { \
224 LoopSIMD<T,S,A> out; \
225 DUNE_PRAGMA_OMP_SIMD \
226 for(std::size_t i=0; i<S; i++){ \
227 out[i] = v[i] SYMBOL s; \
231 template<class T, std::size_t S, std::size_t A, class U, std::size_t AU> \
232 auto operator SYMBOL(const LoopSIMD<T,S,A> &v, \
233 const LoopSIMD<U,S,AU> &w) { \
234 LoopSIMD<T,S,A> out; \
235 DUNE_PRAGMA_OMP_SIMD \
236 for(std::size_t i=0; i<S; i++){ \
237 out[i] = v[i] SYMBOL w[i]; \
241 static_assert(true, "expecting ;")
246#undef DUNE_SIMD_LOOP_BITSHIFT_OP
249#define DUNE_SIMD_LOOP_COMPARISON_OP(SYMBOL) \
250 template<class T, std::size_t S, std::size_t A, class U> \
251 auto operator SYMBOL(const LoopSIMD<T,S,A> &v, const U s) { \
252 Simd::Mask<LoopSIMD<T,S,A>> out; \
253 DUNE_PRAGMA_OMP_SIMD \
254 for(std::size_t i=0; i<S; i++){ \
255 out[i] = v[i] SYMBOL s; \
259 template<class T, std::size_t S, std::size_t A> \
260 auto operator SYMBOL(const Simd::Scalar<T> s, const LoopSIMD<T,S,A> &v) { \
261 Simd::Mask<LoopSIMD<T,S,A>> out; \
262 DUNE_PRAGMA_OMP_SIMD \
263 for(std::size_t i=0; i<S; i++){ \
264 out[i] = s SYMBOL v[i]; \
268 template<class T, std::size_t S, std::size_t A> \
269 auto operator SYMBOL(const LoopSIMD<T,S,A> &v, \
270 const LoopSIMD<T,S,A> &w) { \
271 Simd::Mask<LoopSIMD<T,S,A>> out; \
272 DUNE_PRAGMA_OMP_SIMD \
273 for(std::size_t i=0; i<S; i++){ \
274 out[i] = v[i] SYMBOL w[i]; \
278 static_assert(true, "expecting ;")
286#undef DUNE_SIMD_LOOP_COMPARISON_OP
289#define DUNE_SIMD_LOOP_BOOLEAN_OP(SYMBOL) \
290 template<class T, std::size_t S, std::size_t A> \
291 auto operator SYMBOL(const LoopSIMD<T,S,A> &v, const Simd::Scalar<T> s) { \
292 Simd::Mask<LoopSIMD<T,S,A>> out; \
293 DUNE_PRAGMA_OMP_SIMD \
294 for(std::size_t i=0; i<S; i++){ \
295 out[i] = v[i] SYMBOL s; \
299 template<class T, std::size_t S, std::size_t A> \
300 auto operator SYMBOL(const Simd::Mask<T> s, const LoopSIMD<T,S,A> &v) { \
301 Simd::Mask<LoopSIMD<T,S,A>> out; \
302 DUNE_PRAGMA_OMP_SIMD \
303 for(std::size_t i=0; i<S; i++){ \
304 out[i] = s SYMBOL v[i]; \
308 template<class T, std::size_t S, std::size_t A> \
309 auto operator SYMBOL(const LoopSIMD<T,S,A> &v, \
310 const LoopSIMD<T,S,A> &w) { \
311 Simd::Mask<LoopSIMD<T,S,A>> out; \
312 DUNE_PRAGMA_OMP_SIMD \
313 for(std::size_t i=0; i<S; i++){ \
314 out[i] = v[i] SYMBOL w[i]; \
318 static_assert(true, "expecting ;")
322#undef DUNE_SIMD_LOOP_BOOLEAN_OP
325 template<
class T, std::
size_t S, std::
size_t A>
328 for(std::size_t i=0; i<S-1; i++) {
336 namespace Overloads {
343 template<
class T, std::
size_t S, std::
size_t A>
348 template<
class U,
class T, std::
size_t S, std::
size_t A>
354 template<
class T, std::
size_t S, std::
size_t A>
357 template<
class T, std::
size_t S, std::
size_t A>
359 ->
decltype(std::move(
Simd::lane(l%lanes<T>(), v[l/lanes<T>()])))
361 return std::move(
Simd::lane(l%lanes<T>(), v[l/lanes<T>()]));
364 template<
class T, std::
size_t S, std::
size_t A>
366 ->
decltype(
Simd::lane(l%lanes<T>(), v[l/lanes<T>()]))
368 return Simd::lane(l%lanes<T>(), v[l/lanes<T>()]);
371 template<
class T, std::
size_t S, std::
size_t A>
373 ->
decltype(
Simd::lane(l%lanes<T>(), v[l/lanes<T>()]))
375 return Simd::lane(l%lanes<T>(), v[l/lanes<T>()]);
378 template<
class T, std::
size_t S, std::
size_t AM, std::
size_t AD>
382 for(std::size_t i=0; i<S; i++) {
388 template<
class M,
class T, std::
size_t S, std::
size_t A>
399 template<
class M, std::
size_t S, std::
size_t A>
402 for(std::size_t i=0; i<S; i++) {
408 template<
class M, std::
size_t S, std::
size_t A>
411 for(std::size_t i=0; i<S; i++) {
417 template<
class M, std::
size_t S, std::
size_t A>
420 for(std::size_t i=0; i<S; i++) {
426 template<
class M, std::
size_t S, std::
size_t A>
429 for(std::size_t i=0; i<S; i++) {
446#define DUNE_SIMD_LOOP_CMATH_UNARY_OP(expr) \
447 template<class T, std::size_t S, std::size_t A, typename Sfinae = \
448 typename std::enable_if_t<!std::is_integral<Simd::Scalar<T>>::value> > \
449 auto expr(const LoopSIMD<T,S,A> &v) { \
451 LoopSIMD<T,S,A> out; \
452 for(std::size_t i=0; i<S; i++) { \
453 out[i] = expr(v[i]); \
457 static_assert(true, "expecting ;")
459#define DUNE_SIMD_LOOP_CMATH_UNARY_OP_WITH_RETURN(expr, returnType) \
460 template<class T, std::size_t S, std::size_t A, typename Sfinae = \
461 typename std::enable_if_t<!std::is_integral<Simd::Scalar<T>>::value> > \
462 auto expr(const LoopSIMD<T,S,A> &v) { \
464 LoopSIMD<returnType,S> out; \
465 for(std::size_t i=0; i<S; i++) { \
466 out[i] = expr(v[i]); \
470 static_assert(true, "expecting ;")
517#undef DUNE_SIMD_LOOP_CMATH_UNARY_OP
518#undef DUNE_SIMD_LOOP_CMATH_UNARY_OP_WITH_RETURN
540#define DUNE_SIMD_LOOP_STD_UNARY_OP(expr) \
541 template<class T, std::size_t S, std::size_t A> \
542 auto expr(const LoopSIMD<T,S,A> &v) { \
544 LoopSIMD<T,S,A> out; \
545 for(std::size_t i=0; i<S; i++) { \
546 out[i] = expr(v[i]); \
551 template<class T, std::size_t S, std::size_t A> \
552 auto expr(const LoopSIMD<std::complex<T>,S,A> &v) { \
554 LoopSIMD<T,S,A> out; \
555 for(std::size_t i=0; i<S; i++) { \
556 out[i] = expr(v[i]); \
560 static_assert(true, "expecting ;")
565#undef DUNE_SIMD_LOOP_STD_UNARY_OP
567#define DUNE_SIMD_LOOP_STD_BINARY_OP(expr) \
568 template<class T, std::size_t S, std::size_t A> \
569 auto expr(const LoopSIMD<T,S,A> &v, const LoopSIMD<T,S,A> &w) { \
571 LoopSIMD<T,S,A> out; \
572 for(std::size_t i=0; i<S; i++) { \
573 out[i] = expr(v[i],w[i]); \
577 static_assert(true, "expecting ;")
582#undef DUNE_SIMD_LOOP_STD_BINARY_OP
584 namespace MathOverloads {
585 template<
class T, std::
size_t S, std::
size_t A>
588 for(
auto l :
range(S))
589 out[l] = Dune::isNaN(v[l]);
593 template<
class T, std::
size_t S, std::
size_t A>
596 for(
auto l :
range(S))
597 out[l] = Dune::isInf(v[l]);
601 template<
class T, std::
size_t S, std::
size_t A>
604 for(
auto l :
range(S))
605 out[l] = Dune::isFinite(v[l]);
610 template<
class T, std::
size_t S, std::
size_t A>
612 public std::integral_constant<bool, IsNumber<T>::value>{
615#ifdef CLANG_WARNING_DISABLED
616# pragma clang diagnostic pop
617# undef CLANG_WARNING_DISABLED
620#ifdef GCC_WARNING_DISABLED
621# pragma GCC diagnostic pop
622# undef GCC_WARNING_DISABLED
Traits for type conversions and type information.
Some useful basic math stuff.
#define DUNE_SIMD_LOOP_BINARY_OP(SYMBOL)
Definition loop.hh:177
#define DUNE_SIMD_LOOP_BOOLEAN_OP(SYMBOL)
Definition loop.hh:289
#define DUNE_SIMD_LOOP_STD_BINARY_OP(expr)
Definition loop.hh:567
#define DUNE_SIMD_LOOP_STD_UNARY_OP(expr)
Definition loop.hh:540
#define DUNE_SIMD_LOOP_BITSHIFT_OP(SYMBOL)
Definition loop.hh:221
#define DUNE_SIMD_LOOP_CMATH_UNARY_OP(expr)
Definition loop.hh:446
#define DUNE_PRAGMA_OMP_SIMD
Definition loop.hh:49
#define DUNE_SIMD_LOOP_CMATH_UNARY_OP_WITH_RETURN(expr, returnType)
Definition loop.hh:459
#define DUNE_SIMD_LOOP_ASSIGNMENT_OP(SYMBOL)
Definition loop.hh:145
std::integral_constant< std::size_t, i > index_constant
An index constant with value i.
Definition indices.hh:30
static StaticIntegralRange< T, to, from > range(std::integral_constant< T, from >, std::integral_constant< T, to >) noexcept
Definition rangeutilities.hh:300
std::ostream & operator<<(std::ostream &s, const bigunsignedint< k > &x)
Definition bigunsignedint.hh:278
bool anyTrue(const Mask &mask)
Whether any entry is true
Definition simd/interface.hh:429
V cond(M &&mask, const V &ifTrue, const V &ifFalse)
Like the ?: operator.
Definition simd/interface.hh:386
bool allTrue(const Mask &mask)
Whether all entries are true
Definition simd/interface.hh:439
bool anyFalse(const Mask &mask)
Whether any entry is false
Definition simd/interface.hh:449
constexpr std::size_t lanes()
Number of lanes in a SIMD type.
Definition simd/interface.hh:305
decltype(auto) lane(std::size_t l, V &&v)
Extract an element of a SIMD type.
Definition simd/interface.hh:324
Rebind< bool, V > Mask
Mask type type of some SIMD type.
Definition simd/interface.hh:289
bool allFalse(const Mask &mask)
Whether all entries are false
Definition simd/interface.hh:459
typename Overloads::ScalarType< std::decay_t< V > >::type Scalar
Element type of some SIMD type.
Definition simd/interface.hh:235
Mask< V > mask(ADLTag< 0, std::is_same< V, Mask< V > >::value >, const V &v)
implements Simd::mask()
Definition defaults.hh:153
bool allFalse(ADLTag< 0 >, const Mask &mask)
implements Simd::allFalse()
Definition defaults.hh:124
bool allTrue(ADLTag< 0 >, const Mask &mask)
implements Simd::allTrue()
Definition defaults.hh:104
bool anyFalse(ADLTag< 0 >, const Mask &mask)
implements Simd::anyFalse()
Definition defaults.hh:114
Dune namespace.
Definition alignedallocator.hh:13
DUNE_SIMD_LOOP_COMPARISON_OP(<)
bool anyTrue(ADLTag< 5 >, const AlignedNumber< bool, align > &mask)
Definition debugalign.hh:543
const AlignedNumber< T, align > & cond(ADLTag< 5 >, AlignedNumber< bool, align > mask, const AlignedNumber< T, align > &ifTrue, const AlignedNumber< T, align > &ifFalse)
Definition debugalign.hh:535
T & lane(ADLTag< 5 >, std::size_t l, AlignedNumber< T, align > &v)
Definition debugalign.hh:520
bool isNaN(const FieldVector< K, SIZE > &b, PriorityTag< 2 >, ADLTag)
Definition fvector.hh:604
bool isInf(const FieldVector< K, SIZE > &b, PriorityTag< 2 >, ADLTag)
Definition fvector.hh:594
auto isFinite(const FieldVector< K, SIZE > &b, PriorityTag< 2 >, ADLTag)
Definition fvector.hh:584
Whether this type acts as a scalar in the context of (hierarchically blocked) containers.
Definition typetraits.hh:194
Tag to make sure the functions in this namespace can be found by ADL.
Definition math.hh:230
Tag used to force late-binding lookup in Dune::Simd::Overloads.
Definition base.hh:182
should have a member type type
Definition standard.hh:60
should have a member type type
Definition standard.hh:67
should be derived from a Dune::index_constant
Definition standard.hh:74
LoopSIMD(Simd::Scalar< T > i)
Definition loop.hh:75
DUNE_SIMD_LOOP_PREFIX_OP(++)
auto operator!() const
Definition loop.hh:121
DUNE_SIMD_LOOP_POSTFIX_OP(--)
DUNE_SIMD_LOOP_ASSIGNMENT_OP * DUNE_SIMD_LOOP_ASSIGNMENT_OP(/=);DUNE_SIMD_LOOP_ASSIGNMENT_OP(%=
DUNE_SIMD_LOOP_ASSIGNMENT_OP & DUNE_SIMD_LOOP_ASSIGNMENT_OP(|=);DUNE_SIMD_LOOP_ASSIGNMENT_OP(^=
DUNE_SIMD_LOOP_UNARY_OP(-)
DUNE_SIMD_LOOP_PREFIX_OP(--)
DUNE_SIMD_LOOP_POSTFIX_OP(++)
DUNE_SIMD_LOOP_ASSIGNMENT_OP(-=)
LoopSIMD(const LoopSIMD< T, S, OA > &other)
Definition loop.hh:80
LoopSIMD()
Definition loop.hh:70
DUNE_SIMD_LOOP_UNARY_OP(~)
DUNE_SIMD_LOOP_ASSIGNMENT_OP(+=)
DUNE_SIMD_LOOP_UNARY_OP(+)
DUNE_SIMD_LOOP_ASSIGNMENT_OP(<<=)
DUNE_SIMD_LOOP_ASSIGNMENT_OP(> >=)
Simd::Scalar< T > type
Definition loop.hh:345
Helper class for tagging priorities.
Definition typeutilities.hh:73
Include file for users of the SIMD abstraction layer.