tetl 0.1.0
Embedded Template Library
Loading...
Searching...
No Matches
mdspan.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: BSL-1.0
2// SPDX-FileCopyrightText: Copyright (C) 2019 Tobias Hienzsch
3
4#ifndef TETL_MDSPAN_MDSPAN_HPP
5#define TETL_MDSPAN_MDSPAN_HPP
6
7#include <etl/_config/all.hpp>
8
9#include <etl/_array/array.hpp>
10#include <etl/_contracts/check.hpp>
11#include <etl/_mdspan/default_accessor.hpp>
12#include <etl/_mdspan/layout_left.hpp>
13#include <etl/_mdspan/layout_right.hpp>
14#include <etl/_span/span.hpp>
15#include <etl/_type_traits/extent.hpp>
16#include <etl/_type_traits/is_array.hpp>
17#include <etl/_type_traits/is_constructible.hpp>
18#include <etl/_type_traits/is_convertible.hpp>
19#include <etl/_type_traits/is_default_constructible.hpp>
20#include <etl/_type_traits/is_nothrow_constructible.hpp>
21#include <etl/_type_traits/is_object.hpp>
22#include <etl/_type_traits/is_pointer.hpp>
23#include <etl/_type_traits/rank.hpp>
24#include <etl/_type_traits/remove_all_extents.hpp>
25#include <etl/_type_traits/remove_cv.hpp>
26#include <etl/_type_traits/remove_pointer.hpp>
27#include <etl/_type_traits/remove_reference.hpp>
28#include <etl/_utility/index_sequence.hpp>
29#include <etl/_utility/move.hpp>
30
31namespace etl {
32
33/// \ingroup mdspan
34template <
35 typename ElementType,
36 typename Extents,
37 typename LayoutPolicy = layout_right,
38 typename AccessorPolicy = default_accessor<ElementType>
39>
40struct mdspan {
41 using extents_type = Extents;
42 using layout_type = LayoutPolicy;
43 using accessor_type = AccessorPolicy;
44 using mapping_type = typename layout_type::template mapping<extents_type>;
45 using element_type = ElementType;
46 using value_type = remove_cv_t<element_type>;
47 using index_type = typename extents_type::index_type;
48 using size_type = typename extents_type::size_type;
49 using rank_type = typename extents_type::rank_type;
50 using data_handle_type = typename accessor_type::data_handle_type;
51 using reference = typename accessor_type::reference;
52
53 [[nodiscard]] static constexpr auto rank() noexcept -> rank_type
54 {
55 return extents_type::rank();
56 }
57
58 [[nodiscard]] static constexpr auto rank_dynamic() noexcept -> rank_type
59 {
60 return extents_type::rank_dynamic();
61 }
62
63 [[nodiscard]] static constexpr auto static_extent(rank_type r) noexcept -> size_t
64 {
65 return Extents::static_extent(r);
66 }
67
68 [[nodiscard]] constexpr auto extent(rank_type r) const noexcept -> index_type
69 {
70 return extents().extent(r);
71 }
72
73 // Constructor (1)
74 constexpr mdspan()
75 requires((rank_dynamic() > 0)
76 and is_default_constructible_v<data_handle_type>
77 and is_default_constructible_v<mapping_type>
78 and is_default_constructible_v<accessor_type>)
79 : _ptr()
80 , _map()
81 , _acc()
82 {
83 }
84
85 // Constructor (2)
86 template <typename... OtherIndexTypes>
87 requires((is_convertible_v<OtherIndexTypes, index_type> and ...)
88 and (is_nothrow_constructible_v<index_type, OtherIndexTypes> and ...)
89 and ((sizeof...(OtherIndexTypes) == rank()) || (sizeof...(OtherIndexTypes) == rank_dynamic()))
90 and is_constructible_v<mapping_type, extents_type>
91 and is_default_constructible_v<accessor_type>)
92 explicit constexpr mdspan(data_handle_type ptr, OtherIndexTypes... exts)
93 : _ptr(etl::move(ptr))
94 , _map(extents_type(static_cast<index_type>(etl::move(exts))...))
95 {
96 }
97
98 // Constructor (3)
99 template <typename OtherIndexType, size_t N>
100 requires(is_convertible_v<OtherIndexType const&, index_type>
101 and is_nothrow_constructible_v<index_type, OtherIndexType const&>
102 and (N == rank() or N == rank_dynamic())
103 and is_constructible_v<mapping_type, extents_type>
104 and is_default_constructible_v<accessor_type>)
105 explicit(N != rank_dynamic()) constexpr mdspan(data_handle_type p, span<OtherIndexType, N> exts)
106 : _ptr(etl::move(p))
107 , _map(extents_type(exts))
108 , _acc()
109 {
110 }
111
112 // Constructor (4)
113 template <typename OtherIndexType, size_t N>
114 requires(is_convertible_v<OtherIndexType const&, index_type>
115 and is_nothrow_constructible_v<index_type, OtherIndexType const&>
116 and (N == rank() or N == rank_dynamic())
117 and is_constructible_v<mapping_type, extents_type>
118 and is_default_constructible_v<accessor_type>)
119 explicit(N != rank_dynamic()) constexpr mdspan(data_handle_type p, array<OtherIndexType, N> const& exts)
120 : _ptr(etl::move(p))
121 , _map(extents_type(exts))
122 , _acc()
123 {
124 }
125
126 // Constructor (5)
127 constexpr mdspan(data_handle_type ptr, extents_type const& ext)
128 requires(is_constructible_v<mapping_type, mapping_type const&> and is_default_constructible_v<accessor_type>)
129 : _ptr(etl::move(ptr))
130 , _map(ext)
131 {
132 }
133
134 // Constructor (6)
135 constexpr mdspan(data_handle_type ptr, mapping_type const& m)
136 requires(is_default_constructible_v<accessor_type>)
137 : _ptr(etl::move(ptr))
138 , _map(m)
139 {
140 }
141
142 // Constructor (7)
143 constexpr mdspan(data_handle_type ptr, mapping_type const& m, accessor_type const& a)
144 : _ptr(etl::move(ptr))
145 , _map(m)
146 , _acc(a)
147 {
148 }
149
150 template <typename OtherElement, typename OtherExtents, typename OtherLayout, typename OtherAccessor>
151 requires((is_constructible_v<mapping_type, typename OtherLayout::template mapping<OtherExtents> const&>
152 and is_constructible_v<accessor_type, OtherAccessor const&>))
153 explicit((
154 not is_convertible_v<typename OtherLayout::template mapping<OtherExtents> const&, mapping_type>
156 )) constexpr mdspan(mdspan<OtherElement, OtherExtents, OtherLayout, OtherAccessor> const& other)
157 : _ptr(other.data_handle())
158 , _map(other.mapping())
159 , _acc(other.accessor())
160 {
161 static_assert(is_constructible_v<extents_type, OtherExtents>);
162 static_assert(is_constructible_v<data_handle_type, typename OtherAccessor::data_handle_type const&>);
163 }
164
165 constexpr mdspan(mdspan const& rhs) = default;
166 constexpr mdspan(mdspan&& rhs) = default; // NOLINT(performance-noexcept-move-constructor)
167
168 template <typename... OtherIndexTypes>
169 requires(
170 (is_convertible_v<OtherIndexTypes, index_type> && ...)
171 and (is_nothrow_constructible_v<index_type, OtherIndexTypes> && ...)
172 and sizeof...(OtherIndexTypes) == rank()
173 )
174 [[nodiscard]] constexpr auto operator()(OtherIndexTypes... indices) const -> reference
175 {
176 auto const idx = static_cast<etl::size_t>(_map(extents_type::index_cast(etl::move(indices))...));
177 return _acc.access(_ptr, idx);
178 }
179
180#if defined(__cpp_multidimensional_subscript)
181 template <typename... OtherIndexTypes>
182 requires(
183 (is_convertible_v<OtherIndexTypes, index_type> && ...)
184 and (is_nothrow_constructible_v<index_type, OtherIndexTypes> && ...)
185 and sizeof...(OtherIndexTypes) == rank()
186 )
187 [[nodiscard]] constexpr auto operator[](OtherIndexTypes... indices) const -> reference
188 {
189 return (*this)(etl::move(indices)...);
190 }
191#endif
192
193 template <typename OtherIndexType>
194 requires(
195 is_convertible_v<OtherIndexType const&, index_type>
196 and is_nothrow_constructible_v<index_type, OtherIndexType const&>
197 )
198 [[nodiscard]] constexpr auto operator[](span<OtherIndexType, rank()> indices) const -> reference
199 {
200 return [&]<size_t... Is>(index_sequence<Is...> /*seq*/) -> reference {
201 return (*this)(indices[Is]...);
202 }(make_index_sequence<rank()>{});
203 }
204
205 template <typename OtherIndexType>
206 requires(
207 is_convertible_v<OtherIndexType const&, index_type>
208 and is_nothrow_constructible_v<index_type, OtherIndexType const&>
209 )
210 [[nodiscard]] constexpr auto operator[](array<OtherIndexType, rank()> const& indices) const -> reference
211 {
212 return (*this)[etl::span{indices}];
213 }
214
215 [[nodiscard]] constexpr auto data_handle() const noexcept -> data_handle_type const&
216 {
217 return _ptr;
218 }
219 [[nodiscard]] constexpr auto mapping() const noexcept -> mapping_type const&
220 {
221 return _map;
222 }
223 [[nodiscard]] constexpr auto accessor() const noexcept -> accessor_type const&
224 {
225 return _acc;
226 }
227
228 [[nodiscard]] constexpr auto extents() const noexcept -> extents_type const&
229 {
230 return _map.extents();
231 }
232 [[nodiscard]] constexpr auto stride(rank_type r) const -> index_type
233 {
234 return _map.stride(r);
235 }
236 [[nodiscard]] constexpr auto empty() const noexcept -> bool
237 {
238 return size() == size_type{};
239 }
240 [[nodiscard]] constexpr auto size() const noexcept -> size_type
241 {
242 return static_cast<size_type>(extents().fwd_prod_of_extents(rank()));
243 }
244
245 [[nodiscard]] constexpr auto is_unique() const -> bool
246 {
247 return _map.is_unique();
248 }
249 [[nodiscard]] constexpr auto is_exhaustive() const -> bool
250 {
251 return _map.is_exhaustive();
252 }
253 [[nodiscard]] constexpr auto is_strided() const -> bool
254 {
255 return _map.is_strided();
256 }
257
258 [[nodiscard]] static constexpr auto is_always_unique() -> bool
259 {
260 return mapping_type::is_always_unique();
261 }
262 [[nodiscard]] static constexpr auto is_always_exhaustive() -> bool
263 {
264 return mapping_type::is_always_exhaustive();
265 }
266 [[nodiscard]] static constexpr auto is_always_strided() -> bool
267 {
268 return mapping_type::is_always_strided();
269 }
270
271private:
272 TETL_NO_UNIQUE_ADDRESS data_handle_type _ptr; // NOLINT(modernize-use-default-member-init)
273 TETL_NO_UNIQUE_ADDRESS mapping_type _map; // NOLINT(modernize-use-default-member-init)
274 TETL_NO_UNIQUE_ADDRESS accessor_type _acc; // NOLINT(modernize-use-default-member-init)
275};
276
277template <typename CArray>
278 requires(is_array_v<CArray> && rank_v<CArray> == 1)
279mdspan(CArray&) -> mdspan<remove_all_extents_t<CArray>, extents<size_t, extent_v<CArray, 0>>>;
280
281template <typename Pointer>
282 requires(is_pointer_v<remove_reference_t<Pointer>>)
283mdspan(Pointer&&) -> mdspan<remove_pointer_t<remove_reference_t<Pointer>>, extents<size_t>>;
284
285template <typename ElementType, typename... Integrals>
286 requires((is_convertible_v<Integrals, size_t> && ...) && sizeof...(Integrals) > 0)
287explicit mdspan(ElementType*, Integrals...) -> mdspan<ElementType, dextents<size_t, sizeof...(Integrals)>>;
288
289template <typename ElementType, typename IndexType, size_t... ExtentsPack>
290mdspan(ElementType*, extents<IndexType, ExtentsPack...> const&)
291 -> mdspan<ElementType, extents<IndexType, ExtentsPack...>>;
292
293template <typename ElementType, typename MappingType>
294mdspan(ElementType*, MappingType const&)
295 -> mdspan<ElementType, typename MappingType::extents_type, typename MappingType::layout_type>;
296
297template <typename MappingType, typename AccessorType>
298mdspan(typename AccessorType::data_handle_type const&, MappingType const&, AccessorType const&) -> mdspan<
299 typename AccessorType::element_type,
300 typename MappingType::extents_type,
301 typename MappingType::layout_type,
302 AccessorType
303>;
304
305template <typename ElementType, typename Extents, typename LayoutPolicy, typename Container>
306struct mdarray;
307
308template <class ElementType, class Extents, class Layout, class Container>
309mdspan(mdarray<ElementType, Extents, Layout, Container>) -> mdspan<
310 typename decltype(declval<mdarray<ElementType, Extents, Layout, Container>>().to_mdspan())::element_type,
311 typename decltype(declval<mdarray<ElementType, Extents, Layout, Container>>().to_mdspan())::extens_type,
312 typename decltype(declval<mdarray<ElementType, Extents, Layout, Container>>().to_mdspan())::layout_type,
313 typename decltype(declval<mdarray<ElementType, Extents, Layout, Container>>().to_mdspan())::accessor_type
314>;
315
316} // namespace etl
317
318#endif // TETL_MDSPAN_MDSPAN_HPP
Definition adjacent_find.hpp:9
mdspan(typename AccessorType::data_handle_type const &, MappingType const &, AccessorType const &) -> mdspan< typename AccessorType::element_type, typename MappingType::extents_type, typename MappingType::layout_type, AccessorType >
mdspan(CArray &) -> mdspan< remove_all_extents_t< CArray >, extents< size_t, extent_v< CArray, 0 > > >
mdspan(mdarray< ElementType, Extents, Layout, Container >) -> mdspan< typename decltype(declval< mdarray< ElementType, Extents, Layout, Container > >().to_mdspan())::element_type, typename decltype(declval< mdarray< ElementType, Extents, Layout, Container > >().to_mdspan())::extens_type, typename decltype(declval< mdarray< ElementType, Extents, Layout, Container > >().to_mdspan())::layout_type, typename decltype(declval< mdarray< ElementType, Extents, Layout, Container > >().to_mdspan())::accessor_type >
mdspan(ElementType *, Integrals...) -> mdspan< ElementType, dextents< size_t, sizeof...(Integrals)> >
mdspan(Pointer &&) -> mdspan< remove_pointer_t< remove_reference_t< Pointer > >, extents< size_t > >
mdspan(ElementType *, MappingType const &) -> mdspan< ElementType, typename MappingType::extents_type, typename MappingType::layout_type >
mdspan(ElementType *, extents< IndexType, ExtentsPack... > const &) -> mdspan< ElementType, extents< IndexType, ExtentsPack... > >
A container that encapsulates fixed size arrays.
Definition array.hpp:49
Definition default_accessor.hpp:13
Definition extents.hpp:23
Definition layout.hpp:14
Definition mdarray.hpp:26
Definition mdspan.hpp:40
static constexpr auto is_always_unique() -> bool
Definition mdspan.hpp:258
constexpr mdspan(data_handle_type ptr, mapping_type const &m)
Definition mdspan.hpp:135
static constexpr auto rank() noexcept -> rank_type
Definition mdspan.hpp:53
constexpr auto accessor() const noexcept -> accessor_type const &
Definition mdspan.hpp:223
constexpr auto operator()(OtherIndexTypes... indices) const -> reference
Definition mdspan.hpp:174
constexpr mdspan(data_handle_type ptr, extents_type const &ext)
Definition mdspan.hpp:127
constexpr auto stride(rank_type r) const -> index_type
Definition mdspan.hpp:232
constexpr auto operator[](span< OtherIndexType, rank()> indices) const -> reference
Definition mdspan.hpp:198
OtherAccessor const & other
Definition mdspan.hpp:158
constexpr auto operator[](array< OtherIndexType, rank()> const &indices) const -> reference
Definition mdspan.hpp:210
explicit((not is_convertible_v< typename OtherLayout::template mapping< OtherExtents > const &, mapping_type > or not is_convertible_v< OtherAccessor const &, accessor_type >)) const expr mdspan(mdspan< OtherElement
constexpr auto mapping() const noexcept -> mapping_type const &
Definition mdspan.hpp:219
constexpr mdspan(data_handle_type ptr, mapping_type const &m, accessor_type const &a)
Definition mdspan.hpp:143
explicit(N !=rank_dynamic()) const expr mdspan(data_handle_type p
constexpr auto extent(rank_type r) const noexcept -> index_type
Definition mdspan.hpp:68
span< OtherIndexType, N > exts
Definition mdspan.hpp:107
constexpr auto empty() const noexcept -> bool
Definition mdspan.hpp:236
constexpr auto data_handle() const noexcept -> data_handle_type const &
Definition mdspan.hpp:215
array< OtherIndexType, N > const & exts
Definition mdspan.hpp:121
static constexpr auto rank_dynamic() noexcept -> rank_type
Definition mdspan.hpp:58
static constexpr auto is_always_exhaustive() -> bool
Definition mdspan.hpp:262
constexpr auto is_unique() const -> bool
Definition mdspan.hpp:245
constexpr mdspan(mdspan &&rhs)=default
constexpr auto is_strided() const -> bool
Definition mdspan.hpp:253
constexpr auto is_exhaustive() const -> bool
Definition mdspan.hpp:249
constexpr mdspan(data_handle_type ptr, OtherIndexTypes... exts)
Definition mdspan.hpp:92
static constexpr auto static_extent(rank_type r) noexcept -> size_t
Definition mdspan.hpp:63
constexpr auto extents() const noexcept -> extents_type const &
Definition mdspan.hpp:228
constexpr auto size() const noexcept -> size_type
Definition mdspan.hpp:240
static constexpr auto is_always_strided() -> bool
Definition mdspan.hpp:266
constexpr mdspan(mdspan const &rhs)=default