blob: d747ad40de21f80193238ca939f62c552abd3af5 [file]
// { dg-do run { target c++26 } }
#include <mdspan>
#include <testsuite_hooks.h>
#include <cstddef>
#include <cstdint>
constexpr size_t dyn = std::dynamic_extent;
template<typename Extents, typename CInt>
constexpr bool
check_collapsing(Extents exts, CInt ci_raw)
{
using IndexType = typename Extents::index_type;
auto ci_expected = std::cw<IndexType{ci_raw.value}>;
auto [ci] = std::canonical_slices(exts, ci_raw);
static_assert(std::same_as<decltype(ci), decltype(ci_expected)>);
VERIFY(std::cmp_equal(ci.value, ci_raw.value));
auto [i] = std::canonical_slices(exts, ci_raw.value);
static_assert(std::same_as<decltype(i), IndexType>);
VERIFY(std::cmp_equal(i, ci_raw.value));
return true;
}
template<typename Extents>
constexpr bool
test_scalar(Extents exts)
{
using IndexType = typename Extents::index_type;
check_collapsing(exts, std::cw<uint8_t{0}>);
check_collapsing(exts, std::cw<IndexType{0}>);
check_collapsing(exts, std::cw<uint8_t{4}>);
check_collapsing(exts, std::cw<IndexType{4}>);
return true;
}
constexpr bool
test_scalar()
{
test_scalar(std::extents<int, dyn>{5});
test_scalar(std::extents<int, 5>{});
test_scalar(std::extents<unsigned int, dyn>{5});
test_scalar(std::extents<unsigned int, 5>{});
return true;
}
constexpr void
assert_same(auto lhs, auto rhs)
{
static_assert(std::same_as<decltype(lhs), decltype(rhs)>);
VERIFY(lhs == rhs);
}
template<template<typename, typename> typename Pair>
constexpr bool
test_pair(auto exts, auto cbegin, auto cend, auto coffset, auto cextent)
{
using IndexType = typename decltype(exts)::index_type;
auto c1 = std::cw<IndexType{1}>;
auto raw_cc = Pair{cbegin, cend};
auto [cc] = std::canonical_slices(exts, raw_cc);
assert_same(cc.offset, coffset);
assert_same(cc.extent, cextent);
assert_same(cc.stride, c1);
auto raw_cd = Pair{cbegin, cend.value};
auto [cd] = std::canonical_slices(exts, raw_cd);
assert_same(cd.offset, coffset);
assert_same(cd.extent, cextent.value);
assert_same(cd.stride, c1);
auto raw_dc = Pair{cbegin.value, cend};
auto [dc] = std::canonical_slices(exts, raw_dc);
assert_same(dc.offset, coffset.value);
assert_same(dc.extent, cextent.value);
assert_same(dc.stride, c1);
auto raw_dd = Pair{cbegin.value, cend.value};
auto [dd] = std::canonical_slices(exts, raw_dd);
assert_same(dd.offset, coffset.value);
assert_same(dd.extent, cextent.value);
assert_same(dd.stride, c1);
return true;
}
template<template<typename, typename> typename Pair>
constexpr bool
test_pair()
{
test_pair<Pair>(std::extents<int, dyn>{5}, std::cw<uint8_t{2}>,
std::cw<uint8_t{5}>, std::cw<2>, std::cw<3>);
test_pair<Pair>(std::extents<int, 5>{}, std::cw<uint8_t{2}>,
std::cw<uint8_t{5}>, std::cw<2>, std::cw<3>);
test_pair<Pair>(std::extents<int, 0>{}, std::cw<uint8_t{0}>,
std::cw<uint8_t{0}>, std::cw<0>, std::cw<0>);
test_pair<Pair>(std::extents<int, dyn>{0}, std::cw<uint8_t{0}>,
std::cw<uint8_t{0}>, std::cw<0>, std::cw<0>);
return true;
}
template<typename Lower, typename Upper>
struct Range
{
Lower lower;
Upper upper;
};
constexpr bool
test_pair_all()
{
test_pair<std::pair>();
test_pair<std::tuple>();
test_pair<std::range_slice>();
test_pair<Range>();
return true;
}
template<template<typename, typename, typename> typename Triple>
constexpr bool
test_triple(auto exts, auto ce, auto cf, auto cl, auto cs)
{
using IndexType = decltype(exts)::index_type;
auto coffset = std::cw<IndexType{cf.value}>;
auto cextent = std::cw<IndexType{ce.value}>;
auto cstride = std::cw<IndexType{cs.value}>;
auto raw_ccc = Triple{cf, cl, cs};
auto [ccc] = std::canonical_slices(exts, raw_ccc);
assert_same(ccc.offset, coffset);
assert_same(ccc.extent, cextent);
assert_same(ccc.stride, cstride);
auto raw_dcc = Triple{cf.value, cl, cs};
auto [dcc] = std::canonical_slices(exts, raw_dcc);
assert_same(dcc.offset, coffset.value);
assert_same(dcc.extent, cextent.value);
assert_same(dcc.stride, cstride);
auto raw_cdc = Triple{cf, cl.value, cs};
auto [cdc] = std::canonical_slices(exts, raw_cdc);
assert_same(cdc.offset, coffset);
assert_same(cdc.extent, cextent.value);
assert_same(cdc.stride, cstride);
auto raw_ccd = Triple{cf, cl, cs.value};
auto [ccd] = std::canonical_slices(exts, raw_ccd);
assert_same(ccd.offset, coffset);
assert_same(ccd.extent, cextent.value);
assert_same(ccd.stride, cstride.value);
return true;
}
template<template<typename, typename, typename> typename Triple>
constexpr bool
test_triple_zero_extent(auto exts, auto cf, auto cs)
{
using IndexType = typename decltype(exts)::index_type;
auto raw_ccc = Triple{cf, cf, cs};
auto [ccc] = std::canonical_slices(exts, raw_ccc);
assert_same(ccc.stride, std::cw<IndexType{1}>);
auto raw_ccd = Triple{cf, cf, cs.value};
auto [ccd] = std::canonical_slices(exts, raw_ccd);
assert_same(ccd.stride, std::cw<IndexType{1}>);
auto raw_cdd = Triple{cf, cf.value, cs.value};
auto [cdd] = std::canonical_slices(exts, raw_cdd);
assert_same(cdd.stride, IndexType(1));
auto raw_dcd = Triple{cf.value, cf, cs.value};
auto [dcd] = std::canonical_slices(exts, raw_dcd);
assert_same(dcd.stride, IndexType(1));
auto raw_ddd = Triple{cf.value, cf.value, cs.value};
auto [ddd] = std::canonical_slices(exts, raw_ddd);
assert_same(cdd.stride, IndexType(1));
if constexpr (decltype(cs)::value > 0)
{
auto cstride = std::cw<IndexType(cs.value)>;
auto raw_cdc = Triple{cf, cf.value, cs};
auto [cdc] = std::canonical_slices(exts, raw_cdc);
assert_same(cdc.stride, cstride);
auto raw_dcc = Triple{cf.value, cf, cs};
auto [dcc] = std::canonical_slices(exts, raw_dcc);
assert_same(dcc.stride, cstride);
auto raw_ddc = Triple{cf.value, cf.value, cs};
auto [ddc] = std::canonical_slices(exts, raw_ddc);
assert_same(cdc.stride, cstride);
}
return true;
}
template<template<typename, typename, typename> typename Triple>
constexpr bool
test_triple()
{
auto run = [](auto exts) {
test_triple<Triple>(exts, std::cw<uint8_t{5}>,
std::cw<uint8_t{0}>, std::cw<uint8_t{5}>, std::cw<uint8_t{1}>);
test_triple<Triple>(exts, std::cw<uint8_t{3}>,
std::cw<uint8_t{0}>, std::cw<uint8_t{5}>, std::cw<uint8_t{2}>);
test_triple<Triple>(exts, std::cw<uint8_t{2}>,
std::cw<uint8_t{1}>, std::cw<uint8_t{5}>, std::cw<uint8_t{3}>);
test_triple<Triple>(exts, std::cw<uint8_t{1}>,
std::cw<uint8_t{1}>, std::cw<uint8_t{5}>, std::cw<uint8_t{9}>);
test_triple_zero_extent<Triple>(exts,
std::cw<uint8_t{0}>, std::cw<uint8_t{9}>);
test_triple_zero_extent<Triple>(exts,
std::cw<uint8_t{0}>, std::cw<uint8_t{0}>);
test_triple_zero_extent<Triple>(exts,
std::cw<uint8_t{5}>, std::cw<uint8_t{9}>);
test_triple_zero_extent<Triple>(exts,
std::cw<uint8_t{5}>, std::cw<uint8_t{0}>);
};
run(std::extents<int, 5>{});
run(std::extents<int, dyn>{5});
test_triple_zero_extent<Triple>(std::extents<int, 0>{},
std::cw<uint8_t{0}>, std::cw<uint8_t{9}>);
test_triple_zero_extent<Triple>(std::extents<int, dyn>{0},
std::cw<uint8_t{0}>, std::cw<uint8_t{0}>);
return true;
}
constexpr bool
test_triple_all()
{
test_triple<std::range_slice>();
return true;
}
constexpr bool
test_extent_slice(auto exts, auto co, auto ce, auto cs)
{
using IndexType = decltype(exts)::index_type;
auto coffset = std::cw<IndexType{co.value}>;
auto cextent = std::cw<IndexType{ce.value}>;
auto cstride = std::cw<IndexType{cs.value}>;
auto raw_ccc = std::extent_slice{co, ce, cs};
auto [ccc] = std::canonical_slices(exts, raw_ccc);
assert_same(ccc.offset, coffset);
assert_same(ccc.extent, cextent);
assert_same(ccc.stride, cstride);
auto raw_dcc = std::extent_slice{co.value, ce, cs};
auto [dcc] = std::canonical_slices(exts, raw_dcc);
assert_same(dcc.offset, coffset.value);
assert_same(dcc.extent, cextent);
assert_same(dcc.stride, cstride);
auto raw_cdc = std::extent_slice{co, ce.value, cs};
auto [cdc] = std::canonical_slices(exts, raw_cdc);
assert_same(cdc.offset, coffset);
assert_same(cdc.extent, cextent.value);
assert_same(cdc.stride, cstride);
auto raw_ccd = std::extent_slice{co, ce, cs.value};
auto [ccd] = std::canonical_slices(exts, raw_ccd);
assert_same(ccd.offset, coffset);
assert_same(ccd.extent, cextent);
assert_same(ccd.stride, cstride.value);
return true;
}
constexpr bool
test_extent_slice()
{
auto run = [](auto exts)
{
auto cs = std::cw<uint8_t{1}>;
test_extent_slice(exts, std::cw<uint8_t{2}>, std::cw<uint8_t{2}>, std::cw<uint8_t{2}>);
test_extent_slice(exts, std::cw<uint8_t{0}>, std::cw<uint8_t{5}>, std::cw<uint8_t{1}>);
test_extent_slice(exts, std::cw<uint8_t{0}>, std::cw<uint8_t{0}>, std::cw<uint8_t{1}>);
test_extent_slice(exts, std::cw<uint8_t{0}>, std::cw<uint8_t{0}>, std::cw<uint8_t{3}>);
test_extent_slice(exts, std::cw<uint8_t{0}>, std::cw<uint8_t{0}>, std::cw<uint8_t{0}>);
test_extent_slice(exts, std::cw<uint8_t{0}>, std::cw<uint8_t{0}>, std::cw<uint8_t{9}>);
};
run(std::extents<int, 5>{});
run(std::extents<int, dyn>{5});
return true;
}
constexpr bool
test_all()
{
test_scalar();
test_pair_all();
test_triple_all();
test_extent_slice();
return true;
}
int
main()
{
test_all();
static_assert(test_all());
return 0;
}