Loading...
Searching...
No Matches
mdspan.hh
Go to the documentation of this file.
// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
// vi: set et ts=4 sw=2 sts=2:
// SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root
// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception
#ifndef DUNE_COMMON_STD_MDSPAN_HH
#define DUNE_COMMON_STD_MDSPAN_HH
#include <array>
#include <span>
#include <type_traits>
#include <utility>
#if __has_include(<version>)
#include <version>
#endif
#include <dune/common/indices.hh>
#include <dune/common/std/default_accessor.hh>
#include <dune/common/std/extents.hh>
#include <dune/common/std/layout_right.hh>
#include <dune/common/std/no_unique_address.hh>
namespace Dune::Std {
template <class Element, class Extents, class LayoutPolicy = Std::layout_right,
class AccessorPolicy = Std::default_accessor<Element>>
class mdspan
{
static_assert(std::is_object_v<Element>);
static_assert(!std::is_abstract_v<Element>);
static_assert(!std::is_array_v<Element>);
static_assert(std::is_same_v<Element, typename AccessorPolicy::element_type>);
public:
using element_type = Element;
using extents_type = Extents;
using layout_type = LayoutPolicy;
using accessor_type = AccessorPolicy;
using value_type = std::remove_cv_t<Element>;
using mapping_type = typename layout_type::template mapping<extents_type>;
using index_type = typename extents_type::index_type;
using size_type = typename extents_type::size_type;
using rank_type = typename extents_type::rank_type;
using data_handle_type = typename accessor_type::data_handle_type;
using reference = typename accessor_type::reference;
private:
// [mdspan.layout.reqmts]
static_assert(std::is_nothrow_move_constructible_v<mapping_type>);
static_assert(std::is_nothrow_move_assignable_v<mapping_type>);
static_assert(std::is_nothrow_swappable_v<mapping_type>);
// [mdspan.accessor.reqmts]
static_assert(std::is_nothrow_move_constructible_v<accessor_type>);
static_assert(std::is_nothrow_move_assignable_v<accessor_type>);
static_assert(std::is_nothrow_swappable_v<accessor_type>);
public:
template <class E = extents_type, class D = data_handle_type, class M = mapping_type, class A = accessor_type,
std::enable_if_t<(E::rank_dynamic() > 0), int> = 0,
std::enable_if_t<std::is_default_constructible_v<D>, int> = 0,
std::enable_if_t<std::is_default_constructible_v<M>, int> = 0,
std::enable_if_t<std::is_default_constructible_v<A>, int> = 0>
constexpr mdspan ()
: data_handle_{}
, mapping_{}
, accessor_{}
{}
template <class... IndexTypes,
class E = extents_type, class M = mapping_type, class A = accessor_type,
std::enable_if_t<(sizeof...(IndexTypes) == E::rank() || sizeof...(IndexTypes) == E::rank_dynamic()), int> = 0,
std::enable_if_t<(... && std::is_convertible_v<IndexTypes, index_type>), int> = 0,
std::enable_if_t<(... && std::is_nothrow_constructible_v<index_type, IndexTypes>), int> = 0,
std::enable_if_t<std::is_constructible_v<M, E>, int> = 0,
std::enable_if_t<std::is_default_constructible_v<A>, int> = 0>
explicit constexpr mdspan (data_handle_type p, IndexTypes... exts)
: mdspan(std::move(p), extents_type(index_type(std::move(exts))...))
{}
template <class IndexType, std::size_t N,
std::enable_if_t<std::is_convertible_v<const IndexType&, index_type>, int> = 0,
std::enable_if_t<std::is_nothrow_constructible_v<index_type,const IndexType&>, int> = 0,
std::enable_if_t<(N == extents_type::rank_dynamic() || N == extents_type::rank()), int> = 0>
#if __cpp_conditional_explicit >= 201806L
explicit(N != extents_type::rank_dynamic())
#endif
constexpr mdspan (data_handle_type p, std::span<IndexType,N> exts)
: mdspan(std::move(p), extents_type(exts))
{}
template <class IndexType, std::size_t N,
std::enable_if_t<std::is_convertible_v<IndexType, index_type>, int> = 0,
std::enable_if_t<(N == extents_type::rank_dynamic() || N == extents_type::rank()), int> = 0>
#if __cpp_conditional_explicit >= 201806L
explicit(N != extents_type::rank_dynamic())
#endif
constexpr mdspan (data_handle_type p, const std::array<IndexType,N>& exts)
: mdspan(std::move(p), extents_type(exts))
{}
template <class M = mapping_type,
std::enable_if_t<std::is_constructible_v<M, const extents_type&>, int> = 0>
constexpr mdspan (data_handle_type p, const extents_type& e)
: mdspan(std::move(p), mapping_type(e))
{}
template <class A = accessor_type,
std::enable_if_t<std::is_default_constructible_v<A>, int> = 0>
constexpr mdspan (data_handle_type p, const mapping_type& m)
: mdspan(std::move(p), m, accessor_type{})
{}
constexpr mdspan (data_handle_type p, const mapping_type& m, const accessor_type& a)
: data_handle_(std::move(p))
, mapping_(m)
, accessor_(a)
{}
template <class OtherElementType, class OtherExtends, class OtherLayoutPolicy, class OtherAccessor,
std::enable_if_t<std::is_constructible_v<mapping_type, const typename OtherLayoutPolicy::template mapping<OtherExtends>&>, int> = 0,
std::enable_if_t<std::is_constructible_v<accessor_type, const OtherAccessor&>, int> = 0>
#if __cpp_conditional_explicit >= 201806L
explicit(!std::is_convertible_v<const typename OtherLayoutPolicy::template mapping<OtherExtends>&, mapping_type>
|| !std::is_convertible_v<const OtherAccessor&, accessor_type>)
#endif
constexpr mdspan (const mdspan<OtherElementType,OtherExtends,OtherLayoutPolicy,OtherAccessor>& other) noexcept
: mdspan(data_handle_type(other.data_handle()), mapping_type(other.mapping()),
accessor_type(other.accessor()))
{}
template <class... Indices,
std::enable_if_t<(sizeof...(Indices) == extents_type::rank()), int> = 0,
std::enable_if_t<(... && std::is_convertible_v<Indices, index_type>), int> = 0,
std::enable_if_t<(... && std::is_nothrow_constructible_v<index_type,Indices>), int> = 0>
constexpr reference operator() (Indices... indices) const
{
return accessor_.access(data_handle_, mapping_(index_type(std::move(indices))...));
}
#if __cpp_multidimensional_subscript >= 202110L
template <class... Indices,
std::enable_if_t<(sizeof...(Indices) == extents_type::rank()), int> = 0,
std::enable_if_t<(... && std::is_convertible_v<Indices, index_type>), int> = 0,
std::enable_if_t<(... && std::is_nothrow_constructible_v<index_type,Indices>), int> = 0>
constexpr reference operator[] (Indices... indices) const
{
return accessor_.access(data_handle_, mapping_(index_type(std::move(indices))...));
}
#else // __cpp_multidimensional_subscript
template <class Index, class E = extents_type,
std::enable_if_t<std::is_convertible_v<Index,index_type>, int> = 0,
std::enable_if_t<(E::rank() == 1), int> = 0>
constexpr reference operator[] (Index index) const
{
return accessor_.access(data_handle_, mapping_(index_type(std::move(index))));
}
#endif // __cpp_multidimensional_subscript
template <class Index,
std::enable_if_t<std::is_convertible_v<const Index&, index_type>, int> = 0,
std::enable_if_t<std::is_nothrow_constructible_v<index_type, const Index&>, int> = 0>
constexpr reference operator[] (std::span<Index,extents_type::rank()> indices) const
{
return unpackIntegerSequence([&](auto... ii) -> reference {
return accessor_.access(data_handle_, mapping_(index_type(indices[ii])...)); },
std::make_index_sequence<extents_type::rank()>{});
}
template <class Index,
std::enable_if_t<std::is_convertible_v<const Index&, index_type>, int> = 0,
std::enable_if_t<std::is_nothrow_constructible_v<index_type, const Index&>, int> = 0>
constexpr reference operator[] (const std::array<Index,extents_type::rank()>& indices) const
{
return std::apply([&](auto... ii) -> reference {
return accessor_.access(data_handle_, mapping_(index_type(ii)...)); }, indices);
}
constexpr const extents_type& extents () const noexcept { return mapping_.extents(); }
constexpr const mapping_type& mapping () const noexcept { return mapping_; }
constexpr const accessor_type& accessor () const noexcept { return accessor_; }
constexpr const data_handle_type& data_handle () const noexcept { return data_handle_; };
static constexpr rank_type rank () noexcept { return extents_type::rank(); }
static constexpr rank_type rank_dynamic () noexcept { return extents_type::rank_dynamic(); }
static constexpr std::size_t static_extent (rank_type r) noexcept { return extents_type::static_extent(r); }
constexpr index_type extent (rank_type r) const noexcept { return extents().extent(r); }
constexpr size_type size () const noexcept
{
size_type s = 1;
for (rank_type r = 0; r < rank(); ++r)
s *= extent(r);
return s;
}
[[nodiscard]] constexpr bool empty () const noexcept { return size() == 0; }
static constexpr bool is_always_unique () { return mapping_type::is_always_unique(); }
static constexpr bool is_always_exhaustive () { return mapping_type::is_always_exhaustive(); }
static constexpr bool is_always_strided () { return mapping_type::is_always_strided(); }
constexpr bool is_unique () const { return mapping_.is_unique(); }
constexpr bool is_exhaustive () const { return mapping_.is_exhaustive(); }
constexpr bool is_strided () const { return mapping_.is_strided(); }
constexpr index_type stride (rank_type r) const { return mapping_.stride(r); }
friend constexpr void swap (mdspan& x, mdspan& y) noexcept
{
using std::swap;
swap(x.data_handle_, y.data_handle_);
swap(x.mapping_, y.mapping_);
swap(x.accessor_, y.accessor_);
}
private:
data_handle_type data_handle_;
DUNE_NO_UNIQUE_ADDRESS mapping_type mapping_;
DUNE_NO_UNIQUE_ADDRESS accessor_type accessor_;
};
// deduction guides
// @{
template <class CArray,
std::enable_if_t<std::is_array_v<CArray>, int> = 0,
std::enable_if_t<(std::rank_v<CArray> == 1), int> = 0>
mdspan (CArray&)
-> mdspan<std::remove_all_extents_t<CArray>, Std::extents<std::size_t, std::extent_v<CArray,0>>>;
template <class Pointer,
std::enable_if_t<std::is_pointer_v<std::remove_reference_t<Pointer>>, int> = 0>
mdspan (Pointer&&)
-> mdspan<std::remove_pointer_t<std::remove_reference_t<Pointer>>, Std::extents<std::size_t>>;
template <class ElementType, class... II,
std::enable_if_t<(... && std::is_convertible_v<II,std::size_t>), int> = 0,
std::enable_if_t<(sizeof...(II) > 0), int> = 0>
mdspan (ElementType*, II...)
-> mdspan<ElementType, Std::dextents<std::size_t, sizeof...(II)>>;
template <class ElementType, class SizeType, std::size_t N>
mdspan (ElementType*, std::span<SizeType,N>)
-> mdspan<ElementType, Std::dextents<std::size_t, N>>;
template <class ElementType, class SizeType, std::size_t N>
mdspan (ElementType*, const std::array<SizeType,N>&)
-> mdspan<ElementType, Std::dextents<std::size_t, N>>;
template <class ElementType, class IndexType, std::size_t... exts>
mdspan (ElementType*, const Std::extents<IndexType,exts...>&)
-> mdspan<ElementType, Std::extents<IndexType,exts...>>;
template <class ElementType, class Mapping,
class Extents = typename Mapping::extents_type,
class Layout = typename Mapping::layout_type>
mdspan (ElementType*, const Mapping&)
-> mdspan<ElementType, Extents, Layout>;
template <class Mapping, class Accessor,
class DataHandle = typename Accessor::data_handle_type,
class Element = typename Accessor::element_type,
class Extents = typename Mapping::extents_type,
class Layout = typename Mapping::layout_type>
mdspan (const DataHandle&, const Mapping&, const Accessor&)
-> mdspan<Element, Extents, Layout, Accessor>;
// @}
} // end namespace Dune::Std
#endif // DUNE_COMMON_STD_MDSPAN_HH
extents.hh
default_accessor.hh
no_unique_address.hh
DUNE_NO_UNIQUE_ADDRESS
#define DUNE_NO_UNIQUE_ADDRESS
Definition no_unique_address.hh:24
layout_right.hh
indices.hh
Dune::unpackIntegerSequence
decltype(auto) constexpr unpackIntegerSequence(F &&f, std::integer_sequence< I, i... > sequence)
Unpack an std::integer_sequence<I,i...> to std::integral_constant<I,i>...
Definition indices.hh:124
Dune::Std::dextents
typename Impl::DExtentsImpl< IndexType, std::make_integer_sequence< std::size_t, R > >::type dextents
Alias of extents of given rank R and purely dynamic extents. See [mdspan.extents.dextents].
Definition extents.hh:258
std
STL namespace.
Dune::Indices
Namespace with predefined compile time indices for the range [0,19].
Definition indices.hh:50
Dune::Std
Namespace for features backported from new C++ standards.
Definition algorithm.hh:19
Dune::Std::mdspan
mdspan(CArray &) -> mdspan< std::remove_all_extents_t< CArray >, Std::extents< std::size_t, std::extent_v< CArray, 0 > > >
Dune::Std::default_accessor::data_handle_type
element_type * data_handle_type
Definition default_accessor.hh:27
Dune::Std::default_accessor::reference
element_type & reference
Definition default_accessor.hh:28
Dune::Std::extents
Multidimensional index space with dynamic and static extents.
Definition extents.hh:55
Dune::Std::mdspan
A multi-dimensional non-owning array view.
Definition mdspan.hh:65
Dune::Std::mdspan::mdspan
constexpr mdspan(data_handle_type p, std::span< IndexType, N > exts)
Construct from the dynamic extents given as an array.
Definition mdspan.hh:132
Dune::Std::mdspan< element_type, extents_type, layout_type >::reference
typename accessor_type::reference reference
Definition mdspan.hh:83
Dune::Std::mdspan::mdspan
constexpr mdspan(data_handle_type p, const mapping_type &m, const accessor_type &a)
Construct from the pointer to the data of the tensor, an index mapping, and an accessor.
Definition mdspan.hh:162
Dune::Std::mdspan< element_type, extents_type, layout_type >::extents_type
extents_type extents_type
Definition mdspan.hh:73
Dune::Std::mdspan::rank_dynamic
static constexpr rank_type rank_dynamic() noexcept
Number of dimensions of the tensor.
Definition mdspan.hh:270
Dune::Std::mdspan::is_always_unique
static constexpr bool is_always_unique()
Return true only if for every i and j where (i != j || ...) => mapping(i...) != mapping(j....
Definition mdspan.hh:294
Dune::Std::mdspan< element_type, extents_type, layout_type >::index_type
typename extents_type::index_type index_type
Definition mdspan.hh:79
Dune::Std::mdspan< element_type, extents_type, layout_type >::layout_type
layout_type layout_type
Definition mdspan.hh:74
Dune::Std::mdspan::is_strided
constexpr bool is_strided() const
Return true only if for every rank index r of extents there exists an integer sr such that,...
Definition mdspan.hh:314
Dune::Std::mdspan::mdspan
constexpr mdspan(data_handle_type p, const mapping_type &m)
Construct from the pointer to the data of the tensor and an index mapping.
Definition mdspan.hh:157
Dune::Std::mdspan< element_type, extents_type, layout_type >::rank_type
typename extents_type::rank_type rank_type
Definition mdspan.hh:81
Dune::Std::mdspan::mdspan
constexpr mdspan(data_handle_type p, const extents_type &e)
Construct from the pointer to the data of the tensor and its extents.
Definition mdspan.hh:150
Dune::Std::mdspan< element_type, extents_type, layout_type >::element_type
element_type element_type
Definition mdspan.hh:72
Dune::Std::mdspan::is_always_exhaustive
static constexpr bool is_always_exhaustive()
Return true only if for all k in the range [0, mapping.required_span_size() ) there exists an i such ...
Definition mdspan.hh:297
Dune::Std::mdspan::mdspan
constexpr mdspan(const mdspan< OtherElementType, OtherExtends, OtherLayoutPolicy, OtherAccessor > &other) noexcept
Converting constructor.
Definition mdspan.hh:177
Dune::Std::mdspan::operator[]
constexpr reference operator[](Index index) const
Access specified element at position [i0] For a rank one mdspan, the operator[i] is added to support ...
Definition mdspan.hh:220
Dune::Std::mdspan::extents
constexpr const extents_type & extents() const noexcept
Number of elements in all dimensions of the tensor,.
Definition mdspan.hh:251
Dune::Std::mdspan::extent
constexpr index_type extent(rank_type r) const noexcept
Number of elements in the r'th dimension of the tensor.
Definition mdspan.hh:276
Dune::Std::mdspan::swap
friend constexpr void swap(mdspan &x, mdspan &y) noexcept
Overloads the std::swap algorithm for std::mdspan. Exchanges the state of x with that of y.
Definition mdspan.hh:321
Dune::Std::mdspan::is_always_strided
static constexpr bool is_always_strided()
Return true only if for every rank index r of extents there exists an integer sr such that,...
Definition mdspan.hh:300
Dune::Std::mdspan::size
constexpr size_type size() const noexcept
The number of elements accessible by this multi-dimensional span.
Definition mdspan.hh:279
Dune::Std::mdspan< element_type, extents_type, layout_type >::value_type
std::remove_cv_t< element_type > value_type
Definition mdspan.hh:77
Dune::Std::mdspan< element_type, extents_type, layout_type >::data_handle_type
typename accessor_type::data_handle_type data_handle_type
Definition mdspan.hh:82
Dune::Std::mdspan::empty
constexpr bool empty() const noexcept
Checks if the size of the index space is zero.
Definition mdspan.hh:288
Dune::Std::mdspan::accessor
constexpr const accessor_type & accessor() const noexcept
The accessor policy object.
Definition mdspan.hh:257
Dune::Std::mdspan< element_type, extents_type, layout_type >::accessor_type
Std::default_accessor< element_type > accessor_type
Definition mdspan.hh:75
Dune::Std::mdspan::mdspan
constexpr mdspan(data_handle_type p, const std::array< IndexType, N > &exts)
Construct from the dynamic extents given as an array.
Definition mdspan.hh:143
Dune::Std::mdspan::is_exhaustive
constexpr bool is_exhaustive() const
Return true only if for all k in the range [0, mapping.required_span_size() ) there exists an i such ...
Definition mdspan.hh:307
Dune::Std::mdspan::rank
static constexpr rank_type rank() noexcept
Number of dimensions of the tensor.
Definition mdspan.hh:267
Dune::Std::mdspan::static_extent
static constexpr std::size_t static_extent(rank_type r) noexcept
Number of elements in the r'th dimension of the tensor.
Definition mdspan.hh:273
Dune::Std::mdspan< element_type, extents_type, layout_type >::mapping
constexpr const mapping_type & mapping() const noexcept
Definition mdspan.hh:254
Dune::Std::mdspan::data_handle
constexpr const data_handle_type & data_handle() const noexcept
The pointer to the underlying flat sequence.
Definition mdspan.hh:260
Dune::Std::mdspan::stride
constexpr index_type stride(rank_type r) const
The stride along the specified dimension.
Definition mdspan.hh:317
Dune::Std::mdspan::is_unique
constexpr bool is_unique() const
Return true only if for every i and j where (i != j || ...) => mapping(i...) != mapping(j....
Definition mdspan.hh:303
Dune::Std::mdspan::mdspan
constexpr mdspan()
Default constructor value-initializes all members.
Definition mdspan.hh:106
Dune::Std::mdspan< element_type, extents_type, layout_type >::size_type
typename extents_type::size_type size_type
Definition mdspan.hh:80
Dune::Std::mdspan< element_type, extents_type, layout_type >::mapping_type
typename layout_type::template mapping< extents_type > mapping_type
Definition mdspan.hh:78