Skip to content
Open
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
218 changes: 152 additions & 66 deletions source/containers.tex
Original file line number Diff line number Diff line change
Expand Up @@ -21280,7 +21280,9 @@

// \ref{mdspan.sub}, \tcode{submdspan} creation
template<class OffsetType, class LengthType, class StrideType>
struct strided_slice;
struct extent_slice;
template<class FirstType, class LastType, class StrideType = std::constant_wrapper<1zu>>
struct range_slice;

template<class LayoutMapping>
struct submdspan_mapping_result;
Expand Down Expand Up @@ -25543,11 +25545,17 @@
\item
\tcode{is_convertible_v<$S$, IndexType>} is \tcode{true};
\item
$S$ is a specialization of \tcode{strided_slice} and
$S$ is a specialization of \tcode{extent_slice} and
\tcode{is_convertible_v<$X$, IndexType>} is \tcode{true} for $X$ denoting
\tcode{$S$::offset_type},
\tcode{$S$::extent_type}, and
\tcode{$S$::stride_type}; or
\tcode{$S$::stride_type};
\item
$S$ is a specialization of \tcode{range_slice} and
\tcode{is_convertible_v<X, IndexType>} is \tcode{true} for $X$ denoting type of
\tcode{$S$::first},
\tcode{$S$::last}, and
\tcode{$S$::stride} members; or
\item
all of the following hold:
\begin{itemize}
Expand Down Expand Up @@ -25580,7 +25588,7 @@
\item
$S$ is a canonical \tcode{submdspan} index type for \tcode{IndexType}; or
\item
$S$ is a specialization of \tcode{strided_slice}
$S$ is a specialization of \tcode{extent_slice}
where all of the following hold:
\begin{itemize}
\item
Expand All @@ -25596,7 +25604,7 @@
\pnum
A type \tcode{S} is a \defnadj{collapsing}{slice type} if
it is neither \tcode{full_extent_t} nor
a specialization of \tcode{strided_slice}.
a specialization of \tcode{extent_slice}.
\begin{note}
Each collapsing slice type in \tcode{submdspan_mapping}'s parameter pack
of slice specifier types
Expand All @@ -25607,7 +25615,7 @@
A type \tcode{S} is a \defnadj{unit-stride}{slice type} if
\begin{itemize}
\item
\tcode{S} is a specialization of \tcode{strided_slice}
\tcode{S} is a specialization of \tcode{extent_slice}
where \tcode{S::stride_type} is a specialization of \tcode{constant_wrapper} and
\tcode{S::stride_type::value} is equal to 1, or
\item
Expand All @@ -25624,6 +25632,10 @@
\item
\range{$0$}{e.extent($k$)},
if \tcode{S} is \tcode{full_extent_t};
\item
\range{E::index_type(s.offset)}{E::index_type(s.offset)},
if \tcode{S} is a specialization of \tcode{extent_slice} and
\tcode{E::index_type(s.extent)} is zero; otherwise
\item
\range{E::index_type(s.offset)}{E::index_type(s.offset + s.extent)},
if \tcode{S} is a specialization of \tcode{stri\-ded_slice}; otherwise
Expand All @@ -25640,19 +25652,33 @@
either $x$ is equal to \tcode{dynamic_extent}; or
\begin{itemize}
\item
if \tcode{S} is a specialization of \tcode{strided_slice}:
if \tcode{S} is a specialization of \tcode{extent_slice}:
\begin{itemize}
\item
if \tcode{S::offset_type} is a specialization of \tcode{constant_wrapper},
then \tcode{S::offset_type::value} is less than or equal to $x$;
$o$ is less than or equal to $x$;
\item
if \tcode{S::offset_type} is a specialization of \tcode{constant_wrapper},
then \tcode{S::extent_type::value} is less than or equal to $x$; and
$e$ is less than or equal to $x$;
\item
if both \tcode{S::offset_type} and \tcode{S::extent_type}
are specializations of \tcode{constant_wrapper},
then \tcode{S::offset_type::value + S::extent_type::value}
is less than or equal to $x$; or
if $e$ is greater than one,
then $t$ is greater than zero,
\item
if $e$ is greater than zero,
then $o + 1 + (e - 1) * t$ is less than or equal to $x$
\end{itemize}
where
\begin{itemize}
\item
$o$ is value of \tcode{S::offset_type::value}
if \tcode{S::offset_type} is a specialization of \tcode{constant_wrapper} and
\tcode{0} otherwise,
\item
$e$ is value of \tcode{S::extent_type::value}
if \tcode{S::extend_type} is a specialization of \tcode{constant_wrapper} and
\tcode{0} otherwise,
\item
$t$ is value of \tcode{S::stride_type::value}
if \tcode{S::stride_type} is a specialization of \tcode{constant_wrapper} and
\tcode{1} otherwise.
\end{itemize}
\item
if $S$ is a specialization of \tcode{constant_wrapper},
Expand All @@ -25674,26 +25700,27 @@
contains the \tcode{submdspan} slice range of \tcode{s}
for the $k^\text{th}$ extent of \tcode{e}; and
\item
if \tcode{S} is a specialization of \tcode{strided_slice}, then:
if \tcode{S} is a specialization of \tcode{extent_slice}, then:
\begin{itemize}
\item \tcode{s.extent} is greater than or equal to zero, and
\item either \tcode{s.extent} equals zero or \tcode{s.stride} is greater than zero.
\item either \tcode{s.extent} is less than two or \tcode{s.stride} is greater than zero.
\end{itemize}
\end{itemize}

