Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
ff64bc8
Improve `mdspan::empty`
JMazurkiewicz Jun 21, 2023
8d7468c
Improve `_Is_index_space_size_representable` and rename it to `_Is_st…
JMazurkiewicz Jun 21, 2023
3e791db
`layout_left`: Guard checks with `#if _CONTAINER_DEBUG_LEVEL > 0`
JMazurkiewicz Jun 21, 2023
9363526
`layout_left`: Implement `mapping(const extents_type&)` constructor's…
JMazurkiewicz Jun 21, 2023
7c29805
`layout_right`: Guard checks with `#if _CONTAINER_DEBUG_LEVEL > 0`
JMazurkiewicz Jun 21, 2023
e416aef
`layout_right`: Implement `mapping(const extents_type&)` constructor'…
JMazurkiewicz Jun 21, 2023
6cd745b
`layout_stride`: Guard checks with `#if _CONTAINER_DEBUG_LEVEL > 0`
JMazurkiewicz Jun 21, 2023
e59d020
`layout_left`: Use `for` loop instead of huge lambda expression in pr…
JMazurkiewicz Jun 21, 2023
e1b3512
`layout_right`: Use `for` loop instead of huge lambda expression in p…
JMazurkiewicz Jun 21, 2023
63e652b
`layout_stride`: implement default constructor's preconditions
JMazurkiewicz Jun 21, 2023
1e5341e
`layout_stride`: implement `mapping(extents_type, array/span)` constr…
JMazurkiewicz Jun 21, 2023
6ce8adc
`extents`: Improve `extents(exts...)` constructor's preconditions
JMazurkiewicz Jun 22, 2023
f6aed8d
`mdspan`: Implement `mdspan(other mdspan)` constructor's preconditions
JMazurkiewicz Jun 22, 2023
b3e4c4e
`extents`: expose `_Static_extents` array
JMazurkiewicz Jun 22, 2023
360d1f7
`mdspan`: Implement precondition check in `operator[]`
JMazurkiewicz Jun 22, 2023
76e0498
`mdspan`: Implement `mdspan::size`'s preconditions
JMazurkiewicz Jun 22, 2023
1a04c33
`extents`: Document DevCom-10398426 workaround
JMazurkiewicz Jun 22, 2023
6044c69
layouts: fix `_Contains_multidimensional_index` checks
JMazurkiewicz Jun 22, 2023
77c4a0b
`layout_stride`: fix death test
JMazurkiewicz Jun 22, 2023
0a3b516
Those invisible...
JMazurkiewicz Jun 22, 2023
f65dd87
Add missing `template` keyword
JMazurkiewicz Jun 22, 2023
172f2d5
`mdspan`: Use `cmp_equal` instead of regular `==` in precondition check
JMazurkiewicz Jun 22, 2023
eb1ee89
Silence Clang's constexpr limit error in `layout_(left|right)`'s tests
JMazurkiewicz Jun 22, 2023
ca14e4b
Drive-by: use `ranges::adjacent_find` instead of `views::pairwise_tra…
JMazurkiewicz Jun 23, 2023
a7f66df
Drive-by: fix exhaustiveness check in `get_mapping_properties`.
JMazurkiewicz Jun 23, 2023
72d2ff8
`layouts`: Improve preconditions checks in `operator()`
JMazurkiewicz Jul 2, 2023
fbee069
`mdspan`: Manually inline call to `extents_type::static_extent` in `s…
JMazurkiewicz Jul 2, 2023
5fa6e18
`layouts`: `_IndexSeq` -> `_Index_seq`
JMazurkiewicz Jul 2, 2023
d847e1a
`mdspan`: Improve precondition in `mdspan::operator[]`
JMazurkiewicz Jul 2, 2023
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
290 changes: 212 additions & 78 deletions stl/inc/mdspan

Large diffs are not rendered by default.

