blob: 4e65eac4164f8d98c51a1a5e367f40a9c8099f45 [file] [log] [blame]
// { dg-do run { target c++26 } }
// { dg-require-effective-target x86 }
#include "test_setup.h"
#include <utility>
template <typename V>
struct Tests
{
using T = typename V::value_type;
using M = typename V::mask_type;
static constexpr M alternating = M([](int i) { return 1 == (i & 1); });
static constexpr M k010 = M([](int i) { return 1 == (i % 3); });
static constexpr M k00111 = M([](int i) { return 2 < (i % 5); });
ADD_TEST(mask_conversion) {
std::array {alternating, k010, k00111},
[](auto& t, M k) {
template for (auto tmp : {char(), short(), int(), double()})
{
using U = decltype(tmp);
using M2 = simd::rebind_t<U, M>;
using M3 = simd::mask<U, V::size()>;
const M2 ref2 = M2([&](int i) { return k[i]; });
t.verify_equal(M2(k), ref2);
t.verify_equal(M(M2(k)), k);
if constexpr (!std::is_same_v<M2, M3>)
{
const M3 ref3 = M3([&](int i) { return k[i]; });
t.verify_equal(M3(k), ref3);
t.verify_equal(M(M3(k)), k);
t.verify_equal(M2(M3(k)), ref2);
t.verify_equal(M3(M2(k)), ref3);
}
}
}
};
ADD_TEST(mask_reductions_sanity) {
std::tuple {M(true)},
[](auto& t, M x) {
t.verify_equal(std::simd::reduce_min_index(x), 0);
t.verify_equal(std::simd::reduce_max_index(x), V::size - 1);
t.verify_precondition_failure("An empty mask does not have a min_index.", [&] {
std::simd::reduce_min_index(!x);
});
t.verify_precondition_failure("An empty mask does not have a max_index.", [&] {
std::simd::reduce_max_index(!x);
});
}
};
ADD_TEST(mask_reductions) {
std::tuple{test_iota<V>, test_iota<V> == T(0)},
[](auto& t, V v, M k0) {
// Caveat:
// k0[n0 * (test_iota_max<V> + 1)] is true if it exists
// k[n * (test_iota_max<V> + 1) + i] is true if it exists
// none_of(k) is true if i > test_iota_max<V>
// by construction of test_iota_max:
static_assert(test_iota_max<V> < V::size());
for (int i = 0; i < int(test_iota_max<V>) + 1; ++i)
{
M k = v == T(i);
const int nk = 1 + (V::size() - i - 1) / (test_iota_max<V> + 1);
const int maxk = (nk - 1) * (test_iota_max<V> + 1) + i;
t.verify(maxk < V::size());
const int nk0 = 1 + (V::size() - 1) / (test_iota_max<V> + 1);
const int maxk0 = (nk0 - 1) * (test_iota_max<V> + 1);
t.verify(maxk0 < V::size());
const int maxkork0 = std::max(maxk, maxk0);
t.verify_equal(k[i], true);
t.verify_equal(std::as_const(k)[i], true);
t.verify_equal(std::simd::reduce_min_index(k), i)(k);
t.verify_equal(std::simd::reduce_max_index(k), maxk)(k);
t.verify_equal(std::simd::reduce_min_index(k || k0), 0);
t.verify_equal(std::simd::reduce_max_index(k || k0), maxkork0);
t.verify_equal(k, k);
t.verify_not_equal(!k, k);
t.verify_equal(k | k, k);
t.verify_equal(k & k, k);
t.verify(none_of(k ^ k));
t.verify_equal(std::simd::reduce_count(k), nk);
if constexpr (sizeof(T) <= sizeof(0ULL))
t.verify_equal(-std::simd::reduce(-k), nk)(k)(-k);
t.verify_equal(std::simd::reduce_count(!k), V::size - nk)(!k);
if constexpr (V::size <= 128 && sizeof(T) <= sizeof(0ULL))
t.verify_equal(-std::simd::reduce(-!k), V::size - nk)(-!k);
t.verify(any_of(k));
t.verify(bool(any_of(k & k0) ^ (i != 0)));
k = M([&](int j) { return j == 0 ? true : k[j]; });
t.verify_equal(k[i], true);
t.verify_equal(std::as_const(k)[i], true);
t.verify_equal(k[0], true);
t.verify_equal(std::as_const(k)[0], true);
t.verify_equal(std::simd::reduce_min_index(k), 0)(k);
t.verify_equal(std::simd::reduce_max_index(k), maxk)(k);
}
}
};
};
#include "create_tests.h" // { dg-prune-output "Wpsabi" }