\rSec4[mdspan.sub.strided.slice]{\tcode{strided_slice}}
\rSec4[mdspan.sub.range.slices]{\tcode{Range slices}}

\pnum
\tcode{strided_slice} represents a set of
\tcode{extent_slice} and \tcode{range_slice} represent a set of
\tcode{extent} regularly spaced integer indices.
The indices start at \tcode{offset}, and
The indices start at \tcode{offset} and \tcode{first} respectively, and
increase by increments of \tcode{stride}.

\indexlibraryglobal{strided_slice}%
\indexlibraryglobal{extent_slice}%
\indexlibraryglobal{range_slice}%
\begin{codeblock}
namespace std {
template<class OffsetType, class ExtentType, class StrideType>
struct strided_slice {
struct extent_slice {
using offset_type = OffsetType;
using extent_type = ExtentType;
using stride_type = StrideType;
Expand All @@ -25702,21 +25729,31 @@
[[no_unique_address]] extent_type extent{};
[[no_unique_address]] stride_type stride{};
};

template<class FirstType, class LastType, class StrideType = std::constant_wrapper<1zu>>
struct range_slice {
[[no_unique_address]] FirstType first{};
[[no_unique_address]] LastType last{};
[[no_unique_address]] StrideType stride{};
};
}
\end{codeblock}

\pnum
\tcode{strided_slice} has the data members and special members specified above.
It has no base classes or members other than those specified.
\tcode{extent_slice} and \tcode{range_slice}
have the data members and special members specified above.
They have no base classes or members other than those specified.

\pnum
\mandates
\tcode{OffsetType}, \tcode{ExtentType}, and \tcode{StrideType}
\tcode{OffsetType}, \tcode{ExtentType},
\tcode{FirstType}, \tcode{LastType}, and \tcode{StrideType}
are signed or unsigned integer types, or
model \exposconcept{integral-constant-like}.
\begin{note}
\tcode{strided_slice\{.offset = 1, .extent = 10, .stride = 3\}}
indicates the indices \tcode{1}, \tcode{4}, \tcode{7}, and \tcode{10}.
Both \tcode{extent_slice\{.offset = 1, .extent = 4, .stride = 3\}} and
\tcode{range_slice\{.first = 1, .last = 11, .stride = 3\}}
indicate the indices \tcode{1}, \tcode{4}, \tcode{7}, and \tcode{10}.
Indices are selected from the half-open interval \range{1}{1 + 10}.
\end{note}

Expand Down Expand Up @@ -25756,14 +25793,26 @@

\begin{itemdecl}
template<class T>
concept @\defexposconcept{is-strided-slice}@ = @\seebelow;@
concept @\defexposconcept{is-extent-slice}@ = @\seebelow;@
\end{itemdecl}

\begin{itemdescr}
\pnum
The concept \tcode{\exposconcept{is-strided-slice}<T>}
The concept \tcode{\exposconcept{is-extent-slice}<T>}
is satisfied and modeled if and only
if \tcode{T} is a specialization of \tcode{strided_slice}.
if \tcode{T} is a specialization of \tcode{extent_slice}.
\end{itemdescr}

\begin{itemdecl}
template<class T>
concept @\defexposconcept{is-range-slice}@ = @\seebelow;@
\end{itemdecl}

\begin{itemdescr}
\pnum
The concept \tcode{\exposconcept{is-range-slice}<T>}
is satisfied and modeled if and only
if \tcode{T} is a specialization of \tcode{range_slice}.
\end{itemdescr}

\indexlibraryglobal{\exposid{canonical-index}}%
Expand Down Expand Up @@ -25796,6 +25845,53 @@
\end{itemize}
\end{itemdescr}

\begin{itemdecl}
template<class IndexType, class OffsetType, class SpanType, class... StrideTypes>
constexpr auto @\exposid{canonical-range-slice}@(OffsetType offset, SpanType span, StrideTypes... strides);
\end{itemdecl}

\begin{itemdescr}
\pnum
Let:
\begin{itemize}
\item
\tcode{StrideType} denote
\tcode{constant_wrapper<IndexType(1)>}
if \tcode{StrideTypes} is an empty pack or
\tcode{SpanType} denotes \tcode{constant_wrapper<IndexType(0)>}, otherwise
\tcode{StrideTypes...[0]};
\item
\tcode{stride} be
\tcode{StrideType()} if \tcode{StrideType}
is a specialization of \tcode{constant_wrapper}, otherwise
\tcode{IndexType(1)} if \tcode{span == 0} is \tcode{true}, otherwise
\tcode{strides...[0]};
\item
\exposid{extent-value} be \tcode{1 + (span - 1) / stride}
if \tcode{span != 0} is \tcode{true}, and
\tcode{0} otherwise;
\item
\tcode{extent} be \tcode{cw<IndexType(\exposid{extent-value})>}
if both \tcode{SpanType} and \tcode{StrideType}
are specializations of \tcode{constant_wrapper}, and
\tcode{IndexType(\exposid{extent-value})} otherwise.
\end{itemize}

\pnum
\mandates
\tcode{sizeof...(StrideTypes) <= 1} is \tcode{true}, and
if \tcode{StrideType} is a specialization of \tcode{con\-stant_wrapper},
then \tcode{StrideType::value > 0} is \tcode{true}.

\pnum
\expects
\tcode{stride > 0} is \tcode{true}.

\pnum
\returns
\tcode{extent_slice\{ .offset = offset, .extent = extent, .stride = stride \};}
\end{itemdescr}

\indexlibraryglobal{\exposid{canonical-slice}}
\begin{itemdecl}
template<class IndexType, class S>
Expand All @@ -25815,31 +25911,28 @@
return static_cast<full_extent_t>(std::move(s));
} else if constexpr (is_convertible_v<S, IndexType>) {
return @\exposid{canonical-index}@<IndexType>(std::move(s));
} else if constexpr (@\exposconcept{is-strided-slice}@<S>) {
} else if constexpr (@\exposconcept{is-extent-slice}@<S>) {
auto c_extent = @\exposid{canonical-index}@<IndexType>(std::move(s.extent));
auto c_offset = @\exposid{canonical-index}@<IndexType>(std::move(s.offset));
if constexpr (is_same_v<decltype(c_extent), constant_wrapper<IndexType(0)>>) {
return strided_slice{
.offset = c_offset,
.extent = c_extent,
.stride = cw<IndexType(1)>
};
} else {
return strided_slice{
.offset = c_offset,
.extent = c_extent,
.stride = @\exposid{canonical-index}@<IndexType>(std::move(s.stride))
};
}
return extent_slice{
.offset = @\exposid{canonical-index}@<IndexType>(std::move(s.extent)),
.extent = @\exposid{canonical-index}@<IndexType>(std::move(s.offset)),
.stride = @\exposid{canonical-index}@<IndexType>(std::move(s.stride))
};
} else if constexpr (@\exposid{is-range-slice}@<S>) {
auto c_first = canonical-index<IndexType>(std::move(s.first));
auto c_last = canonical-index<IndexType>(std::move(s.last));
return @\exposid{canonical-slice-range}@<IndexType>(
c_first,
@\exposid{canonical-index}@<IndexType>(c_last - c_first),
@\exposid{canonical-index}@<IndexType>(std::move(s.stride)));
} else {
auto [s_first, s_last] = std::move(s);
auto c_first = @\exposid{canonical-index}@<IndexType>(std::move(s_first));
auto c_last = @\exposid{canonical-index}@<IndexType>(std::move(s_last));
return strided_slice{
.offset = c_first,
.extent = @\exposid{canonical-index}@<IndexType>(c_last - c_first),
.stride = cw<IndexType(1)>
};
return @\exposid{canonical-slice-range}@<IndexType>(
c_first,
@\exposid{canonical-index}@<IndexType>(c_last - c_first));
}
\end{codeblock}
\end{itemdescr}
Expand Down Expand Up @@ -25929,7 +26022,7 @@
\tcode{\placeholder{MAP_RANK}(slices, Extents::rank())}; and

