blob: 8840d07879ccf9632f9dc13425c06cc57f9e7427 [file] [log] [blame]
// { dg-do run { target c++23 } }
#include <mdspan>
#include <cstdint>
#include <algorithm>
#include <testsuite_hooks.h>
constexpr size_t dyn = std::dynamic_extent;
template<typename Mapping>
constexpr void
invoke_stride(Mapping m)
{
// Only checking for UB, e.g. signed overflow.
for(size_t i = 0; i < Mapping::extents_type::rank(); ++i)
m.stride(i);
}
template<typename Mapping>
constexpr void
verify_required_span_size(Mapping m)
{ VERIFY(m.required_span_size() == 0); }
template<typename Mapping>
constexpr void
verify_all(Mapping m)
{
verify_required_span_size(m);
invoke_stride(m);
}
template<typename Layout, typename Int>
constexpr void
test_static_overflow()
{
constexpr Int n1 = std::numeric_limits<Int>::max();
constexpr size_t n2 = std::dynamic_extent - 1;
// Allow some room for padding.
constexpr size_t n = (std::cmp_less(n1, n2) ? size_t(n1) : n2) - 4;
verify_all(typename Layout::mapping<std::extents<Int, n, n, 0, n, n>>{});
verify_all(typename Layout::mapping<std::extents<Int, 0, n, n, n>>{});
verify_all(typename Layout::mapping<std::extents<Int, dyn, n, n, n>>{});
verify_all(typename Layout::mapping<std::extents<Int, n, n, n, 0>>{});
verify_all(typename Layout::mapping<std::extents<Int, n, n, n, dyn>>{});
}
template<typename Int, size_t N>
constexpr std::array<Int, N>
make_strides()
{
std::array<Int, N> strides;
std::ranges::fill(strides, Int(1));
return strides;
}
template<typename Layout, typename Extents>
constexpr typename Layout::mapping<Extents>
make_mapping(Extents exts)
{
using IndexType = typename Extents::index_type;
constexpr auto rank = Extents::rank();
constexpr auto strides = make_strides<IndexType, rank>();
if constexpr (std::same_as<Layout, std::layout_stride>)
return typename Layout::mapping(exts, strides);
else
return typename Layout::mapping(exts);
}
template<typename Layout, typename Int>
constexpr void
test_dynamic_overflow()
{
constexpr Int n1 = std::numeric_limits<Int>::max();
constexpr size_t n2 = std::dynamic_extent - 1;
// Allow some room for padding.
constexpr Int n = (std::cmp_less(n1, n2) ? n1 : Int(n2)) - 4;
verify_all(make_mapping<Layout>(
std::extents<Int, dyn, dyn, 0, dyn, dyn>{n, n, n, n}));
verify_all(make_mapping<Layout>(
std::extents<Int, dyn, dyn, dyn, dyn, dyn>{n, n, 0, n, n}));
verify_all(make_mapping<Layout>(
std::extents<Int, dyn, dyn, dyn, 0>{n, n, n}));
verify_all(make_mapping<Layout>(
std::extents<Int, dyn, dyn, dyn, dyn>{n, n, n, 0}));
verify_all(make_mapping<Layout>(
std::extents<Int, 0, dyn, dyn, dyn>{n, n, n}));
verify_all(make_mapping<Layout>(
std::extents<Int, dyn, dyn, dyn, dyn>{0, n, n, n}));
}
template<typename Layout, typename Int>
constexpr void
test_overflow()
{
test_static_overflow<Layout, Int>();
test_dynamic_overflow<Layout, Int>();
}
template<typename Layout>
constexpr bool
test_all()
{
test_overflow<Layout, signed char>();
test_overflow<Layout, short int>();
test_overflow<Layout, int>();
test_overflow<Layout, long int>();
test_overflow<Layout, long long int>();
test_overflow<Layout, unsigned char>();
test_overflow<Layout, unsigned short int>();
test_overflow<Layout, unsigned int>();
test_overflow<Layout, unsigned long int>();
test_overflow<Layout, unsigned long long int>();
test_overflow<Layout, size_t>();
return true;
}
template<template<size_t> typename Layout>
constexpr bool
test_padded_all()
{
static_assert(test_all<Layout<0>>());
static_assert(test_all<Layout<1>>());
static_assert(test_all<Layout<2>>());
static_assert(test_all<Layout<dyn>>());
return true;
}
int
main()
{
static_assert(test_all<std::layout_left>());
static_assert(test_all<std::layout_right>());
static_assert(test_all<std::layout_stride>());
#if __cplusplus > 202302L
static_assert(test_padded_all<std::layout_left_padded>());
static_assert(test_padded_all<std::layout_right_padded>());
#endif
return 0;
}