Skip to content

Add implementation of span, mdspan and mdarray

Simon Praetorius requested to merge feature/mdspan into master

Summary

This MR provides a reference implementation of std::span, std::mdspan, and std::mdarray including all its utilities, std::dynamic_extent, std::extents, std::layout_[left|right|stride], and std::default_accessor, plus a few backports of c++20 standard library functions, e.g. std::to_address. All these entities are put into the Dune::Std namespace including an import of the actual standard implementation if available.

Motivation

In Dune we do not have tensor data structures. The containers and views provided in this MR can be the basis for such an implementation. A reference code is available in https://gitlab.dune-project.org/simon.praetorius/dune-tensor. Also, these types could be the start of a reimplementation of DenseVector and DenseMatrix and all their derived types.

Deprecation

While posting these implementations here, they are meant to be deprecated once the standard libraries we support in Dune all ship their implementation of these classes. Currently, it is only the most recent version, clang-18, with its libc++ that supports at least std::mdspan. In the module dune-tensor there are already CI jobs testing with this compiler and this library. Other classes, like std::span or the utility std::to_address might be deprecated more early, once we support only c++20 compatible compilers. The implementation in this MR is (mostly) c++17 compatible.

Provided classes

Dune::Std::span

A contiguous sequence of elements with static or dynamic extent. The implementation is based on the C++ standard working draft https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/n4971.pdf and the documentation provided in https://en.cppreference.com/w/cpp/container/span.

Example

std::vector v{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

// view data as contiguous memory representing 10 elements
auto s1 = Dune::Std::span(v.data(), 10);

// view data as contiguous memory with static size
auto s2 = Dune::Std::span<int,10>(v.data());

// write data using 2D view
for (std::size_t i = 0; i != s1.size(); i++)
  s1[i] = 2*i;

Not that dynamic extents are specified by the constant Dune::Std::dynamic_extent.

Dune::Std::mdspan

A multi-dimensional non-owning array view. The implementation is based in the standard proposal https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p0009r17.html and the C++ standard working draft https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/n4971.pdf.

Example

std::vector v{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

// view data as contiguous memory representing 2 rows and 5 columns
// with row-major ordering.
auto ms = Dune::Std::mdspan(v.data(), 2, 5);

// or with static shape given by Std::extents
auto ms2 = Dune::Std::mdspan<int,Dune::Std::extents<int,2,5>>(v.data());

// write data using 2D view
for (std::size_t i = 0; i != ms.extent(0); i++)
  for (std::size_t j = 0; j != ms.extent(1); j++)
    ms(i, j) = i + j;   // or ms[i, j]

Dune::Std::mdarray

An owning multi-dimensional array analog of mdspan. The implementation is inspired by the mdarray c++ standard proposals https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p1684r5.html.

Example

// two-dimensional array with 2 rows and 6 columns of static shape
Dune::Std::mdarray<double, Dune::Std::extents<std::size_t,2,6>> m1{};

// same two-dimensional array but with dynamic shape
Dune::Std::mdarray<double, Dune::Std::dextents<std::size_t,2>> m2{2,6};

// storage type similar to the Dune::FieldMatrix
template <class T, int m, int n>
using FieldMatrix = Dune::Std::mdarray<T,
  Dune::Std::extents<int,m,n>, Dune::Std::layout_right, std::array<T,m*n>>;

// store data into the array using two indices
for (std::size_t i = 0; i != m1.extent(0); i++)
  for (std::size_t j = 0; j != m1.extent(1); j++)
    m1(i, j) = i + j;  // or m1[i, j]

Note that std::mdarray is not yet fully standardized, but hopefully will be in c++26. There is also no other reference implementation following the recent proposal. The Kokkos implementation (in the current stable branch) still follows the proposal version R4.

Edited by Simon Praetorius

Merge request reports