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 <type_traits>
36
37#include "test_macros.h"
38#include "../ConvertibleToIntegral.h"
39
40template <class E, class S>
41constexpr void test_construction(E e, S s) {
42 using M = std::layout_stride::mapping<E>;
43 ASSERT_NOEXCEPT(M{e, s});
44 M m(e, s);
45
46 // check correct extents are returned
47 ASSERT_NOEXCEPT(m.extents());
48 assert(m.extents() == e);
49
50 // check required_span_size()
51 typename E::index_type expected_size = 1;
52 for (typename E::rank_type r = 0; r < E::rank(); r++) {
53 if (e.extent(r) == 0) {
54 expected_size = 0;
55 break;
56 }
57 expected_size += (e.extent(r) - 1) * static_cast<typename E::index_type>(s[r]);
58 }
59 assert(m.required_span_size() == expected_size);
60
61 // check strides: node stride function is constrained on rank>0, e.extent(r) is not
62 auto strides = m.strides();
63 ASSERT_NOEXCEPT(m.strides());
64 if constexpr (E::rank() > 0) {
65 for (typename E::rank_type r = 0; r < E::rank(); r++) {
66 assert(m.stride(r) == static_cast<typename E::index_type>(s[r]));
67 assert(strides[r] == m.stride(r));
68 }
69 }
70}
71
72constexpr bool test() {
73 constexpr size_t D = std::dynamic_extent;
74 {
75 std::array<int, 0> s{};
76 test_construction(e: std::extents<int>(), s);
77 }
78 {
79 std::array<int, 1> s{1};
80 test_construction(std::extents<unsigned, D>(7), s);
81 }
82 {
83 std::array<int, 1> s{1};
84 test_construction(std::extents<unsigned, D>(0), s);
85 }
86 {
87 std::array<int, 1> s{2};
88 test_construction(e: std::extents<unsigned, 7>(), s);
89 }
90 {
91 std::array<IntType, 1> s{1};
92 test_construction(std::extents<int, D>(7), s);
93 }
94 {
95 std::array<int, 2> s{3, 30};
96 test_construction(std::extents<unsigned, 7, 8>(), s);
97 }
98 {
99 std::array<int, 4> s{20, 2, 200, 2000};
100 test_construction(std::extents<int64_t, D, 8, D, D>(7, 9, 10), s);
101 test_construction(std::extents<int64_t, D, 8, D, D>(0, 9, 10), s);
102 test_construction(std::extents<int64_t, D, 8, D, D>(0, 8, 0), s);
103 }
104 {
105 std::array<int, 4> s{200, 20, 20, 2000};
106 test_construction(std::extents<int64_t, D, D, D, D>(7, 0, 8, 9), s);
107 test_construction(std::extents<int64_t, D, D, D, D>(7, 8, 0, 9), s);
108 test_construction(std::extents<int64_t, D, D, D, D>(7, 1, 8, 9), s);
109 test_construction(std::extents<int64_t, D, D, D, D>(7, 8, 1, 9), s);
110 test_construction(std::extents<int64_t, D, D, D, D>(7, 1, 1, 9), s);
111 test_construction(std::extents<int64_t, D, D, D, D>(7, 0, 0, 9), s);
112 test_construction(std::extents<int64_t, D, D, D, D>(7, 1, 1, 9), s);
113 test_construction(std::extents<int64_t, D, D, D, D>(7, 1, 0, 9), s);
114 test_construction(std::extents<int64_t, D, D, D, D>(7, 0, 1, 9), s);
115 }
116
117 {
118 using mapping_t = std::layout_stride::mapping<std::dextents<unsigned, 2>>;
119 // wrong strides size
120 static_assert(!std::is_constructible_v<mapping_t, std::dextents<int, 2>, std::array<int, 3>>);
121 static_assert(!std::is_constructible_v<mapping_t, std::dextents<int, 2>, std::array<int, 1>>);
122 // wrong extents rank
123 static_assert(!std::is_constructible_v<mapping_t, std::dextents<int, 3>, std::array<int, 2>>);
124 // none-convertible strides
125 static_assert(!std::is_constructible_v<mapping_t, std::dextents<int, 2>, std::array<IntType, 2>>);
126 }
127 {
128 // not no-throw constructible index_type from stride
129 using mapping_t = std::layout_stride::mapping<std::dextents<unsigned char, 2>>;
130 static_assert(std::is_convertible_v<IntType, unsigned char>);
131 static_assert(!std::is_constructible_v<mapping_t, std::dextents<int, 2>, std::array<IntType, 2>>);
132 }
133
134 return true;
135}
136
137int main(int, char**) {
138 test();
139 static_assert(test());
140 return 0;
141}
142

source code of libcxx/test/std/containers/views/mdspan/layout_stride/ctor.extents_array.pass.cpp