tetl 0.1.0
Embedded Template Library
Loading...
Searching...
No Matches
mdarray.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: BSL-1.0
2// SPDX-FileCopyrightText: Copyright (C) 2023 Tobias Hienzsch
3
4#ifndef TETL_ARRAY_MDARRAY_HPP
5#define TETL_ARRAY_MDARRAY_HPP
6
7#include <etl/_array/array.hpp>
8#include <etl/_iterator/size.hpp>
9#include <etl/_mdspan/mdspan.hpp>
10#include <etl/_memory/to_address.hpp>
11#include <etl/_span/span.hpp>
12#include <etl/_type_traits/declval.hpp>
13#include <etl/_type_traits/is_assignable.hpp>
14#include <etl/_type_traits/is_constructible.hpp>
15#include <etl/_type_traits/is_convertible.hpp>
16#include <etl/_type_traits/is_nothrow_constructible.hpp>
17#include <etl/_utility/as_const.hpp>
18#include <etl/_utility/forward.hpp>
19#include <etl/_utility/index_sequence.hpp>
20#include <etl/_utility/move.hpp>
21
22namespace etl {
23
24/// \ingroup mdarray
25template <typename ElementType, typename Extents, typename LayoutPolicy, typename Container>
26struct mdarray {
27private:
28 template <typename C, typename... Args>
29 static constexpr auto array_or_constructible_from = is_etl_array<C> or is_constructible_v<C, Args...>;
30
31public:
32 using extents_type = Extents;
33 using layout_type = LayoutPolicy;
34 using container_type = Container;
35 using mapping_type = typename layout_type::template mapping<extents_type>;
36 using element_type = ElementType;
37 using mdspan_type = mdspan<element_type, extents_type, layout_type>;
38 using const_mdspan_type = mdspan<element_type const, extents_type, layout_type>;
39 using value_type = element_type;
40 using index_type = typename Extents::index_type;
41 using size_type = typename Extents::size_type;
42 using rank_type = typename Extents::rank_type;
43 using pointer = decltype(etl::to_address(etl::declval<container_type>().begin()));
44 using reference = typename container_type::reference;
45 using const_pointer = decltype(etl::to_address(etl::declval<container_type>().cbegin()));
46 using const_reference = typename container_type::const_reference;
47
48 [[nodiscard]] static constexpr auto rank() noexcept -> rank_type
49 {
50 return Extents::rank();
51 }
52 [[nodiscard]] static constexpr auto rank_dynamic() noexcept -> rank_type
53 {
54 return Extents::rank_dynamic();
55 }
56 [[nodiscard]] static constexpr auto static_extent(rank_type r) noexcept -> size_t
57 {
58 return Extents::static_extent(r);
59 }
60 [[nodiscard]] constexpr auto extent(rank_type r) const noexcept -> index_type
61 {
62 return extents().extent(r);
63 }
64
65 // [mdarray.ctors], mdarray constructors
66 constexpr mdarray()
67 requires(rank_dynamic() != 0)
68 = default;
69 constexpr mdarray(mdarray const& rhs) = default;
70 constexpr mdarray(mdarray&& rhs) = default;
71
72 template <typename... OtherIndexTypes>
73 requires(
74 (is_convertible_v<OtherIndexTypes, index_type> and ...)
75 and (is_nothrow_constructible_v<index_type, OtherIndexTypes> and ...)
76 and (is_constructible_v<extents_type, OtherIndexTypes...>)
77 and (is_constructible_v<mapping_type, extents_type>)
78 and (array_or_constructible_from<Container, size_t>)
79 )
80 explicit constexpr mdarray(OtherIndexTypes... exts)
81 : mdarray(extents_type(static_cast<index_type>(etl::move(exts))...))
82 {
83 }
84
85 explicit constexpr mdarray(extents_type const& ext)
86 requires(
87 is_constructible_v<mapping_type, extents_type const&> and array_or_constructible_from<Container, size_t>
88 )
89 : mdarray(mapping_type(ext))
90 {
91 }
92
93 explicit constexpr mdarray(mapping_type const& m)
94 requires(array_or_constructible_from<Container, size_t>)
95 : _map(m)
96 , _ctr([&]() -> container_type {
97 if constexpr (is_constructible_v<Container, size_t>) {
98 return container_type(static_cast<size_t>(_map.required_span_size()));
99 } else {
100 return {};
101 }
102 }())
103 {
104 }
105
106 constexpr mdarray(extents_type const& ext, value_type const& val)
107 requires(
108 is_constructible_v<mapping_type, extents_type const&>
109 and array_or_constructible_from<Container, size_t, value_type>
110 )
111 : mdarray(mapping_type(ext), val)
112 {
113 }
114
115 constexpr mdarray(mapping_type const& m, value_type const& val)
116 requires(array_or_constructible_from<Container, size_t, value_type>)
117 : _map(m)
118 , _ctr([&]() -> container_type {
119 if constexpr (is_constructible_v<Container, size_t, value_type>) {
120 return container_type(static_cast<size_t>(_map.required_span_size()), val);
121 } else {
122 return value_to_array<element_type, container_type().size()>(val);
123 }
124 }())
125 {
126 }
127
128 constexpr mdarray(extents_type const& ext, container_type const& c)
129 requires(is_constructible_v<mapping_type, extents_type const&>)
130 : mdarray(mapping_type(ext), c)
131 {
132 }
133
134 constexpr mdarray(mapping_type const& m, container_type const& c)
135 : _map(m)
136 , _ctr(c)
137 {
138 }
139
140 constexpr mdarray(extents_type const& ext, container_type&& c)
141 requires(is_constructible_v<mapping_type, extents_type const&>)
142 : mdarray(mapping_type(ext), etl::move(c))
143 {
144 }
145
146 constexpr mdarray(mapping_type const& m, container_type&& c)
147 : _map(m)
148 , _ctr(etl::move(c))
149 {
150 }
151
152 // template <typename OtherElementType, typename OtherExtents, typename OtherLayoutPolicy,
153 // typename OtherContainer> explicit(see below) constexpr mdarray(
154 // mdarray<OtherElementType, OtherExtents, OtherLayoutPolicy, OtherContainer> const& other);
155
156 // template <typename OtherElementType, typename OtherExtents, typename OtherLayoutPolicy,
157 // typename Accessor> explicit(see below) constexpr mdarray(
158 // mdspan<OtherElementType, OtherExtents, OtherLayoutPolicy, Accessor> const& other);
159
160 constexpr auto operator=(mdarray const& rhs) -> mdarray& = default;
161 constexpr auto operator=(mdarray&& rhs) -> mdarray& = default;
162
163#if defined(__cpp_multidimensional_subscript)
164 template <typename... OtherIndexTypes>
165 requires(
166 (is_convertible_v<OtherIndexTypes, index_type> and ...)
167 and (is_nothrow_constructible_v<index_type, OtherIndexTypes> and ...)
168 and (sizeof...(OtherIndexTypes) == rank())
169 )
170 [[nodiscard]] constexpr auto operator[](OtherIndexTypes... indices) -> reference
171 {
172 return (*this)(etl::move(indices)...);
173 }
174
175 template <typename... OtherIndexTypes>
176 requires(
177 (is_convertible_v<OtherIndexTypes, index_type> and ...)
178 and (is_nothrow_constructible_v<index_type, OtherIndexTypes> and ...)
179 and (sizeof...(OtherIndexTypes) == rank())
180 )
181 [[nodiscard]] constexpr auto operator[](OtherIndexTypes... indices) const -> const_reference
182 {
183 return (*this)(etl::move(indices)...);
184 }
185#endif
186
187 template <typename... OtherIndexTypes>
188 requires(
189 (is_convertible_v<OtherIndexTypes, index_type> and ...)
190 and (is_nothrow_constructible_v<index_type, OtherIndexTypes> and ...)
191 and (sizeof...(OtherIndexTypes) == rank())
192 )
193 [[nodiscard]] constexpr auto operator()(OtherIndexTypes... indices) -> reference
194 {
195 return _ctr[static_cast<size_t>(_map(static_cast<index_type>(etl::move(indices))...))];
196 }
197
198 template <typename... OtherIndexTypes>
199 requires(
200 (is_convertible_v<OtherIndexTypes, index_type> and ...)
201 and (is_nothrow_constructible_v<index_type, OtherIndexTypes> and ...)
202 and (sizeof...(OtherIndexTypes) == rank())
203 )
204 [[nodiscard]] constexpr auto operator()(OtherIndexTypes... indices) const -> const_reference
205 {
206 return _ctr[static_cast<size_t>(_map(static_cast<index_type>(etl::move(indices))...))];
207 }
208
209 template <typename OtherIndexType>
210 requires(
211 is_convertible_v<OtherIndexType const&, index_type>
212 and is_nothrow_constructible_v<index_type, OtherIndexType const&>
213 )
214 [[nodiscard]] constexpr auto operator[](span<OtherIndexType, rank()> indices) -> reference
215 {
216 return [&]<size_t... Is>(index_sequence<Is...> /*seq*/) -> decltype(auto) {
217 return (*this)(etl::as_const(indices[Is])...);
218 }(make_index_sequence<rank()>());
219 }
220
221 template <typename OtherIndexType>
222 requires(
223 is_convertible_v<OtherIndexType const&, index_type>
224 and is_nothrow_constructible_v<index_type, OtherIndexType const&>
225 )
226 [[nodiscard]] constexpr auto operator[](span<OtherIndexType, rank()> indices) const -> const_reference
227 {
228 return [&]<size_t... Is>(index_sequence<Is...> /*seq*/) -> decltype(auto) {
229 return (*this)(etl::as_const(indices[Is])...);
230 }(make_index_sequence<rank()>());
231 }
232
233 template <typename OtherIndexType>
234 requires(
235 is_convertible_v<OtherIndexType const&, index_type>
236 and is_nothrow_constructible_v<index_type, OtherIndexType const&>
237 )
238 [[nodiscard]] constexpr auto operator[](array<OtherIndexType, rank()> const& indices) -> reference
239 {
240 return operator[](span{indices});
241 }
242
243 template <typename OtherIndexType>
244 requires(
245 is_convertible_v<OtherIndexType const&, index_type>
246 and is_nothrow_constructible_v<index_type, OtherIndexType const&>
247 )
248 [[nodiscard]] constexpr auto operator[](array<OtherIndexType, rank()> const& indices) const -> const_reference
249 {
250 return operator[](span{indices});
251 }
252
253 [[nodiscard]] constexpr auto size() const -> size_type
254 {
255 return size_type(extents().fwd_prod_of_extents(rank()));
256 }
257 [[nodiscard]] constexpr auto empty() const noexcept -> bool
258 {
259 return size() == 0;
260 }
261
262 [[nodiscard]] constexpr auto extents() const -> extents_type const&
263 {
264 return _map.extents();
265 }
266 [[nodiscard]] constexpr auto mapping() const -> mapping_type const&
267 {
268 return _map;
269 }
270 [[nodiscard]] constexpr auto stride(size_t r) const -> index_type
271 {
272 return _map.stride(r);
273 }
274
275 [[nodiscard]] constexpr auto container_size() const
276 {
277 return _ctr.size();
278 }
279 [[nodiscard]] constexpr auto container_data() -> pointer
280 {
281 return to_address(_ctr.begin());
282 }
283 [[nodiscard]] constexpr auto container_data() const -> const_pointer
284 {
285 return to_address(_ctr.cbegin());
286 }
287 [[nodiscard]] constexpr auto extract_container() && -> container_type&&
288 {
289 return etl::move(_ctr);
290 }
291
292 [[nodiscard]] constexpr auto is_unique() const -> bool
293 {
294 return _map.is_unique();
295 }
296 [[nodiscard]] constexpr auto is_exhaustive() const -> bool
297 {
298 return _map.is_exhaustive();
299 }
300 [[nodiscard]] constexpr auto is_strided() const -> bool
301 {
302 return _map.is_strided();
303 }
304
305 [[nodiscard]] static constexpr auto is_always_unique() -> bool
306 {
307 return mapping_type::is_always_unique();
308 }
309 [[nodiscard]] static constexpr auto is_always_exhaustive() -> bool
310 {
311 return mapping_type::is_always_exhaustive();
312 }
313 [[nodiscard]] static constexpr auto is_always_strided() -> bool
314 {
315 return mapping_type::is_always_strided();
316 }
317
318 template <typename OtherElement, typename OtherExtents, typename OtherLayout, typename OtherAccessor>
319 // requires is_assignable_v<mdspan<OtherElement, OtherExtents, OtherLayout, OtherAccessor>, mdspan_type>
320 [[nodiscard]] constexpr operator mdspan<OtherElement, OtherExtents, OtherLayout, OtherAccessor>()
321 {
322 return mdspan_type(container_data(), _map);
323 }
324
325 template <typename OtherElement, typename OtherExtents, typename OtherLayout, typename OtherAccessor>
326 // requires is_assignable_v<mdspan<OtherElement, OtherExtents, OtherLayout, OtherAccessor>, const_mdspan_type>
327 [[nodiscard]] constexpr operator mdspan<OtherElement, OtherExtents, OtherLayout, OtherAccessor>() const
328 {
329 return const_mdspan_type(container_data(), _map);
330 }
331
332 template <typename OtherAccessor = default_accessor<element_type>>
333 // requires is_assignable_v<typename OtherAccessor::data_handle_type, pointer>
334 [[nodiscard]] constexpr auto to_mdspan(OtherAccessor const& a = default_accessor<element_type>())
335 -> mdspan<element_type, extents_type, layout_type, OtherAccessor>
336 {
337 return mdspan<element_type, extents_type, layout_type, OtherAccessor>(container_data(), _map, a);
338 }
339
340 template <typename OtherAccessor = default_accessor<element_type const>>
341 // requires is_assignable_v<typename OtherAccessor::data_handle_type, const_pointer>
342 [[nodiscard]] constexpr auto to_mdspan(OtherAccessor const& a = default_accessor<element_type const>()) const
343 -> mdspan<element_type const, extents_type, layout_type, OtherAccessor>
344 {
345 return mdspan<element_type const, extents_type, layout_type, OtherAccessor>(container_data(), _map, a);
346 }
347
348 friend constexpr void swap(mdarray& lhs, mdarray& rhs) noexcept
349 {
350 swap(lhs._map, rhs._map);
351 swap(lhs._ctr, rhs._ctr);
352 }
353
354private:
355 template <typename Value, size_t N>
356 [[nodiscard]] static constexpr auto value_to_array(Value const& t) -> array<Value, N>
357 {
358 constexpr auto value = []<typename V>(auto /*i*/, V&& v) -> decltype(auto) { return etl::forward<V&&>(v); };
359 return [&]<size_t... Indices>(index_sequence<Indices...>) {
360 return array<Value, N>{value(Indices, t)...};
361 }(make_index_sequence<N>());
362 }
363
364 mapping_type _map;
365 container_type _ctr;
366};
367
368} // namespace etl
369
370#endif // TETL_ARRAY_MDARRAY_HPP
Definition adjacent_find.hpp:9
A container that encapsulates fixed size arrays.
Definition array.hpp:49
Definition default_accessor.hpp:13
Definition mdarray.hpp:26
constexpr auto to_mdspan(OtherAccessor const &a=default_accessor< element_type >()) -> mdspan< element_type, extents_type, layout_type, OtherAccessor >
Definition mdarray.hpp:334
static constexpr auto is_always_unique() -> bool
Definition mdarray.hpp:305
constexpr auto operator=(mdarray &&rhs) -> mdarray &=default
constexpr auto operator[](array< OtherIndexType, rank()> const &indices) const -> const_reference
Definition mdarray.hpp:248
static constexpr auto rank() noexcept -> rank_type
Definition mdarray.hpp:48
constexpr auto mapping() const -> mapping_type const &
Definition mdarray.hpp:266
constexpr mdarray(extents_type const &ext, container_type &&c)
Definition mdarray.hpp:140
constexpr mdarray(extents_type const &ext, container_type const &c)
Definition mdarray.hpp:128
constexpr auto extents() const -> extents_type const &
Definition mdarray.hpp:262
constexpr auto stride(size_t r) const -> index_type
Definition mdarray.hpp:270
constexpr auto container_data() -> pointer
Definition mdarray.hpp:279
friend constexpr void swap(mdarray &lhs, mdarray &rhs) noexcept
Definition mdarray.hpp:348
constexpr auto extract_container() &&-> container_type &&
Definition mdarray.hpp:287
constexpr mdarray(mapping_type const &m, container_type &&c)
Definition mdarray.hpp:146
constexpr auto size() const -> size_type
Definition mdarray.hpp:253
constexpr mdarray(mapping_type const &m, value_type const &val)
Definition mdarray.hpp:115
constexpr auto operator()(OtherIndexTypes... indices) const -> const_reference
Definition mdarray.hpp:204
constexpr auto operator[](span< OtherIndexType, rank()> indices) const -> const_reference
Definition mdarray.hpp:226
constexpr auto operator=(mdarray const &rhs) -> mdarray &=default
constexpr mdarray(extents_type const &ext)
Definition mdarray.hpp:85
constexpr mdarray(mapping_type const &m, container_type const &c)
Definition mdarray.hpp:134
constexpr auto operator()(OtherIndexTypes... indices) -> reference
Definition mdarray.hpp:193
constexpr auto extent(rank_type r) const noexcept -> index_type
Definition mdarray.hpp:60
constexpr auto empty() const noexcept -> bool
Definition mdarray.hpp:257
constexpr auto operator[](span< OtherIndexType, rank()> indices) -> reference
Definition mdarray.hpp:214
static constexpr auto rank_dynamic() noexcept -> rank_type
Definition mdarray.hpp:52
static constexpr auto is_always_exhaustive() -> bool
Definition mdarray.hpp:309
constexpr auto is_unique() const -> bool
Definition mdarray.hpp:292
constexpr auto container_size() const
Definition mdarray.hpp:275
constexpr auto to_mdspan(OtherAccessor const &a=default_accessor< element_type const >()) const -> mdspan< element_type const, extents_type, layout_type, OtherAccessor >
Definition mdarray.hpp:342
constexpr mdarray(mdarray const &rhs)=default
constexpr auto container_data() const -> const_pointer
Definition mdarray.hpp:283
constexpr auto is_strided() const -> bool
Definition mdarray.hpp:300
constexpr auto is_exhaustive() const -> bool
Definition mdarray.hpp:296
constexpr mdarray(mapping_type const &m)
Definition mdarray.hpp:93
constexpr mdarray(extents_type const &ext, value_type const &val)
Definition mdarray.hpp:106
static constexpr auto static_extent(rank_type r) noexcept -> size_t
Definition mdarray.hpp:56
constexpr auto operator[](array< OtherIndexType, rank()> const &indices) -> reference
Definition mdarray.hpp:238
constexpr mdarray(mdarray &&rhs)=default
constexpr operator mdspan< OtherElement, OtherExtents, OtherLayout, OtherAccessor >()
Definition mdarray.hpp:320
constexpr operator mdspan< OtherElement, OtherExtents, OtherLayout, OtherAccessor >() const
Definition mdarray.hpp:327
static constexpr auto is_always_strided() -> bool
Definition mdarray.hpp:313
constexpr mdarray(OtherIndexTypes... exts)
Definition mdarray.hpp:80
Definition mdspan.hpp:40