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 ;")
60 DUNE_SIMD_LOOP_PREFIX_OP(++);
61 DUNE_SIMD_LOOP_PREFIX_OP(--);
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 ;")
75 DUNE_SIMD_LOOP_UNARY_OP(+);
76 DUNE_SIMD_LOOP_UNARY_OP(-);
77 DUNE_SIMD_LOOP_UNARY_OP(~);
79 auto operator!()
const {
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 ;")
97 DUNE_SIMD_LOOP_POSTFIX_OP(++);
98 DUNE_SIMD_LOOP_POSTFIX_OP(--);
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 ;")
117 DUNE_SIMD_LOOP_ASSIGNMENT_OP(+=);
118 DUNE_SIMD_LOOP_ASSIGNMENT_OP(-=);
119 DUNE_SIMD_LOOP_ASSIGNMENT_OP(*=);
120 DUNE_SIMD_LOOP_ASSIGNMENT_OP(/=);
121 DUNE_SIMD_LOOP_ASSIGNMENT_OP(%=);
122 DUNE_SIMD_LOOP_ASSIGNMENT_OP(<<=);
123 DUNE_SIMD_LOOP_ASSIGNMENT_OP(>>=);
124 DUNE_SIMD_LOOP_ASSIGNMENT_OP(&=);
125 DUNE_SIMD_LOOP_ASSIGNMENT_OP(|=);
126 DUNE_SIMD_LOOP_ASSIGNMENT_OP(^=);
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 ;")
159 DUNE_SIMD_LOOP_BINARY_OP(+);
160 DUNE_SIMD_LOOP_BINARY_OP(-);
161 DUNE_SIMD_LOOP_BINARY_OP(*);
162 DUNE_SIMD_LOOP_BINARY_OP(/);
163 DUNE_SIMD_LOOP_BINARY_OP(%);
165 DUNE_SIMD_LOOP_BINARY_OP(&);
166 DUNE_SIMD_LOOP_BINARY_OP(|);
167 DUNE_SIMD_LOOP_BINARY_OP(^);
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 ;")
192 DUNE_SIMD_LOOP_BITSHIFT_OP(<<);
193 DUNE_SIMD_LOOP_BITSHIFT_OP(>>);
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 ;")
226 DUNE_SIMD_LOOP_COMPARISON_OP(<);
227 DUNE_SIMD_LOOP_COMPARISON_OP(>);
228 DUNE_SIMD_LOOP_COMPARISON_OP(<=);
229 DUNE_SIMD_LOOP_COMPARISON_OP(>=);
230 DUNE_SIMD_LOOP_COMPARISON_OP(==);
231 DUNE_SIMD_LOOP_COMPARISON_OP(!=);
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 ;")
263 DUNE_SIMD_LOOP_BOOLEAN_OP(&&);
264 DUNE_SIMD_LOOP_BOOLEAN_OP(||);
265#undef DUNE_SIMD_LOOP_BOOLEAN_OP
268 template<
class T, std::
size_t S>
269 std::ostream& operator<< (std::ostream &os,
const LoopSIMD<T,S> &v) {
271 for(std::size_t i=0; i<S-1; i++) {
279 namespace Overloads {
286 template<
class T, std::
size_t S>
287 struct ScalarType<LoopSIMD<T,S>> {
291 template<
class U,
class T, std::
size_t S>
292 struct RebindType<U, LoopSIMD<T,S>> {
293 using type = LoopSIMD<U,S>;
297 template<
class T, std::
size_t S>
300 template<
class T, std::
size_t S>
301 T&& lane(ADLTag<5>, std::size_t l, LoopSIMD<T,S> &&v) {
302 return std::move(v[l]);
305 template<
class T, std::
size_t S>
306 const T& lane(ADLTag<5>, std::size_t l,
const LoopSIMD<T,S> &v) {
310 template<
class T, std::
size_t S>
311 T& lane(ADLTag<5>, std::size_t l, LoopSIMD<T,S> &v) {
315 template<
class T, std::
size_t S>
316 auto cond(ADLTag<5>, LoopSIMD<bool,S>
mask,
317 LoopSIMD<T,S> ifTrue, LoopSIMD<T,S> ifFalse) {
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>
326 auto cond(ADLTag<5, std::is_same<
bool, Scalar<M> >::value>, M
mask,
327 LoopSIMD<T,Simd::lanes<M>()> ifTrue,
328 LoopSIMD<T,Simd::lanes<M>()> ifFalse)
330 LoopSIMD<T,Simd::lanes<M>()> out;
336 template<std::
size_t S>
337 bool anyTrue(ADLTag<5>, LoopSIMD<bool,S>
mask) {
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 ;")
409 DUNE_SIMD_LOOP_CMATH_UNARY_OP(cos);
410 DUNE_SIMD_LOOP_CMATH_UNARY_OP(sin);
411 DUNE_SIMD_LOOP_CMATH_UNARY_OP(tan);
412 DUNE_SIMD_LOOP_CMATH_UNARY_OP(acos);
413 DUNE_SIMD_LOOP_CMATH_UNARY_OP(asin);
414 DUNE_SIMD_LOOP_CMATH_UNARY_OP(atan);
415 DUNE_SIMD_LOOP_CMATH_UNARY_OP(cosh);
416 DUNE_SIMD_LOOP_CMATH_UNARY_OP(sinh);
417 DUNE_SIMD_LOOP_CMATH_UNARY_OP(tanh);
418 DUNE_SIMD_LOOP_CMATH_UNARY_OP(acosh);
419 DUNE_SIMD_LOOP_CMATH_UNARY_OP(asinh);
420 DUNE_SIMD_LOOP_CMATH_UNARY_OP(atanh);
422 DUNE_SIMD_LOOP_CMATH_UNARY_OP(exp);
423 DUNE_SIMD_LOOP_CMATH_UNARY_OP(log);
424 DUNE_SIMD_LOOP_CMATH_UNARY_OP(log10);
425 DUNE_SIMD_LOOP_CMATH_UNARY_OP(exp2);
426 DUNE_SIMD_LOOP_CMATH_UNARY_OP(expm1);
427 DUNE_SIMD_LOOP_CMATH_UNARY_OP_WITH_RETURN(ilogb,
int);
428 DUNE_SIMD_LOOP_CMATH_UNARY_OP(log1p);
429 DUNE_SIMD_LOOP_CMATH_UNARY_OP(log2);
430 DUNE_SIMD_LOOP_CMATH_UNARY_OP(logb);
432 DUNE_SIMD_LOOP_CMATH_UNARY_OP(sqrt);
433 DUNE_SIMD_LOOP_CMATH_UNARY_OP(cbrt);
435 DUNE_SIMD_LOOP_CMATH_UNARY_OP(erf);
436 DUNE_SIMD_LOOP_CMATH_UNARY_OP(erfc);
437 DUNE_SIMD_LOOP_CMATH_UNARY_OP(tgamma);
438 DUNE_SIMD_LOOP_CMATH_UNARY_OP(lgamma);
440 DUNE_SIMD_LOOP_CMATH_UNARY_OP(ceil);
441 DUNE_SIMD_LOOP_CMATH_UNARY_OP(floor);
442 DUNE_SIMD_LOOP_CMATH_UNARY_OP(
trunc);
443 DUNE_SIMD_LOOP_CMATH_UNARY_OP(
round);
444 DUNE_SIMD_LOOP_CMATH_UNARY_OP_WITH_RETURN(lround,
long);
445 DUNE_SIMD_LOOP_CMATH_UNARY_OP_WITH_RETURN(llround,
long long);
446 DUNE_SIMD_LOOP_CMATH_UNARY_OP(rint);
447 DUNE_SIMD_LOOP_CMATH_UNARY_OP_WITH_RETURN(lrint,
long);
448 DUNE_SIMD_LOOP_CMATH_UNARY_OP_WITH_RETURN(llrint,
long long);
449 DUNE_SIMD_LOOP_CMATH_UNARY_OP(nearbyint);
451 DUNE_SIMD_LOOP_CMATH_UNARY_OP(fabs);
452 DUNE_SIMD_LOOP_CMATH_UNARY_OP(abs);
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 ;")
499 DUNE_SIMD_LOOP_STD_UNARY_OP(real);
500 DUNE_SIMD_LOOP_STD_UNARY_OP(imag);
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 ;")
516 DUNE_SIMD_LOOP_STD_BINARY_OP(
max);
517 DUNE_SIMD_LOOP_STD_BINARY_OP(
min);
519#undef DUNE_SIMD_LOOP_STD_BINARY_OP
521 namespace MathOverloads {
522 template<
class T, std::
size_t S>
523 auto isNaN(
const LoopSIMD<T,S> &v, PriorityTag<3>, ADLTag) {
524 LoopSIMD<bool,S> out;
525 for(
auto l : range(S))
526 out[l] = Dune::isNaN(v[l]);
530 template<
class T, std::
size_t S>
531 auto isInf(
const LoopSIMD<T,S> &v, PriorityTag<3>, ADLTag) {
532 LoopSIMD<bool,S> out;
533 for(
auto l : range(S))
534 out[l] = Dune::isInf(v[l]);
538 template<
class T, std::
size_t S>
539 auto isFinite(
const LoopSIMD<T,S> &v, PriorityTag<3>, ADLTag) {
540 LoopSIMD<bool,S> out;
541 for(
auto l : range(S))
542 out[l] = Dune::isFinite(v[l]);
547 template<
class T, std::
size_t S>
548 struct IsNumber<LoopSIMD<T,S>> :
549 public std::integral_constant<bool, IsNumber<T>::value>{
553# pragma GCC diagnostic pop
std::integral_constant< std::size_t, i > index_constant
An index constant with value i.
Definition: indices.hh:28
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
Mask< V > mask(ADLTag< 0, std::is_same< V, Mask< V > >::value >, const V &v)
implements Simd::mask()
Definition: defaults.hh:151
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
bool anyFalse(ADLTag< 0 >, const Mask &mask)
implements Simd::anyFalse()
Definition: defaults.hh:112
auto min(ADLTag< 0 >, const V &v1, const V &v2)
implements binary Simd::min()
Definition: defaults.hh:87
auto max(ADLTag< 0 >, const V &v1, const V &v2)
implements binary Simd::max()
Definition: defaults.hh:79
constexpr std::size_t lanes()
Number of lanes in a SIMD type.
Definition: interface.hh:303
decltype(auto) lane(std::size_t l, V &&v)
Extract an element of a SIMD type.
Definition: interface.hh:322
Some useful basic math stuff.
Dune namespace.
Definition: alignedallocator.hh:14
const T1 cond(bool b, const T1 &v1, const T2 &v2)
conditional evaluate
Definition: conditional.hh:26
Include file for users of the SIMD abstraction layer.
Traits for type conversions and type information.