3#ifndef DUNE_COMMON_SIMD_TEST_HH 
    4#define DUNE_COMMON_SIMD_TEST_HH 
   20#include <unordered_set> 
   24#include <dune/common/hybridutilities.hh> 
   27#include <dune/common/simd/loop.hh> 
   29#include <dune/common/std/type_traits.hh> 
   30#include <dune/common/typelist.hh> 
   38      template<
class T, 
class SFINAE = 
void>
 
   39      struct LessThenComparable : std::false_type {};
 
   41      struct LessThenComparable<T, 
std::
void_t<decltype(std::declval<T>()
 
   42                                                   < std::declval<T>())> > :
 
   46      template<
class Dst, 
class Src>
 
   47      struct CopyConstHelper
 
   51      template<
class Dst, 
class Src>
 
   52      struct CopyConstHelper<Dst, const Src>
 
   54        using type = std::add_const_t<Dst>;
 
   57      template<
class Dst, 
class Src>
 
   58      struct CopyVolatileHelper
 
   62      template<
class Dst, 
class Src>
 
   63      struct CopyVolatileHelper<Dst, volatile Src>
 
   65        using type = std::add_volatile_t<Dst>;
 
   68      template<
class Dst, 
class Src>
 
   69      struct CopyReferenceHelper
 
   73      template<
class Dst, 
class Src>
 
   74      struct CopyReferenceHelper<Dst, Src&>
 
   76        using type = std::add_lvalue_reference_t<Dst>;
 
   79      template<
class Dst, 
class Src>
 
   80      struct CopyReferenceHelper<Dst, Src&&>
 
   82        using type = std::add_rvalue_reference_t<Dst>;
 
   85      template<
class Dst, 
class Src>
 
   86      using CopyRefQual = 
typename CopyReferenceHelper<
 
   87        typename CopyVolatileHelper<
 
   88          typename CopyConstHelper<
 
   90            std::remove_reference_t<Src>
 
   92          std::remove_reference_t<Src>
 
   97      template<
class Mark, 
class Types,
 
   99                 std::make_index_sequence<TypeListSize<Types>::value - 1> >
 
  101      template<
class Mark, 
class Types, std::size_t... I>
 
  102      struct RemoveEnd<Mark, Types, 
std::index_sequence<I...>>
 
  104        using Back = TypeListEntry_t<TypeListSize<Types>::value - 1, Types>;
 
  105        static_assert(std::is_same<Mark, Back>::value,
 
  106                      "TypeList not terminated by proper EndMark");
 
  107        using type = TypeList<TypeListEntry_t<I, Types>...>;
 
  110      template<
class T, 
class List, 
class = 
void>
 
  114      struct TypeInList<T, 
TypeList<> > : std::false_type {};
 
  116      template<
class T, 
class... Rest>
 
  117      struct TypeInList<T, 
TypeList<T, Rest...> > : std::true_type {};
 
  119      template<
class T, 
class Head, 
class... Rest>
 
  120      struct TypeInList<T, 
TypeList<Head, Rest...>,
 
  121                        std::enable_if_t<!std::is_same<T, Head>::value> > :
 
  122        TypeInList<T, TypeList<Rest...> >::type
 
  126      struct IsLoop : std::false_type {};
 
  127      template<
class T, std::
size_t S>
 
  128      struct IsLoop<LoopSIMD<T, S> > : std::true_type {};
 
  137      constexpr bool debugTypes(std::true_type) { 
return true; }
 
  138      template<
class... Types>
 
  140      constexpr bool debugTypes(std::false_type) { 
return false; }
 
  156    template<
class... Types>
 
  162    using IsLoop = 
