1 //===----------------------------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 10 11 // <mdspan> 12 13 // namespace std { 14 // template<class Extents> 15 // class layout_stride::mapping { 16 // 17 // ... 18 // static constexpr bool is_always_unique() noexcept { return true; } 19 // static constexpr bool is_always_exhaustive() noexcept { return false; } 20 // static constexpr bool is_always_strided() noexcept { return true; } 21 // 22 // static constexpr bool is_unique() noexcept { return true; } 23 // static constexpr bool is_exhaustive() noexcept; 24 // static constexpr bool is_strided() noexcept { return true; } 25 // ... 26 // }; 27 // } 28 // 29 // 30 // layout_stride::mapping<E> is a trivially copyable type that models regular for each E. 31 // 32 // constexpr bool is_exhaustive() const noexcept; 33 // 34 // Returns: 35 // - true if rank_ is 0. 36 // - Otherwise, true if there is a permutation P of the integers in the range [0, rank_) such that 37 // stride(p0) equals 1, and stride(pi) equals stride(pi_1) * extents().extent(pi_1) for i in the 38 // range [1, rank_), where pi is the ith element of P. 39 // - Otherwise, false. 40 41 #include <array> 42 #include <cassert> 43 #include <concepts> 44 #include <cstddef> 45 #include <mdspan> 46 #include <span> // dynamic_extent 47 #include <type_traits> 48 49 #include "test_macros.h" 50 51 template <class E> 52 constexpr void 53 test_layout_mapping_stride(E ext, std::array<typename E::index_type, E::rank()> strides, bool exhaustive) { 54 using M = std::layout_stride::mapping<E>; 55 M m(ext, strides); 56 const M c_m = m; 57 assert(m.strides() == strides); 58 assert(c_m.strides() == strides); 59 assert(m.extents() == ext); 60 assert(c_m.extents() == ext); 61 assert(M::is_unique() == true); 62 assert(m.is_exhaustive() == exhaustive); 63 assert(c_m.is_exhaustive() == exhaustive); 64 assert(M::is_strided() == true); 65 assert(M::is_always_unique() == true); 66 assert(M::is_always_exhaustive() == false); 67 assert(M::is_always_strided() == true); 68 69 ASSERT_NOEXCEPT(m.strides()); 70 ASSERT_NOEXCEPT(c_m.strides()); 71 ASSERT_NOEXCEPT(m.extents()); 72 ASSERT_NOEXCEPT(c_m.extents()); 73 ASSERT_NOEXCEPT(M::is_unique()); 74 ASSERT_NOEXCEPT(m.is_exhaustive()); 75 ASSERT_NOEXCEPT(c_m.is_exhaustive()); 76 ASSERT_NOEXCEPT(M::is_strided()); 77 ASSERT_NOEXCEPT(M::is_always_unique()); 78 ASSERT_NOEXCEPT(M::is_always_exhaustive()); 79 ASSERT_NOEXCEPT(M::is_always_strided()); 80 81 for (typename E::rank_type r = 0; r < E::rank(); r++) { 82 assert(m.stride(r) == strides[r]); 83 assert(c_m.stride(r) == strides[r]); 84 ASSERT_NOEXCEPT(m.stride(r)); 85 ASSERT_NOEXCEPT(c_m.stride(r)); 86 } 87 88 typename E::index_type expected_size = 1; 89 for (typename E::rank_type r = 0; r < E::rank(); r++) { 90 if (ext.extent(r) == 0) { 91 expected_size = 0; 92 break; 93 } 94 expected_size += (ext.extent(r) - 1) * static_cast<typename E::index_type>(strides[r]); 95 } 96 assert(m.required_span_size() == expected_size); 97 assert(c_m.required_span_size() == expected_size); 98 ASSERT_NOEXCEPT(m.required_span_size()); 99 ASSERT_NOEXCEPT(c_m.required_span_size()); 100 101 static_assert(std::is_trivially_copyable_v<M>); 102 static_assert(std::regular<M>); 103 } 104 105 constexpr bool test() { 106 constexpr size_t D = std::dynamic_extent; 107 test_layout_mapping_stride(std::extents<int>(), std::array<int, 0>{}, true); 108 test_layout_mapping_stride(std::extents<signed char, 4, 5>(), std::array<signed char, 2>{1, 4}, true); 109 test_layout_mapping_stride(std::extents<signed char, 4, 5>(), std::array<signed char, 2>{1, 5}, false); 110 test_layout_mapping_stride(std::extents<unsigned, D, 4>(7), std::array<unsigned, 2>{20, 2}, false); 111 test_layout_mapping_stride(std::extents<size_t, D, D, D, D>(3, 3, 3, 3), std::array<size_t, 4>{3, 1, 9, 27}, true); 112 return true; 113 } 114 115 int main(int, char**) { 116 test(); 117 static_assert(test()); 118 return 0; 119 } 120