Dune Core Modules (unstable)

mdspan.hh
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 <type_traits>
10#include <utility>
11#if __has_include(<version>)
12 #include <version>
13#endif
14
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/span.hh>
20
21namespace Dune::Std {
22
61template <class Element, class Extents, class LayoutPolicy = Std::layout_right,
62 class AccessorPolicy = Std::default_accessor<Element>>
63class mdspan
64{
65 static_assert(std::is_object_v<Element>);
66 static_assert(!std::is_abstract_v<Element>);
67 static_assert(!std::is_array_v<Element>);
68 static_assert(std::is_same_v<Element, typename AccessorPolicy::element_type>);
69
70public:
71 using element_type = Element;
72 using extents_type = Extents;
73 using layout_type = LayoutPolicy;
74 using accessor_type = AccessorPolicy;
75
76 using value_type = std::remove_cv_t<Element>;
77 using mapping_type = typename layout_type::template mapping<extents_type>;
78 using index_type = typename extents_type::index_type;
79 using size_type = typename extents_type::size_type;
80 using rank_type = typename extents_type::rank_type;
81 using data_handle_type = typename accessor_type::data_handle_type;
82 using reference = typename accessor_type::reference;
83
84private:
85 // [mdspan.layout.reqmts]
86 static_assert(std::is_nothrow_move_constructible_v<mapping_type>);
87 static_assert(std::is_nothrow_move_assignable_v<mapping_type>);
88 static_assert(std::is_nothrow_swappable_v<mapping_type>);
89
90 // [mdspan.accessor.reqmts]
91 static_assert(std::is_nothrow_move_constructible_v<accessor_type>);
92 static_assert(std::is_nothrow_move_assignable_v<accessor_type>);
93 static_assert(std::is_nothrow_swappable_v<accessor_type>);
94
95public:
98
100 template <class E = extents_type, class D = data_handle_type, class M = mapping_type, class A = accessor_type,
101 std::enable_if_t<(E::rank_dynamic() > 0), int> = 0,
102 std::enable_if_t<std::is_default_constructible_v<D>, int> = 0,
103 std::enable_if_t<std::is_default_constructible_v<M>, int> = 0,
104 std::enable_if_t<std::is_default_constructible_v<A>, int> = 0>
105 constexpr mdspan ()
106 : data_handle_{}
107 , mapping_{}
108 , accessor_{}
109 {}
110
112 template <class... IndexTypes,
113 class E = extents_type, class M = mapping_type, class A = accessor_type,
114 std::enable_if_t<(sizeof...(IndexTypes) == E::rank() || sizeof...(IndexTypes) == E::rank_dynamic()), int> = 0,
115 std::enable_if_t<(... && std::is_convertible_v<IndexTypes, index_type>), int> = 0,
116 std::enable_if_t<(... && std::is_nothrow_constructible_v<index_type, IndexTypes>), int> = 0,
117 std::enable_if_t<std::is_constructible_v<M, E>, int> = 0,
118 std::enable_if_t<std::is_default_constructible_v<A>, int> = 0>
119 explicit constexpr mdspan (data_handle_type p, IndexTypes... exts)
120 : mdspan(std::move(p), extents_type(index_type(std::move(exts))...))
121 {}
122
124 template <class IndexType, std::size_t N,
125 std::enable_if_t<std::is_convertible_v<const IndexType&, index_type>, int> = 0,
126 std::enable_if_t<std::is_nothrow_constructible_v<index_type,const IndexType&>, int> = 0,
127 std::enable_if_t<(N == extents_type::rank_dynamic() || N == extents_type::rank()), int> = 0>
128 #if __cpp_conditional_explicit >= 201806L
129 explicit(N != extents_type::rank_dynamic())
130 #endif
131 constexpr mdspan (data_handle_type p, Std::span<IndexType,N> exts)
132 : mdspan(std::move(p), extents_type(exts))
133 {}
134
136 template <class IndexType, std::size_t N,
137 std::enable_if_t<std::is_convertible_v<IndexType, index_type>, int> = 0,
138 std::enable_if_t<(N == extents_type::rank_dynamic() || N == extents_type::rank()), int> = 0>
139 #if __cpp_conditional_explicit >= 201806L
140 explicit(N != extents_type::rank_dynamic())
141 #endif
142 constexpr mdspan (data_handle_type p, const std::array<IndexType,N>& exts)
143 : mdspan(std::move(p), extents_type(exts))
144 {}
145
147 template <class M = mapping_type,
148 std::enable_if_t<std::is_constructible_v<M, const extents_type&>, int> = 0>
149 constexpr mdspan (data_handle_type p, const extents_type& e)
150 : mdspan(std::move(p), mapping_type(e))
151 {}
152
154 template <class A = accessor_type,
155 std::enable_if_t<std::is_default_constructible_v<A>, int> = 0>
156 constexpr mdspan (data_handle_type p, const mapping_type& m)
157 : mdspan(std::move(p), m, accessor_type{})
158 {}
159
161 constexpr mdspan (data_handle_type p, const mapping_type& m, const accessor_type& a)
162 : data_handle_(std::move(p))
163 , mapping_(m)
164 , accessor_(a)
165 {}
166
167
169 template <class OtherElementType, class OtherExtends, class OtherLayoutPolicy, class OtherAccessor,
170 std::enable_if_t<std::is_constructible_v<mapping_type, const typename OtherElementType::template mapping<OtherExtends>&>, int> = 0,
171 std::enable_if_t<std::is_constructible_v<accessor_type, const OtherAccessor&>, int> = 0>
172 #if __cpp_conditional_explicit >= 201806L
173 explicit(!std::is_convertible_v<const typename OtherElementType::template mapping<OtherExtends>&, mapping_type>
174 || !std::is_convertible_v<const OtherAccessor&, accessor_type>)
175 #endif
177 : mdspan(data_handle_type(other.data_handle()), mapping_type(other.mapping()),
178 accessor_type(other.accessor()))
179 {}
180
182
183
186
191 template <class... Indices,
192 std::enable_if_t<(sizeof...(Indices) == extents_type::rank()), int> = 0,
193 std::enable_if_t<(... && std::is_convertible_v<Indices, index_type>), int> = 0,
194 std::enable_if_t<(... && std::is_nothrow_constructible_v<index_type,Indices>), int> = 0>
195 constexpr reference operator() (Indices... indices) const
196 {
197 return accessor_.access(data_handle_, mapping_(index_type(std::move(indices))...));
198 }
199
200#if __cpp_multidimensional_subscript >= 202110L
201
203 template <class... Indices,
204 std::enable_if_t<(sizeof...(Indices) == extents_type::rank()), int> = 0,
205 std::enable_if_t<(... && std::is_convertible_v<Indices, index_type>), int> = 0,
206 std::enable_if_t<(... && std::is_nothrow_constructible_v<index_type,Indices>), int> = 0>
207 constexpr reference operator[] (Indices... indices) const
208 {
209 return accessor_.access(data_handle_, mapping_(index_type(std::move(indices))...));
210 }
211
212#else // __cpp_multidimensional_subscript
213
216 template <class Index, class E = extents_type,
217 std::enable_if_t<std::is_convertible_v<Index,index_type>, int> = 0,
218 std::enable_if_t<(E::rank() == 1), int> = 0>
219 constexpr reference operator[] (Index index) const
220 {
221 return accessor_.access(data_handle_, mapping_(index_type(std::move(index))));
222 }
223
224#endif // __cpp_multidimensional_subscript
225
227 template <class Index,
228 std::enable_if_t<std::is_convertible_v<const Index&, index_type>, int> = 0,
229 std::enable_if_t<std::is_nothrow_constructible_v<index_type, const Index&>, int> = 0>
230 constexpr reference operator[] (Std::span<Index,extents_type::rank()> indices) const
231 {
232 return unpackIntegerSequence([&](auto... ii) -> reference {
233 return accessor_.access(data_handle_, mapping_(index_type(indices[ii])...)); },
234 std::make_index_sequence<extents_type::rank()>{});
235 }
236
238 template <class Index,
239 std::enable_if_t<std::is_convertible_v<const Index&, index_type>, int> = 0,
240 std::enable_if_t<std::is_nothrow_constructible_v<index_type, const Index&>, int> = 0>
241 constexpr reference operator[] (const std::array<Index,extents_type::rank()>& indices) const
242 {
243 return std::apply([&](auto... ii) -> reference {
244 return accessor_.access(data_handle_, mapping_(index_type(ii)...)); }, indices);
245 }
246
248
250 constexpr const extents_type& extents () const noexcept { return mapping_.extents(); }
251
253 constexpr const mapping_type& mapping () const noexcept { return mapping_; }
254
256 constexpr const accessor_type& accessor () const noexcept { return accessor_; }
257
259 constexpr const data_handle_type& data_handle () const noexcept { return data_handle_; };
260
261
264
266 static constexpr rank_type rank () noexcept { return extents_type::rank(); }
267
269 static constexpr rank_type rank_dynamic () noexcept { return extents_type::rank_dynamic(); }
270
272 static constexpr std::size_t static_extent (rank_type r) noexcept { return extents_type::static_extent(r); }
273
275 constexpr index_type extent (rank_type r) const noexcept { return extents().extent(r); }
276
278 constexpr size_type size () const noexcept
279 {
280 size_type s = 1;
281 for (rank_type r = 0; r < rank(); ++r)
282 s *= extent(r);
283 return s;
284 }
285
287 [[nodiscard]] constexpr bool empty () const noexcept { return size() == 0; }
288
290
291
293 static constexpr bool is_always_unique () { return mapping_type::is_always_unique(); }
294
296 static constexpr bool is_always_exhaustive () { return mapping_type::is_always_exhaustive(); }
297
299 static constexpr bool is_always_strided () { return mapping_type::is_always_strided(); }
300
302 constexpr bool is_unique () const { return mapping_.is_unique(); }
303
306 constexpr bool is_exhaustive () const { return mapping_.is_exhaustive(); }
307
313 constexpr bool is_strided () const { return mapping_.is_strided(); }
314
316 constexpr index_type stride (rank_type r) const { return mapping_.stride(r); }
317
318
320 friend constexpr void swap (mdspan& x, mdspan& y) noexcept
321 {
322 using std::swap;
323 swap(x.data_handle_, y.data_handle_);
324 swap(x.mapping_, y.mapping_);
325 swap(x.accessor_, y.accessor_);
326 }
327
328
329private:
330 data_handle_type data_handle_;
331 [[no_unique_address]] mapping_type mapping_;
332 [[no_unique_address]] accessor_type accessor_;
333};
334
335// deduction guides
336// @{
337
338template <class CArray,
339 std::enable_if_t<std::is_array_v<CArray>, int> = 0,
340 std::enable_if_t<(std::rank_v<CArray> == 1), int> = 0>
341mdspan (CArray&)
342 -> mdspan<std::remove_all_extents_t<CArray>, Std::extents<std::size_t, std::extent_v<CArray,0>>>;
343
344template <class Pointer,
345 std::enable_if_t<std::is_pointer_v<std::remove_reference_t<Pointer>>, int> = 0>
346mdspan (Pointer&&)
347 -> mdspan<std::remove_pointer_t<std::remove_reference_t<Pointer>>, Std::extents<std::size_t>>;
348
349template <class ElementType, class... II,
350 std::enable_if_t<(... && std::is_convertible_v<II,std::size_t>), int> = 0,
351 std::enable_if_t<(sizeof...(II) > 0), int> = 0>
352mdspan (ElementType*, II...)
353 -> mdspan<ElementType, Std::dextents<std::size_t, sizeof...(II)>>;
354
355template <class ElementType, class SizeType, std::size_t N>
356mdspan (ElementType*, Std::span<SizeType,N>&)
357 -> mdspan<ElementType, Std::dextents<std::size_t, N>>;
358
359template <class ElementType, class SizeType, std::size_t N>
360mdspan (ElementType*, const std::array<SizeType,N>&)
361 -> mdspan<ElementType, Std::dextents<std::size_t, N>>;
362
363template <class ElementType, class IndexType, std::size_t... exts>
364mdspan (ElementType*, const Std::extents<IndexType,exts...>&)
365 -> mdspan<ElementType, Std::extents<IndexType,exts...>>;
366
367template <class ElementType, class Mapping,
368 class Extents = typename Mapping::extents_type,
369 class Layout = typename Mapping::layout_type>
370mdspan (ElementType*, const Mapping&)
371 -> mdspan<ElementType, Extents, Layout>;
372
373template <class Mapping, class Accessor,
374 class DataHandle = typename Accessor::data_handle_type,
375 class Element = typename Accessor::element_type,
376 class Extents = typename Mapping::extents_type,
377 class Layout = typename Mapping::layout_type>
378mdspan (const DataHandle&, const Mapping&, const Accessor&)
379 -> mdspan<Element, Extents, Layout, Accessor>;
380
381// @}
382
383} // end namespace Dune::Std
384
385#endif // DUNE_COMMON_STD_MDSPAN_HH
Multidimensional index space with dynamic and static extents.
Definition: extents.hh:54
A multi-dimensional non-owning array view.
Definition: mdspan.hh:64
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:161
static constexpr rank_type rank_dynamic() noexcept
Number of dimensions of the tensor.
Definition: mdspan.hh:269
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:293
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:313
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:156
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:149
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:296
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:219
constexpr const extents_type & extents() const noexcept
Number of elements in all dimensions of the tensor,.
Definition: mdspan.hh:250
constexpr index_type extent(rank_type r) const noexcept
Number of elements in the r'th dimension of the tensor.
Definition: mdspan.hh:275
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:320
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:299
constexpr size_type size() const noexcept
The number of elements accessible by this multi-dimensional span.
Definition: mdspan.hh:278
constexpr bool empty() const noexcept
Checks if the size of the index space is zero.
Definition: mdspan.hh:287
constexpr const accessor_type & accessor() const noexcept
The accessor policy object.
Definition: mdspan.hh:256
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:306
static constexpr rank_type rank() noexcept
Number of dimensions of the tensor.
Definition: mdspan.hh:266
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:272
constexpr const mapping_type & mapping() const noexcept
Index mapping of a layout policy.
Definition: mdspan.hh:253
constexpr const data_handle_type & data_handle() const noexcept
The pointer to the underlying flat sequence.
Definition: mdspan.hh:259
constexpr index_type stride(rank_type r) const
The stride along the specified dimension.
Definition: mdspan.hh:316
constexpr bool is_unique() const
Return true only if for every i and j where (i != j || ...) => mapping(i...) != mapping(j....
Definition: mdspan.hh:302
constexpr mdspan()
Default constructor value-initializes all members.
Definition: mdspan.hh:105
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:259
Namespace for features backported from new C++ standards.
Definition: default_accessor.hh:10
STL namespace.
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Jul 15, 22:36, 2024)