blob: ab7f98afa98e54ca293d6667f4865274984a2317 [file] [log] [blame]
// Copyright (C) 2020-2026 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
// expensive: * [1-9] * *
#include "bits/main.h"
template <typename V>
void
test()
{
using M = typename V::mask_type;
// loads
constexpr size_t alignment = 2 * std::experimental::memory_alignment_v<M>;
alignas(alignment) bool mem[3 * M::size()];
std::memset(mem, 0, sizeof(mem));
for (std::size_t i = 1; i < sizeof(mem) / sizeof(*mem); i += 2)
{
COMPARE(mem[i - 1], false);
mem[i] = true;
}
using std::experimental::element_aligned;
using std::experimental::vector_aligned;
constexpr size_t stride_alignment
= M::size() & 1
? 1
: M::size() & 2
? 2
: M::size() & 4
? 4
: M::size() & 8
? 8
: M::size() & 16
? 16
: M::size() & 32
? 32
: M::size() & 64
? 64
: M::size() & 128 ? 128
: M::size() & 256 ? 256 : 512;
using stride_aligned_t = std::conditional_t<
M::size() == stride_alignment, decltype(vector_aligned),
std::experimental::overaligned_tag<stride_alignment * sizeof(bool)>>;
constexpr stride_aligned_t stride_aligned = {};
constexpr auto overaligned = std::experimental::overaligned<alignment>;
const M alternating_mask = make_alternating_mask<M>();
M x(&mem[M::size()], stride_aligned);
COMPARE(x, M::size() % 2 == 1 ? !alternating_mask : alternating_mask)
<< x.__to_bitset()
<< ", alternating_mask: " << alternating_mask.__to_bitset();
x = {&mem[1], element_aligned};
COMPARE(x, !alternating_mask);
x = M{mem, overaligned};
COMPARE(x, alternating_mask);
x.copy_from(&mem[M::size()], stride_aligned);
COMPARE(x, M::size() % 2 == 1 ? !alternating_mask : alternating_mask);
x.copy_from(&mem[1], element_aligned);
COMPARE(x, !alternating_mask);
x.copy_from(mem, vector_aligned);
COMPARE(x, alternating_mask);
x = !alternating_mask;
where(alternating_mask, x).copy_from(&mem[M::size()], stride_aligned);
COMPARE(x, M::size() % 2 == 1 ? !alternating_mask : M{true});
x = M(true); // 1111
where(alternating_mask, x).copy_from(&mem[1], element_aligned); // load .0.0
COMPARE(x, !alternating_mask); // 1010
where(alternating_mask, x).copy_from(mem, overaligned); // load .1.1
COMPARE(x, M{true}); // 1111
// stores
memset(mem, 0, sizeof(mem));
x = M(true);
x.copy_to(&mem[M::size()], stride_aligned);
std::size_t i = 0;
for (; i < M::size(); ++i)
{
COMPARE(mem[i], false);
}
for (; i < 2 * M::size(); ++i)
{
COMPARE(mem[i], true) << "i: " << i << ", x: " << x;
}
for (; i < 3 * M::size(); ++i)
{
COMPARE(mem[i], false);
}
memset(mem, 0, sizeof(mem));
x.copy_to(&mem[1], element_aligned);
COMPARE(mem[0], false);
for (i = 1; i <= M::size(); ++i)
{
COMPARE(mem[i], true);
}
for (; i < 3 * M::size(); ++i)
{
COMPARE(mem[i], false);
}
memset(mem, 0, sizeof(mem));
alternating_mask.copy_to(mem, overaligned);
for (i = 0; i < M::size(); ++i)
{
COMPARE(mem[i], (i & 1) == 1);
}
for (; i < 3 * M::size(); ++i)
{
COMPARE(mem[i], false);
}
x.copy_to(mem, vector_aligned);
where(alternating_mask, !x).copy_to(mem, overaligned);
for (i = 0; i < M::size(); ++i)
{
COMPARE(mem[i], i % 2 == 0);
}
for (; i < 3 * M::size(); ++i)
{
COMPARE(mem[i], false);
}
}