typename Impl::IsLoop<T>::type;
 
  166      std::ostream &log_ = std::cerr;
 
  169      std::unordered_set<std::type_index> seen_;
 
  176      void complain(
const char *file, 
int line, 
const char *func,
 
  179      void complain(
const char *file, 
int line, 
const char *func,
 
  180                    const std::string &opname, 
const char *expr);
 
  186#define DUNE_SIMD_CHECK(expr)                                           \ 
  187      ((expr) ? void() : complain(__FILE__, __LINE__, __func__, #expr)) 
  191#define DUNE_SIMD_CHECK_OP(expr)                                \ 
  192      ((expr) ? void() : complain(__FILE__, __LINE__, __func__, \ 
  193                                  DUNE_SIMD_OPNAME, #expr)) 
  197      static std::decay_t<T> prvalue(T &&t)
 
  199        return std::forward<T>(t);
 
  204      static bool is42(
const V &v)
 
  208        for(std::size_t l = 0; l < 
lanes(v); ++l)
 
  224        for(std::size_t l = 0; l < 
lanes(vec); ++l)
 
  225          lane(l, vec) = l + 1;
 
  231      static bool is123(
const V &v)
 
  235        for(std::size_t l = 0; l < 
lanes(v); ++l)
 
  243      static V leftVector()
 
  248        for(std::size_t l = 0; l < 
lanes(res); ++l)
 
  254      static V rightVector()
 
  259        for(std::size_t l = 0; l < 
lanes(res); ++l)
 
  267      static T leftScalar()
 
  273      static T rightScalar()
 
  280      template<
class Dst, 
class Src>
 
  281      using CopyRefQual = Impl::CopyRefQual<Dst, Src>;
 
  288      template<
class Op, 
class... Vectors>
 
  290        decltype(std::declval<Op>().
 
  305        static_assert(std::is_same<T, std::decay_t<T> >::value, 
"Scalar types " 
  306                      "must not be references, and must not include " 
  308        [[maybe_unused]] T a{};
 
  312      [[deprecated(
"Warning: please include bool in the Rebinds for " 
  313                          "simd type V, as Masks are not checked otherwise.")]]
 
  314      void warnMissingMaskRebind(std::true_type) {}
 
  316      void warnMissingMaskRebind(std::false_type) {}
 
  318      template<
class V, 
class Rebinds, 
template<
class> 
class RebindPrune,
 
  319               template<
class> 
class RebindAccept, 
class Recurse>
 
  320      void checkRebindOf(Recurse recurse)
 
  323            using T = 
typename decltype(target)::type;
 
  327            log_ << 
"Type " << className<V>() << 
" rebound to " 
  328                 << className<T>() << 
" is " << className<W>() << std::endl;
 
  330            static_assert(std::is_same<W, std::decay_t<W> >::value, 
"Rebound " 
  331                          "types must not be references, and must not include " 
  333            static_assert(lanes<V>() == lanes<W>(), 
"Rebound types must have " 
  334                          "the same number of lanes as the original vector " 
  336            static_assert(std::is_same<T, Scalar<W> >::value, 
"Rebound types " 
  337                          "must have the bound-to scalar type");
 
  339            if constexpr (RebindPrune<W>{}) {
 
  340              log_ << 
"Pruning check of Simd type " << className<W>()
 
  344              using Impl::debugTypes;
 
  345              static_assert(debugTypes<T, V, W>(RebindAccept<W>{}),
 
  346                            "Rebind<T, V> is W, but that is not accepted " 
  352        static_assert(std::is_same<Rebind<Scalar<V>, V>, V>::value, 
"A type " 
  353                      "rebound to its own scalar type must be the same type " 
  354                      "as the original type");
 
  355        static_assert(std::is_same<Rebind<bool, V>, 
Mask<V> >::value, 
"A type " 
  356                      "rebound to bool must be the mask type for that type");
 
  358        constexpr bool hasBool = Impl::TypeInList<bool, Rebinds>::value;
 
  359        warnMissingMaskRebind<V>(Std::bool_constant<!hasBool>{});
 
  371        static_assert(std::is_same<std::size_t, decltype(lanes<V>())>::value,
 
  372                      "return type of lanes<V>() should be std::size_t");
 
  373        static_assert(std::is_same<std::size_t, 
decltype(
lanes(V{}))>::value,
 
  374                      "return type of lanes(V{}) should be std::size_t");
 
  377        [[maybe_unused]] 
constexpr auto size = lanes<V>();
 
  379        DUNE_SIMD_CHECK(lanes<V>() == 
lanes(V{}));
 
  383      void checkDefaultConstruct()
 
  385        { [[maybe_unused]] V vec;      }
 
  386        { [[maybe_unused]] V vec{};    }
 
  387        { [[maybe_unused]] V vec = {}; }
 
  397        for(std::size_t l = 0; l < 
lanes(vec); ++l)
 
  398          lane(l, vec) = l + 1;
 
  399        for(std::size_t l = 0; l < 
lanes(vec); ++l)
 
  401        using MLRes = 
decltype(
lane(0, vec));
 
  402        static_assert(std::is_same<MLRes, Scalar<V>&>::value ||
 
  403                      std::is_same<MLRes, std::decay_t<MLRes> >::value,
 
  404                      "Result of lane() on a mutable lvalue vector must " 
  405                      "either be a mutable reference to a scalar of that " 
  406                      "vector or a proxy object (which itself may not be a " 
  407                      "reference nor const).");
 
  411        for(std::size_t l = 0; l < 
lanes(vec); ++l)
 
  413        using CLRes = 
decltype(
lane(0, vec2));
 
  414        static_assert(std::is_same<CLRes, const Scalar<V>&>::value ||
 
  415                      std::is_same<CLRes, std::decay_t<CLRes> >::value,
 
  416                      "Result of lane() on a const lvalue vector must " 
  417                      "either be a const lvalue reference to a scalar of that " 
  418                      "vector or a proxy object (which itself may not be a " 
  419                      "reference nor const).");
 
  420        static_assert(!std::is_assignable<CLRes, Scalar<V> >::value,
 
  421                      "Result of lane() on a const lvalue vector must not be " 
  422                      "assignable from a scalar.");
 
  425        for(std::size_t l = 0; l < 
lanes(vec); ++l)
 
  427        using RRes = 
decltype(
lane(0, prvalue(vec)));
 
  436        static_assert(std::is_same<RRes, Scalar<V>  >::value ||
 
  437                      std::is_same<RRes, Scalar<V>&&>::value,
 
  438                      "Result of lane() on a rvalue vector V must be " 
  439                      "Scalar<V> or Scalar<V>&&.");
 
  450      void checkCopyMoveConstruct()
 
  453        { V vec   (make123<V>()); DUNE_SIMD_CHECK(is123(vec)); }
 
  454        { V vec =  make123<V>() ; DUNE_SIMD_CHECK(is123(vec)); }
 
  455        { V vec   {make123<V>()}; DUNE_SIMD_CHECK(is123(vec)); }
 
  456        { V vec = {make123<V>()}; DUNE_SIMD_CHECK(is123(vec)); }
 
  459        {       V ref(make123<V>());     V vec   (ref);
 
  460          DUNE_SIMD_CHECK(is123(vec)); DUNE_SIMD_CHECK(is123(ref)); }
 
  461        {       V ref(make123<V>());     V vec =  ref ;
 
  462          DUNE_SIMD_CHECK(is123(vec)); DUNE_SIMD_CHECK(is123(ref)); }
 
  463        {       V ref(make123<V>());     V vec   {ref};
 
  464          DUNE_SIMD_CHECK(is123(vec)); DUNE_SIMD_CHECK(is123(ref)); }
 
  465        {       V ref(make123<V>());     V vec = {ref};
 
  466          DUNE_SIMD_CHECK(is123(vec)); DUNE_SIMD_CHECK(is123(ref)); }
 
  467        { 
const V ref(make123<V>());     V vec   (ref);
 
  468          DUNE_SIMD_CHECK(is123(vec)); }
 
  469        { 
const V ref(make123<V>());     V vec =  ref ;
 
  470          DUNE_SIMD_CHECK(is123(vec)); }
 
  471        { 
const V ref(make123<V>());     V vec   {ref};
 
  472          DUNE_SIMD_CHECK(is123(vec)); }
 
  473        { 
const V ref(make123<V>());     V vec = {ref};
 
  474          DUNE_SIMD_CHECK(is123(vec)); }
 
  477        { V ref(make123<V>());           V vec   (std::move(ref));
 
  478          DUNE_SIMD_CHECK(is123(vec)); }
 
  479        { V ref(make123<V>());           V vec =  std::move(ref) ;
 
  480          DUNE_SIMD_CHECK(is123(vec)); }
 
  481        { V ref(make123<V>());           V vec   {std::move(ref)};
 
  482          DUNE_SIMD_CHECK(is123(vec)); }
 
  483        { V ref(make123<V>());           V vec = {std::move(ref)};
 
  484          DUNE_SIMD_CHECK(is123(vec)); }
 
  488      void checkBroadcastVectorConstruct()
 
  492          DUNE_SIMD_CHECK(is42(vec)); DUNE_SIMD_CHECK(ref == 
Scalar<V>(42)); }
 
  494          DUNE_SIMD_CHECK(is42(vec)); DUNE_SIMD_CHECK(ref == 
Scalar<V>(42)); }
 
  500          DUNE_SIMD_CHECK(is42(vec)); }
 
  501        { 
const Scalar<V> ref = 42;      V vec =  ref ;
 
  502          DUNE_SIMD_CHECK(is42(vec)); }
 
  509        { 
Scalar<V> ref = 42;            V vec   (std::move(ref));
 
  510          DUNE_SIMD_CHECK(is42(vec)); }
 
  511        { 
Scalar<V> ref = 42;            V vec =  std::move(ref) ;
 
  512          DUNE_SIMD_CHECK(is42(vec)); }
 
  520      void checkBroadcastMaskConstruct()
 
  524          DUNE_SIMD_CHECK(is42(vec)); DUNE_SIMD_CHECK(ref == 
Scalar<V>(42)); }
 
  528          DUNE_SIMD_CHECK(is42(vec)); DUNE_SIMD_CHECK(ref == 
Scalar<V>(42)); }
 
  532          DUNE_SIMD_CHECK(is42(vec)); }
 
  536          DUNE_SIMD_CHECK(is42(vec)); }
 
  541        { 
Scalar<V> ref = 42;            V vec   (std::move(ref));
 
  542          DUNE_SIMD_CHECK(is42(vec)); }
 
  545        { 
Scalar<V> ref = 42;            V vec   {std::move(ref)};
 
  546          DUNE_SIMD_CHECK(is42(vec)); }
 
  552      template<
class FromV, 
class ToV>
 
  556          FromV fromVec = make123<FromV>();
 
  557          auto toVec = implCast<ToV>(fromVec);
 
  558          static_assert(std::is_same<
decltype(toVec), ToV>::value,
 
  559                        "Unexpected result type for implCast<ToV>(FromV&)");
 
  560          DUNE_SIMD_CHECK(is123(fromVec));
 
  561          DUNE_SIMD_CHECK(is123(toVec));
 
  565          const FromV fromVec = make123<FromV>();
 
  566          auto toVec = implCast<ToV>(fromVec);
 
  567          static_assert(std::is_same<
decltype(toVec), ToV>::value,
 
  568                        "Unexpected result type for implCast<ToV>(const " 
  570          DUNE_SIMD_CHECK(is123(toVec));
 
  574          auto toVec = implCast<ToV>(make123<FromV>());
 
  575          static_assert(std::is_same<
decltype(toVec), ToV>::value,
 
  576                        "Unexpected result type for implCast<ToV>(FromV&&)");
 
  577          DUNE_SIMD_CHECK(is123(toVec));
 
  588        checkImplCast<V, V>();
 
  589        checkImplCast<V, LoopV>();
 
  590        checkImplCast<LoopV, V>();
 
  595      void checkBroadcast()
 
  600          auto vec = broadcast<V>(ref);
 
  601          static_assert(std::is_same<
decltype(vec), V>::value,
 
  602                        "Unexpected result type for broadcast<V>()");
 
  603          DUNE_SIMD_CHECK(is42(vec));
 
  609          auto vec = broadcast<V>(ref);
 
  610          static_assert(std::is_same<
decltype(vec), V>::value,
 
  611                        "Unexpected result type for broadcast<V>()");
 
  612          DUNE_SIMD_CHECK(is42(vec));
 
  617          static_assert(std::is_same<
decltype(vec), V>::value,
 
  618                        "Unexpected result type for broadcast<V>()");
 
  619          DUNE_SIMD_CHECK(is42(vec));
 
  623          auto vec = broadcast<V>(42);
 
  624          static_assert(std::is_same<
decltype(vec), V>::value,
 
  625                        "Unexpected result type for broadcast<V>()");
 
  626          DUNE_SIMD_CHECK(is42(vec));
 
  630          auto vec = broadcast<V>(42.0);
 
  631          static_assert(std::is_same<
decltype(vec), V>::value,
 
  632                        "Unexpected result type for broadcast<V>()");
 
  633          DUNE_SIMD_CHECK(is42(vec));
 
  638      void checkBracedAssign()
 
  641        { V ref = make123<V>();       V vec; vec = {ref};
 
  642          DUNE_SIMD_CHECK(is123(vec)); DUNE_SIMD_CHECK(is123(ref)); }
 
  643        { 
const V ref = make123<V>(); V vec; vec = {ref};
 
  644          DUNE_SIMD_CHECK(is123(vec)); DUNE_SIMD_CHECK(is123(ref)); }
 
  647        { V vec; vec = {make123<V>()}; DUNE_SIMD_CHECK(is123(vec)); }
 
  651      void checkBracedBroadcastAssign()
 
  670#define DUNE_SIMD_POSTFIX_OP(NAME, SYMBOL)              \ 
  671      struct OpPostfix##NAME                            \ 
  674        auto operator()(V&& v) const                    \ 
  675          -> decltype(std::forward<V>(v) SYMBOL)        \ 
  677          return std::forward<V>(v) SYMBOL;             \ 
  681#define DUNE_SIMD_PREFIX_OP(NAME, SYMBOL)               \ 
  682      struct OpPrefix##NAME                             \ 
  685        auto operator()(V&& v) const                    \ 
  686          -> decltype(SYMBOL std::forward<V>(v))        \ 
  688          return SYMBOL std::forward<V>(v);             \ 
  692      DUNE_SIMD_POSTFIX_OP(Decrement,        -- );
 
  693      DUNE_SIMD_POSTFIX_OP(Increment,        ++ );
 
  695      DUNE_SIMD_PREFIX_OP (Decrement,        -- );
 
  696      DUNE_SIMD_PREFIX_OP (Increment,        ++ );
 
  698      DUNE_SIMD_PREFIX_OP (Plus,             +  );
 
  699      DUNE_SIMD_PREFIX_OP (Minus,            -  );
 
  700      DUNE_SIMD_PREFIX_OP (LogicNot,         !  );
 
  706#pragma GCC diagnostic push 
  707#pragma GCC diagnostic ignored "-Wpragmas" 
  708#pragma GCC diagnostic ignored "-Wunknown-warning-option"  
  709#pragma GCC diagnostic ignored "-Wbool-operation" 
  710      DUNE_SIMD_PREFIX_OP (BitNot,           ~  );
 
  711#pragma GCC diagnostic pop 
  713#undef DUNE_SIMD_POSTFIX_OP 
  714#undef DUNE_SIMD_PREFIX_OP 
  716      template<
class V, 
class Op>
 
  721#define DUNE_SIMD_OPNAME (className<Op(V)>()) 
  723        auto val = leftVector<std::decay_t<V>>();
 
  727        auto &&result = op(
static_cast<V
>(arg));
 
  728        using T = 
Scalar<std::decay_t<
decltype(result)> >;
 
  729        for(std::size_t l = 0; l < 
lanes(val); ++l)
 
  746               == 
static_cast<T
>(op(
lane(l, 
static_cast<V
>(val)))));
 
  750        for(std::size_t l = 0; l < lanes<std::decay_t<V> >(); ++l)
 
  751          DUNE_SIMD_CHECK_OP(
lane(l, val) == 
lane(l, arg));
 
  752#undef DUNE_SIMD_OPNAME 
  755      template<
class V, 
class Op>
 
  765      template<
class V, 
class Op>
 
  766      void checkUnaryOpsV(Op op)
 
  768        checkUnaryOpV<V&>(op);
 
  769        checkUnaryOpV<const V&>(op);
 
  770        checkUnaryOpV<V&&>(op);
 
  784#define DUNE_SIMD_INFIX_OP(NAME, SYMBOL)                                \ 
  785      struct OpInfix##NAME                                              \ 
  787        template<class V1, class V2>                                    \ 
  788        decltype(auto) operator()(V1&& v1, V2&& v2) const               \ 
  790          return std::forward<V1>(v1) SYMBOL std::forward<V2>(v2);      \ 
  792        template<class S1, class S2>                                    \ 
  793        auto scalar(S1&& s1, S2&& s2) const                             \ 
  794          -> decltype(std::forward<S1>(s1) SYMBOL std::forward<S2>(s2)); \ 
  805#define DUNE_SIMD_ASSIGN_OP(NAME, SYMBOL)                               \ 
  806      struct OpInfix##NAME                                              \ 
  808        template<class V1, class V2>                                    \ 
  809        decltype(auto) operator()(V1&& v1, V2&& v2) const               \ 
  811          return std::forward<V1>(v1) SYMBOL std::forward<V2>(v2);      \ 
  813        template<class S1, class S2>                                    \ 
  814        auto scalar(S1& s1, S2&& s2) const                              \ 
  815          -> decltype(s1 SYMBOL std::forward<S2>(s2));                  \ 
  818#define DUNE_SIMD_REPL_OP(NAME, REPLFN, SYMBOL)                         \ 
  819      struct OpInfix##NAME                                              \ 
  821        template<class V1, class V2>                                    \ 
  822        decltype(auto) operator()(V1&& v1, V2&& v2) const               \ 
  824          return Simd::REPLFN(std::forward<V1>(v1), std::forward<V2>(v2)); \ 
  826        template<class S1, class S2>                                    \ 
  827        auto scalar(S1&& s1, S2&& s2) const                             \ 
  828          -> decltype(std::forward<S1>(s1) SYMBOL std::forward<S2>(s2)); \ 
  831      DUNE_SIMD_INFIX_OP(Mul,              *  );
 
  832      DUNE_SIMD_INFIX_OP(Div,              /  );
 
  833      DUNE_SIMD_INFIX_OP(Remainder,        %  );
 
  835      DUNE_SIMD_INFIX_OP(Plus,             +  );
 
  836      DUNE_SIMD_INFIX_OP(Minus,            -  );
 
  838      DUNE_SIMD_INFIX_OP(LeftShift,        << );
 
  839      DUNE_SIMD_INFIX_OP(RightShift,       >> );
 
  841      DUNE_SIMD_INFIX_OP(Less,             <  );
 
  842      DUNE_SIMD_INFIX_OP(Greater,          >  );
 
  843      DUNE_SIMD_INFIX_OP(LessEqual,        <= );
 
  844      DUNE_SIMD_INFIX_OP(GreaterEqual,     >= );
 
  846      DUNE_SIMD_INFIX_OP(Equal,            == );
 
  847      DUNE_SIMD_INFIX_OP(NotEqual,         != );
 
  849      DUNE_SIMD_INFIX_OP(BitAnd,           &  );
 
  850      DUNE_SIMD_INFIX_OP(BitXor,           ^  );
 
  851      DUNE_SIMD_INFIX_OP(BitOr,            |  );
 
  855      DUNE_SIMD_REPL_OP(LogicAnd, 
maskAnd, && );
 
  856      DUNE_SIMD_REPL_OP(LogicOr,  
maskOr,  || );
 
  858      DUNE_SIMD_ASSIGN_OP(Assign,           =  );
 
  859      DUNE_SIMD_ASSIGN_OP(AssignMul,        *= );
 
  860      DUNE_SIMD_ASSIGN_OP(AssignDiv,        /= );
 
  861      DUNE_SIMD_ASSIGN_OP(AssignRemainder,  %= );
 
  862      DUNE_SIMD_ASSIGN_OP(AssignPlus,       += );
 
  863      DUNE_SIMD_ASSIGN_OP(AssignMinus,      -= );
 
  864      DUNE_SIMD_ASSIGN_OP(AssignLeftShift,  <<=);
 
  865      DUNE_SIMD_ASSIGN_OP(AssignRightShift, >>=);
 
  866      DUNE_SIMD_ASSIGN_OP(AssignAnd,        &= );
 
  867      DUNE_SIMD_ASSIGN_OP(AssignXor,        ^= );
 
  868      DUNE_SIMD_ASSIGN_OP(AssignOr,         |= );
 
  870#undef DUNE_SIMD_INFIX_OP 
  871#undef DUNE_SIMD_REPL_OP 
  872#undef DUNE_SIMD_ASSIGN_OP 
  875      struct OpInfixComma {};
 
  877      template<
class T1, 
class T2>
 
  878      void checkCommaOp(
const std::decay_t<T1> &val1,
 
  879                        const std::decay_t<T2> &val2)
 
  881#define DUNE_SIMD_OPNAME (className<OpInfixComma(T1, T2)>()) 
  882        static_assert(std::is_same<decltype((std::declval<T1>(),
 
  883                                             std::declval<T2>())), T2>::value,
 
  884                      "Type and value category of the comma operator must " 
  885                      "match that of the second operand");
 
  894#pragma GCC diagnostic push 
  895#pragma GCC diagnostic ignored "-Wunused-value" 
  896        auto &&result = (
static_cast<T1
>(arg1),
 
  897                         static_cast<T2
>(arg2));
 
  898#pragma GCC diagnostic pop 
  899        if(std::is_reference<T2>::value)
 
  903          DUNE_SIMD_CHECK_OP(&result == &arg2);
 
  905          DUNE_SIMD_CHECK_OP(
allTrue(val1 == arg1));
 
  906          DUNE_SIMD_CHECK_OP(
allTrue(val2 == arg2));
 
  912          DUNE_SIMD_CHECK_OP(
allTrue(result == arg2));
 
  914          DUNE_SIMD_CHECK_OP(
allTrue(val1 == arg1));
 
  918#undef DUNE_SIMD_OPNAME 
  943      template<
class V1, 
class V2, 
class Op>
 
  944      std::enable_if_t<Std::is_detected_v<ScalarResult, Op, V1, V2> >
 
  947#define DUNE_SIMD_OPNAME (className<Op(V1, V2)>()) 
  948        static_assert(std::is_same<std::decay_t<V1>, std::decay_t<V2> >::value,
 
  949                      "Internal testsystem error: called with two types that " 
  950                      "don't decay to the same thing");
 
  953        auto vref1 = leftVector<std::decay_t<V1>>();
 
  954        auto vref2 = rightVector<std::decay_t<V2>>();
 
  961        auto &&vopres = op(
static_cast<V1
>(vop1), 
static_cast<V2
>(vop2));
 
  962        using VR = 
decltype(vopres);
 
  965        static_assert(lanes<std::decay_t<VR> >() == 
lanes<std::decay_t<V1> >(),
 
  966                      "The result must have the same number of lanes as the " 
  978               == 
static_cast<T
>(op(
lane(l, 
static_cast<V1
>(vref1)),
 
  979                                    lane(l, 
static_cast<V2
>(vref2)))));
 
  984          DUNE_SIMD_CHECK_OP(
lane(l, vop1) == 
lane(l, vref1));
 
  988          DUNE_SIMD_CHECK_OP(
lane(l, vop2) == 
lane(l, vref2));
 
  990#undef DUNE_SIMD_OPNAME 
  993      template<
class V1, 
class V2, 
class Op>
 
  994      std::enable_if_t<!Std::is_detected_v<ScalarResult, Op, V1, V2> >
 
 1003      template<
class V1, 
class V2>
 
 1006        static_assert(std::is_same<std::decay_t<V1>, std::decay_t<V2> >::value,
 
 1007                      "Internal testsystem error: called with two types that " 
 1008                      "don't decay to the same thing");
 
 1010        checkCommaOp<V1, V2>(leftVector<std::decay_t<V1>>(),
 
 1011                             rightVector<std::decay_t<V2>>());
 
 1047      template<
class V1, 
class T2, 
class Op>
 
 1048      std::enable_if_t<Std::is_detected_v<ScalarResult, Op, V1, T2> >
 
 1051#define DUNE_SIMD_OPNAME (className<Op(V1, T2)>()) 
 1052        static_assert(std::is_same<Scalar<std::decay_t<V1> >,
 
 1053                      std::decay_t<T2> >::value,
 
 1054                      "Internal testsystem error: called with a scalar that " 
 1055                      "does not match the vector type.");
 
 1058        auto sinit2 = rightScalar<std::decay_t<T2>>();
 
 1061        auto vref1 = leftVector<std::decay_t<V1>>();
 
 1062        auto sref2 = sinit2;
 
 1069        auto &&vopres = op(
static_cast<V1
>(vop1), 
static_cast<T2
>(sop2));
 
 1070        using VR = 
decltype(vopres);
 
 1073        static_assert(lanes<std::decay_t<VR> >() == 
lanes<std::decay_t<V1> >(),
 
 1074                      "The result must have the same number of lanes as the " 
 1078        DUNE_SIMD_CHECK_OP(sop2 == sinit2);
 
 1081        using T = 
Scalar<std::decay_t<
decltype(vopres)> >;
 
 1089               == 
static_cast<T
>(op(
lane(l, 
static_cast<V1
>(vref1)),
 
 1090                                            static_cast<T2
>(sref2) )));
 
 1092          DUNE_SIMD_CHECK_OP(sref2 == sinit2);
 
 1097          DUNE_SIMD_CHECK_OP(
lane(l, vop1) == 
lane(l, vref1));
 
 1099#undef DUNE_SIMD_OPNAME 
 1102      template<
class V1, 
class T2, 
class Op>
 
 1103      std::enable_if_t<!Std::is_detected_v<ScalarResult, Op, V1, T2> >
 
 1112      template<
class V1, 
class T2>
 
 1115        static_assert(std::is_same<Scalar<std::decay_t<V1> >,
 
 1116                      std::decay_t<T2> >::value,
 
 1117                      "Internal testsystem error: called with a scalar that " 
 1118                      "does not match the vector type.");
 
 1120        checkCommaOp<V1, T2>(leftVector<std::decay_t<V1>>(),
 
 1121                             rightScalar<std::decay_t<T2>>());
 
 1150      template<
class V1, 
class T2, 
class Op>
 
 1151      std::enable_if_t<Std::is_detected_v<ScalarResult, Op, V1, T2> >
 
 1154#define DUNE_SIMD_OPNAME (className<Op(V1, T2)>()) 
 1155        static_assert(std::is_same<Scalar<std::decay_t<V1> >,
 
 1156                      std::decay_t<T2> >::value,
 
 1157                      "Internal testsystem error: called with a scalar that " 
 1158                      "does not match the vector type.");
 
 1161        auto sinit2 = rightScalar<std::decay_t<T2>>();
 
 1164        auto vop1 = leftVector<std::decay_t<V1>>();
 
 1165        using V2 = CopyRefQual<V1, T2>;
 
 1166        std::decay_t<V2> vop2(sinit2);
 
 1169        op(
static_cast<V1
>(vop1), 
static_cast<V2
>(vop2));
 
 1173          DUNE_SIMD_CHECK_OP(
lane(l, vop2) == sinit2);
 
 1175#undef DUNE_SIMD_OPNAME 
 1178      template<
class V1, 
class T2, 
class Op>
 
 1179      std::enable_if_t<!Std::is_detected_v<ScalarResult, Op, V1, T2> >
 
 1188      template<
class V1, 
class T2>
 
 1226      template<
class V1, 
class V2, 
class Op>
 
 1227      std::enable_if_t<Std::is_detected_v<ScalarResult, Op, V1, V2> >
 
 1230        using P2 = 
decltype(
lane(0, std::declval<V2>()));
 
 1231        using T2 = CopyRefQual<Scalar<V2>, V2>;
 
 1232#define DUNE_SIMD_OPNAME (className<Op(V1, P2)>()) 
 1233        static_assert(std::is_same<Scalar<V1>, 
Scalar<V2> >::value,
 
 1234                      "Internal testsystem error: called with two vector " 
 1235                      "types whose scalar types don't match.");
 
 1238        auto sinit2 = rightScalar<Scalar<V2>>();
 
 1241        auto vref1 = leftVector<std::decay_t<V1>>();
 
 1242        auto sref2 = sinit2;
 
 1247        lane(0, vop2) = sref2; 
 
 1251          op(
static_cast<V1
>(vop1), 
lane(0, 
static_cast<V2
>(vop2)));
 
 1252        using VR = 
decltype(vopres);
 
 1255        static_assert(lanes<std::decay_t<VR> >() == 
lanes<std::decay_t<V1> >(),
 
 1256                      "The result must have the same number of lanes as the " 
 1260        DUNE_SIMD_CHECK_OP(
lane(0, vop2) == sinit2);
 
 1263        using T = 
Scalar<
decltype(vopres)>;
 
 1271               == 
static_cast<T
>(op(
lane(l, 
static_cast<V1
>(vref1)),
 
 1272                                            static_cast<T2
>(sref2) )));
 
 1274          DUNE_SIMD_CHECK_OP(sref2 == sinit2);
 
 1279          DUNE_SIMD_CHECK_OP(
lane(l, vop1) == 
lane(l, vref1));
 
 1281#undef DUNE_SIMD_OPNAME 
 1284      template<
class V1, 
class V2, 
class Op>
 
 1285      std::enable_if_t<!Std::is_detected_v<ScalarResult, Op, V1, V2> >
 
 1294      template<
class V1, 
class V2>
 
 1306      struct OpInfixSwappedArgs
 
 1310        template<
class V1, 
class V2>
 
 1311        decltype(
auto) 
operator()(V1&& v1, V2&& v2) 
const 
 1313          return orig(std::forward<V2>(v2), std::forward<V1>(v1));
 
 1315        template<
class S1, 
class S2>
 
 1316        auto scalar(S1&& s1, S2&& s2) 
const 
 1317          -> 
decltype(orig.scalar(std::forward<S2>(s2), std::forward<S1>(s1)));
 
 1320      template<
class T1, 
class V2, 
class Op>
 
 1323        checkBinaryOpVS(v2, t1, OpInfixSwappedArgs<Op>{op});
 
 1326      template<
class T1, 
class V2>
 
 1329        static_assert(std::is_same<std::decay_t<T1>,
 
 1331                      "Internal testsystem error: called with a scalar that " 
 1332                      "does not match the vector type.");
 
 1334        checkCommaOp<T1, V2>(leftScalar<std::decay_t<T1>>(),
 
 1335                             rightVector<std::decay_t<V2>>());
 
 1338      template<
class V1, 
class V2, 
class Op>
 
 1341        checkBinaryOpVP(v2, v1, OpInfixSwappedArgs<Op>{op});
 
 1344      template<
class V1, 
class V2>
 
 1376      template<
class T1, 
class V2, 
class Op>
 
 1379        checkBinaryOpVVAgainstVS(v2, t1, OpInfixSwappedArgs<Op>{op});
 
 1382      template<
class V1, 
class T2>
 
 1391      template<
class T1, 
class T2, 
bool condition, 
class Checker>
 
 1392      void checkBinaryRefQual(Checker checker)
 
 1394        if constexpr (condition) {
 
 1403      template<
class V, 
class Checker>
 
 1404      void checkBinaryOps(Checker checker)
 
 1406        using Std::bool_constant;
 
 1408        constexpr bool isMask = std::is_same<Scalar<V>, 
bool>::value;
 
 1410        constexpr bool do_   = 
false;
 
 1411        constexpr bool do_SV = 
true;
 
 1412        constexpr bool do_VV = 
true;
 
 1413        constexpr bool do_VS = 
true;
 
 1415#define DUNE_SIMD_DO(M1, M2, M3, V1, V2, V3, NAME)              \ 
 1416        checker(bool_constant<isMask ? do_##M1 : do_##V1>{},    \ 
 1417                bool_constant<isMask ? do_##M2 : do_##V2>{},    \ 
 1418                bool_constant<isMask ? do_##M3 : do_##V3>{},    \ 
 1423        DUNE_SIMD_DO(  ,   ,   , SV, VV, VS, InfixMul             );
 
 1424        DUNE_SIMD_DO(  ,   ,   , SV, VV, VS, InfixDiv             );
 
 1425        DUNE_SIMD_DO(  ,   ,   , SV, VV, VS, InfixRemainder       );
 
 1427        DUNE_SIMD_DO(  ,   ,   , SV, VV, VS, InfixPlus            );
 
 1428        DUNE_SIMD_DO(  ,   ,   , SV, VV, VS, InfixMinus           );
 
 1430        DUNE_SIMD_DO(  ,   ,   ,   , VV, VS, InfixLeftShift       );
 
 1431        DUNE_SIMD_DO(  ,   ,   ,   , VV, VS, InfixRightShift      );
 
 1433        DUNE_SIMD_DO(  ,   ,   , SV, VV, VS, InfixLess            );
 
 1434        DUNE_SIMD_DO(  ,   ,   , SV, VV, VS, InfixGreater         );
 
 1435        DUNE_SIMD_DO(  ,   ,   , SV, VV, VS, InfixLessEqual       );
 
 1436        DUNE_SIMD_DO(  ,   ,   , SV, VV, VS, InfixGreaterEqual    );
 
 1438        DUNE_SIMD_DO(  ,   ,   , SV, VV, VS, InfixEqual           );
 
 1439        DUNE_SIMD_DO(  ,   ,   , SV, VV, VS, InfixNotEqual        );
 
 1441        DUNE_SIMD_DO(  , VV,   , SV, VV, VS, InfixBitAnd          );
 
 1442        DUNE_SIMD_DO(  , VV,   , SV, VV, VS, InfixBitXor          );
 
 1443        DUNE_SIMD_DO(  , VV,   , SV, VV, VS, InfixBitOr           );
 
 1445        DUNE_SIMD_DO(SV, VV, VS, SV, VV, VS, InfixLogicAnd        );
 
 1446        DUNE_SIMD_DO(SV, VV, VS, SV, VV, VS, InfixLogicOr         );
 
 1448        DUNE_SIMD_DO(  , VV,   ,   , VV, VS, InfixAssign          );
 
 1449        DUNE_SIMD_DO(  ,   ,   ,   , VV, VS, InfixAssignMul       );
 
 1450        DUNE_SIMD_DO(  ,   ,   ,   , VV, VS, InfixAssignDiv       );
 
 1451        DUNE_SIMD_DO(  ,   ,   ,   , VV, VS, InfixAssignRemainder );
 
 1452        DUNE_SIMD_DO(  ,   ,   ,   , VV, VS, InfixAssignPlus      );
 
 1453        DUNE_SIMD_DO(  ,   ,   ,   , VV, VS, InfixAssignMinus     );
 
 1454        DUNE_SIMD_DO(  ,   ,   ,   , VV, VS, InfixAssignLeftShift );
 
 1455        DUNE_SIMD_DO(  ,   ,   ,   , VV, VS, InfixAssignRightShift);
 
 1456        DUNE_SIMD_DO(  , VV,   ,   , VV, VS, InfixAssignAnd       );
 
 1457        DUNE_SIMD_DO(  , VV,   ,   , VV, VS, InfixAssignXor       );
 
 1458        DUNE_SIMD_DO(  , VV,   ,   , VV, VS, InfixAssignOr        );
 
 1460        DUNE_SIMD_DO(SV, VV, VS, SV,   , VS, InfixComma           );
 
 1471      void checkAutoCopy()
 
 1473        using RValueResult = 
decltype(autoCopy(
lane(0, std::declval<V>())));
 
 1474        static_assert(std::is_same<RValueResult, Scalar<V> >::value,
 
 1475                      "Result of autoCopy() must always be Scalar<V>");
 
 1477        using MutableLValueResult =
 
 1478          decltype(autoCopy(
lane(0, std::declval<V&>())));
 
 1479        static_assert(std::is_same<MutableLValueResult, Scalar<V> >::value,
 
 1480                      "Result of autoCopy() must always be Scalar<V>");
 
 1482        using ConstLValueResult =
 
 1483          decltype(autoCopy(
lane(0, std::declval<const V&>())));
 
 1484        static_assert(std::is_same<ConstLValueResult, Scalar<V> >::value,
 
 1485                      "Result of autoCopy() must always be Scalar<V>");
 
 1487        V vec = make123<V>();
 
 1488        for(std::size_t l = 0; l < 
lanes(vec); ++l)
 
 1494      void checkBoolReductions()
 
 1499        DUNE_SIMD_CHECK(
allTrue (
static_cast<M&
>(trueVec)) == 
true);
 
 1500        DUNE_SIMD_CHECK(
anyTrue (
static_cast<M&
>(trueVec)) == 
true);
 
 1501        DUNE_SIMD_CHECK(
allFalse(
static_cast<M&
>(trueVec)) == 
false);
 
 1502        DUNE_SIMD_CHECK(
anyFalse(
static_cast<M&
>(trueVec)) == 
false);
 
 1505        DUNE_SIMD_CHECK(
allTrue (
static_cast<const M&
>(trueVec)) == 
true);
 
 1506        DUNE_SIMD_CHECK(
anyTrue (
static_cast<const M&
>(trueVec)) == 
true);
 
 1507        DUNE_SIMD_CHECK(
allFalse(
static_cast<const M&
>(trueVec)) == 
false);
 
 1508        DUNE_SIMD_CHECK(
anyFalse(
static_cast<const M&
>(trueVec)) == 
false);
 
 1511        DUNE_SIMD_CHECK(
allTrue (M(
true)) == 
true);
 
 1512        DUNE_SIMD_CHECK(
anyTrue (M(
true)) == 
true);
 
 1513        DUNE_SIMD_CHECK(
allFalse(M(
true)) == 
false);
 
 1514        DUNE_SIMD_CHECK(
anyFalse(M(
true)) == 
false);
 
 1519        DUNE_SIMD_CHECK(
allTrue (
static_cast<M&
>(falseVec)) == 
false);
 
 1520        DUNE_SIMD_CHECK(
anyTrue (
static_cast<M&
>(falseVec)) == 
false);
 
 1521        DUNE_SIMD_CHECK(
allFalse(
static_cast<M&
>(falseVec)) == 
true);
 
 1522        DUNE_SIMD_CHECK(
anyFalse(
static_cast<M&
>(falseVec)) == 
true);
 
 1525        DUNE_SIMD_CHECK(
allTrue (
static_cast<const M&
>(falseVec)) == 
false);
 
 1526        DUNE_SIMD_CHECK(
anyTrue (
static_cast<const M&
>(falseVec)) == 
false);
 
 1527        DUNE_SIMD_CHECK(
allFalse(
static_cast<const M&
>(falseVec)) == 
true);
 
 1528        DUNE_SIMD_CHECK(
anyFalse(
static_cast<const M&
>(falseVec)) == 
true);
 
 1531        DUNE_SIMD_CHECK(
allTrue (M(
false)) == 
false);
 
 1532        DUNE_SIMD_CHECK(
anyTrue (M(
false)) == 
false);
 
 1533        DUNE_SIMD_CHECK(
allFalse(M(
false)) == 
true);
 
 1534        DUNE_SIMD_CHECK(
anyFalse(M(
false)) == 
true);
 
 1536        auto mixedVec = broadcast<M>(0);
 
 1537        for(std::size_t l = 0; l < 
lanes(mixedVec); ++l)
 
 1538          lane(l, mixedVec) = (l % 2);
 
 1542          (
allTrue (
static_cast<M&
>(mixedVec)) == 
false);
 
 1544          (
anyTrue (
static_cast<M&
>(mixedVec)) == (lanes<M>() > 1));
 
 1546          (
allFalse(
static_cast<M&
>(mixedVec)) == (lanes<M>() == 1));
 
 1548          (
anyFalse(
static_cast<M&
>(mixedVec)) == 
true);
 
 1552          (
allTrue (
static_cast<const M&
>(mixedVec)) == 
false);
 
 1554          (
anyTrue (
static_cast<const M&
>(mixedVec)) == (lanes<M>() > 1));
 
 1556          (
allFalse(
static_cast<const M&
>(mixedVec)) == (lanes<M>() == 1));
 
 1558          (
anyFalse(
static_cast<const M&
>(mixedVec)) == 
true);
 
 1561        DUNE_SIMD_CHECK(
allTrue (M(mixedVec)) == 
false);
 
 1562        DUNE_SIMD_CHECK(
anyTrue (M(mixedVec)) == (lanes<M>() > 1));
 
 1563        DUNE_SIMD_CHECK(
allFalse(M(mixedVec)) == (lanes<M>() == 1));
 
 1564        DUNE_SIMD_CHECK(
anyFalse(M(mixedVec)) == 
true);
 
 1573          (std::is_same<decltype(cond(std::declval<M>(), std::declval<V>(),
 
 1574                                      std::declval<V>())), V>::value,
 
 1575           "The result of cond(M, V, V) should have exactly the type V");
 
 1578          (std::is_same<decltype(cond(std::declval<const M&>(),
 
 1579                                      std::declval<const V&>(),
 
 1580                                      std::declval<const V&>())), V>::value,
 
 1581           "The result of cond(const M&, const V&, const V&) should have " 
 1582           "exactly the type V");
 
 1585          (std::is_same<decltype(cond(std::declval<M&>(), std::declval<V&>(),
 
 1586                                      std::declval<V&>())), V>::value,
 
 1587           "The result of cond(M&, V&, V&) should have exactly the type V");
 
 1589        V vec1 = leftVector<V>();
 
 1590        V vec2 = rightVector<V>();
 
 1592        DUNE_SIMD_CHECK(
allTrue(
cond(M(
true),  vec1, vec2) == vec1));
 
 1593        DUNE_SIMD_CHECK(
allTrue(
cond(M(
false), vec1, vec2) == vec2));
 
 1595        auto mixedResult = broadcast<V>(0);
 
 1596        auto mixedMask = broadcast<M>(
false);
 
 1597        for(std::size_t l = 0; l < 
lanes(mixedMask); ++l)
 
 1599          lane(l, mixedMask  ) = (l % 2);
 
 1600          lane(l, mixedResult) = 
lane(l, (l % 2) ? vec1 : vec2);
 
 1603        DUNE_SIMD_CHECK(
allTrue(
cond(mixedMask, vec1, vec2) == mixedResult));
 
 1607      void checkBoolCond()
 
 1610          (std::is_same<decltype(cond(std::declval<bool>(), std::declval<V>(),
 
 1611                                      std::declval<V>())), V>::value,
 
 1612           "The result of cond(bool, V, V) should have exactly the type V");
 
 1615          (std::is_same<decltype(cond(std::declval<const bool&>(),
 
 1616                                      std::declval<const V&>(),
 
 1617                                      std::declval<const V&>())), V>::value,
 
 1618           "The result of cond(const bool&, const V&, const V&) should have " 
 1619           "exactly the type V");
 
 1622          (std::is_same<decltype(cond(std::declval<bool&>(),
 
 1624                                      std::declval<V&>())), V>::value,
 
 1625           "The result of cond(bool&, V&, V&) should have exactly the type V");
 
 1627        V vec1 = leftVector<V>();
 
 1628        V vec2 = rightVector<V>();
 
 1630        DUNE_SIMD_CHECK(
allTrue(
cond(
true,  vec1, vec2) == vec1));
 
 1631        DUNE_SIMD_CHECK(
allTrue(
cond(
false, vec1, vec2) == vec2));
 
 1635      std::enable_if_t<!Impl::LessThenComparable<Scalar<V> >::value>
 
 1636      checkHorizontalMinMax() {}
 
 1639      std::enable_if_t<Impl::LessThenComparable<Scalar<V> >::value>
 
 1640      checkHorizontalMinMax()
 
 1643          (std::is_same<decltype(max(std::declval<V>())), 
Scalar<V> >::value,
 
 1644           "The result of max(V) should be exactly Scalar<V>");
 
 1647          (std::is_same<decltype(min(std::declval<V>())), 
Scalar<V> >::value,
 
 1648           "The result of min(V) should be exactly Scalar<V>");
 
 1651          (std::is_same<decltype(max(std::declval<V&>())), 
Scalar<V> >::value,
 
 1652           "The result of max(V) should be exactly Scalar<V>");
 
 1655          (std::is_same<decltype(min(std::declval<V&>())), 
Scalar<V> >::value,
 
 1656           "The result of min(V) should be exactly Scalar<V>");
 
 1658        const V vec1 = leftVector<V>();
 
 1665      std::enable_if_t<!Impl::LessThenComparable<Scalar<V> >::value>
 
 1666      checkBinaryMinMax() {}
 
 1669      std::enable_if_t<Impl::LessThenComparable<Scalar<V> >::value>
 
 1676          (std::is_same<decltype(Simd::max(std::declval<V>(),
 
 1677                                           std::declval<V>())), V>::value,
 
 1678           "The result of Simd::max(V, V) should be exactly V");
 
 1680          (std::is_same<decltype(Simd::min(std::declval<V>(),
 
 1681                                           std::declval<V>())), V>::value,
 
 1682           "The result of Simd::min(V, V) should be exactly V");
 
 1685          (std::is_same<decltype(Simd::max(std::declval<V&>(),
 
 1686                                           std::declval<V&>())), V>::value,
 
 1687           "The result of Simd::max(V&, V&) should be exactly V");
 
 1689          (std::is_same<decltype(Simd::min(std::declval<V&>(),
 
 1690                                           std::declval<V&>())), V>::value,
 
 1691           "The result of Simd::min(V&, V&) should be exactly V");
 
 1693        const V arg1 = leftVector<V>();
 
 1694        const V arg2 = rightVector<V>();
 
 1697        for(
auto l : 
range(lanes<V>()))
 
 1710        const V vec1 = leftVector<V>();
 
 1712        std::string reference;
 
 1714          const char *sep = 
"";
 
 1717            std::ostringstream stream;
 
 1718            stream << 
lane(l, vec1);
 
 1721            reference += stream.str();
 
 1727          std::ostringstream stream;
 
 1729          if(
lanes(vec1) == 1)
 
 1730            DUNE_SIMD_CHECK(stream.str() == reference);
 
 1732            DUNE_SIMD_CHECK(stream.str() == 
"<" + reference + 
">");
 
 1736          std::ostringstream stream;
 
 1737          stream << 
vio(vec1);
 
 1738          DUNE_SIMD_CHECK(stream.str() == 
"<" + reference + 
">");
 
 1742#undef DUNE_SIMD_CHECK 
 1807      template<
class V> 
void checkType();
 
 1808      template<
class V> 
void checkNonOps();
 
 1809      template<
class V> 
void checkUnaryOps();
 
 1810      template<
class V> 
void checkBinaryOps();
 
 1811      template<
class V> 
void checkBinaryOpsVectorVector();
 
 1812      template<
class V> 
void checkBinaryOpsScalarVector();
 
 1813      template<
class V> 
void checkBinaryOpsVectorScalar();
 
 1814      template<
class V> 
void checkBinaryOpsProxyVector();
 
 1815      template<
class V> 
void checkBinaryOpsVectorProxy();
 
 1836      template<
class V, 
class Rebinds,
 
 1837               template<
class> 
class RebindPrune = 
IsLoop,
 
 1841        if(seen_.emplace(typeid (V)).second == 
false)
 
 1849        auto recurse = [
this](
auto w) {
 
 1850          using W = 
typename decltype(w)::type;
 
 1851          this->
template check<W, Rebinds, RebindPrune, RebindAccept>();
 
 1853        checkRebindOf<V, Rebinds, RebindPrune, RebindAccept>(recurse);
 
 1866    template<
class V> 
void UnitTest::checkType()
 
 1868      static_assert(std::is_same<V, std::decay_t<V> >::value, 
"Simd types " 
 1869                    "must not be references, and must not include " 
 1872      log_ << 
"Checking SIMD type " << className<V>() << std::endl;
 
 1876      checkBinaryOps<V>();
 
 1878    template<
class V> 
void UnitTest::checkNonOps()
 
 1880      constexpr auto isMask = 
typename std::is_same<Scalar<V>, 
bool>::type{};
 
 1885      checkDefaultConstruct<V>();
 
 1887      checkCopyMoveConstruct<V>();
 
 1889      checkBroadcast<V>();
 
 1890      if constexpr (isMask)
 
 1891        this->
template checkBroadcastMaskConstruct<V>();
 
 1893        this->
template checkBroadcastVectorConstruct<V>();
 
 1894      checkBracedAssign<V>();
 
 1895      checkBracedBroadcastAssign<V>();
 
 1901      if constexpr (isMask)
 
 1902        this->
template checkBoolReductions<V>();
 
 1905      checkHorizontalMinMax<V>();
 
 1906      checkBinaryMinMax<V>();
 
 1909    template<
class V> 
void UnitTest::checkUnaryOps()
 
 1911      if constexpr (std::is_same_v<Scalar<V>, 
bool>) {
 
 1913        auto check = [
this](
auto op) {
 
 1914          this->
template checkUnaryOpsV<V>(op);
 
 1929        check(OpPrefixLogicNot{});
 
 1934        auto check = [
this](
auto op) {
 
 1935          this->
template checkUnaryOpsV<V>(op);
 
 1947        check(OpPrefixMinus{});
 
 1948        check(OpPrefixLogicNot{});
 
 1949        check(OpPrefixBitNot{});
 
 1952    template<
class V> 
void UnitTest::checkBinaryOps()
 
 1954      checkBinaryOpsVectorVector<V>();
 
 1955      checkBinaryOpsScalarVector<V>();
 
 1956      checkBinaryOpsVectorScalar<V>();
 
 1957      checkBinaryOpsProxyVector<V>();
 
 1958      checkBinaryOpsVectorProxy<V>();
 
 1960    template<
class V> 
void UnitTest::checkBinaryOpsVectorVector()
 
 1962      auto checker = [
this](
auto doSV, 
auto doVV, 
auto doVS, 
auto op) {
 
 1963        auto check = [
this,op](
auto t1, 
auto t2) {
 
 1964          this->checkBinaryOpVV(t1, t2, op);
 
 1966        this->checkBinaryRefQual<V, V, doVV>(check);
 
 1968      checkBinaryOps<V>(checker);
 
 1970    template<
class V> 
void UnitTest::checkBinaryOpsScalarVector()
 
 1972      auto checker = [
this](
auto doSV, 
auto doVV, 
auto doVS, 
auto op) {
 
 1973        auto check = [
this,op](
auto t1, 
auto t2) {
 
 1974          this->checkBinaryOpSV(t1, t2, op);
 
 1976        this->checkBinaryRefQual<Scalar<V>, V, doSV>(check);
 
 1978        auto crossCheck = [
this,op](
auto t1, 
auto t2) {
 
 1979          this->checkBinaryOpVVAgainstSV(t1, t2, op);
 
 1981        this->checkBinaryRefQual<Scalar<V>, V, doSV && doVV>(crossCheck);
 
 1983      checkBinaryOps<V>(checker);
 
 1985    template<
class V> 
void UnitTest::checkBinaryOpsVectorScalar()
 
 1987      auto checker = [
this](
auto doSV, 
auto doVV, 
auto doVS, 
auto op) {
 
 1988        auto check = [
this,op](
auto t1, 
auto t2) {
 
 1989          this->checkBinaryOpVS(t1, t2, op);
 
 1991        this->checkBinaryRefQual<V, Scalar<V>, doVS>(check);
 
 1993        auto crossCheck = [
this,op](
auto t1, 
auto t2) {
 
 1994          this->checkBinaryOpVVAgainstVS(t1, t2, op);
 
 1996        this->checkBinaryRefQual<V, Scalar<V>, doVV && doVS>(crossCheck);
 
 1998      checkBinaryOps<V>(checker);
 
 2000    template<
class V> 
void UnitTest::checkBinaryOpsProxyVector()
 
 2002      auto checker = [
this](
auto doSV, 
auto doVV, 
auto doVS, 
auto op) {
 
 2003        auto check = [
this,op](
auto t1, 
auto t2) {
 
 2004          this->checkBinaryOpPV(t1, t2, op);
 
 2006        this->checkBinaryRefQual<V, V, doSV>(check);
 
 2008      checkBinaryOps<V>(checker);
 
 2010    template<
class V> 
void UnitTest::checkBinaryOpsVectorProxy()
 
 2012      auto checker = [
this](
auto doSV, 
auto doVV, 
auto doVS, 
auto op) {
 
 2013        auto check = [
this,op](
auto t1, 
auto t2) {
 
 2014          this->checkBinaryOpVP(t1, t2, op);
 
 2016        this->checkBinaryRefQual<V, V, doVS>(check);
 
 2018      checkBinaryOps<V>(checker);
 
A free function to provide the demangled class name of a given object or type as a string.
 
IO interface of the SIMD abstraction.
 
typename Impl::voider< Types... >::type void_t
Is void for all valid input types. The workhorse for C++11 SFINAE-techniques.
Definition: typetraits.hh:40
 
constexpr GeometryType line
GeometryType representing a line.
Definition: type.hh:498
 
constexpr void forEach(Range &&range, F &&f)
Range based for loop.
Definition: hybridutilities.hh:257
 
static constexpr IntegralRange< std::decay_t< T > > range(T &&from, U &&to) noexcept
free standing function for setting up a range based for loop over an integer range for (auto i: range...
Definition: rangeutilities.hh:288
 
bool anyTrue(const Mask &mask)
Whether any entry is true
Definition: interface.hh:429
 
auto maskOr(const V1 &v1, const V2 &v2)
Logic or of masks.
Definition: interface.hh:499
 
V cond(M &&mask, const V &ifTrue, const V &ifFalse)
Like the ?: operator.
Definition: interface.hh:386
 
auto io(const V &v)
construct a stream inserter
Definition: io.hh:106
 
bool allTrue(const Mask &mask)
Whether all entries are true
Definition: interface.hh:439
 
auto vio(const V &v)
construct a stream inserter
Definition: io.hh:90
 
typename Overloads::RebindType< std::decay_t< S >, std::decay_t< V > >::type Rebind
Construct SIMD type with different scalar type.
Definition: interface.hh:253
 
auto max(const V &v1, const V &v2)
The binary maximum value over two simd objects.
Definition: interface.hh:409
 
bool anyFalse(const Mask &mask)
Whether any entry is false
Definition: interface.hh:449
 
constexpr std::size_t lanes()
Number of lanes in a SIMD type.
Definition: interface.hh:305
 
decltype(auto) lane(std::size_t l, V &&v)
Extract an element of a SIMD type.
Definition: interface.hh:324
 
Rebind< bool, V > Mask
Mask type type of some SIMD type.
Definition: interface.hh:289
 
bool allFalse(const Mask &mask)
Whether all entries are false
Definition: interface.hh:459
 
auto maskAnd(const V1 &v1, const V2 &v2)
Logic and of masks.
Definition: interface.hh:509
 
typename Overloads::ScalarType< std::decay_t< V > >::type Scalar
Element type of some SIMD type.
Definition: interface.hh:235
 
auto min(const V &v1, const V &v2)
The binary minimum value over two simd objects.
Definition: interface.hh:419
 
std::tuple< MetaType< T >... > TypeList
A simple type list.
Definition: typelist.hh:87
 
typename Impl::RemoveEnd< EndMark, TypeList< Types... > >::type RebindList
A list of types with the final element removed.
Definition: test.hh:158
 
typename Impl::IsLoop< T >::type IsLoop
check whether a type is an instance of LoopSIMD
Definition: test.hh:162
 
Dune namespace.
Definition: alignedallocator.hh:13
 
constexpr std::integral_constant< std::size_t, sizeof...(II)> size(std::integer_sequence< T, II... >)
Return the size of the sequence.
Definition: integersequence.hh:75
 
Utilities for reduction like operations on ranges.
 
Include file for users of the SIMD abstraction layer.
 
template which always yields a true value
Definition: typetraits.hh:134
 
Check if a type is callable with ()-operator and given arguments.
Definition: typetraits.hh:162
 
final element marker for RebindList
Definition: test.hh:145
 
Traits for type conversions and type information.