5#ifndef DUNE_COMMON_STD_MDSPAN_HH
6#define DUNE_COMMON_STD_MDSPAN_HH
11#if __has_include(<version>)
15#include <dune/common/indices.hh>
16#include <dune/common/std/default_accessor.hh>
17#include <dune/common/std/extents.hh>
18#include <dune/common/std/layout_right.hh>
19#include <dune/common/std/no_unique_address.hh>
20#include <dune/common/std/span.hh>
62template <
class Element,
class Extents,
class LayoutPolicy = Std::layout_right,
63 class AccessorPolicy = Std::default_accessor<Element>>
66 static_assert(std::is_object_v<Element>);
67 static_assert(!std::is_abstract_v<Element>);
68 static_assert(!std::is_array_v<Element>);
69 static_assert(std::is_same_v<Element, typename AccessorPolicy::element_type>);
72 using element_type = Element;
73 using extents_type = Extents;
74 using layout_type = LayoutPolicy;
75 using accessor_type = AccessorPolicy;
77 using value_type = std::remove_cv_t<Element>;
78 using mapping_type =
typename layout_type::template mapping<extents_type>;
79 using index_type =
typename extents_type::index_type;
80 using size_type =
typename extents_type::size_type;
81 using rank_type =
typename extents_type::rank_type;
82 using data_handle_type =
typename accessor_type::data_handle_type;
83 using reference =
typename accessor_type::reference;
87 static_assert(std::is_nothrow_move_constructible_v<mapping_type>);
88 static_assert(std::is_nothrow_move_assignable_v<mapping_type>);
89 static_assert(std::is_nothrow_swappable_v<mapping_type>);
92 static_assert(std::is_nothrow_move_constructible_v<accessor_type>);
93 static_assert(std::is_nothrow_move_assignable_v<accessor_type>);
94 static_assert(std::is_nothrow_swappable_v<accessor_type>);
101 template <
class E = extents_type,
class D = data_handle_type,
class M = mapping_type,
class A = accessor_type,
102 std::enable_if_t<(E::rank_dynamic() > 0),
int> = 0,
103 std::enable_if_t<std::is_default_constructible_v<D>,
int> = 0,
104 std::enable_if_t<std::is_default_constructible_v<M>,
int> = 0,
105 std::enable_if_t<std::is_default_constructible_v<A>,
int> = 0>
113 template <
class... IndexTypes,
114 class E = extents_type,
class M = mapping_type,
class A = accessor_type,
115 std::enable_if_t<(
sizeof...(IndexTypes) == E::rank() ||
sizeof...(IndexTypes) == E::rank_dynamic()),
int> = 0,
116 std::enable_if_t<(... && std::is_convertible_v<IndexTypes, index_type>),
int> = 0,
117 std::enable_if_t<(... && std::is_nothrow_constructible_v<index_type, IndexTypes>),
int> = 0,
118 std::enable_if_t<std::is_constructible_v<M, E>,
int> = 0,
119 std::enable_if_t<std::is_default_constructible_v<A>,
int> = 0>
120 explicit constexpr mdspan (data_handle_type p, IndexTypes... exts)
121 :
mdspan(std::move(p), extents_type(index_type(std::move(exts))...))
125 template <
class IndexType, std::size_t N,
126 std::enable_if_t<std::is_convertible_v<const IndexType&, index_type>,
int> = 0,
127 std::enable_if_t<std::is_nothrow_constructible_v<index_type,const IndexType&>,
int> = 0,
128 std::enable_if_t<(N == extents_type::rank_dynamic() || N == extents_type::rank()),
int> = 0>
129 #
if __cpp_conditional_explicit >= 201806L
130 explicit(N != extents_type::rank_dynamic())
133 :
mdspan(std::move(p), extents_type(exts))
137 template <
class IndexType, std::size_t N,
138 std::enable_if_t<std::is_convertible_v<IndexType, index_type>,
int> = 0,
139 std::enable_if_t<(N == extents_type::rank_dynamic() || N == extents_type::rank()),
int> = 0>
140 #
if __cpp_conditional_explicit >= 201806L
141 explicit(N != extents_type::rank_dynamic())
143 constexpr mdspan (data_handle_type p,
const std::array<IndexType,N>& exts)
144 :
mdspan(std::move(p), extents_type(exts))
148 template <
class M = mapping_type,
149 std::enable_if_t<std::is_constructible_v<M, const extents_type&>,
int> = 0>
150 constexpr mdspan (data_handle_type p,
const extents_type& e)
155 template <
class A = accessor_type,
156 std::enable_if_t<std::is_default_constructible_v<A>,
int> = 0>
157 constexpr mdspan (data_handle_type p,
const mapping_type& m)
158 :
mdspan(
std::move(p), m, accessor_type{})
162 constexpr mdspan (data_handle_type p,
const mapping_type& m,
const accessor_type& a)
163 : data_handle_(
std::move(p))
170 template <
class OtherElementType,
class OtherExtends,
class OtherLayoutPolicy,
class OtherAccessor,
171 std::enable_if_t<std::is_constructible_v<mapping_type, const typename OtherElementType::template mapping<OtherExtends>&>,
int> = 0,
172 std::enable_if_t<std::is_constructible_v<accessor_type, const OtherAccessor&>,
int> = 0>
173 #if __cpp_conditional_explicit >= 201806L
174 explicit(!std::is_convertible_v<const typename OtherElementType::template mapping<OtherExtends>&, mapping_type>
175 || !std::is_convertible_v<const OtherAccessor&, accessor_type>)
192 template <
class... Indices,
193 std::enable_if_t<(
sizeof...(Indices) == extents_type::rank()),
int> = 0,
194 std::enable_if_t<(... && std::is_convertible_v<Indices, index_type>),
int> = 0,
195 std::enable_if_t<(... && std::is_nothrow_constructible_v<index_type,Indices>),
int> = 0>
196 constexpr reference
operator() (Indices... indices)
const
198 return accessor_.access(data_handle_, mapping_(index_type(std::move(indices))...));
201#if __cpp_multidimensional_subscript >= 202110L
204 template <
class... Indices,
205 std::enable_if_t<(
sizeof...(Indices) == extents_type::rank()),
int> = 0,
206 std::enable_if_t<(... && std::is_convertible_v<Indices, index_type>),
int> = 0,
207 std::enable_if_t<(... && std::is_nothrow_constructible_v<index_type,Indices>),
int> = 0>
208 constexpr reference
operator[] (Indices... indices)
const
210 return accessor_.access(data_handle_, mapping_(index_type(std::move(indices))...));
217 template <
class Index,
class E = extents_type,
218 std::enable_if_t<std::is_convertible_v<Index,index_type>,
int> = 0,
219 std::enable_if_t<(E::rank() == 1),
int> = 0>
220 constexpr reference
operator[] (Index index)
const
222 return accessor_.access(data_handle_, mapping_(index_type(std::move(index))));
228 template <
class Index,
229 std::enable_if_t<std::is_convertible_v<const Index&, index_type>,
int> = 0,
230 std::enable_if_t<std::is_nothrow_constructible_v<index_type, const Index&>,
int> = 0>
234 return accessor_.access(data_handle_, mapping_(index_type(indices[ii])...)); },
235 std::make_index_sequence<extents_type::rank()>{});
239 template <
class Index,
240 std::enable_if_t<std::is_convertible_v<const Index&, index_type>,
int> = 0,
241 std::enable_if_t<std::is_nothrow_constructible_v<index_type, const Index&>,
int> = 0>
242 constexpr reference
operator[] (
const std::array<Index,extents_type::rank()>& indices)
const
244 return std::apply([&](
auto... ii) -> reference {
245 return accessor_.access(data_handle_, mapping_(index_type(ii)...)); }, indices);
251 constexpr const extents_type&
extents () const noexcept {
return mapping_.extents(); }
254 constexpr const mapping_type&
mapping () const noexcept {
return mapping_; }
257 constexpr const accessor_type&
accessor () const noexcept {
return accessor_; }
260 constexpr const data_handle_type&
data_handle () const noexcept {
return data_handle_; };
267 static constexpr rank_type
rank () noexcept {
return extents_type::rank(); }
270 static constexpr rank_type
rank_dynamic () noexcept {
return extents_type::rank_dynamic(); }
273 static constexpr std::size_t
static_extent (rank_type r)
noexcept {
return extents_type::static_extent(r); }
276 constexpr index_type
extent (rank_type r)
const noexcept {
return extents().extent(r); }
279 constexpr size_type
size () const noexcept
282 for (rank_type r = 0; r <
rank(); ++r)
288 [[nodiscard]]
constexpr bool empty () const noexcept {
return size() == 0; }
303 constexpr bool is_unique ()
const {
return mapping_.is_unique(); }
314 constexpr bool is_strided ()
const {
return mapping_.is_strided(); }
317 constexpr index_type
stride (rank_type r)
const {
return mapping_.stride(r); }
324 swap(x.data_handle_, y.data_handle_);
325 swap(x.mapping_, y.mapping_);
326 swap(x.accessor_, y.accessor_);
331 data_handle_type data_handle_;
332 DUNE_NO_UNIQUE_ADDRESS mapping_type mapping_;
333 DUNE_NO_UNIQUE_ADDRESS accessor_type accessor_;
339template <
class CArray,
340 std::enable_if_t<std::is_array_v<CArray>,
int> = 0,
341 std::enable_if_t<(std::rank_v<CArray> == 1),
int> = 0>
345template <
class Pointer,
346 std::enable_if_t<std::is_pointer_v<std::remove_reference_t<Pointer>>,
int> = 0>
350template <
class ElementType,
class... II,
351 std::enable_if_t<(... && std::is_convertible_v<II,std::size_t>),
int> = 0,
352 std::enable_if_t<(
sizeof...(II) > 0),
int> = 0>
353mdspan (ElementType*, II...)
354 -> mdspan<ElementType,
Std::dextents<std::size_t,
sizeof...(II)>>;
356template <
class ElementType,
class SizeType, std::
size_t N>
358 -> mdspan<ElementType, Std::dextents<std::size_t, N>>;
360template <
class ElementType,
class SizeType, std::
size_t N>
361mdspan (ElementType*,
const std::array<SizeType,N>&)
362 -> mdspan<ElementType, Std::dextents<std::size_t, N>>;
364template <
class ElementType,
class IndexType, std::size_t... exts>
366 -> mdspan<ElementType,
Std::extents<IndexType,exts...>>;
368template <
class ElementType,
class Mapping,
369 class Extents =
typename Mapping::extents_type,
370 class Layout =
typename Mapping::layout_type>
371mdspan (ElementType*,
const Mapping&)
372 -> mdspan<ElementType, Extents, Layout>;
374template <
class Mapping,
class Accessor,
375 class DataHandle =
typename Accessor::data_handle_type,
376 class Element =
typename Accessor::element_type,
377 class Extents =
typename Mapping::extents_type,
378 class Layout =
typename Mapping::layout_type>
379mdspan (
const DataHandle&,
const Mapping&,
const Accessor&)
380 -> mdspan<Element, Extents, Layout, Accessor>;
Multidimensional index space with dynamic and static extents.
Definition: extents.hh:55
A multi-dimensional non-owning array view.
Definition: mdspan.hh:65
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
static constexpr rank_type rank_dynamic() noexcept
Number of dimensions of the tensor.
Definition: mdspan.hh:270
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
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
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
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
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
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
constexpr const extents_type & extents() const noexcept
Number of elements in all dimensions of the tensor,.
Definition: mdspan.hh:251
constexpr index_type extent(rank_type r) const noexcept
Number of elements in the r'th dimension of the tensor.
Definition: mdspan.hh:276
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
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
constexpr size_type size() const noexcept
The number of elements accessible by this multi-dimensional span.
Definition: mdspan.hh:279
constexpr bool empty() const noexcept
Checks if the size of the index space is zero.
Definition: mdspan.hh:288
constexpr const accessor_type & accessor() const noexcept
The accessor policy object.
Definition: mdspan.hh:257
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
static constexpr rank_type rank() noexcept
Number of dimensions of the tensor.
Definition: mdspan.hh:267
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
constexpr const mapping_type & mapping() const noexcept
Index mapping of a layout policy.
Definition: mdspan.hh:254
constexpr const data_handle_type & data_handle() const noexcept
The pointer to the underlying flat sequence.
Definition: mdspan.hh:260
constexpr index_type stride(rank_type r) const
The stride along the specified dimension.
Definition: mdspan.hh:317
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
constexpr mdspan()
Default constructor value-initializes all members.
Definition: mdspan.hh:106
A contiguous sequence of elements with static or dynamic extent.
Definition: span.hh:126
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
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
Namespace for features backported from new C++ standards.
Definition: default_accessor.hh:10