18 changes: 8 additions & 10 deletions tests/std/include/test_mdspan_support.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -267,14 +267,13 @@ struct MappingProperties {
template <class Mapping>
requires (!details::PermissiveTest<Mapping>::test())
MappingProperties<Mapping> get_mapping_properties(const Mapping& mapping) {
using IndexType = typename Mapping::index_type;
constexpr IndexType zero = 0;
constexpr auto rank = Mapping::extents_type::rank();
using IndexType = typename Mapping::index_type;
constexpr auto rank = Mapping::extents_type::rank();
constexpr std::make_index_sequence<rank> rank_indices;

auto get_extent = [&](size_t i) { return mapping.extents().extent(i); };
auto multidim_indices = [&]<size_t... Indices>(std::index_sequence<Indices...>) {
return std::views::cartesian_product(std::views::iota(zero, get_extent(Indices))...);
return std::views::cartesian_product(std::views::iota(IndexType{0}, get_extent(Indices))...);
}(rank_indices);

auto map_index = [&](const auto& tpl) { return std::apply([&](auto... i) { return mapping(i...); }, tpl); };
Expand All @@ -284,19 +283,18 @@ MappingProperties<Mapping> get_mapping_properties(const Mapping& mapping) {
MappingProperties<Mapping> props{};

// Find required span size (N4950 [mdspan.layout.reqmts]/12)
if (std::ranges::contains(std::views::iota(0u, rank) | std::views::transform(get_extent), zero)) {
if (std::ranges::contains(std::views::iota(0u, rank) | std::views::transform(get_extent), IndexType{0})) {
props.req_span_size = 0;
} else {
props.req_span_size = static_cast<IndexType>(1 + mapped_indices.back());
}

// Is mapping unique? (N4950 [mdspan.layout.reqmts]/14)
props.uniqueness = !std::ranges::contains(std::views::pairwise_transform(mapped_indices, std::minus{}), zero);
props.uniqueness = std::ranges::adjacent_find(mapped_indices) == mapped_indices.end();

{ // Is mapping exhaustive? (N4950 [mdspan.layout.reqmts]/16)
const auto diffs = std::views::pairwise_transform(mapped_indices, [](auto x, auto y) { return y - x; });
props.exhaustiveness = std::ranges::find_if_not(diffs, [](auto x) { return x == 1; }) == diffs.end();
}
// Is mapping exhaustive? (N4950 [mdspan.layout.reqmts]/16)
props.exhaustiveness =
std::ranges::adjacent_find(mapped_indices, [](auto x, auto y) { return y - x > 1; }) == mapped_indices.end();

{ // Is mapping strided? (N4950 [mdspan.layout.reqmts]/18)
props.strideness = true; // assumption
Expand Down
1 change: 1 addition & 0 deletions tests/std/test.lst
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,7 @@ tests\P0009R18_mdspan_layout_right_death
tests\P0009R18_mdspan_layout_stride
tests\P0009R18_mdspan_layout_stride_death
tests\P0009R18_mdspan_mdspan
tests\P0009R18_mdspan_mdspan_death
tests\P0019R8_atomic_ref
tests\P0024R2_parallel_algorithms_adjacent_difference
tests\P0024R2_parallel_algorithms_adjacent_find
Expand Down
8 changes: 8 additions & 0 deletions tests/std/tests/P0009R18_mdspan_extents_death/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,13 @@ void test_construction_from_pack_with_unrepresentable_as_index_type_values_2() {
[[maybe_unused]] extents<unsigned char, 1, dynamic_extent> e{ConvertibleToInt<unsigned char>{.val = 1}, 256};
}

void test_construction_from_pack_with_unrepresentable_as_index_type_values_3() {
static_assert(signed_integral<char>, "char is not signed integral");
// Either sizeof...(exts) must be equal to 0 or each element of exts must be nonnegative and must be representable
// as value of type index_type
[[maybe_unused]] extents<signed char, 1, dynamic_extent> e{static_cast<char>(-1)};
}

void test_construction_from_span_with_invalid_values() {
int vals[] = {1, 2};
span s{vals};
Expand Down Expand Up @@ -93,6 +100,7 @@ int main(int argc, char* argv[]) {
test_construction_from_pack_with_invalid_values,
test_construction_from_pack_with_unrepresentable_as_index_type_values_1,
test_construction_from_pack_with_unrepresentable_as_index_type_values_2,
test_construction_from_pack_with_unrepresentable_as_index_type_values_3,
test_construction_from_span_with_invalid_values,
test_construction_from_span_with_unrepresentable_as_index_type_values,
test_construction_from_array_with_invalid_values,
Expand Down
10 changes: 5 additions & 5 deletions tests/std/tests/P0009R18_mdspan_layout_left/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ constexpr void check_members(const extents<IndexType, Extents...>& ext, index_se

void check_mapping_properties() {
if constexpr (!is_permissive) {
auto check = []([[maybe_unused]] const auto& mapping) {
auto check = [](const auto& mapping) {
const auto props = get_mapping_properties(mapping);
assert(props.req_span_size == mapping.required_span_size());
assert(props.uniqueness);
Expand Down Expand Up @@ -465,6 +465,9 @@ constexpr void check_correctness() {
#endif // ^^^ !defined(__cpp_multidimensional_subscript) ^^^
}

#ifdef __clang__
if (!is_constant_evaluated()) // FIXME clang hits constexpr limit here
#endif
{ // 2x3x2x3 tensor
const array values{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
26, 27, 28, 29, 30, 31, 32, 33, 34, 35};
Expand All @@ -491,10 +494,7 @@ constexpr void check_correctness() {
}

constexpr bool test() {
check_members_with_various_extents(
[]<class IndexType, size_t... Extents>(const extents<IndexType, Extents...>& ext) {
check_members(ext, make_index_sequence<sizeof...(Extents)>{});
});
check_members_with_various_extents([]<class E>(const E& e) { check_members(e, make_index_sequence<E::rank()>{}); });
if (!is_constant_evaluated()) { // too heavy for compile time
check_mapping_properties();
}
Expand Down
19 changes: 16 additions & 3 deletions tests/std/tests/P0009R18_mdspan_layout_left_death/test.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#define _CONTAINER_DEBUG_LEVEL 1

#include <array>
#include <cstddef>
#include <mdspan>
Expand All @@ -10,7 +12,17 @@

using namespace std;

// TRANSITION, Test Construction From extents_type
void test_construction_from_extents_type_with_signed_index_type() {
using Ext = dextents<signed char, 3>;
// The size of the multidimensional index space e must be representable as a value of type index_type
[[maybe_unused]] layout_left::mapping<Ext> m{Ext{5, 4, 7}};
}

void test_construction_from_extents_type_with_unsigned_index_type() {
using Ext = dextents<unsigned char, 3>;
// The size of the multidimensional index space e must be representable as a value of type index_type
[[maybe_unused]] layout_left::mapping<Ext> m{Ext{5, 10, 6}};
}

void test_construction_from_other_left_mapping() {
layout_left::mapping<dextents<int, 1>> m1{dextents<int, 1>{256}};
Expand All @@ -26,7 +38,7 @@ void test_construction_from_other_right_mapping() {

void test_construction_from_other_stride_mapping_1() {
using Ext = extents<int, 2, 4>;
layout_stride::mapping<Ext> m1{Ext{}, array{1, 1}};
layout_stride::mapping<Ext> m1{Ext{}, array{4, 1}};
// For all r in the range [0, extents_type::rank()), other.stride(r) must be equal to
// extents().fwd-prod-of-extents(r)
layout_left::mapping<Ext> m2{m1};
Expand All @@ -53,7 +65,8 @@ void test_stride_function() {
int main(int argc, char* argv[]) {
std_testing::death_test_executive exec;
exec.add_death_tests({
// TRANSITION Construction From extents_type
test_construction_from_extents_type_with_signed_index_type,
test_construction_from_extents_type_with_unsigned_index_type,
test_construction_from_other_left_mapping,
test_construction_from_other_right_mapping,
test_construction_from_other_stride_mapping_1,
Expand Down
10 changes: 5 additions & 5 deletions tests/std/tests/P0009R18_mdspan_layout_right/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ constexpr void check_members(const extents<IndexType, Extents...>& ext, index_se
static_assert(same_as<typename Mapping::rank_type, typename Ext::rank_type>);
static_assert(same_as<typename Mapping::layout_type, layout_right>);

#ifdef __clang__
if (!is_constant_evaluated()) // FIXME clang hits constexpr limit here
#endif
{ // Check default and copy constructor
const Mapping m;
Mapping cpy = m;
Expand Down Expand Up @@ -160,7 +163,7 @@ constexpr void check_members(const extents<IndexType, Extents...>& ext, index_se

void check_mapping_properties() {
if constexpr (!is_permissive) {
auto check = []([[maybe_unused]] const auto& mapping) {
auto check = [](const auto& mapping) {
const auto props = get_mapping_properties(mapping);
assert(props.req_span_size == mapping.required_span_size());
assert(props.uniqueness);
Expand Down Expand Up @@ -514,10 +517,7 @@ constexpr void check_correctness() {
}

constexpr bool test() {
check_members_with_various_extents(
[]<class IndexType, size_t... Extents>(const extents<IndexType, Extents...>& ext) {
check_members(ext, make_index_sequence<sizeof...(Extents)>{});
});
check_members_with_various_extents([]<class E>(const E& e) { check_members(e, make_index_sequence<E::rank()>{}); });
if (!is_constant_evaluated()) { // too heavy for compile time
check_mapping_properties();
}
Expand Down
19 changes: 16 additions & 3 deletions tests/std/tests/P0009R18_mdspan_layout_right_death/test.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#define _CONTAINER_DEBUG_LEVEL 1

#include <array>
#include <cstddef>
#include <mdspan>
Expand All @@ -10,7 +12,17 @@

using namespace std;

// TRANSITION, Test Construction From extents_type
void test_construction_from_extents_type_with_signed_index_type() {
using Ext = dextents<signed char, 3>;
// The size of the multidimensional index space e must be representable as a value of type index_type
[[maybe_unused]] layout_right::mapping<Ext> m{Ext{5, 4, 7}};
}

void test_construction_from_extents_type_with_unsigned_index_type() {
using Ext = dextents<unsigned char, 3>;
// The size of the multidimensional index space e must be representable as a value of type index_type
[[maybe_unused]] layout_right::mapping<Ext> m{Ext{5, 10, 6}};
}

void test_construction_from_other_right_mapping() {
layout_right::mapping<dextents<int, 1>> m1{dextents<int, 1>{256}};
Expand All @@ -26,7 +38,7 @@ void test_construction_from_other_left_mapping() {

void test_construction_from_other_stride_mapping_1() {
using Ext = extents<int, 2, 4>;
layout_stride::mapping<Ext> m1{Ext{}, array{3, 1}};
layout_stride::mapping<Ext> m1{Ext{}, array{1, 2}};
// For all r in the range [0, extents_type::rank()), other.stride(r) must be equal to
// extents().rev-prod-of-extents(r)
layout_right::mapping<Ext> m2{m1};
Expand All @@ -53,7 +65,8 @@ void test_stride_function() {
int main(int argc, char* argv[]) {
std_testing::death_test_executive exec;
exec.add_death_tests({
// TRANSITION Construction From extents_type
test_construction_from_extents_type_with_signed_index_type,
test_construction_from_extents_type_with_unsigned_index_type,
test_construction_from_other_right_mapping,
test_construction_from_other_left_mapping,
test_construction_from_other_stride_mapping_1,
Expand Down
39 changes: 33 additions & 6 deletions tests/std/tests/P0009R18_mdspan_layout_stride_death/test.cpp
Original file line number Diff line number Diff line change
@@ -1,24 +1,49 @@
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#define _CONTAINER_DEBUG_LEVEL 1

#include <array>
#include <cstddef>
#include <mdspan>
#include <span>

#include <test_death.hpp>
#include <test_mdspan_support.hpp>

using namespace std;

void test_construction_from_extents_and_array() {
void test_default_construction() {
using Ext = extents<signed char, dynamic_extent, 4, 5, 7>;
// Value of layout_right::mapping<extents_type>().required_span_size() must be
// representable as a value of type index_type
[[maybe_unused]] layout_stride::mapping<Ext> m{}; // NB: strides are [140, 35, 7, 1]
}

void test_construction_from_extents_and_array_1() {
// Value of s[i] must be greater than 0 for all i in the range [0, rank_)
[[maybe_unused]] layout_stride::mapping<dextents<int, 1>> m1{extents<int, 1>{}, array<int, 1>{-1}};
}

void test_construction_from_extents_and_span() {
void test_construction_from_extents_and_array_2() {
using Ext = extents<signed char, 120>;
// REQUIRED-SPAN-SIZE(e, s) must be representable as a value of type index_type
[[maybe_unused]] layout_stride::mapping<Ext> m{Ext{}, array<int, 1>{2}};
}


void test_construction_from_extents_and_span_1() {
array<int, 1> s{-1};
// Value of s[i] must be greater than 0 for all i in the range [0, rank_)
[[maybe_unused]] layout_stride::mapping<dextents<int, 1>> m1{extents<int, 1>{}, span{s}};
[[maybe_unused]] layout_stride::mapping<dextents<int, 1>> m{extents<int, 1>{}, span{s}};
}

void test_construction_from_extents_and_span_2() {
using Ext = extents<unsigned char, 130>;
array<ConvertibleToInt<int>, 1> a{{{.val = 2}}};
const span s{a};
// REQUIRED-SPAN-SIZE(e, s) must be representable as a value of type index_type
[[maybe_unused]] layout_stride::mapping<Ext> m{Ext{}, s};
}

void test_construction_from_strided_layout_mapping() {
Expand All @@ -36,9 +61,11 @@ void test_call_operator() {
int main(int argc, char* argv[]) {
std_testing::death_test_executive exec;
exec.add_death_tests({
// TRANSITION more tests
test_construction_from_extents_and_array,
test_construction_from_extents_and_span,
test_default_construction,
test_construction_from_extents_and_array_1,
test_construction_from_extents_and_array_2,
test_construction_from_extents_and_span_1,
test_construction_from_extents_and_span_2,
test_construction_from_strided_layout_mapping,
test_call_operator,
});
Expand Down
4 changes: 4 additions & 0 deletions tests/std/tests/P0009R18_mdspan_mdspan_death/env.lst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

RUNALL_INCLUDE ..\concepts_latest_matrix.lst
60 changes: 60 additions & 0 deletions tests/std/tests/P0009R18_mdspan_mdspan_death/test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#define _CONTAINER_DEBUG_LEVEL 1

#include <array>
#include <mdspan>

#include <test_death.hpp>

using namespace std;

constexpr array<int, 256> some_ints{};

void test_construction_from_other_mdspan() {
auto mds1 = mdspan{some_ints.data(), 8, 2, 8};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an occurrence of "almost always auto" which we conventionally avoid. mdspan mds1{some_ints.data(), 8, 2, 8}; is the preferred form.

Occurs below.

// For each rank index r of extents_type, static_extent(r) == dynamic_extent || static_extent(r) == other.extent(r)
// must be true
[[maybe_unused]] mdspan<const int, extents<int, 8, 8, 2>> mds2{mds1};
}

#ifdef __cpp_multidimensional_subscript // TRANSITION, P2128R6
void test_access_with_invalid_multidimensional_index_1() {
auto mds = mdspan{some_ints.data(), 4, 4};
// I must be a multidimensional index in extents()
(void) mds[3, 4];
}
#endif // __cpp_multidimensional_subscript

void test_access_with_invalid_multidimensional_index_2() {
auto mds = mdspan{some_ints.data(), 5, 5};
// I must be a multidimensional index in extents()
(void) mds[array{4, 5}];
}

void test_size_when_index_type_is_signed() {
auto mds = mdspan{some_ints.data(), dextents<signed char, 3>{8, 8, 4}};
// The size of the multidimensional index space extents() must be representable as a value of type size_type
(void) mds.size();
}

void test_size_when_index_type_is_unsigned() {
auto mds = mdspan{some_ints.data(), dextents<unsigned char, 3>{8, 8, 4}};
// The size of the multidimensional index space extents() must be representable as a value of type size_type
(void) mds.size();
}

int main(int argc, char* argv[]) {
std_testing::death_test_executive exec;
exec.add_death_tests({
test_construction_from_other_mdspan,
#ifdef __cpp_multidimensional_subscript // TRANSITION, P2128R6
test_access_with_invalid_multidimensional_index_1,
#endif // __cpp_multidimensional_subscript
test_access_with_invalid_multidimensional_index_2,
test_size_when_index_type_is_signed,
test_size_when_index_type_is_unsigned,
});
return exec.run(argc, argv);
}