dune-common 2.12-git
Loading...
Searching...
No Matches
mdspan.hh
Go to the documentation of this file.
1// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2// vi: set et ts=4 sw=2 sts=2:
3// SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root
4// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception
5#ifndef DUNE_COMMON_STD_MDSPAN_HH
6#define DUNE_COMMON_STD_MDSPAN_HH
7
8#include <array>
9#include <span>
10#include <stdexcept>
11#include <type_traits>
12#include <utility>
13#if __has_include(<version>)
14 #include <version>
15#endif
16
23
24namespace Dune::Std {
25
64template <class Element, class Extents, class LayoutPolicy = Std::layout_right,
65 class AccessorPolicy = Std::default_accessor<Element>>
66class mdspan
67{
68 static_assert(std::is_object_v<Element>);
69 static_assert(!std::is_abstract_v<Element>);
70 static_assert(!std::is_array_v<Element>);
71 static_assert(std::is_same_v<Element, typename AccessorPolicy::element_type>);
72
73public:
74 using element_type = Element;
75 using extents_type = Extents;
76 using layout_type = LayoutPolicy;
77 using accessor_type = AccessorPolicy;
78
80 using mapping_type = typename layout_type::template mapping<extents_type>;
81 using index_type = typename extents_type::index_type;
82 using size_type = typename extents_type::size_type;
83 using rank_type = typename extents_type::rank_type;
84 using data_handle_type = typename accessor_type::data_handle_type;
85 using reference = typename accessor_type::reference;
86
87private:
88 // [mdspan.layout.reqmts]
89 static_assert(std::is_nothrow_move_constructible_v<mapping_type>);
90 static_assert(std::is_nothrow_move_assignable_v<mapping_type>);
91 static_assert(std::is_nothrow_swappable_v<mapping_type>);
92
93 // [mdspan.accessor.reqmts]
94 static_assert(std::is_nothrow_move_constructible_v<accessor_type>);
95 static_assert(std::is_nothrow_move_assignable_v<accessor_type>);
96 static_assert(std::is_nothrow_swappable_v<accessor_type>);
97
98public:
101
103 template <class E = extents_type, class D = data_handle_type, class M = mapping_type, class A = accessor_type,
104 std::enable_if_t<(E::rank_dynamic() > 0), int> = 0,
105 std::enable_if_t<std::is_default_constructible_v<D>, int> = 0,
106 std::enable_if_t<std::is_default_constructible_v<M>, int> = 0,
107 std::enable_if_t<std::is_default_constructible_v<A>, int> = 0>
108 constexpr mdspan ()
109 : data_handle_{}
110 , mapping_{}
111 , accessor_{}
112 {}
113
115 template <class... IndexTypes,
116 class E = extents_type, class M = mapping_type, class A = accessor_type,
117 std::enable_if_t<(sizeof...(IndexTypes) == E::rank() || sizeof...(IndexTypes) == E::rank_dynamic()), int> = 0,
118 std::enable_if_t<(... && std::is_convertible_v<IndexTypes, index_type>), int> = 0,
119 std::enable_if_t<(... && std::is_nothrow_constructible_v<index_type, IndexTypes>), int> = 0,
120 std::enable_if_t<std::is_constructible_v<M, E>, int> = 0,
121 std::enable_if_t<std::is_default_constructible_v<A>, int> = 0>
122 explicit constexpr mdspan (data_handle_type p, IndexTypes... exts)
123 : mdspan(std::move(p), extents_type(index_type(std::move(exts))...))
124 {}
125
127 template <class IndexType, std::size_t N,
130 std::enable_if_t<(N == extents_type::rank_dynamic() || N == extents_type::rank()), int> = 0>
131 #if __cpp_conditional_explicit >= 201806L
132 explicit(N != extents_type::rank_dynamic())
133 #endif
135 : mdspan(std::move(p), extents_type(exts))
136 {}
137
139 template <class IndexType, std::size_t N,
141 std::enable_if_t<(N == extents_type::rank_dynamic() || N == extents_type::rank()), int> = 0>
142 #if __cpp_conditional_explicit >= 201806L
143 explicit(N != extents_type::rank_dynamic())
144 #endif
146 : mdspan(std::move(p), extents_type(exts))
147 {}
148
150 template <class M = mapping_type,
152 constexpr mdspan (data_handle_type p, const extents_type& e)
153 : mdspan(std::move(p), mapping_type(e))
154 {}
155
157 template <class A = accessor_type,
159 constexpr mdspan (data_handle_type p, const mapping_type& m)
160 : mdspan(std::move(p), m, accessor_type{})
161 {}
162
164 constexpr mdspan (data_handle_type p, const mapping_type& m, const accessor_type& a)
165 : data_handle_(std::move(p))
166 , mapping_(m)
167 , accessor_(a)
168 {}
169
170
172 template <class OtherElementType, class OtherExtends, class OtherLayoutPolicy, class OtherAccessor,
175 #if __cpp_conditional_explicit >= 201806L
176 explicit(!std::is_convertible_v<const typename OtherLayoutPolicy::template mapping<OtherExtends>&, mapping_type>
177 || !std::is_convertible_v<const OtherAccessor&, accessor_type>)
178 #endif
183
185
186
189
194 template <class... Indices,
195 std::enable_if_t<(sizeof...(Indices) == extents_type::rank()), int> = 0,
196 std::enable_if_t<(... && std::is_convertible_v<Indices, index_type>), int> = 0,
197 std::enable_if_t<(... && std::is_nothrow_constructible_v<index_type,Indices>), int> = 0>
198 constexpr reference operator() (Indices... indices) const
199 {
200 return accessor_.access(data_handle_, mapping_(index_type(std::move(indices))...));
201 }
202
203#if __cpp_multidimensional_subscript >= 202110L
204
206 template <class... Indices,
207 std::enable_if_t<(sizeof...(Indices) == extents_type::rank()), int> = 0,
208 std::enable_if_t<(... && std::is_convertible_v<Indices, index_type>), int> = 0,
209 std::enable_if_t<(... && std::is_nothrow_constructible_v<index_type,Indices>), int> = 0>
210 constexpr reference operator[] (Indices... indices) const
211 {
212 return accessor_.access(data_handle_, mapping_(index_type(std::move(indices))...));
213 }
214
215#else // __cpp_multidimensional_subscript
216
219 template <class Index, class E = extents_type,
221 std::enable_if_t<(E::rank() == 1), int> = 0>
222 constexpr reference operator[] (Index index) const
223 {
224 return accessor_.access(data_handle_, mapping_(index_type(std::move(index))));
225 }
226
227#endif // __cpp_multidimensional_subscript
228
230 template <class Index,
233 constexpr reference operator[] (std::span<Index,extents_type::rank()> indices) const
234 {
235 return unpackIntegerSequence([&](auto... ii) -> reference {
236 return accessor_.access(data_handle_, mapping_(index_type(indices[ii])...)); },
237 std::make_index_sequence<extents_type::rank()>{});
238 }
239
241 template <class Index,
244 constexpr reference operator[] (const std::array<Index,extents_type::rank()>& indices) const
245 {
246 return std::apply([&](auto... ii) -> reference {
247 return accessor_.access(data_handle_, mapping_(index_type(ii)...)); }, indices);
248 }
249
251 template <class... Indices,
252 std::enable_if_t<(sizeof...(Indices) == extents_type::rank()), int> = 0,
253 std::enable_if_t<(... && std::is_convertible_v<Indices, index_type>), int> = 0,
254 std::enable_if_t<(... && std::is_nothrow_constructible_v<index_type,Indices>), int> = 0>
255 constexpr reference at (Indices... indices) const
256 {
257 if (!Impl::indexInIndexSpace(*this, indices...))
258 throw std::out_of_range("mdspan index out of range");
259 return accessor_.access(data_handle_, mapping_(index_type(std::move(indices))...));
260 }
261
263 template <class Index,
266 constexpr reference at (std::span<Index,extents_type::rank()> indices) const
267 {
268 if (!Impl::indexInIndexSpace(*this, indices))
269 throw std::out_of_range("mdspan index out of range");
270 return unpackIntegerSequence([&](auto... ii) -> reference {
271 return accessor_.access(data_handle_, mapping_(index_type(indices[ii])...)); },
272 std::make_index_sequence<extents_type::rank()>{});
273 }
274
276 template <class Index,
279 constexpr reference at (const std::array<Index,extents_type::rank()>& indices) const
280 {
281 if (!Impl::indexInIndexSpace(*this, indices))
282 throw std::out_of_range("mdspan index out of range");
283 return std::apply([&](auto... ii) -> reference {
284 return accessor_.access(data_handle_, mapping_(index_type(ii)...)); }, indices);
285 }
286
288
290 constexpr const extents_type& extents () const noexcept { return mapping_.extents(); }
291
293 constexpr const mapping_type& mapping () const noexcept { return mapping_; }
294
296 constexpr const accessor_type& accessor () const noexcept { return accessor_; }
297
299 constexpr const data_handle_type& data_handle () const noexcept { return data_handle_; };
300
301
304
306 static constexpr rank_type rank () noexcept { return extents_type::rank(); }
307
309 static constexpr rank_type rank_dynamic () noexcept { return extents_type::rank_dynamic(); }
310
312 static constexpr std::size_t static_extent (rank_type r) noexcept { return extents_type::static_extent(r); }
313
315 constexpr index_type extent (rank_type r) const noexcept { return extents().extent(r); }
316
318 constexpr size_type size () const noexcept
319 {
320 size_type s = 1;
321 for (rank_type r = 0; r < rank(); ++r)
322 s *= extent(r);
323 return s;
324 }
325
327 [[nodiscard]] constexpr bool empty () const noexcept { return size() == 0; }
328
330
331
333 static constexpr bool is_always_unique () { return mapping_type::is_always_unique(); }
334
336 static constexpr bool is_always_exhaustive () { return mapping_type::is_always_exhaustive(); }
337
339 static constexpr bool is_always_strided () { return mapping_type::is_always_strided(); }
340
342 constexpr bool is_unique () const { return mapping_.is_unique(); }
343
346 constexpr bool is_exhaustive () const { return mapping_.is_exhaustive(); }
347
353 constexpr bool is_strided () const { return mapping_.is_strided(); }
354
356 constexpr index_type stride (rank_type r) const { return mapping_.stride(r); }
357
358
360 friend constexpr void swap (mdspan& x, mdspan& y) noexcept
361 {
362 using std::swap;
363 swap(x.data_handle_, y.data_handle_);
364 swap(x.mapping_, y.mapping_);
365 swap(x.accessor_, y.accessor_);
366 }
367
368
369private:
370 data_handle_type data_handle_;
373};
374
375// deduction guides
376// @{
377
378template <class CArray,
380 std::enable_if_t<(std::rank_v<CArray> == 1), int> = 0>
381mdspan (CArray&)
383
384template <class Pointer,
386mdspan (Pointer&&)
388
389template <class ElementType, class... II,
390 std::enable_if_t<(... && std::is_convertible_v<II,std::size_t>), int> = 0,
391 std::enable_if_t<(sizeof...(II) > 0), int> = 0>
392mdspan (ElementType*, II...)
393 -> mdspan<ElementType, Std::dextents<std::size_t, sizeof...(II)>>;
394
395template <class ElementType, class SizeType, std::size_t N>
398
399template <class ElementType, class SizeType, std::size_t N>
400mdspan (ElementType*, const std::array<SizeType,N>&)
402
403template <class ElementType, class IndexType, std::size_t... exts>
405 -> mdspan<ElementType, Std::extents<IndexType,exts...>>;
406
407template <class ElementType, class Mapping,
408 class Extents = typename Mapping::extents_type,
409 class Layout = typename Mapping::layout_type>
410mdspan (ElementType*, const Mapping&)
412
413template <class Mapping, class Accessor,
414 class DataHandle = typename Accessor::data_handle_type,
415 class Element = typename Accessor::element_type,
416 class Extents = typename Mapping::extents_type,
417 class Layout = typename Mapping::layout_type>
418mdspan (const DataHandle&, const Mapping&, const Accessor&)
420
421// @}
422
423} // end namespace Dune::Std
424
425#endif // DUNE_COMMON_STD_MDSPAN_HH
#define DUNE_NO_UNIQUE_ADDRESS
Definition no_unique_address.hh:24
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
STL namespace.
Namespace for features backported from new C++ standards.
Definition algorithm.hh:19
Multidimensional index space with dynamic and static extents.
Definition extents.hh:55
A multi-dimensional non-owning array view.
Definition mdspan.hh:67
typename accessor_type::reference reference
Definition mdspan.hh:85
Element element_type
Definition mdspan.hh:74
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:164
constexpr reference at(const std::array< Index, extents_type::rank()> &indices) const
Access specified element with bounds checking.
Definition mdspan.hh:279
Extents extents_type
Definition mdspan.hh:75
static constexpr rank_type rank_dynamic() noexcept
Number of dimensions of the tensor.
Definition mdspan.hh:309
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:333
typename extents_type::index_type index_type
Definition mdspan.hh:81
LayoutPolicy layout_type
Definition mdspan.hh:76
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:353
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:159
typename extents_type::rank_type rank_type
Definition mdspan.hh:83
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:152
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:336
constexpr reference at(std::span< Index, extents_type::rank()> indices) const
Access specified element with bounds checking.
Definition mdspan.hh:266
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:222
constexpr const extents_type & extents() const noexcept
Number of elements in all dimensions of the tensor,.
Definition mdspan.hh:290
constexpr index_type extent(rank_type r) const noexcept
Number of elements in the r'th dimension of the tensor.
Definition mdspan.hh:315
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:360
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:339
constexpr size_type size() const noexcept
The number of elements accessible by this multi-dimensional span.
Definition mdspan.hh:318
typename accessor_type::data_handle_type data_handle_type
Definition mdspan.hh:84
constexpr bool empty() const noexcept
Checks if the size of the index space is zero.
Definition mdspan.hh:327
constexpr reference at(Indices... indices) const
Access specified element with bounds checking.
Definition mdspan.hh:255
constexpr const accessor_type & accessor() const noexcept
The accessor policy object.
Definition mdspan.hh:296
AccessorPolicy accessor_type
Definition mdspan.hh:77
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:346
static constexpr rank_type rank() noexcept
Number of dimensions of the tensor.
Definition mdspan.hh:306
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:312
constexpr const mapping_type & mapping() const noexcept
Index mapping of a layout policy.
Definition mdspan.hh:293
constexpr const data_handle_type & data_handle() const noexcept
The pointer to the underlying flat sequence.
Definition mdspan.hh:299
constexpr index_type stride(rank_type r) const
The stride along the specified dimension.
Definition mdspan.hh:356
constexpr bool is_unique() const
Return true only if for every i and j where (i != j || ...) => mapping(i...) != mapping(j....
Definition mdspan.hh:342
constexpr mdspan()
Default constructor value-initializes all members.
Definition mdspan.hh:108
typename extents_type::size_type size_type
Definition mdspan.hh:82
typename layout_type::template mapping< extents_type > mapping_type
Definition mdspan.hh:80
T apply(T... args)
T swap(T... args)