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
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
97 changes: 63 additions & 34 deletions stl/inc/mdspan
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,15 @@ public:
return _Result;
}

// TRANSITION, LWG ISSUE? I believe that this function should return 'index_type'
_NODISCARD constexpr index_type _Rev_prod_of_extents(const rank_type _Idx) const noexcept {
index_type _Result = 1;
for (rank_type _Dim = _Idx + 1; _Dim < rank(); ++_Dim) {
_Result *= extent(_Dim);
}
return _Result;
}

_NODISCARD static _CONSTEVAL bool _Is_index_space_size_representable() {
if constexpr (rank_dynamic() == 0 && rank() > 0) {
return _STD in_range<index_type>((_Extents * ...));
Expand Down Expand Up @@ -354,12 +363,11 @@ public:
if constexpr (extents_type::rank() > 0) {
const bool _Verify = [&]<size_t... _Indices>(index_sequence<_Indices...>) {
index_type _Prod = 1;
return (
(_Other.stride(_Indices)
== (_Indices + 1 == extents_type::rank()
? _Prod
: _STD exchange(_Prod, static_cast<index_type>(_Prod * _Exts.extent(_Indices + 1)))))
&& ...);
return ((_Other.stride(_Indices)
== (_Indices == extents_type::rank() - 1
? _Prod
: _STD exchange(_Prod, static_cast<index_type>(_Prod * _Exts.extent(_Indices)))))
&& ...);
}
(make_index_sequence<extents_type::rank()>{});
_STL_VERIFY(_Verify, "For all r in the range [0, extents_type::rank()), other.stride(r) must be equal to "
Expand Down Expand Up @@ -456,24 +464,52 @@ public:
constexpr mapping() noexcept = default;
constexpr mapping(const mapping&) noexcept = default;

constexpr mapping(const extents_type& _Exts_) noexcept : _Exts(_Exts_) {}
constexpr mapping(const extents_type& _Exts_) noexcept : _Exts(_Exts_) {
// TRANSITION, CHECK [mdspan.layout.right.cons]/1 (REQUIRES '_Multiply_with_overflow_check' FROM #3561)
}

template <class _OtherExtents>
requires is_constructible_v<extents_type, _OtherExtents>
constexpr explicit(!is_convertible_v<_OtherExtents, extents_type>)
mapping(const mapping<_OtherExtents>& _Other) noexcept
: _Exts(_Other.extents()) {}
: _Exts(_Other.extents()) {
_STL_VERIFY(_STD in_range<index_type>(_Other.required_span_size()),
"Value of other.required_span_size() must be representable as a value of type index_type (N4944 "
"[mdspan.layout.right.cons]/4).");
}

template <class _OtherExtents>
requires (extents_type::rank() <= 1) && is_constructible_v<extents_type, _OtherExtents>
constexpr explicit(!is_convertible_v<_OtherExtents, extents_type>)
mapping(const layout_left::mapping<_OtherExtents>& _Other) noexcept
: _Exts(_Other.extents()) {}
: _Exts(_Other.extents()) {
_STL_VERIFY(_STD in_range<index_type>(_Other.required_span_size()),
"Value of other.required_span_size() must be representable as a value of type index_type (N4944 "
"[mdspan.layout.right.cons]/7).");
}

template <class _OtherExtents>
requires is_constructible_v<extents_type, _OtherExtents>
constexpr explicit(extents_type::rank() > 0) mapping(const layout_stride::template mapping<_OtherExtents>& _Other)
: _Exts(_Other.extents()) {}
: _Exts(_Other.extents()) {
if constexpr (extents_type::rank() > 0) {
const bool _Verify = [&]<size_t... _Indices>(index_sequence<_Indices...>) {
index_type _Prod = stride(0);
return (
(_Other.stride(_Indices)
== (_Indices == extents_type::rank() - 1
? _Prod
: _STD exchange(_Prod, static_cast<index_type>(_Prod / _Exts.extent(_Indices + 1)))))
&& ...);
}
(make_index_sequence<extents_type::rank()>{});
_STL_VERIFY(_Verify, "For all r in the range [0, extents_type::rank()), other.stride(r) must be equal to "
"extents().rev-prod-of-extents(r) (N4944 [mdspan.layout.right.cons]/10.1).");
}
_STL_VERIFY(_STD in_range<index_type>(_Other.required_span_size()),
"Value of other.required_span_size() must be representable as a value of type index_type (N4944 "
"[mdspan.layout.right.cons]/10.2).");
}

constexpr mapping& operator=(const mapping&) noexcept = default;

Expand All @@ -482,19 +518,14 @@ public:
}

_NODISCARD constexpr index_type required_span_size() const noexcept {
index_type _Result = 1;
for (rank_type _Dim = 0; _Dim < extents_type::rank(); ++_Dim) {
_Result *= _Exts.extent(_Dim);
}
return _Result;
return _Exts._Fwd_prod_of_extents(extents_type::rank());
}

template <class... _Indices>
requires (sizeof...(_Indices) == extents_type::rank()) && (is_convertible_v<_Indices, index_type> && ...)
&& (is_nothrow_constructible_v<index_type, _Indices> && ...)
_NODISCARD constexpr index_type operator()(_Indices... _Idx) const noexcept {
return _Index_impl<conditional_t<true, index_type, _Indices>...>(
static_cast<index_type>(_Idx)..., make_index_sequence<extents_type::rank()>{});
template <class... _IndexTypes>
requires (sizeof...(_IndexTypes) == extents_type::rank()) && (is_convertible_v<_IndexTypes, index_type> && ...)
&& (is_nothrow_constructible_v<index_type, _IndexTypes> && ...)
_NODISCARD constexpr index_type operator()(_IndexTypes... _Indices) const noexcept {
return _Index_impl(make_index_sequence<extents_type::rank()>{}, static_cast<index_type>(_Indices)...);
}

_NODISCARD static constexpr bool is_always_unique() noexcept {
Expand All @@ -509,27 +540,24 @@ public:
return true;
}

_NODISCARD constexpr bool is_unique() const noexcept {
_NODISCARD static constexpr bool is_unique() noexcept {
return true;
}

_NODISCARD constexpr bool is_exhaustive() const noexcept {
_NODISCARD static constexpr bool is_exhaustive() noexcept {
return true;
}

_NODISCARD constexpr bool is_strided() const noexcept {
_NODISCARD static constexpr bool is_strided() noexcept {
return true;
}

_NODISCARD constexpr index_type stride(const rank_type _Rank) const noexcept
_NODISCARD constexpr index_type stride(const rank_type _Idx) const noexcept
requires (extents_type::rank() > 0)
{
index_type _Result = 1;
for (rank_type _Dim = _Rank + 1; _Dim < extents_type::rank(); ++_Dim) {
_Result *= _Exts.extent(_Dim);
}

return _Result;
_STL_VERIFY(_Idx < extents_type::rank(),
"Value of i must be less than extents_type::rank() (N4944 [mdspan.layout.right.obs]/6).");
return _Exts._Rev_prod_of_extents(_Idx);
}

template <class _OtherExtents>
Expand All @@ -541,10 +569,11 @@ public:
private:
extents_type _Exts{};

template <class... _IndexType, size_t... _Seq>
constexpr index_type _Index_impl(_IndexType... _Idx, index_sequence<_Seq...>) const noexcept {
template <class... _IndexTypes, size_t... _Seq>
_NODISCARD constexpr index_type _Index_impl(index_sequence<_Seq...>, _IndexTypes... _Indices) const noexcept {
_STL_INTERNAL_STATIC_ASSERT((same_as<_IndexTypes, index_type> && ...));
index_type _Result = 0;
((void) (_Result = _Idx + _Exts.extent(_Seq) * _Result), ...);
((_Result = static_cast<index_type>(_Indices + _Exts.extent(_Seq) * _Result)), ...);
return _Result;
}
};
Expand Down
2 changes: 2 additions & 0 deletions tests/std/test.lst
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,8 @@ tests\P0009R18_mdspan_extents
tests\P0009R18_mdspan_extents_death
tests\P0009R18_mdspan_layout_left
tests\P0009R18_mdspan_layout_left_death
tests\P0009R18_mdspan_layout_right
tests\P0009R18_mdspan_layout_right_death
tests\P0019R8_atomic_ref
tests\P0024R2_parallel_algorithms_adjacent_difference
tests\P0024R2_parallel_algorithms_adjacent_find
Expand Down
43 changes: 24 additions & 19 deletions tests/std/tests/P0009R18_mdspan_layout_left/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,6 @@

using namespace std;

template <class Mapping, class... Indices>
concept CanInvokeCallOperatorOfMapping = requires(Mapping m, Indices... i) {
{ m(i...) } -> same_as<typename Mapping::index_type>;
};

template <class IndexType, size_t... Extents, size_t... Indices>
constexpr void do_check_members(const extents<IndexType, Extents...>& ext, index_sequence<Indices...>) {
using Ext = extents<IndexType, Extents...>;
Expand Down Expand Up @@ -83,9 +78,12 @@ constexpr void do_check_members(const extents<IndexType, Extents...>& ext, index
#pragma warning(push) // TRANSITION, "/analyze:only" BUG?
#pragma warning(disable : 28020) // The expression '0<=_Param_(1)&&_Param_(1)<=1-1' is not true at this call
{ // Check construction from layout_stride::mapping
array<IndexType, Ext::rank()> strides{1};
for (size_t i = 1; i < Ext::rank(); ++i) {
strides[i] = static_cast<IndexType>(strides[i - 1] * ext.extent(i));
array<IndexType, Ext::rank()> strides{};
if constexpr (Ext::rank() > 0) {
strides.front() = 1;
for (size_t i = 1; i < Ext::rank(); ++i) {
strides[i] = static_cast<IndexType>(strides[i - 1] * ext.extent(i - 1));
}
}

using StrideMapping = layout_stride::mapping<Ext>;
Expand Down Expand Up @@ -141,6 +139,7 @@ constexpr void do_check_members(const extents<IndexType, Extents...>& ext, index

{ // Check comparisons
assert(m == m);
assert(!(m != m));
// Other tests are defined in 'check_comparisons' function
}
}
Expand Down Expand Up @@ -215,6 +214,12 @@ constexpr void check_construction_from_other_stride_mapping() {
static_assert(!is_constructible_v<Mapping, layout_stride::mapping<extents<int, 2>>>);
}

{ // Check correctness
using Ext = extents<int, 4, 3, 2, 3, 4>;
layout_stride::mapping<Ext> stride_mapping{Ext{}, array{1, 4, 12, 24, 72}};
[[maybe_unused]] layout_left::mapping<Ext> m{stride_mapping};
}

{ // Check implicit conversions
static_assert(
!NotImplicitlyConstructibleFrom<layout_left::mapping<extents<int>>, layout_stride::mapping<extents<int>>>);
Expand All @@ -230,25 +235,25 @@ constexpr void check_construction_from_other_stride_mapping() {
constexpr void check_call_operator() {
{ // Check call with invalid amount of indices
using Mapping = layout_left::mapping<dextents<int, 3>>;
static_assert(!CanInvokeCallOperatorOfMapping<Mapping, int>);
static_assert(!CanInvokeCallOperatorOfMapping<Mapping, int, int>);
static_assert(CanInvokeCallOperatorOfMapping<Mapping, int, int, int>);
static_assert(!CanInvokeCallOperatorOfMapping<Mapping, int, int, int, int>);
static_assert(!CheckCallOperatorOfLayoutMapping<Mapping, int>);
static_assert(!CheckCallOperatorOfLayoutMapping<Mapping, int, int>);
static_assert(CheckCallOperatorOfLayoutMapping<Mapping, int, int, int>);
static_assert(!CheckCallOperatorOfLayoutMapping<Mapping, int, int, int, int>);
}

{ // Check call with invalid types
using Mapping = layout_left::mapping<dextents<long, 2>>;
static_assert(CanInvokeCallOperatorOfMapping<Mapping, long, long>);
static_assert(CanInvokeCallOperatorOfMapping<Mapping, long, short>);
static_assert(CanInvokeCallOperatorOfMapping<Mapping, long, ConvertibleToInt<long>>);
static_assert(CanInvokeCallOperatorOfMapping<Mapping, long, ConvertibleToInt<short>>);
static_assert(!CanInvokeCallOperatorOfMapping<Mapping, long, NonConvertibleToAnything>);
static_assert(CheckCallOperatorOfLayoutMapping<Mapping, long, long>);
static_assert(CheckCallOperatorOfLayoutMapping<Mapping, long, short>);
static_assert(CheckCallOperatorOfLayoutMapping<Mapping, long, ConvertibleToInt<long>>);
static_assert(CheckCallOperatorOfLayoutMapping<Mapping, long, ConvertibleToInt<short>>);
static_assert(!CheckCallOperatorOfLayoutMapping<Mapping, long, NonConvertibleToAnything>);
}

{ // Check call with types that might throw during conversion
using Mapping = layout_left::mapping<dextents<long long, 1>>;
static_assert(CanInvokeCallOperatorOfMapping<Mapping, ConvertibleToInt<long long, IsNothrow::yes>>);
static_assert(!CanInvokeCallOperatorOfMapping<Mapping, ConvertibleToInt<long long, IsNothrow::no>>);
static_assert(CheckCallOperatorOfLayoutMapping<Mapping, ConvertibleToInt<long long, IsNothrow::yes>>);
static_assert(!CheckCallOperatorOfLayoutMapping<Mapping, ConvertibleToInt<long long, IsNothrow::no>>);
}

{ // Check various mappings
Expand Down
4 changes: 4 additions & 0 deletions tests/std/tests/P0009R18_mdspan_layout_right/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
Loading