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 // template<class OtherIndexType> 14 // constexpr mapping(const extents_type& e, array<OtherIndexType, rank_> s) noexcept; 15 // 16 // Constraints: 17 // - is_convertible_v<const OtherIndexType&, index_type> is true, and 18 // - is_nothrow_constructible_v<index_type, const OtherIndexType&> is true. 19 // 20 // Preconditions: 21 // - s[i] > 0 is true for all i in the range [0, rank_). 22 // - REQUIRED-SPAN-SIZE(e, s) is representable as a value of type index_type ([basic.fundamental]). 23 // - If rank_ is greater than 0, then there exists a permutation P of the integers in the range [0, rank_), 24 // such that s[pi] >= s[pi_1] * e.extent(pi_1) is true for all i in the range [1, rank_), where pi is the ith element of P. 25 // Note 1: For layout_stride, this condition is necessary and sufficient for is_unique() to be true. 26 // 27 // Effects: Direct-non-list-initializes extents_ with e, and for all d in the range [0, rank_), 28 // direct-non-list-initializes strides_[d] with as_const(s[d]). 29 30 #include <array> 31 #include <cassert> 32 #include <cstddef> 33 #include <cstdint> 34 #include <mdspan> 35 #include <span> // dynamic_extent 36 #include <type_traits> 37 38 #include "test_macros.h" 39 #include "../ConvertibleToIntegral.h" 40 41 template <class E, class S> 42 constexpr void test_construction(E e, S s) { 43 using M = std::layout_stride::mapping<E>; 44 ASSERT_NOEXCEPT(M{e, s}); 45 M m(e, s); 46 47 // check correct extents are returned 48 ASSERT_NOEXCEPT(m.extents()); 49 assert(m.extents() == e); 50 51 // check required_span_size() 52 typename E::index_type expected_size = 1; 53 for (typename E::rank_type r = 0; r < E::rank(); r++) { 54 if (e.extent(r) == 0) { 55 expected_size = 0; 56 break; 57 } 58 expected_size += (e.extent(r) - 1) * static_cast<typename E::index_type>(s[r]); 59 } 60 assert(m.required_span_size() == expected_size); 61 62 // check strides: node stride function is constrained on rank>0, e.extent(r) is not 63 auto strides = m.strides(); 64 ASSERT_NOEXCEPT(m.strides()); 65 if constexpr (E::rank() > 0) { 66 for (typename E::rank_type r = 0; r < E::rank(); r++) { 67 assert(m.stride(r) == static_cast<typename E::index_type>(s[r])); 68 assert(strides[r] == m.stride(r)); 69 } 70 } 71 } 72 73 constexpr bool test() { 74 constexpr size_t D = std::dynamic_extent; 75 { 76 std::array<int, 0> s{}; 77 test_construction(std::extents<int>(), s); 78 } 79 { 80 std::array<int, 1> s{1}; 81 test_construction(std::extents<unsigned, D>(7), s); 82 } 83 { 84 std::array<int, 1> s{1}; 85 test_construction(std::extents<unsigned, D>(0), s); 86 } 87 { 88 std::array<int, 1> s{2}; 89 test_construction(std::extents<unsigned, 7>(), s); 90 } 91 { 92 std::array<IntType, 1> s{1}; 93 test_construction(std::extents<int, D>(7), s); 94 } 95 { 96 std::array<int, 2> s{3, 30}; 97 test_construction(std::extents<unsigned, 7, 8>(), s); 98 } 99 { 100 std::array<int, 4> s{20, 2, 200, 2000}; 101 test_construction(std::extents<int64_t, D, 8, D, D>(7, 9, 10), s); 102 test_construction(std::extents<int64_t, D, 8, D, D>(0, 9, 10), s); 103 test_construction(std::extents<int64_t, D, 8, D, D>(0, 8, 0), s); 104 } 105 { 106 std::array<int, 4> s{200, 20, 20, 2000}; 107 test_construction(std::extents<int64_t, D, D, D, D>(7, 0, 8, 9), s); 108 test_construction(std::extents<int64_t, D, D, D, D>(7, 8, 0, 9), s); 109 test_construction(std::extents<int64_t, D, D, D, D>(7, 1, 8, 9), s); 110 test_construction(std::extents<int64_t, D, D, D, D>(7, 8, 1, 9), s); 111 test_construction(std::extents<int64_t, D, D, D, D>(7, 1, 1, 9), s); 112 test_construction(std::extents<int64_t, D, D, D, D>(7, 0, 0, 9), s); 113 test_construction(std::extents<int64_t, D, D, D, D>(7, 1, 1, 9), s); 114 test_construction(std::extents<int64_t, D, D, D, D>(7, 1, 0, 9), s); 115 test_construction(std::extents<int64_t, D, D, D, D>(7, 0, 1, 9), s); 116 } 117 118 { 119 using mapping_t = std::layout_stride::mapping<std::dextents<unsigned, 2>>; 120 // wrong strides size 121 static_assert(!std::is_constructible_v<mapping_t, std::dextents<int, 2>, std::array<int, 3>>); 122 static_assert(!std::is_constructible_v<mapping_t, std::dextents<int, 2>, std::array<int, 1>>); 123 // wrong extents rank 124 static_assert(!std::is_constructible_v<mapping_t, std::dextents<int, 3>, std::array<int, 2>>); 125 // none-convertible strides 126 static_assert(!std::is_constructible_v<mapping_t, std::dextents<int, 2>, std::array<IntType, 2>>); 127 } 128 { 129 // not no-throw constructible index_type from stride 130 using mapping_t = std::layout_stride::mapping<std::dextents<unsigned char, 2>>; 131 static_assert(std::is_convertible_v<IntType, unsigned char>); 132 static_assert(!std::is_constructible_v<mapping_t, std::dextents<int, 2>, std::array<IntType, 2>>); 133 } 134 135 return true; 136 } 137 138 int main(int, char**) { 139 test(); 140 static_assert(test()); 141 return 0; 142 } 143