\item
for each rank index $k$ of \tcode{Extents} such that
for each rank index $k$ of \tcode{extents<IndexType, Extents...>} such that
the type of \tcode{slices...[$k$]} is not a collapsing slice type,
\tcode{SubExt\-ents::static_extent(\placeholder{MAP_RANK}(slices, $k$))}
equals the following, where $\Sigma_k$
Expand All @@ -25938,20 +26031,13 @@
\begin{itemize}
\item
\tcode{Extents::static_extent($k$)}
if $\Sigma_k$ denotes the \tcode{full_extent_t};
otherwise

\item
\tcode{0},
if $\Sigma_k$ is a specialization of \tcode{strided_slice} and
\tcode{$\Sigma_k$::extent_type} denotes \tcode{constant_wrapper<IndexType(0)>};
if $\Sigma_k$ denotes \tcode{full_extent_t};
otherwise

\item
\tcode{1 + (($\Sigma_k$::extent_type::value - 1) / $\Sigma_k$::stride_type::value)},
if $\Sigma_k$ is a specialization of \tcode{strided_slice} whose
\tcode{extent_type} and \tcode{stride_type}
denote specializations of \tcode{constant_wrapper};
\tcode{$\Sigma_k$::extent_type::value}
if $\Sigma_k$ is a specialization of \tcode{extent_slice} whose
\tcode{extent_type} denotes a specialization of \tcode{constant_wrapper};

