Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 17 additions & 3 deletions stl/inc/mdspan
Original file line number Diff line number Diff line change
Expand Up @@ -826,8 +826,9 @@ public:
using layout_type = layout_stride;

private:
using _Extents_base = _Maybe_fully_static_extents<extents_type>;
using _Strides_base = _Maybe_empty_array<index_type, _Extents::rank()>;
using _Extents_base = _Maybe_fully_static_extents<extents_type>;
using _Strides_base = _Maybe_empty_array<index_type, _Extents::rank()>;
using _Stride_extent_pair = pair<rank_type, rank_type>;

static_assert(_Is_extents<extents_type>,
"Extents must be a specialization of std::extents (N4950 [mdspan.layout.stride.overview]/2).");
Expand All @@ -847,6 +848,7 @@ private:
bool _Found_zero = false;
bool _Overflow = false;
index_type _Req_span_size = 0;
array<_Stride_extent_pair, extents_type::rank()> _Pairs;
for (rank_type _Idx = 0; _Idx < extents_type::_Rank; ++_Idx) {
const index_type _Stride = this->_Array[_Idx];
_STL_VERIFY(_Stride > 0, "Value of s[i] must be greater than 0 for all i in the range [0, rank_) "
Expand All @@ -861,9 +863,22 @@ private:
_Overflow = _Mul_overflow(static_cast<index_type>(_Ext - 1), _Stride, _Prod)
|| _Add_overflow(_Req_span_size, _Prod, _Req_span_size);
}

_Pairs[_Idx] = {static_cast<rank_type>(_Stride), static_cast<rank_type>(_Ext)};
}
_STL_VERIFY(_Found_zero || !_Overflow, "REQUIRED-SPAN-SIZE(e, s) must be representable as a value of type "
"index_type (N4950 [mdspan.layout.stride.cons]/4.2).");

if (!_Found_zero) {
_RANGES sort(_Pairs);
for (rank_type _Idx = 1; _Idx < extents_type::_Rank; ++_Idx) {
_STL_VERIFY(_Pairs[_Idx].first >= _Pairs[_Idx - 1].first * _Pairs[_Idx - 1].second,
"If rank_ is greater than 0, then there must exist a permutation P of the integers in the "
"range [0, rank_), such that 's[p(i)] >= s[p(i-1)] * e.extent(p(i-1))' is true for all i in "
"the range [1, rank_), where p(i) is the i-th element of P (N5008 "
"[mdspan.layout.stride.cons]/4.3).");
}
}
}
#endif // _ITERATOR_DEBUG_LEVEL != 0
}
Expand Down Expand Up @@ -1111,7 +1126,6 @@ private:
}

