1 #ifndef DUNE_COMMON_SIMD_LOOP_HH
2 #define DUNE_COMMON_SIMD_LOOP_HH
21 # pragma GCC diagnostic push
22 # pragma GCC diagnostic ignored "-Wbool-operation"
23 # pragma GCC diagnostic ignored "-Wint-in-bool-context"
33 template<
class T, std::
size_t S>
51 #define DUNE_SIMD_LOOP_PREFIX_OP(SYMBOL) \
52 auto operator SYMBOL() { \
53 for(std::size_t i=0; i<S; i++){ \
58 static_assert(true, "expecting ;")
62 #undef DUNE_SIMD_LOOP_PREFIX_OP
65 #define DUNE_SIMD_LOOP_UNARY_OP(SYMBOL) \
66 auto operator SYMBOL() const { \
68 for(std::size_t i=0; i<S; i++){ \
69 out[i] = SYMBOL((*this)[i]); \
73 static_assert(true, "expecting ;")
81 for(std::size_t i=0; i<S; i++){
82 out[i] = !((*this)[i]);
86 #undef DUNE_SIMD_LOOP_UNARY_OP
89 #define DUNE_SIMD_LOOP_POSTFIX_OP(SYMBOL) \
90 auto operator SYMBOL(int){ \
91 LoopSIMD<T,S> out = *this; \
95 static_assert(true, "expecting ;")
99 #undef DUNE_SIMD_LOOP_POSTFIX_OP
102 #define DUNE_SIMD_LOOP_ASSIGNMENT_OP(SYMBOL) \
103 auto operator SYMBOL(const T s) { \
104 for(std::size_t i=0; i<S; i++){ \
105 (*this)[i] SYMBOL s; \
109 auto operator SYMBOL(const LoopSIMD<T,S> &v) { \
110 for(std::size_t i=0; i<S; i++){ \
111 (*this)[i] SYMBOL v[i]; \
115 static_assert(true, "expecting ;")
127 #undef DUNE_SIMD_LOOP_ASSIGNMENT_OP
131 #define DUNE_SIMD_LOOP_BINARY_OP(SYMBOL) \
132 template<class T, std::size_t S> \
133 auto operator SYMBOL(const LoopSIMD<T,S> &v, const T s) { \
135 for(std::size_t i=0; i<S; i++){ \
136 out[i] = v[i] SYMBOL s; \
140 template<class T, std::size_t S> \
141 auto operator SYMBOL(const T s, const LoopSIMD<T,S> &v) { \
143 for(std::size_t i=0; i<S; i++){ \
144 out[i] = s SYMBOL v[i]; \
148 template<class T, std::size_t S> \
149 auto operator SYMBOL(const LoopSIMD<T,S> &v, \
150 const LoopSIMD<T,S> &w) { \
152 for(std::size_t i=0; i<S; i++){ \
153 out[i] = v[i] SYMBOL w[i]; \
157 static_assert(true, "expecting ;")
169 #undef DUNE_SIMD_LOOP_BINARY_OP
172 #define DUNE_SIMD_LOOP_BITSHIFT_OP(SYMBOL) \
173 template<class T, std::size_t S, class U> \
174 auto operator SYMBOL(const LoopSIMD<T,S> &v, const U s) { \
176 for(std::size_t i=0; i<S; i++){ \
177 out[i] = v[i] SYMBOL s; \
181 template<class T, std::size_t S, class U> \
182 auto operator SYMBOL(const LoopSIMD<T,S> &v, \
183 const LoopSIMD<U,S> &w) { \
185 for(std::size_t i=0; i<S; i++){ \
186 out[i] = v[i] SYMBOL w[i]; \
190 static_assert(true, "expecting ;")
195 #undef DUNE_SIMD_LOOP_BITSHIFT_OP
198 #define DUNE_SIMD_LOOP_COMPARISON_OP(SYMBOL) \
199 template<class T, std::size_t S, class U> \
200 auto operator SYMBOL(const LoopSIMD<T,S> &v, const U s) { \
201 LoopSIMD<bool,S> out; \
202 for(std::size_t i=0; i<S; i++){ \
203 out[i] = v[i] SYMBOL s; \
207 template<class T, std::size_t S> \
208 auto operator SYMBOL(const T s, const LoopSIMD<T,S> &v) { \
209 LoopSIMD<bool,S> out; \
210 for(std::size_t i=0; i<S; i++){ \
211 out[i] = s SYMBOL v[i]; \
215 template<class T, std::size_t S> \
216 auto operator SYMBOL(const LoopSIMD<T,S> &v, \
217 const LoopSIMD<T,S> &w) { \
218 LoopSIMD<bool,S> out; \
219 for(std::size_t i=0; i<S; i++){ \
220 out[i] = v[i] SYMBOL w[i]; \
224 static_assert(true, "expecting ;")
232 #undef DUNE_SIMD_LOOP_COMPARISON_OP
235 #define DUNE_SIMD_LOOP_BOOLEAN_OP(SYMBOL) \
236 template<class T, std::size_t S> \
237 auto operator SYMBOL(const LoopSIMD<T,S> &v, const T s) { \
238 LoopSIMD<bool,S> out; \
239 for(std::size_t i=0; i<S; i++){ \
240 out[i] = v[i] SYMBOL s; \
244 template<class T, std::size_t S> \
245 auto operator SYMBOL(const bool s, const LoopSIMD<T,S> &v) { \
246 LoopSIMD<bool,S> out; \
247 for(std::size_t i=0; i<S; i++){ \
248 out[i] = s SYMBOL v[i]; \
252 template<class T, std::size_t S> \
253 auto operator SYMBOL(const LoopSIMD<T,S> &v, \
254 const LoopSIMD<T,S> &w) { \
255 LoopSIMD<bool,S> out; \
256 for(std::size_t i=0; i<S; i++){ \
257 out[i] = v[i] SYMBOL w[i]; \
261 static_assert(true, "expecting ;")
265 #undef DUNE_SIMD_LOOP_BOOLEAN_OP
268 template<
class T, std::
size_t S>
271 for(std::size_t i=0; i<S-1; i++) {
279 namespace Overloads {
286 template<
class T, std::
size_t S>
291 template<
class U,
class T, std::
size_t S>
297 template<
class T, std::
size_t S>
300 template<
class T, std::
size_t S>
302 return std::move(v[l]);
305 template<
class T, std::
size_t S>
310 template<
class T, std::
size_t S>
315 template<
class T, std::
size_t S>
319 for(std::size_t i=0; i<S; i++) {
320 out[i] =
mask[i] ? ifTrue[i] : ifFalse[i];
325 template<
class M,
class T>
327 LoopSIMD<T,Simd::lanes<M>()> ifTrue,
328 LoopSIMD<T,Simd::lanes<M>()> ifFalse)
336 template<std::
size_t S>
339 for(std::size_t i=0; i<S; i++) {
345 template<std::
size_t S>
348 for(std::size_t i=0; i<S; i++) {
354 template<std::
size_t S>
357 for(std::size_t i=0; i<S; i++) {
363 template<std::
size_t S>
366 for(std::size_t i=0; i<S; i++) {
383 #define DUNE_SIMD_LOOP_CMATH_UNARY_OP(expr) \
384 template<class T, std::size_t S, typename Sfinae = \
385 typename std::enable_if_t<!std::is_integral<T>::value> > \
386 auto expr(const LoopSIMD<T,S> &v) { \
389 for(std::size_t i=0; i<S; i++) { \
390 out[i] = expr(v[i]); \
394 static_assert(true, "expecting ;")
396 #define DUNE_SIMD_LOOP_CMATH_UNARY_OP_WITH_RETURN(expr, returnType) \
397 template<class T, std::size_t S, typename Sfinae = \
398 typename std::enable_if_t<!std::is_integral<T>::value> > \
399 auto expr(const LoopSIMD<T,S> &v) { \
401 LoopSIMD<returnType,S> out; \
402 for(std::size_t i=0; i<S; i++) { \
403 out[i] = expr(v[i]); \
407 static_assert(true, "expecting ;")
454 #undef DUNE_SIMD_LOOP_CMATH_UNARY_OP
455 #undef DUNE_SIMD_LOOP_CMATH_UNARY_OP_WITH_RETURN
477 #define DUNE_SIMD_LOOP_STD_UNARY_OP(expr) \
478 template<class T, std::size_t S> \
479 auto expr(const LoopSIMD<T,S> &v) { \
482 for(std::size_t i=0; i<S; i++) { \
483 out[i] = expr(v[i]); \
488 template<class T, std::size_t S> \
489 auto expr(const LoopSIMD<std::complex<T>,S> &v) { \
492 for(std::size_t i=0; i<S; i++) { \
493 out[i] = expr(v[i]); \
497 static_assert(true, "expecting ;")
502 #undef DUNE_SIMD_LOOP_STD_UNARY_OP
504 #define DUNE_SIMD_LOOP_STD_BINARY_OP(expr) \
505 template<class T, std::size_t S> \
506 auto expr(const LoopSIMD<T,S> &v, const LoopSIMD<T,S> &w) { \
509 for(std::size_t i=0; i<S; i++) { \
510 out[i] = expr(v[i],w[i]); \
514 static_assert(true, "expecting ;")
519 #undef DUNE_SIMD_LOOP_STD_BINARY_OP
521 namespace MathOverloads {
522 template<
class T, std::
size_t S>
525 for(
auto l :
range(S))
530 template<
class T, std::
size_t S>
533 for(
auto l :
range(S))
538 template<
class T, std::
size_t S>
541 for(
auto l :
range(S))
547 template<
class T, std::
size_t S>
549 public std::integral_constant<bool, IsNumber<T>::value>{
553 # pragma GCC diagnostic pop
Some useful basic math stuff.
Traits for type conversions and type information.
std::integral_constant< std::size_t, i > index_constant
An index constant with value i.
Definition: indices.hh:28
std::ostream & operator<<(std::ostream &s, const bigunsignedint< k > &x)
Definition: bigunsignedint.hh:273
I round(const T &val, typename EpsilonType< T >::Type epsilon)
round using epsilon
Definition: float_cmp.cc:309
I trunc(const T &val, typename EpsilonType< T >::Type epsilon)
truncate using epsilon
Definition: float_cmp.cc:405
constexpr std::size_t lanes()
Number of lanes in a SIMD type.
Definition: simd/interface.hh:303
decltype(auto) lane(std::size_t l, V &&v)
Extract an element of a SIMD type.
Definition: simd/interface.hh:322
typename Overloads::ScalarType< std::decay_t< V > >::type Scalar
Element type of some SIMD type.
Definition: simd/interface.hh:233
bool allFalse(ADLTag< 0 >, const Mask &mask)
implements Simd::allFalse()
Definition: defaults.hh:122
bool allTrue(ADLTag< 0 >, const Mask &mask)
implements Simd::allTrue()
Definition: defaults.hh:102
Mask< V > mask(ADLTag< 0, std::is_same< V, Mask< V > >::value >, const V &v)
implements Simd::mask()
Definition: defaults.hh:151
bool anyFalse(ADLTag< 0 >, const Mask &mask)
implements Simd::anyFalse()
Definition: defaults.hh:112
Dune namespace.
Definition: alignedallocator.hh:14
DUNE_SIMD_LOOP_CMATH_UNARY_OP_WITH_RETURN(ilogb, int)
DUNE_SIMD_LOOP_STD_BINARY_OP(max)
DUNE_SIMD_LOOP_BOOLEAN_OP && DUNE_SIMD_LOOP_BOOLEAN_OP(||);template< class T, std::size_t S > std::ostream &operator<<(std::ostream &os, const LoopSIMD< T, S > &v
Definition: loop.hh:264
DUNE_SIMD_LOOP_BINARY_OP(+)
static StaticIntegralRange< T, to, from > range(std::integral_constant< T, from >, std::integral_constant< T, to >) noexcept
Definition: rangeutilities.hh:297
DUNE_SIMD_LOOP_CMATH_UNARY_OP(cos)
DUNE_SIMD_LOOP_COMPARISON_OP(<)
DUNE_SIMD_LOOP_BITSHIFT_OP(<<)
DUNE_SIMD_LOOP_STD_UNARY_OP(real)
auto min(const AlignedNumber< T, align > &a, const AlignedNumber< T, align > &b)
Definition: debugalign.hh:434
auto max(const AlignedNumber< T, align > &a, const AlignedNumber< T, align > &b)
Definition: debugalign.hh:412
bool anyTrue(ADLTag< 5 >, const AlignedNumber< bool, align > &mask)
Definition: debugalign.hh:530
T & lane(ADLTag< 5 >, std::size_t l, AlignedNumber< T, align > &v)
Definition: debugalign.hh:507
const AlignedNumber< T, align > & cond(ADLTag< 5 >, AlignedNumber< bool, align > mask, const AlignedNumber< T, align > &ifTrue, const AlignedNumber< T, align > &ifFalse)
Definition: debugalign.hh:522
bool isNaN(const FieldVector< K, SIZE > &b, PriorityTag< 2 >, ADLTag)
Definition: fvector.hh:613
bool isInf(const FieldVector< K, SIZE > &b, PriorityTag< 2 >, ADLTag)
Definition: fvector.hh:603
auto isFinite(const FieldVector< K, SIZE > &b, PriorityTag< 2 >, ADLTag)
Definition: fvector.hh:593
auto isInf(const LoopSIMD< T, S > &v, PriorityTag< 3 >, ADLTag)
Definition: loop.hh:531
auto isNaN(const LoopSIMD< T, S > &v, PriorityTag< 3 >, ADLTag)
Definition: loop.hh:523
auto isFinite(const LoopSIMD< T, S > &v, PriorityTag< 3 >, ADLTag)
Definition: loop.hh:539
Tag to make sure the functions in this namespace can be found by ADL.
Definition: math.hh:227
Tag used to force late-binding lookup in Dune::Simd::Overloads.
Definition: base.hh:180
should have a member type type
Definition: standard.hh:58
should have a member type type
Definition: standard.hh:65
should be derived from a Dune::index_constant
Definition: standard.hh:72
DUNE_SIMD_LOOP_ASSIGNMENT_OP & DUNE_SIMD_LOOP_ASSIGNMENT_OP(|=);DUNE_SIMD_LOOP_ASSIGNMENT_OP(^=
DUNE_SIMD_LOOP_ASSIGNMENT_OP(>>=)
DUNE_SIMD_LOOP_PREFIX_OP(++)
DUNE_SIMD_LOOP_PREFIX_OP(--)
DUNE_SIMD_LOOP_UNARY_OP(-)
LoopSIMD(T i)
Definition: loop.hh:42
DUNE_SIMD_LOOP_ASSIGNMENT_OP(-=)
LoopSIMD()
Definition: loop.hh:39
DUNE_SIMD_LOOP_ASSIGNMENT_OP * DUNE_SIMD_LOOP_ASSIGNMENT_OP(/=);DUNE_SIMD_LOOP_ASSIGNMENT_OP(%=
DUNE_SIMD_LOOP_POSTFIX_OP(--)
DUNE_SIMD_LOOP_POSTFIX_OP(++)
auto operator!() const
Definition: loop.hh:79
DUNE_SIMD_LOOP_UNARY_OP(~)
DUNE_SIMD_LOOP_ASSIGNMENT_OP(<<=)
DUNE_SIMD_LOOP_ASSIGNMENT_OP(+=)
DUNE_SIMD_LOOP_UNARY_OP(+)
T type
Definition: loop.hh:288
Whether this type acts as a scalar in the context of (hierarchically blocked) containers.
Definition: typetraits.hh:163
Helper class for tagging priorities.
Definition: typeutilities.hh:71
Include file for users of the SIMD abstraction layer.