\item
otherwise,
Expand All @@ -25969,8 +26055,8 @@
where $\sigma_k$ denotes \tcode{slices...[$k$]}:
\begin{itemize}
\item
\tcode{$\sigma_k$.extent == 0 ? 0 : 1 + ($\sigma_k$.extent - 1) / $\sigma_k$.stride}
if the type of $\sigma_k$ is a specialization of \tcode{strided_slice},
\tcode{$\sigma_k$.extent}
if the type of $\sigma_k$ is a specialization of \tcode{extent_slice},
\item
otherwise,
$U - L$, where \range{$L$}{$U$} is the \tcode{submdspan} slice range
Expand Down Expand Up @@ -26008,7 +26094,7 @@
\item \tcode{IT},
\item \tcode{full_extent_t},
\item a specialization of \tcode{constant_wrapper}, or
\item a specialization of \tcode{strided_slice}.
\item a specialization of \tcode{extent_slice}.
\end{itemize}
\end{itemize}

Expand Down Expand Up @@ -26133,8 +26219,8 @@
\begin{itemize}
\item
\tcode{stride(k) * s.stride}
if the type of \tcode{s} is a specialization of \tcode{strided_slice} and
\tcode{s.stride < s.ex\-tent} is \tcode{true},
if the type of \tcode{s} is a specialization of \tcode{extent_slice} and
\tcode{s.extent > 1} is \tcode{true},
where \tcode{s} is \tcode{slices...[$k$]};
\item
otherwise, \tcode{stride($k$)}.
Expand Down
2 changes: 1 addition & 1 deletion source/support.tex
Original file line number Diff line number Diff line change
Expand Up @@ -852,7 +852,7 @@
#define @\defnlibxname{cpp_lib_string_subview}@ 202506L // also in \libheader{string}, \libheader{string_view}
#define @\defnlibxname{cpp_lib_string_udls}@ 201304L // also in \libheader{string}
#define @\defnlibxname{cpp_lib_string_view}@ 202403L // also in \libheader{string}, \libheader{string_view}
#define @\defnlibxname{cpp_lib_submdspan}@ 202511L // freestanding, also in \libheader{mdspan}
#define @\defnlibxname{cpp_lib_submdspan}@ 202603L // freestanding, also in \libheader{mdspan}
#define @\defnlibxname{cpp_lib_syncbuf}@ 201803L // also in \libheader{iosfwd}, \libheader{syncstream}
#define @\defnlibxname{cpp_lib_task}@ 202506L // also in \libheader{execution}
#define @\defnlibxname{cpp_lib_text_encoding}@ 202306L // also in \libheader{text_encoding}
Expand Down
Loading