Draft: Return Padded Layouts From Dune::Std::submdspan
Summary
This merge request extends the Dune::Std::submdspan implementation so that it returns layout_left_padded or layout_right_padded for submatrix-like slices whenever the resulting mapping can be represented by a padded layout.
It builds on two independent merge requests:
- !1639: adds the standard-shaped
Dune::Std::submdspanutility. - !1641: adds
Dune::Std::layout_left_paddedandDune::Std::layout_right_padded.
This MR combines both pieces in the way described by the padded-layout proposal P2642R0: subviews that are more specific than layout_stride, but not representable by plain layout_left or layout_right, should use a padded layout where possible.
Motivation
The important case is a contiguous submatrix of a matrix with standard dense storage.
For a row-major matrix, consecutive entries within one row are contiguous. If we take a submatrix by selecting a range of columns, consecutive entries inside each submatrix row are still contiguous. However, moving from one submatrix row to the next must use the stride of the original matrix row, not the smaller row length of the submatrix.
For a source matrix with row stride S, a row-major submatrix maps indices as:
(i,j) -> base + i*S + jA plain layout_right mapping for the submatrix would use the submatrix extent as row stride. That is wrong when the submatrix does not include the full original row. layout_stride can represent the mapping, but it loses useful structure: the rightmost dimension is still contiguous and only the row stride is padded. layout_right_padded expresses exactly that. The layout_left_padded case is symmetric for column-major storage.
This matters for:
- submatrices of row-major or column-major matrices,
- slices of tensors where the relevant fast dimensions remain contiguous,
- views into pitched or leading-dimension storage,
- SIMD- or cache-aligned storage where row or column strides are deliberately larger than the logical extent,
- downstream code that wants layout information more precise than
layout_stride.
Dune has SIMD-related infrastructure, and preserving the fact that one dimension remains contiguous can be useful for vectorized kernels and data-layout-aware algorithms.
Behavior
The existing submdspan layout selection is extended as follows:
- Keep returning
layout_rightfor fixed leading indices followed by full dimensions. - Keep returning
layout_leftfor the symmetric fixed trailing-index case. - Return
layout_right_paddedfor row-major submatrix-like slices where the rightmost dimension remains contiguous and the row stride is inherited from the source mapping. - Return
layout_left_paddedfor the corresponding column-major case. - Preserve the padded layout family when slicing an already padded layout, if the result is still representable by that padded layout.
- Fall back to
layout_stridefor general slices, fixed middle indices, non-unit strides, or higher-rank slices whose resulting strides cannot be represented by the padded mapping.
The higher-rank case is handled conservatively. For rank greater than two, the dimension that contributes to outer strides must remain full. Otherwise the view is still regular, but no longer representable by the simple padded layout mapping and should remain layout_stride.
Examples
Row-Major Submatrix
#include <array>
#include <dune/common/std/mdspan.hh>
#include <dune/common/std/submdspan.hh>
std::array<double, 4*5> data{};
Dune::Std::mdspan matrix(data.data(), 4, 5);
// Rows [1,3), columns [1,4).
auto block = Dune::Std::submdspan(
matrix,
std::pair{1, 3},
std::pair{1, 4});
// The view keeps contiguous columns, but the row stride is still 5.
static_assert(std::is_same_v<
typename decltype(block)::layout_type,
Dune::Std::layout_right_padded<5>>);Column-Major Submatrix
#include <array>
#include <dune/common/std/layout_left.hh>
#include <dune/common/std/mdspan.hh>
#include <dune/common/std/submdspan.hh>
using Extents = Dune::Std::extents<int, 4, 5>;
using Mapping = Dune::Std::layout_left::mapping<Extents>;
std::array<double, 4*5> data{};
Dune::Std::mdspan<double, Extents, Dune::Std::layout_left> matrix(data.data(), Mapping{});
auto block = Dune::Std::submdspan(
matrix,
std::pair{1, 3},
std::pair{1, 4});
// The first dimension remains contiguous, but the column stride is inherited.
static_assert(std::is_same_v<
typename decltype(block)::layout_type,
Dune::Std::layout_left_padded<4>>);Slicing An Already Padded Layout
#include <vector>
#include <dune/common/std/extents.hh>
#include <dune/common/std/layout_right_padded.hh>
#include <dune/common/std/mdspan.hh>
#include <dune/common/std/submdspan.hh>
using Extents = Dune::Std::dextents<int, 2>;
using Layout = Dune::Std::layout_right_padded<>;
using Mapping = Layout::mapping<Extents>;
Mapping mapping(Extents{4, 5}, 8); // runtime row stride
std::vector<double> data(mapping.required_span_size());
Dune::Std::mdspan<double, Extents, Layout> matrix(data.data(), mapping);
auto block = Dune::Std::submdspan(
matrix,
std::pair{1, 3},
std::pair{1, 4});
static_assert(std::is_same_v<
typename decltype(block)::layout_type,
Dune::Std::layout_right_padded<>>);Tensor Slice
For tensors, padded layouts are returned only when the relevant fast dimensions remain representable by the padded mapping.
std::array<double, 2*4*5> data{};
Dune::Std::mdspan tensor(data.data(), 2, 4, 5);
// Keep leading dimension and the middle dimension full, slice the fastest one.
auto view = Dune::Std::submdspan(
tensor,
Dune::Std::full_extent,
Dune::Std::full_extent,
std::pair{1, 4});
static_assert(std::is_same_v<
typename decltype(view)::layout_type,
Dune::Std::layout_right_padded<5>>);Relation To The Base MRs
This MR is intentionally small and depends on the APIs introduced in !1639 and !1641.
- Without !1639, there is no
submdspanentry point that needs layout selection. - Without !1641, representable submatrix views have to fall back to
layout_stride. - With both pieces available, this MR teaches
submdspanto return the more precise padded layout when that is valid.
Implementation Notes
The layout-selection code now checks for padded-representable cases before falling back to layout_stride.
For rank two:
- row-major contiguous submatrices can return
layout_right_padded, - column-major contiguous submatrices can return
layout_left_padded.
For rank greater than two:
- the fast dimensions must remain contiguous,
- dimensions contributing to outer strides must remain full,
- otherwise the result stays
layout_stride.
The implementation also preserves static padding where it can be inferred from static source extents, and keeps dynamic padding for dynamically padded source layouts.
Tests
The submdspan tests cover:
- row-major submatrices returning
layout_right_padded, - column-major submatrices returning
layout_left_padded, - slicing already padded layouts while preserving the padded layout family,
- dynamic runtime padding,
- rank-three cases where padded layout preservation is valid,
- fallback to
layout_stridefor cases that are regular but not representable as padded layouts.