[PATCH v6 2/7] libstdc++: Implement submdspan and submdspan_mapping for layout_left. [PR110352]
Luc Grosheintz
luc.grosheintz@gmail.com
Tue Dec 9 12:51:44 GMT 2025
On 12/9/25 10:58, Jonathan Wakely wrote:
> On Tue, 9 Dec 2025 at 09:37, Tomasz Kamiński <tkaminsk@redhat.com> wrote:
>>
>> From: Luc Grosheintz <luc.grosheintz@gmail.com>
>>
>> Implements `submdspan` and `submdspan_mapping` for layout_left as
>> described in P3663 (Future proofing mdspan).
>>
>> When computing the offset of the submdspan, one must check that the
>> lower bound of the slice range isn't out-of-range. There's a few
>> cases when the lower bound is never out-of-range:
>>
>> - full_extent and exts.extent(k) != 0,
>> - collapsing slice types.
>>
>> If those conditions are known to hold, no checks are generated.
>>
>> Similarly, if all slices are full_extent, there's no need to call
>> mapping(0,...,0) for standardized mappings.
>>
>> The implementation prepares to use the symmetry between layout_left and
>> layout_right and introduces concepts like a "layout side", i.e. left,
>> right or unknown/strided.
>>
>> The tests use an iterator to replace nested for-loops. Which also makes
>> it easier to write the core test logic in a rank-independent manner.
>>
>> PR libstdc++/110352
>>
>> libstdc++-v3/ChangeLog:
>>
>> * include/std/mdspan (__mdspan::__is_submdspan_mapping_result)
>> (__mdspan::__submdspan_mapping_result, __mdspan::__fwd_prod)
>> (__mdspan::__acceptable_slice_type, __mdspan::__slice_begin)
>> (__mdspan::__suboffset, __mdspan::_LayoutSide, __mdspan::__mapping_side)
>> (__mdspan::_StridesTrait, __mdspan::__substrides_generic)
>> (__mdspan::__substrides_standardized, __mdspan::__substrides)
>> (__mdspan::__is_unit_stride_slice, __mdspan::_SliceKind)
>> (__mdspan::__make_slice_kind, __mdspan::__make_slice_kind_array)
>> (__mdspan::__is_block, __mdspan::__padded_block_begin_generic)
>> (__mdspan::__padded_block_begin, __mpdspan::_SubMdspanMapping)
>> (__mdspan::__submdspan_mapping_impl): Define.
>> (__mdspan::__dynamic_slice_extent, __mdspan::__static_slice_extent)
>> (__mdspan::__subextents): Move eariel in the file.
>
> "earlier"
>
>> (layout_left::mapping::submdspan_mapping, __mdspan::__sliceable_mapping)
>> (__mdspan::__submapping, submdspan): Define.
>> * src/c++23/std.cc.in: Add submdspan.
>> * testsuite/23_containers/mdspan/submdspan/generic.cc: New test.
>> * testsuite/23_containers/mdspan/submdspan/selections/left.cc:
>> Instantiate selection tests for layout_left.
>> * testsuite/23_containers/mdspan/submdspan/selections/testcases.h: Generic
>> tests different selections.
>> * testsuite/23_containers/mdspan/submdspan/submdspan_mapping.cc: New test.
>> * testsuite/23_containers/mdspan/submdspan/submdspan_neg.cc: New test.
>>
>> Reviewed-by: Tomasz Kamiński <tkaminsk@redhat.com>
>> Signed-off-by: Luc Grosheintz <luc.grosheintz@gmail.com>
>> ---
>> v7:
>> - list all new entries in changes.
>> - move submdspan_mapping poison pill before concept,
>> - use const mapping as argument to concept
>> - refactor __submdspan into __submapping funciton.
>>
>> Tested *mdspan* locally.
>
> We've reached the point where I no longer understand the <mdspan>
> code! But this looks OK for trunk, with the typo above fixed.
>
This part of <mdspan> was more tricky than others; and longer. To
figure out how it computes the kind of sublayout, this is one
intuitive way of reading the spec:
- an unpadded (sub-)layout can't have any gaps. An example of
what the spec describes is: x[1, 2, 2:5, :, :] or as a two-
dimensional A[2:5, :]. The key to realize is that it can't
describe anything with gaps.
- the padded layouts allow us to have a gap after the fastest
index. Hence, this time the fastest index can be pair-like. We
can then follow up with collapsing slices (because we simply
increase the gap after the first index). Eventually, we need a
compact run, because we're no longer able to add gaps. It can't
lead with collapsing indexes, because if it did, then the inner
most stride wouldn't be 1 (but all padded layouts have inner-
most stride equal to 1).
- the rest are corner cases; or the generic case which uses
layout_stride which permits gaps after every coordinate.
Let me know if there's anything I can do to make it clearer.
More information about the Libstdc++
mailing list