| // { dg-do run { target c++26 } } | |
| // { dg-require-effective-target x86 } | |
| // { dg-additional-options "-msse2" } | |
| #include "test_setup.h" | |
| template <typename T, std::size_t N, std::size_t Alignment> | |
| class alignas(Alignment) aligned_array | |
| : public std::array<T, N> | |
| {}; | |
| inline constexpr std::multiplies<> mul; | |
| inline constexpr std::bit_and<> bit_and; | |
| inline constexpr std::bit_or<> bit_or; | |
| inline constexpr std::bit_xor<> bit_xor; | |
| inline constexpr auto my_add = [](auto a, auto b) { return a + b; }; | |
| template <typename V> | |
| struct Tests | |
| { | |
| using T = typename V::value_type; | |
| using M = typename V::mask_type; | |
| static_assert(simd::alignment_v<V> <= 256); | |
| static consteval V | |
| poisoned(T x) | |
| { | |
| if constexpr (sizeof(V) == sizeof(T) * V::size()) | |
| return V(x); | |
| else | |
| { | |
| using P = simd::resize_t<sizeof(V) / sizeof(T), V>; | |
| static_assert(P::size() > V::size()); | |
| constexpr auto [...is] = std::_IotaArray<P::size()>; | |
| const T arr[P::size()] = {(is < V::size() ? x : T(7))...}; | |
| return std::bit_cast<V>(P(arr)); | |
| } | |
| } | |
| ADD_TEST(Sum) { | |
| std::tuple {poisoned(0), poisoned(1)}, | |
| [](auto& t, V v0, V v1) { | |
| t.verify_equal(simd::reduce(v0), T(0)); | |
| t.verify_equal(simd::reduce(v1), T(V::size())); | |
| } | |
| }; | |
| ADD_TEST(Product) { | |
| std::tuple {poisoned(0), poisoned(1)}, | |
| [](auto& t, V v0, V v1) { | |
| t.verify_equal(simd::reduce(v0, mul), T(0)); | |
| t.verify_equal(simd::reduce(v1, mul), T(1)); | |
| } | |
| }; | |
| ADD_TEST(UnknownSum) { | |
| std::tuple {poisoned(0), poisoned(1)}, | |
| [](auto& t, V v0, V v1) { | |
| t.verify_equal(simd::reduce(v0, my_add), T(0)); | |
| t.verify_equal(simd::reduce(v1, my_add), T(V::size())); | |
| } | |
| }; | |
| ADD_TEST(And, std::is_integral_v<T>) { | |
| std::tuple {poisoned(0), poisoned(1)}, | |
| [](auto& t, V v0, V v1) { | |
| t.verify_equal(simd::reduce(v0, bit_and), T(0)); | |
| t.verify_equal(simd::reduce(v1, bit_and), T(1)); | |
| } | |
| }; | |
| ADD_TEST(Or, std::is_integral_v<T>) { | |
| std::tuple {poisoned(0), poisoned(1)}, | |
| [](auto& t, V v0, V v1) { | |
| t.verify_equal(simd::reduce(v0, bit_or), T(0)); | |
| t.verify_equal(simd::reduce(v1, bit_or), T(1)); | |
| } | |
| }; | |
| ADD_TEST(Xor, std::is_integral_v<T>) { | |
| std::tuple {poisoned(0), poisoned(1)}, | |
| [](auto& t, V v0, V v1) { | |
| t.verify_equal(simd::reduce(v0, bit_xor), T(0)); | |
| t.verify_equal(simd::reduce(v1, bit_xor), T(V::size() & 1)); | |
| } | |
| }; | |
| }; | |
| #include "create_tests.h" |