965 lines
33 KiB
Markdown
965 lines
33 KiB
Markdown
[mdspan.sub]
|
||
|
||
# 23 Containers library [[containers]](./#containers)
|
||
|
||
## 23.7 Views [[views]](views#mdspan.sub)
|
||
|
||
### 23.7.3 Multidimensional access [[views.multidim]](views.multidim#mdspan.sub)
|
||
|
||
#### 23.7.3.7 submdspan [mdspan.sub]
|
||
|
||
#### [23.7.3.7.1](#overview) Overview [[mdspan.sub.overview]](mdspan.sub.overview)
|
||
|
||
[1](#overview-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25258)
|
||
|
||
The submdspan facilities create a new mdspan viewing a subset of elements of an existing input mdspan[.](#overview-1.sentence-1)
|
||
|
||
The subset viewed by the created mdspan is determined by
|
||
the SliceSpecifier arguments[.](#overview-1.sentence-2)
|
||
|
||
[2](#overview-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25264)
|
||
|
||
For each function defined in [mdspan.sub] that
|
||
takes a parameter pack named slices as an argument:
|
||
|
||
- [(2.1)](#overview-2.1)
|
||
|
||
let index_type be
|
||
* [(2.1.1)](#overview-2.1.1)
|
||
|
||
M::index_type if the function is a member of a class M,
|
||
|
||
* [(2.1.2)](#overview-2.1.2)
|
||
|
||
otherwise, remove_reference_t<decltype(src)>::index_type if the function has a parameter named src,
|
||
|
||
* [(2.1.3)](#overview-2.1.3)
|
||
|
||
otherwise,
|
||
the same type as the function's template argument IndexType;
|
||
|
||
- [(2.2)](#overview-2.2)
|
||
|
||
let rank be the number of elements in slices;
|
||
|
||
- [(2.3)](#overview-2.3)
|
||
|
||
let sk be the kth element of slices;
|
||
|
||
- [(2.4)](#overview-2.4)
|
||
|
||
let Sk be the type of sk; and
|
||
|
||
- [(2.5)](#overview-2.5)
|
||
|
||
let *map-rank* be an array<size_t, rank> such that
|
||
for each k in the range [0, rank),*map-rank*[k] equals:
|
||
* [(2.5.1)](#overview-2.5.1)
|
||
|
||
dynamic_extent if Sk models [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_to [concept.convertible]")<index_type>,
|
||
|
||
* [(2.5.2)](#overview-2.5.2)
|
||
|
||
otherwise,
|
||
the number of types Sj with j<k that
|
||
do not model [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_to [concept.convertible]")<index_type>[.](#overview-2.sentence-1)
|
||
|
||
#### [23.7.3.7.2](#strided.slice) strided_slice [[mdspan.sub.strided.slice]](mdspan.sub.strided.slice)
|
||
|
||
[1](#strided.slice-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25300)
|
||
|
||
strided_slice represents a set ofextent regularly spaced integer indices[.](#strided.slice-1.sentence-1)
|
||
|
||
The indices start at offset, and
|
||
increase by increments of stride[.](#strided.slice-1.sentence-2)
|
||
|
||
[ð](#lib:strided_slice)
|
||
|
||
namespace std {template<class OffsetType, class ExtentType, class StrideType>struct strided_slice {using offset_type = OffsetType; using extent_type = ExtentType; using stride_type = StrideType; [[no_unique_address]] offset_type offset{}; [[no_unique_address]] extent_type extent{}; [[no_unique_address]] stride_type stride{}; };}
|
||
|
||
[2](#strided.slice-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25322)
|
||
|
||
strided_slice has the data members and special members specified above[.](#strided.slice-2.sentence-1)
|
||
|
||
It has no base classes or members other than those specified[.](#strided.slice-2.sentence-2)
|
||
|
||
[3](#strided.slice-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25326)
|
||
|
||
*Mandates*: OffsetType, ExtentType, and StrideType are signed or unsigned integer types, or
|
||
model [*integral-constant-like*](span.syn#concept:integral-constant-like "23.7.2.1 Header <span> synopsis [span.syn]")[.](#strided.slice-3.sentence-1)
|
||
|
||
[*Note [1](#strided.slice-note-1)*:
|
||
|
||
strided_slice{.offset = 1, .extent = 10, .stride = 3} indicates the indices 1, 4, 7, and 10[.](#strided.slice-3.sentence-2)
|
||
|
||
Indices are selected from the half-open interval [1, 1 + 10)[.](#strided.slice-3.sentence-3)
|
||
|
||
â *end note*]
|
||
|
||
#### [23.7.3.7.3](#map.result) submdspan_mapping_result [[mdspan.sub.map.result]](mdspan.sub.map.result)
|
||
|
||
[1](#map.result-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25339)
|
||
|
||
Specializations of submdspan_mapping_result are returned by overloads of submdspan_mapping[.](#map.result-1.sentence-1)
|
||
|
||
[ð](#lib:submdspan_mapping_result)
|
||
|
||
namespace std {template<class LayoutMapping>struct submdspan_mapping_result {[[no_unique_address]] LayoutMapping mapping = LayoutMapping();
|
||
size_t offset{}; };}
|
||
|
||
[2](#map.result-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25354)
|
||
|
||
submdspan_mapping_result has
|
||
the data members and special members specified above[.](#map.result-2.sentence-1)
|
||
|
||
It has no base classes or members other than those specified[.](#map.result-2.sentence-2)
|
||
|
||
[3](#map.result-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25359)
|
||
|
||
LayoutMapping shall meet
|
||
the layout mapping requirements ([[mdspan.layout.policy.reqmts]](mdspan.layout.policy.reqmts "23.7.3.4.3 Layout mapping policy requirements"))[.](#map.result-3.sentence-1)
|
||
|
||
#### [23.7.3.7.4](#helpers) Exposition-only helpers [[mdspan.sub.helpers]](mdspan.sub.helpers)
|
||
|
||
[ð](#lib:de-ice)
|
||
|
||
`template<class T>
|
||
constexpr T de-ice(T val) { return val; }
|
||
template<[integral-constant-like](span.syn#concept:integral-constant-like "23.7.2.1 Header <span> synopsis [span.syn]") T>
|
||
constexpr auto de-ice(T) { return T::value; }
|
||
|
||
template<class IndexType, size_t k, class... SliceSpecifiers>
|
||
constexpr IndexType first_(SliceSpecifiers... slices);
|
||
`
|
||
|
||
[1](#helpers-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25378)
|
||
|
||
*Mandates*: IndexType is a signed or unsigned integer type[.](#helpers-1.sentence-1)
|
||
|
||
[2](#helpers-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25383)
|
||
|
||
Let Ïk denote the following value:
|
||
|
||
- [(2.1)](#helpers-2.1)
|
||
|
||
sk if Sk models [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_to [concept.convertible]")<IndexType>;
|
||
|
||
- [(2.2)](#helpers-2.2)
|
||
|
||
otherwise,get<0>(sk) if Sk models [*index-pair-like*](mdspan.syn#concept:index-pair-like "23.7.3.2 Header <mdspan> synopsis [mdspan.syn]")<IndexType>;
|
||
|
||
- [(2.3)](#helpers-2.3)
|
||
|
||
otherwise,*de-ice*(sk.offset) if Sk is a specialization of strided_slice;
|
||
|
||
- [(2.4)](#helpers-2.4)
|
||
|
||
otherwise,0[.](#helpers-2.sentence-1)
|
||
|
||
[3](#helpers-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25401)
|
||
|
||
*Preconditions*: Ïk is representable as a value of type IndexType[.](#helpers-3.sentence-1)
|
||
|
||
[4](#helpers-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25405)
|
||
|
||
*Returns*: extents<IndexType>::*index-cast*(Ïk)[.](#helpers-4.sentence-1)
|
||
|
||
[ð](#lib:last_)
|
||
|
||
`template<size_t k, class Extents, class... SliceSpecifiers>
|
||
constexpr auto last_(const Extents& src, SliceSpecifiers... slices);
|
||
`
|
||
|
||
[5](#helpers-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25417)
|
||
|
||
*Mandates*: Extents is a specialization of extents[.](#helpers-5.sentence-1)
|
||
|
||
[6](#helpers-6)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25421)
|
||
|
||
Let index_type be typename Extents::index_type[.](#helpers-6.sentence-1)
|
||
|
||
[7](#helpers-7)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25425)
|
||
|
||
Let λk denote the following value:
|
||
|
||
- [(7.1)](#helpers-7.1)
|
||
|
||
*de-ice*(sk) + 1 if Sk models [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_to [concept.convertible]")<index_type>; otherwise
|
||
|
||
- [(7.2)](#helpers-7.2)
|
||
|
||
get<1>(sk) if Sk models [*index-pair-like*](mdspan.syn#concept:index-pair-like "23.7.3.2 Header <mdspan> synopsis [mdspan.syn]")<index_type>; otherwise
|
||
|
||
- [(7.3)](#helpers-7.3)
|
||
|
||
*de-ice*(sk.offset) +*de-ice*(sk.extent) if Sk is a specialization of strided_slice; otherwise
|
||
|
||
- [(7.4)](#helpers-7.4)
|
||
|
||
src.extent(k)[.](#helpers-7.sentence-1)
|
||
|
||
[8](#helpers-8)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25443)
|
||
|
||
*Preconditions*: λk is representable as a value of type index_type[.](#helpers-8.sentence-1)
|
||
|
||
[9](#helpers-9)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25447)
|
||
|
||
*Returns*: Extents::*index-cast*(λk)[.](#helpers-9.sentence-1)
|
||
|
||
[ð](#lib:src-indices)
|
||
|
||
`template<class IndexType, size_t N, class... SliceSpecifiers>
|
||
constexpr array<IndexType, sizeof...(SliceSpecifiers)>
|
||
src-indices(const array<IndexType, N>& indices, SliceSpecifiers... slices);
|
||
`
|
||
|
||
[10](#helpers-10)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25460)
|
||
|
||
*Mandates*: IndexType is a signed or unsigned integer type[.](#helpers-10.sentence-1)
|
||
|
||
[11](#helpers-11)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25464)
|
||
|
||
*Returns*: An array<IndexType, sizeof...(SliceSpecifiers)> src_idx such that
|
||
for each k in the range [0, sizeof...(SliceSpecifiers)),src_idx[k] equals
|
||
|
||
- [(11.1)](#helpers-11.1)
|
||
|
||
*first_*<IndexType, k>(slices...) for each k where *map-rank*[k] equalsdynamic_extent,
|
||
|
||
- [(11.2)](#helpers-11.2)
|
||
|
||
otherwise,*first_*<IndexType, k>(slices...) +indices[*map-rank*[k]].
|
||
|
||
#### [23.7.3.7.5](#extents) submdspan_extents function [[mdspan.sub.extents]](mdspan.sub.extents)
|
||
|
||
[ð](#lib:submdspan_extents)
|
||
|
||
`template<class IndexType, size_t... Extents, class... SliceSpecifiers>
|
||
constexpr auto submdspan_extents(const extents<IndexType, Extents...>& src,
|
||
SliceSpecifiers... slices);
|
||
`
|
||
|
||
[1](#extents-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25496)
|
||
|
||
*Constraints*: sizeof...(slices) equals sizeof...(Extents)[.](#extents-1.sentence-1)
|
||
|
||
[2](#extents-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25500)
|
||
|
||
*Mandates*: For each rank index k of src.extents(),
|
||
exactly one of the following is true:
|
||
|
||
- [(2.1)](#extents-2.1)
|
||
|
||
Sk models [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_to [concept.convertible]")<IndexType>,
|
||
|
||
- [(2.2)](#extents-2.2)
|
||
|
||
Sk models [*index-pair-like*](mdspan.syn#concept:index-pair-like "23.7.3.2 Header <mdspan> synopsis [mdspan.syn]")<IndexType>,
|
||
|
||
- [(2.3)](#extents-2.3)
|
||
|
||
is_convertible_v<Sk, full_extent_t> is true, or
|
||
|
||
- [(2.4)](#extents-2.4)
|
||
|
||
Sk is a specialization of strided_slice[.](#extents-2.sentence-1)
|
||
|
||
[3](#extents-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25511)
|
||
|
||
*Preconditions*: For each rank index k of src.extents(),
|
||
all of the following are true:
|
||
|
||
- [(3.1)](#extents-3.1)
|
||
|
||
if Sk is a specialization of strided_slice
|
||
* [(3.1.1)](#extents-3.1.1)
|
||
|
||
sk.extent=0, or
|
||
|
||
* [(3.1.2)](#extents-3.1.2)
|
||
|
||
sk.stride>0
|
||
|
||
- [(3.2)](#extents-3.2)
|
||
|
||
0 ⤠*first_*<IndexType, k>(slices...) ⤠*last_*<k>(src, slices...) ⤠src.extent(k)
|
||
|
||
[4](#extents-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25528)
|
||
|
||
Let SubExtents be a specialization of extents such that:
|
||
|
||
- [(4.1)](#extents-4.1)
|
||
|
||
SubExtents::rank() equals the number of k such thatSk does not model [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_to [concept.convertible]")<IndexType>; and
|
||
|
||
- [(4.2)](#extents-4.2)
|
||
|
||
for each rank index k of Extents such that*map-rank*[k] != dynamic_extent is true,SubExtents::static_extent(*map-rank*[k]) equals:
|
||
* [(4.2.1)](#extents-4.2.1)
|
||
|
||
Extents::static_extent(k) if is_convertible_v<Sk, full_extent_t> is true;
|
||
otherwise
|
||
|
||
* [(4.2.2)](#extents-4.2.2)
|
||
|
||
*de-ice*(tuple_element_t<1, Sk>()) -*de-ice*(tuple_element_t<0, Sk>()) if Sk models [*index-pair-like*](mdspan.syn#concept:index-pair-like "23.7.3.2 Header <mdspan> synopsis [mdspan.syn]")<IndexType>, and
|
||
both tuple_element_t<0, Sk> and tuple_element_t<1, Sk> model [*integral-constant-like*](span.syn#concept:integral-constant-like "23.7.2.1 Header <span> synopsis [span.syn]"); otherwise
|
||
|
||
* [(4.2.3)](#extents-4.2.3)
|
||
|
||
0,
|
||
if Sk is a specialization of strided_slice, whose extent_type models *integral-constant-like*,
|
||
for which extent_type() equals zero; otherwise
|
||
|
||
* [(4.2.4)](#extents-4.2.4)
|
||
|
||
1 + (*de-ice*(Sk::extent_type()) - 1) /*de-ice*(Sk::stride_type()),
|
||
if Sk is a specialization of strided_slice whose extent_type and stride_type model *integral-constant-like*;
|
||
|
||
* [(4.2.5)](#extents-4.2.5)
|
||
|
||
otherwise, dynamic_extent[.](#extents-4.sentence-1)
|
||
|
||
[5](#extents-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25573)
|
||
|
||
*Returns*: A value ext of type SubExtents such that
|
||
for each k for which *map-rank*[k] != dynamic_extent is true,ext.extent(*map-rank*[k]) equals:
|
||
|
||
- [(5.1)](#extents-5.1)
|
||
|
||
sk.extent == 0 ? 0 : 1 + (*de-ice*(sk.extent) - 1) / *de-ice*(sk.stride) if Sk is a specialization of strided_slice,
|
||
|
||
- [(5.2)](#extents-5.2)
|
||
|
||
otherwise,*last_*<k>(src, slices...) - *first_*<IndexType, k>(slices...)[.](#extents-5.sentence-1)
|
||
|
||
#### [23.7.3.7.6](#map) Specializations of submdspan_mapping [[mdspan.sub.map]](mdspan.sub.map)
|
||
|
||
#### [23.7.3.7.6.1](#map.common) Common [[mdspan.sub.map.common]](mdspan.sub.map.common)
|
||
|
||
[1](#map.common-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25594)
|
||
|
||
The following elements apply to all functions in [[mdspan.sub.map]](#map "23.7.3.7.6 Specializations of submdspan_mapping")[.](#map.common-1.sentence-1)
|
||
|
||
[2](#map.common-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25597)
|
||
|
||
*Constraints*: sizeof...(slices) equals extents_type::rank()[.](#map.common-2.sentence-1)
|
||
|
||
[3](#map.common-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25601)
|
||
|
||
*Mandates*: For each rank index k of extents(),
|
||
exactly one of the following is true:
|
||
|
||
- [(3.1)](#map.common-3.1)
|
||
|
||
Sk models [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_to [concept.convertible]")<index_type>,
|
||
|
||
- [(3.2)](#map.common-3.2)
|
||
|
||
Sk models [*index-pair-like*](mdspan.syn#concept:index-pair-like "23.7.3.2 Header <mdspan> synopsis [mdspan.syn]")<index_type>,
|
||
|
||
- [(3.3)](#map.common-3.3)
|
||
|
||
is_convertible_v<Sk, full_extent_t> is true, or
|
||
|
||
- [(3.4)](#map.common-3.4)
|
||
|
||
Sk is a specialization of strided_slice[.](#map.common-3.sentence-1)
|
||
|
||
[4](#map.common-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25616)
|
||
|
||
*Preconditions*: For each rank index k of extents(),
|
||
all of the following are true:
|
||
|
||
- [(4.1)](#map.common-4.1)
|
||
|
||
if Sk is a specialization of strided_slice,sk.extent is equal to zero orsk.stride is greater than zero; and
|
||
|
||
- [(4.2)](#map.common-4.2)
|
||
|
||
0 ⤠*first_*<index_type, k>(slices...)
|
||
0 ⤠*last_*<k>(extents(), slices...)
|
||
0 ⤠extents().extent(k)
|
||
|
||
[5](#map.common-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25631)
|
||
|
||
Let sub_ext be
|
||
the result of submdspan_extents(extents(), slices...) and
|
||
let SubExtents be decltype(sub_ext)[.](#map.common-5.sentence-1)
|
||
|
||
[6](#map.common-6)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25636)
|
||
|
||
Let sub_strides be
|
||
an array<SubExtents::index_type, SubExtents::rank()> such that for each rank index k of extents() for which *map-rank*[k] is not dynamic_extent,sub_strides[*map-rank*[k]] equals:
|
||
|
||
- [(6.1)](#map.common-6.1)
|
||
|
||
stride(k) * *de-ice*(sk.stride) if Sk is a specialization of strided_slice andsk.stride < sk.extent is true;
|
||
|
||
- [(6.2)](#map.common-6.2)
|
||
|
||
otherwise, stride(k)[.](#map.common-6.sentence-1)
|
||
|
||
[7](#map.common-7)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25651)
|
||
|
||
Let P be a parameter pack
|
||
such that is_same_v<make_index_sequence<rank()>, index_sequence<P...>> is true[.](#map.common-7.sentence-1)
|
||
|
||
[8](#map.common-8)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25656)
|
||
|
||
If *first_*<index_type, k>(slices...) equals extents().extent(k) for any rank index k of extents(), then
|
||
let offset be a value of type size_t equal to(*this).required_span_size()[.](#map.common-8.sentence-1)
|
||
|
||
Otherwise,
|
||
let offset be a value of type size_t equal to(*this)(*first_*<index_type, P>(slices...)...)[.](#map.common-8.sentence-2)
|
||
|
||
[9](#map.common-9)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25666)
|
||
|
||
Given a layout mapping type M, a type S is a[*unit-stride slice for M*](#def:slice,unit-stride "23.7.3.7.6.1 Common [mdspan.sub.map.common]") if
|
||
|
||
- [(9.1)](#map.common-9.1)
|
||
|
||
S is a specialization of strided_slice where S::stride_type models [*integral-constant-like*](span.syn#concept:integral-constant-like "23.7.2.1 Header <span> synopsis [span.syn]") and S::stride_type::value equals 1,
|
||
|
||
- [(9.2)](#map.common-9.2)
|
||
|
||
S models [*index-pair-like*](mdspan.syn#concept:index-pair-like "23.7.3.2 Header <mdspan> synopsis [mdspan.syn]")<M::index_type>, or
|
||
|
||
- [(9.3)](#map.common-9.3)
|
||
|
||
is_convertible_v<S, full_extent_t> is true[.](#map.common-9.sentence-1)
|
||
|
||
#### [23.7.3.7.6.2](#map.left) layout_left specialization of submdspan_mapping [[mdspan.sub.map.left]](mdspan.sub.map.left)
|
||
|
||
[ð](#lib:layout_left::mapping,submdspan-mapping-impl)
|
||
|
||
`template<class Extents>
|
||
template<class... SliceSpecifiers>
|
||
constexpr auto layout_left::mapping<Extents>::submdspan-mapping-impl(
|
||
SliceSpecifiers... slices) const -> see below;
|
||
`
|
||
|
||
[1](#map.left-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25688)
|
||
|
||
*Returns*:
|
||
|
||
- [(1.1)](#map.left-1.1)
|
||
|
||
submdspan_mapping_result{*this, 0},
|
||
if Extents::rank() == 0 is true;
|
||
|
||
- [(1.2)](#map.left-1.2)
|
||
|
||
otherwise,submdspan_mapping_result{layout_left::mapping(sub_ext), offset},
|
||
if SubExtents::rank() == 0 is true;
|
||
|
||
- [(1.3)](#map.left-1.3)
|
||
|
||
otherwise,submdspan_mapping_result{layout_left::mapping(sub_ext), offset},
|
||
if
|
||
* [(1.3.1)](#map.left-1.3.1)
|
||
|
||
for each k in the range [0, SubExtents::rank() - 1)), is_convertible_v<Sk, full_extent_t> is true; and
|
||
|
||
* [(1.3.2)](#map.left-1.3.2)
|
||
|
||
for k equal to SubExtents::rank() - 1, Sk is a unit-stride slice for mapping;
|
||
|
||
[*Note [1](#map.left-note-1)*:
|
||
If the above conditions are true,
|
||
all Sk with k larger than SubExtents::rank() - 1 are convertible to index_type[.](#map.left-1.3.sentence-1)
|
||
â *end note*]
|
||
|
||
- [(1.4)](#map.left-1.4)
|
||
|
||
otherwise,submdspan_mapping_result{layout_left_padded<S_static>::mapping(sub_ext, stride(u + 1)),
|
||
offset} if for a value u for which u+1 is
|
||
the smallest value p larger than zero
|
||
for which Sp is a unit-stride slice for mapping,
|
||
the following conditions are met:
|
||
* [(1.4.1)](#map.left-1.4.1)
|
||
|
||
S0 is a unit-stride slice for mapping; and
|
||
|
||
* [(1.4.2)](#map.left-1.4.2)
|
||
|
||
for each k in the range [u + 1, u + SubExtents::rank() - 1),is_convertible_v<Sk, full_extent_t> is true; and
|
||
|
||
* [(1.4.3)](#map.left-1.4.3)
|
||
|
||
for k equal to u + SubExtents::rank() - 1,Sk is a unit-stride slice for mapping;
|
||
|
||
and where S_static is:
|
||
* [(1.4.4)](#map.left-1.4.4)
|
||
|
||
dynamic_extent,
|
||
if static_extent(k) is dynamic_extent for any k in the range [0, u + 1),
|
||
|
||
* [(1.4.5)](#map.left-1.4.5)
|
||
|
||
otherwise, the product of all valuesstatic_extent(k) for k in the range [0, u + 1);
|
||
|
||
- [(1.5)](#map.left-1.5)
|
||
|
||
otherwise,submdspan_mapping_result{layout_stride::mapping(sub_ext, sub_strides), offset}
|
||
|
||
#### [23.7.3.7.6.3](#map.right) layout_right specialization of submdspan_mapping [[mdspan.sub.map.right]](mdspan.sub.map.right)
|
||
|
||
[ð](#lib:layout_right::mapping,submdspan-mapping-impl)
|
||
|
||
`template<class Extents>
|
||
template<class... SliceSpecifiers>
|
||
constexpr auto layout_right::mapping<Extents>::submdspan-mapping-impl(
|
||
SliceSpecifiers... slices) const -> see below;
|
||
`
|
||
|
||
[1](#map.right-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25764)
|
||
|
||
*Returns*:
|
||
|
||
- [(1.1)](#map.right-1.1)
|
||
|
||
submdspan_mapping_result{*this, 0},
|
||
if Extents::rank() == 0 is true;
|
||
|
||
- [(1.2)](#map.right-1.2)
|
||
|
||
otherwise,submdspan_mapping_result{layout_right::mapping(sub_ext), offset},
|
||
if SubExtents::rank() == 0 is true;
|
||
|
||
- [(1.3)](#map.right-1.3)
|
||
|
||
otherwise,submdspan_mapping_result{layout_left::mapping(sub_ext), offset},
|
||
if
|
||
* [(1.3.1)](#map.right-1.3.1)
|
||
|
||
for each k in the range [*rank_* - SubExtents::rank() + 1, *rank_*), is_convertible_v<Sk, full_extent_t> is true; and
|
||
|
||
* [(1.3.2)](#map.right-1.3.2)
|
||
|
||
for k equal to *_rank* - SubExtents::rank(), Sk is a unit-stride slice for mapping;
|
||
|
||
[*Note [1](#map.right-note-1)*:
|
||
If the above conditions are true,
|
||
all Sk with k<_rank - SubExtents::rank() are convertible to index_type[.](#map.right-1.3.sentence-1)
|
||
â *end note*]
|
||
|
||
- [(1.4)](#map.right-1.4)
|
||
|
||
otherwise,submdspan_mapping_result{layout_right_padded<S_static>::mapping(sub_ext,
|
||
stride(*rank_* - u - 2)), offset} if for a value u for which rank_âuâ2 is
|
||
the largest value p smaller than *rank_* - 1 for which Sp is a unit-stride slice for mapping,
|
||
the following conditions are met:
|
||
* [(1.4.1)](#map.right-1.4.1)
|
||
|
||
for k equal to *rank_* - 1,Sk is a unit-stride slice for mapping; and
|
||
|
||
* [(1.4.2)](#map.right-1.4.2)
|
||
|
||
for each k in the range
|
||
[*rank_* - SubExtents::rank() - u + 1, *rank_* - u - 1),is_convertible_v<Sk, full_extent_t> is true; and
|
||
|
||
* [(1.4.3)](#map.right-1.4.3)
|
||
|
||
for k equal to *rank_* - SubExtents::rank() - u,
|
||
Sk is a unit-stride slice for mapping;
|
||
|
||
and where S_static is:
|
||
* [(1.4.4)](#map.right-1.4.4)
|
||
|
||
dynamic_extent,
|
||
if static_extent(k) is dynamic_extent for any k in the range [*rank_* - u - 1, *rank_*),
|
||
|
||
* [(1.4.5)](#map.right-1.4.5)
|
||
|
||
otherwise, the product of all valuesstatic_extent(k) for k in the range [*rank_* - u - 1, *rank_*);
|
||
|
||
- [(1.5)](#map.right-1.5)
|
||
|
||
otherwise,submdspan_mapping_result{layout_stride::mapping(sub_ext, sub_strides), offset}
|
||
|
||
#### [23.7.3.7.6.4](#map.stride) layout_stride specialization of submdspan_mapping [[mdspan.sub.map.stride]](mdspan.sub.map.stride)
|
||
|
||
[ð](#lib:layout_stride::mapping,submdspan-mapping-impl)
|
||
|
||
`template<class Extents>
|
||
template<class... SliceSpecifiers>
|
||
constexpr auto layout_stride::mapping<Extents>::submdspan-mapping-impl(
|
||
SliceSpecifiers... slices) const -> see below;
|
||
`
|
||
|
||
[1](#map.stride-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25843)
|
||
|
||
*Returns*:
|
||
|
||
- [(1.1)](#map.stride-1.1)
|
||
|
||
submdspan_mapping_result{*this, 0},
|
||
if Extents::rank() == 0 is true;
|
||
|
||
- [(1.2)](#map.stride-1.2)
|
||
|
||
otherwise,submdspan_mapping_result{layout_stride::mapping(sub_ext, sub_strides), offset}
|
||
|
||
#### [23.7.3.7.6.5](#map.leftpad) layout_left_padded specialization of submdspan_mapping [[mdspan.sub.map.leftpad]](mdspan.sub.map.leftpad)
|
||
|
||
[ð](#lib:layout_left_padded::mapping,submdspan-mapping-impl)
|
||
|
||
`template<class Extents>
|
||
template<class... SliceSpecifiers>
|
||
constexpr auto layout_left_padded::mapping<Extents>::submdspan-mapping-impl(
|
||
SliceSpecifiers... slices) const -> see below;
|
||
`
|
||
|
||
[1](#map.leftpad-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25868)
|
||
|
||
*Returns*:
|
||
|
||
- [(1.1)](#map.leftpad-1.1)
|
||
|
||
submdspan_mapping_result{*this, 0},
|
||
if Extents::rank() == 0 is true;
|
||
|
||
- [(1.2)](#map.leftpad-1.2)
|
||
|
||
otherwise,submdspan_mapping_result{layout_left::mapping(sub_ext), offset},
|
||
if *rank_* == 1 is true orSubExtents::rank() == 0 is true;
|
||
|
||
- [(1.3)](#map.leftpad-1.3)
|
||
|
||
otherwise,submdspan_mapping_result{layout_left::mapping(sub_ext), offset},
|
||
if
|
||
* [(1.3.1)](#map.leftpad-1.3.1)
|
||
|
||
SubExtents::rank() == 1 is true and
|
||
|
||
* [(1.3.2)](#map.leftpad-1.3.2)
|
||
|
||
S0 is a unit-stride slice for mapping;
|
||
|
||
- [(1.4)](#map.leftpad-1.4)
|
||
|
||
otherwise,submdspan_mapping_result{layout_left_padded<S_static>::mapping(sub_ext, stride(u + 1)),
|
||
offset} if for a value u for which u + 1 is the smallest value p larger than zero
|
||
for which Sp is a unit-stride slice for mapping,
|
||
the following conditions are met:
|
||
* [(1.4.1)](#map.leftpad-1.4.1)
|
||
|
||
S0 is a unit-stride slice for mapping; and
|
||
|
||
* [(1.4.2)](#map.leftpad-1.4.2)
|
||
|
||
for each k in the range [u + 1, u + SubExtents::rank() - 1),is_convertible_v<Sk, full_extent_t> is true; and
|
||
|
||
* [(1.4.3)](#map.leftpad-1.4.3)
|
||
|
||
for k equal to u + SubExtents::rank() - 1,Sk is a unit-stride slice for mapping;
|
||
|
||
where S_static is:
|
||
* [(1.4.4)](#map.leftpad-1.4.4)
|
||
|
||
dynamic_extent,
|
||
if *static-padding-stride* is dynamic_extent orstatic_extent(k) is dynamic_extent for any k in the range [1, u + 1),
|
||
|
||
* [(1.4.5)](#map.leftpad-1.4.5)
|
||
|
||
otherwise, the product of *static-padding-stride* and
|
||
all values static_extent(k) for k in the range [1, u + 1);
|
||
|
||
- [(1.5)](#map.leftpad-1.5)
|
||
|
||
otherwise,submdspan_mapping_result{layout_stride::mapping(sub_ext, sub_strides), offset}
|
||
|
||
#### [23.7.3.7.6.6](#map.rightpad) layout_right_padded specialization of submdspan_mapping [[mdspan.sub.map.rightpad]](mdspan.sub.map.rightpad)
|
||
|
||
[ð](#lib:layout_right_padded::mapping,submdspan-mapping-impl)
|
||
|
||
`template<class Extents>
|
||
template<class... SliceSpecifiers>
|
||
constexpr auto layout_right_padded::mapping<Extents>::submdspan-mapping-impl(
|
||
SliceSpecifiers... slices) const -> see below;
|
||
`
|
||
|
||
[1](#map.rightpad-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L25939)
|
||
|
||
*Returns*:
|
||
|
||
- [(1.1)](#map.rightpad-1.1)
|
||
|
||
submdspan_mapping_result{*this, 0},
|
||
if *rank_* == 0 is true;
|
||
|
||
- [(1.2)](#map.rightpad-1.2)
|
||
|
||
otherwise,submdspan_mapping_result{layout_right::mapping(sub_ext), offset},
|
||
if *rank_* == 1 is true orSubExtents::rank() == 0 is true;
|
||
|
||
- [(1.3)](#map.rightpad-1.3)
|
||
|
||
otherwise,submdspan_mapping_result{layout_right::mapping(sub_ext), offset},
|
||
if
|
||
* [(1.3.1)](#map.rightpad-1.3.1)
|
||
|
||
SubExtents::rank() == 1 is true and
|
||
|
||
* [(1.3.2)](#map.rightpad-1.3.2)
|
||
|
||
for k equal to *rank_* - 1,Sk is a unit-stride slice for mapping;
|
||
|
||
- [(1.4)](#map.rightpad-1.4)
|
||
|
||
otherwise,submdspan_mapping_result{layout_right_padded<S_static>::mapping(sub_ext,
|
||
stride(*rank_* - u - 2)), offset} if for a value u for which *rank_* - u - 2 is the largest value p smaller than *rank_* - 1 for which Sp is a unit-stride slice for mapping,
|
||
the following conditions are met:
|
||
* [(1.4.1)](#map.rightpad-1.4.1)
|
||
|
||
for k equal to *rank_* - 1,Sk is a unit-stride slice for mapping; and
|
||
|
||
* [(1.4.2)](#map.rightpad-1.4.2)
|
||
|
||
for each k in the range
|
||
[*rank_* - SubExtents::rank() - u + 1, *rank_* - u - 1)),is_convertible_v<Sk, full_extent_t> is true; and
|
||
|
||
* [(1.4.3)](#map.rightpad-1.4.3)
|
||
|
||
for k equal to *rank_* - SubExtents::rank() - u,
|
||
Sk is a unit-stride slice for mapping;
|
||
|
||
and where S_static is:
|
||
* [(1.4.4)](#map.rightpad-1.4.4)
|
||
|
||
dynamic_extent if *static-padding-stride* is dynamic_extent or
|
||
for any k in the range [*rank_* - u - 1, *rank_* - 1)static_extent(k) is dynamic_extent,
|
||
|
||
* [(1.4.5)](#map.rightpad-1.4.5)
|
||
|
||
otherwise, the product of *static-padding-stride* and
|
||
all values static_extent(k) with k in the range [*rank_* - u - 1, *rank_* - 1);
|
||
|
||
- [(1.5)](#map.rightpad-1.5)
|
||
|
||
otherwise,submdspan_mapping_result{layout_stride::mapping(sub_ext, sub_strides), offset}
|
||
|
||
#### [23.7.3.7.7](#sub) submdspan function template [[mdspan.sub.sub]](mdspan.sub.sub)
|
||
|
||
[ð](#lib:submdspan)
|
||
|
||
`template<class ElementType, class Extents, class LayoutPolicy,
|
||
class AccessorPolicy, class... SliceSpecifiers>
|
||
constexpr auto submdspan(
|
||
const mdspan<ElementType, Extents, LayoutPolicy, AccessorPolicy>& src,
|
||
SliceSpecifiers... slices) -> see below;
|
||
`
|
||
|
||
[1](#sub-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L26016)
|
||
|
||
Let index_type be typename Extents::index_type[.](#sub-1.sentence-1)
|
||
|
||
[2](#sub-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L26019)
|
||
|
||
Let sub_map_offset be the result ofsubmdspan_mapping(src.mapping(), slices...)[.](#sub-2.sentence-1)
|
||
|
||
[*Note [1](#sub-note-1)*:
|
||
|
||
This invocation of submdspan_mapping selects a function call via overload resolution
|
||
on a candidate set that includes the lookup set
|
||
found by argument-dependent lookup ([[basic.lookup.argdep]](basic.lookup.argdep "6.5.4 Argument-dependent name lookup"))[.](#sub-2.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[3](#sub-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L26029)
|
||
|
||
*Constraints*:
|
||
|
||
- [(3.1)](#sub-3.1)
|
||
|
||
sizeof...(slices) equals Extents::rank(), and
|
||
|
||
- [(3.2)](#sub-3.2)
|
||
|
||
the expression submdspan_mapping(src.mapping(), slices...) is well-formed when treated as an unevaluated operand[.](#sub-3.sentence-1)
|
||
|
||
[4](#sub-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L26039)
|
||
|
||
*Mandates*:
|
||
|
||
- [(4.1)](#sub-4.1)
|
||
|
||
decltype(submdspan_mapping(src.mapping(), slices...)) is a specialization of submdspan_mapping_result[.](#sub-4.1.sentence-1)
|
||
|
||
- [(4.2)](#sub-4.2)
|
||
|
||
is_same_v<remove_cvref_t<decltype(sub_map_offset.mapping.extents())>,decltype(submdspan_extents(src.mapping(), slices...))> is true[.](#sub-4.2.sentence-1)
|
||
|
||
- [(4.3)](#sub-4.3)
|
||
|
||
For each rank index k of src.extents(),
|
||
exactly one of the following is true:
|
||
* [(4.3.1)](#sub-4.3.1)
|
||
|
||
Sk models [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_to [concept.convertible]")<index_type>,
|
||
|
||
* [(4.3.2)](#sub-4.3.2)
|
||
|
||
Sk models [*index-pair-like*](mdspan.syn#concept:index-pair-like "23.7.3.2 Header <mdspan> synopsis [mdspan.syn]")<index_type>,
|
||
|
||
* [(4.3.3)](#sub-4.3.3)
|
||
|
||
is_convertible_v<Sk, full_extent_t> is true, or
|
||
|
||
* [(4.3.4)](#sub-4.3.4)
|
||
|
||
Sk is a specialization of strided_slice[.](#sub-4.3.sentence-1)
|
||
|
||
[5](#sub-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L26062)
|
||
|
||
*Preconditions*:
|
||
|
||
- [(5.1)](#sub-5.1)
|
||
|
||
For each rank index k of src.extents(),
|
||
all of the following are true:
|
||
* [(5.1.1)](#sub-5.1.1)
|
||
|
||
if Sk is a specialization of strided_slice
|
||
+
|
||
[(5.1.1.1)](#sub-5.1.1.1)
|
||
sk.extent=0, or
|
||
|
||
+
|
||
[(5.1.1.2)](#sub-5.1.1.2)
|
||
sk.stride>0
|
||
|
||
* [(5.1.2)](#sub-5.1.2)
|
||
|
||
0 ⤠*first_*<index_type, k>(slices...) ⤠*last_*<k>(src.extents(), slices...) ⤠src.extent(k)
|
||
|
||
- [(5.2)](#sub-5.2)
|
||
|
||
sub_map_offset.mapping.extents() == submdspan_extents(src.mapping(), slices...) is true; and
|
||
|
||
- [(5.3)](#sub-5.3)
|
||
|
||
for each integer pack I which is a multidimensional index
|
||
in sub_map_offset.mapping.extents(),sub_map_offset.mapping(I...) + sub_map_offset.offset == src.mapping()(*src-indices*(array{I...}, slices...)) is true[.](#sub-5.sentence-1)
|
||
|
||
[*Note [2](#sub-note-2)*:
|
||
|
||
These conditions ensure that the mapping returned by submdspan_mapping matches the algorithmically expected index-mapping given the slice specifiers[.](#sub-5.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[6](#sub-6)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L26100)
|
||
|
||
*Effects*: Equivalent to:auto sub_map_result = submdspan_mapping(src.mapping(), slices...);return mdspan(src.accessor().offset(src.data_handle(), sub_map_result.offset),
|
||
sub_map_result.mapping, typename AccessorPolicy::offset_policy(src.accessor()));
|
||
|
||
[7](#sub-7)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/containers.tex#L26111)
|
||
|
||
[*Example [1](#sub-example-1)*:
|
||
|
||
Given a rank-3 mdspan grid3d representing a three-dimensional grid
|
||
of regularly spaced points in a rectangular prism,
|
||
the function zero_surface sets all elements on
|
||
the surface of the 3-dimensional shape to zero[.](#sub-7.sentence-1)
|
||
|
||
It does so by reusing a function zero_2d that takes a rank-2 mdspan[.](#sub-7.sentence-2)
|
||
|
||
// zero out all elements in an mdspantemplate<class T, class E, class L, class A>void zero_2d(mdspan<T, E, L, A> a) {static_assert(a.rank() == 2); for (int i = 0; i < a.extent(0); i++)for (int j = 0; j < a.extent(1); j++) a[i, j] = 0;}// zero out just the surfacetemplate<class T, class E, class L, class A>void zero_surface(mdspan<T, E, L, A> grid3d) {static_assert(grid3d.rank() == 3);
|
||
zero_2d(submdspan(grid3d, 0, full_extent, full_extent));
|
||
zero_2d(submdspan(grid3d, full_extent, 0, full_extent));
|
||
zero_2d(submdspan(grid3d, full_extent, full_extent, 0));
|
||
zero_2d(submdspan(grid3d, grid3d.extent(0) - 1, full_extent, full_extent));
|
||
zero_2d(submdspan(grid3d, full_extent, grid3d.extent(1) - 1, full_extent));
|
||
zero_2d(submdspan(grid3d, full_extent, full_extent, grid3d.extent(2) - 1));} â *end example*]
|