Implements a suite of tests for the currently implemented parts of layout_left. The individual tests are templated over the layout type, to allow reuse as more layouts are added.
libstdc++/ChangeLog: * testsuite/23_containers/mdspan/layouts/class_mandate_neg.cc: New test. * testsuite/23_containers/mdspan/layouts/ctors.cc: New test. * testsuite/23_containers/mdspan/layouts/mapping.cc: New test. Signed-off-by: Luc Grosheintz <luc.groshei...@gmail.com> --- .../mdspan/layouts/class_mandate_neg.cc | 21 + .../23_containers/mdspan/layouts/ctors.cc | 132 +++++++ .../23_containers/mdspan/layouts/mapping.cc | 371 ++++++++++++++++++ 3 files changed, 524 insertions(+) create mode 100644 libstdc++-v3/testsuite/23_containers/mdspan/layouts/class_mandate_neg.cc create mode 100644 libstdc++-v3/testsuite/23_containers/mdspan/layouts/ctors.cc create mode 100644 libstdc++-v3/testsuite/23_containers/mdspan/layouts/mapping.cc diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/class_mandate_neg.cc b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/class_mandate_neg.cc new file mode 100644 index 00000000000..2fd27d0bd35 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/class_mandate_neg.cc @@ -0,0 +1,21 @@ +// { dg-do compile { target c++23 } } +#include<mdspan> + +constexpr size_t dyn = std::dynamic_extent; + +template<typename Layout> + struct A + { + static constexpr size_t n = (size_t(1) << 7) - 1; + + typename Layout::mapping<std::extents<char>> m0; + typename Layout::mapping<std::extents<char, n, 2, dyn>> m1; + typename Layout::mapping<std::extents<char, n, 2, 0>> m2; + + using extents_type = std::extents<char, n, 4>; + typename Layout::mapping<extents_type> m3; // { dg-error "required from" } + }; + +A<std::layout_left> a_left; // { dg-error "required from" } + +// { dg-prune-output "not representable as index_type" } diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/ctors.cc b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/ctors.cc new file mode 100644 index 00000000000..c7cf5501628 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/ctors.cc @@ -0,0 +1,132 @@ +// { dg-do run { target c++23 } } +#include <mdspan> + +#include <testsuite_hooks.h> + +constexpr size_t dyn = std::dynamic_extent; + +// ctor: mapping(const extents&) +namespace from_extents +{ + template<typename Mapping, typename Extents> + constexpr bool + is_implicit() + { + return std::is_nothrow_constructible_v<Mapping, Extents> + && std::is_convertible_v<Extents, Mapping>; + } + + template<typename Layout> + constexpr void + test_implicit() + { + static_assert(is_implicit<typename Layout::mapping<std::extents<int, 2>>, + std::extents<int, 2>>()); + + static_assert(!is_implicit< + typename Layout::mapping<std::extents<int, dyn>>, + std::extents<int, 2>>()); + } + + template<typename Layout, typename Extents> + constexpr void + test_ctor_extents(Extents exts) + { + typename Layout::mapping<Extents> m(exts); + VERIFY(m.extents() == exts); + } + + template<typename Layout> + constexpr bool + test_ctor_extents_all() + { + test_ctor_extents<Layout>(std::extents<int>()); + test_ctor_extents<Layout>(std::extents<int, 1>()); + test_ctor_extents<Layout>(std::extents<int, 1, 2, dyn>(3)); + return true; + } + + template<typename Layout> + constexpr void + test_all() + { + static_assert(!std::is_constructible_v< + typename Layout::mapping<std::extents<int, 2>>, + std::extents<unsigned int, 2>>); + + static_assert(!std::is_constructible_v< + typename Layout::mapping<std::extents<int, 2>>, + std::extents<int, 3>>); + + test_implicit<Layout>(); + test_ctor_extents_all<Layout>(); + static_assert(test_ctor_extents_all<Layout>()); + } +} + +// ctor: mapping(mapping<OExtents>) +namespace from_same_layout +{ + template<typename Layout> + constexpr bool + test_ctor_mapping() + { + std::extents<int, 1, 2> e; + typename Layout::mapping<std::extents<int, dyn, dyn>> m1(e); + typename Layout::mapping<std::extents<int, 1, 2>> m2(m1); + + VERIFY(m1.extents() == m2.extents()); + return true; + } + + template<typename Layout> + constexpr void + test_constructible() + { + static_assert(!std::is_constructible_v< + typename Layout::mapping<std::extents<int, 1>>, + typename Layout::mapping<std::extents<int>>>); + + static_assert(std::is_nothrow_constructible_v< + typename Layout::mapping<std::extents<int, 1>>, + typename Layout::mapping<std::extents<int, dyn>>>); + } + + template<typename Layout> + constexpr void + test_convertible() + { + static_assert(std::is_convertible_v< + typename Layout::mapping<std::extents<int, 1>>, + typename Layout::mapping<std::extents<int, dyn>>>); + + static_assert(!std::is_convertible_v< + typename Layout::mapping<std::extents<int, dyn>>, + typename Layout::mapping<std::extents<int, 1>>>); + } + + template<typename Layout> + constexpr void + test_all() + { + test_ctor_mapping<Layout>(); + static_assert(test_ctor_mapping<Layout>()); + test_constructible<Layout>(); + test_convertible<Layout>(); + } +} + +template<typename Layout> +constexpr void +test_all() +{ + from_extents::test_all<Layout>(); + from_same_layout::test_all<Layout>(); +} + +int +main() +{ + test_all<std::layout_left>(); + return 0; +} diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/mapping.cc b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/mapping.cc new file mode 100644 index 00000000000..1d7d4c4e1c7 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/mapping.cc @@ -0,0 +1,371 @@ +// { dg-do run { target c++23 } } +#include <mdspan> + +#include <testsuite_hooks.h> + +constexpr size_t dyn = std::dynamic_extent; + +template<typename Layout, typename Extent> + constexpr bool + test_mapping_properties() + { + using M = typename Layout::mapping<Extent>; + static_assert(std::__mdspan::__is_extents<typename M::extents_type>); + static_assert(std::copyable<M>); + static_assert(std::is_nothrow_move_constructible_v<M>); + static_assert(std::is_nothrow_move_assignable_v<M>); + static_assert(std::is_nothrow_swappable_v<M>); + static_assert(std::is_same_v<typename M::index_type, + typename M::extents_type::index_type>); + static_assert(std::is_same_v<typename M::size_type, + typename M::extents_type::size_type>); + static_assert(std::is_same_v<typename M::rank_type, + typename M::extents_type::rank_type>); + static_assert(std::is_same_v<typename M::layout_type, Layout>); + + static_assert(std::is_trivially_copyable_v<M>); + static_assert(std::regular<M>); + + static_assert(M::is_always_unique() && M::is_unique()); + static_assert(M::is_always_strided() && M::is_strided()); + return true; + } + +template<typename Layout> + constexpr bool + test_mapping_properties_all() + { + test_mapping_properties<Layout, std::extents<int>>(); + test_mapping_properties<Layout, std::extents<int, 1>>(); + test_mapping_properties<Layout, std::extents<int, dyn>>(); + return true; + } + +// Check operator()(Indices...) +template<typename Mapping, size_t N> + constexpr typename Mapping::index_type + linear_index(const Mapping& mapping, + const std::array<typename Mapping::index_type, N>& indices) + { + typename Mapping::index_type ret = 0; + for(size_t r = 0; r < indices.size(); ++r) + ret += indices[r] * mapping.stride(r); + return ret; + } + +template<typename Mapping, typename... Indices> + constexpr void + test_linear_index(const Mapping& m, Indices... i) + { + using index_type = typename Mapping::index_type; + index_type expected = linear_index(m, std::array{index_type(i)...}); + VERIFY(m(i...) == expected); + VERIFY(m(char(i)...) == expected); + } + +template<typename Layout> + constexpr void + test_linear_index_0d() + { + constexpr typename Layout::mapping<std::extents<int>> m; + VERIFY(m() == 0); + } + +template<typename Layout> + constexpr void + test_linear_index_2d() + { + typename Layout::mapping<std::extents<int, 3, 256>> m; + test_linear_index(m, 0, 0); + test_linear_index(m, 1, 0); + test_linear_index(m, 0, 1); + test_linear_index(m, 1, 1); + test_linear_index(m, 2, 4); + } + + +template<typename Layout> + struct Mapping3dFactory + { + using Mapping = typename Layout::mapping<std::dextents<size_t, 3>>; + + static constexpr Mapping + create(std::dextents<size_t, 3> exts) + { return Mapping(exts); } + }; + +template<typename Layout> + constexpr void + test_linear_index_3d() + { + auto m = Mapping3dFactory<Layout>::create(std::extents(3, 5, 7)); + test_linear_index(m, 0, 0, 0); + test_linear_index(m, 1, 0, 0); + test_linear_index(m, 0, 1, 0); + test_linear_index(m, 0, 0, 1); + test_linear_index(m, 1, 1, 0); + test_linear_index(m, 2, 4, 6); + } + +struct IntLikeA +{ + operator int() + { return 0; } +}; + +struct IntLikeB +{ + operator int() noexcept + { return 0; } +}; + +struct NotIntLike +{ }; + +template<typename Layout> + constexpr void + test_has_linear_index() + { + using Mapping = typename Layout::mapping<std::extents<int, 3, 5>>; + static_assert(std::invocable<Mapping, int, int>); + static_assert(!std::invocable<Mapping, int>); + static_assert(!std::invocable<Mapping, IntLikeA, int>); + static_assert(std::invocable<Mapping, IntLikeB, int>); + static_assert(!std::invocable<Mapping, NotIntLike, int>); + static_assert(std::invocable<Mapping, double, double>); + } + +template<typename Layout> + constexpr bool + test_linear_index_all() + { + test_linear_index_0d<Layout>(); + test_linear_index_2d<Layout>(); + test_linear_index_3d<Layout>(); + test_has_linear_index<Layout>(); + return true; + } + +template<typename Mapping, typename Mapping::index_type... Counts> + constexpr typename Mapping::index_type + linear_index_end_impl(Mapping m, + std::integer_sequence<typename Mapping::index_type, Counts...>) + { + if constexpr (sizeof...(Counts) == 0) + return 1; + else + { + auto exts = m.extents(); + if(((exts.extent(Counts) == 0) || ...)) + return 0; + + return m((exts.extent(Counts) - 1)...) + 1; + } + } + +template<typename Mapping> + constexpr typename Mapping::index_type + linear_index_end(Mapping m) + { + using index_type = typename Mapping::index_type; + constexpr size_t rank = Mapping::extents_type::rank(); + return linear_index_end_impl(m, + std::make_integer_sequence<index_type, rank>()); + } + +// Check required_span_size +template<typename Mapping> + constexpr void + test_required_span_size(Mapping m) + { + VERIFY(m.required_span_size() == linear_index_end(m)); + } + +template<typename Layout> + constexpr void + test_required_span_size_0d() + { + typename Layout::mapping<std::extents<int>> m; + test_required_span_size(m); + VERIFY(m.required_span_size() == 1); + } + +template<typename Layout> + constexpr void + test_required_span_size_2d() + { + typename Layout::mapping<std::extents<int, 3, 5>> m; + test_required_span_size(m); + } + +template<typename Layout> + constexpr void + test_required_span_size_3d() + { + auto m = Mapping3dFactory<Layout>::create(std::extents(3, 5, 7)); + test_required_span_size(m); + } + +template<typename Layout> + constexpr void + test_required_span_size_zero() + { + auto m = Mapping3dFactory<Layout>::create(std::extents(3, 0, 7)); + test_required_span_size(m); + } + +template<typename Layout> + constexpr bool + test_required_span_size_all() + { + test_required_span_size_0d<Layout>(); + test_required_span_size_2d<Layout>(); + test_required_span_size_3d<Layout>(); + test_required_span_size_zero<Layout>(); + return true; + } + +// Check stride +template<typename Layout> + constexpr void + test_stride_2d(); + +template<> + constexpr void + test_stride_2d<std::layout_left>() + { + std::layout_left::mapping<std::extents<int, 3, 5>> m; + VERIFY(m.stride(0) == 1); + VERIFY(m.stride(1) == 3); + } + +template<typename Layout> + constexpr void + test_stride_3d(); + +template<> + constexpr void + test_stride_3d<std::layout_left>() + { + std::layout_left::mapping m(std::dextents<int, 3>(3, 5, 7)); + VERIFY(m.stride(0) == 1); + VERIFY(m.stride(1) == 3); + VERIFY(m.stride(2) == 3*5); + } + +template<typename Layout> + constexpr bool + test_stride_all() + { + test_stride_2d<Layout>(); + test_stride_3d<Layout>(); + return true; + } + +template<typename Mapping> + concept has_stride = requires (Mapping m) + { + { m.stride(0) } -> std::same_as<typename Mapping::index_type>; + }; + +template<typename Layout> + constexpr void + test_has_stride_0d() + { + using Mapping = typename Layout::mapping<std::extents<int>>; + constexpr bool expected = false; + static_assert(has_stride<Mapping> == expected); + } + +template<typename Layout> + constexpr void + test_has_stride_1d() + { static_assert(has_stride<typename Layout::mapping<std::extents<int, 1>>>); } + +// Check operator== +template<typename Layout> + constexpr void + test_eq() + { + typename Layout::mapping<std::extents<int, 1, 2>> m1; + typename Layout::mapping<std::extents<int, 2, 2>> m2; + typename Layout::mapping<std::dextents<int, 2>> m3(m1); + + VERIFY(m1 == m1); + VERIFY(m1 != m2); + VERIFY(m1 == m3); + VERIFY(m2 != m3); + } + +template<typename Layout> + constexpr void + test_eq_zero() + { + typename Layout::mapping<std::extents<int, 0, 2>> m1; + typename Layout::mapping<std::extents<int, 0, 2>> m2; + typename Layout::mapping<std::extents<int, 2, 0>> m3; + + VERIFY(m1 == m2); + VERIFY(m1 != m3); + } + +template<typename M1, typename M2> + concept has_op_eq = requires (M1 m1, M2 m2) + { + { m1 == m2 } -> std::same_as<bool>; + { m1 != m2 } -> std::same_as<bool>; + }; + +template<typename Layout> + constexpr bool + test_has_op_eq() + { + static_assert(!has_op_eq< + typename Layout::mapping<std::extents<int, 1, 2>>, + typename Layout::mapping<std::extents<int, 1>>>); + + static_assert(has_op_eq< + typename Layout::mapping<std::extents<int, 1>>, + typename Layout::mapping<std::extents<int, 1>>>); + + static_assert(has_op_eq< + typename Layout::mapping<std::extents<int, 1>>, + typename Layout::mapping<std::extents<int, 2>>>); + return true; + } + +template<typename Layout> + constexpr bool + test_mapping_all() + { + test_linear_index_all<Layout>(); + test_required_span_size_all<Layout>(); + test_stride_all<Layout>(); + + test_eq<Layout>(); + test_eq_zero<Layout>(); + return true; + } + +template<typename Layout> +constexpr void +test_all() +{ + static_assert(std::is_trivially_default_constructible_v<Layout>); + static_assert(std::is_trivially_copyable_v<Layout>); + static_assert(test_mapping_properties_all<Layout>()); + + test_mapping_all<Layout>(); + static_assert(test_mapping_all<Layout>()); + + test_has_stride_0d<Layout>(); + test_has_stride_1d<Layout>(); + test_has_op_eq<Layout>(); +} + +int +main() +{ + test_all<std::layout_left>(); + return 0; +} -- 2.49.0