_NODISCARD constexpr bool _Is_exhaustive_special_case() const noexcept {
using _Stride_extent_pair = pair<rank_type, rank_type>;
array<_Stride_extent_pair, extents_type::rank()> _Pairs;
for (rank_type _Idx = 0; _Idx < extents_type::_Rank; ++_Idx) {
rank_type _Ext = static_cast<rank_type>(this->_Exts.extent(_Idx));
Expand Down
46 changes: 23 additions & 23 deletions tests/std/tests/P0009R18_mdspan_layout_stride/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,7 @@ constexpr void check_required_span_size() {
using M1 = layout_stride::mapping<extents<int, 3, 3, 0, 3>>;
static_assert(M1{}.required_span_size() == 0);

layout_stride::mapping<dextents<int, 4>> m2{dextents<int, 4>{3, 0, 3, 3}, array{1, 3, 1, 1}};
layout_stride::mapping<dextents<int, 4>> m2{dextents<int, 4>{3, 0, 3, 3}, array{1, 3, 1, 3}};
assert(m2.required_span_size() == 0);
}

Expand Down Expand Up @@ -800,37 +800,37 @@ constexpr void check_correctness() {

{ // 3x2x2 tensor
using E = extents<int, 3, 2, 2>;
const array vals{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23};
layout_stride::mapping<E> m{E{}, array{8, 1, 6}}; // non-exhaustive mapping
const array vals{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18};
layout_stride::mapping<E> m{E{}, array{7, 1, 3}}; // non-exhaustive mapping
assert(!m.is_exhaustive());
mdspan<const int, E, layout_stride> tensor{vals.data(), m};

#ifdef __cpp_multidimensional_subscript // TRANSITION, P2128R6
assert((tensor[0, 0, 0] == 0));
assert((tensor[0, 0, 1] == 6));
assert((tensor[0, 0, 1] == 3));
assert((tensor[0, 1, 0] == 1));
assert((tensor[0, 1, 1] == 7));
assert((tensor[1, 0, 0] == 8));
assert((tensor[1, 0, 1] == 14));
assert((tensor[1, 1, 0] == 9));
assert((tensor[1, 1, 1] == 15));
assert((tensor[2, 0, 0] == 16));
assert((tensor[2, 0, 1] == 22));
assert((tensor[2, 1, 0] == 17));
assert((tensor[2, 1, 1] == 23));
assert((tensor[0, 1, 1] == 4));
assert((tensor[1, 0, 0] == 7));
assert((tensor[1, 0, 1] == 10));
assert((tensor[1, 1, 0] == 8));
assert((tensor[1, 1, 1] == 11));
assert((tensor[2, 0, 0] == 14));
assert((tensor[2, 0, 1] == 17));
assert((tensor[2, 1, 0] == 15));
assert((tensor[2, 1, 1] == 18));
#else // ^^^ defined(__cpp_multidimensional_subscript) / !defined(__cpp_multidimensional_subscript) vvv
assert((tensor[array{0, 0, 0}] == 0));
assert((tensor[array{0, 0, 1}] == 6));
assert((tensor[array{0, 0, 1}] == 3));
assert((tensor[array{0, 1, 0}] == 1));
assert((tensor[array{0, 1, 1}] == 7));
assert((tensor[array{1, 0, 0}] == 8));
assert((tensor[array{1, 0, 1}] == 14));
assert((tensor[array{1, 1, 0}] == 9));
assert((tensor[array{1, 1, 1}] == 15));
assert((tensor[array{2, 0, 0}] == 16));
assert((tensor[array{2, 0, 1}] == 22));
assert((tensor[array{2, 1, 0}] == 17));
assert((tensor[array{2, 1, 1}] == 23));
assert((tensor[array{0, 1, 1}] == 4));
assert((tensor[array{1, 0, 0}] == 7));
assert((tensor[array{1, 0, 1}] == 10));
assert((tensor[array{1, 1, 0}] == 8));
assert((tensor[array{1, 1, 1}] == 11));
assert((tensor[array{2, 0, 0}] == 14));
assert((tensor[array{2, 0, 1}] == 17));
assert((tensor[array{2, 1, 0}] == 15));
assert((tensor[array{2, 1, 1}] == 18));
#endif // ^^^ !defined(__cpp_multidimensional_subscript) ^^^
}

Expand Down
16 changes: 16 additions & 0 deletions tests/std/tests/P0009R18_mdspan_layout_stride_death/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ void test_construction_from_extents_and_array_2() {
[[maybe_unused]] layout_stride::mapping<Ext> m{Ext{}, array<int, 1>{2}};
}

void test_construction_from_extents_and_array_3() {
using Ext = extents<short, 2, 3, 5>;
const array<short, 3> a{29, 2, 6};
// Incorrect strides
[[maybe_unused]] layout_stride::mapping<Ext> m{Ext{}, a};
}

void test_construction_from_extents_and_span_1() {
array<int, 1> a{-1};
Expand All @@ -44,6 +50,14 @@ void test_construction_from_extents_and_span_2() {
[[maybe_unused]] layout_stride::mapping<Ext> m{Ext{}, s};
}

void test_construction_from_extents_and_span_3() {
using Ext = extents<unsigned char, 3, 3, 1, 1>;
array<long long, 4> a{3, 1, 8, 3};
const span s{a};
// Incorrect strides
[[maybe_unused]] layout_stride::mapping<Ext> m{Ext{}, s};
}

void test_construction_from_strided_layout_mapping() {
layout_right::mapping<extents<int, 256>> m1;
// Value of other.required_span_size() must be representable as a value of type index_type
Expand Down Expand Up @@ -73,8 +87,10 @@ int main(int argc, char* argv[]) {
test_default_construction,
test_construction_from_extents_and_array_1,
test_construction_from_extents_and_array_2,
test_construction_from_extents_and_array_3,
test_construction_from_extents_and_span_1,
test_construction_from_extents_and_span_2,
test_construction_from_extents_and_span_3,
test_construction_from_strided_layout_mapping,
test_call_operator,
test_stride_with_empty_extents,
Expand Down