Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
ah-mdspan.H
Go to the documentation of this file.
1
2/*
3 Aleph_w
4
5 Data structures & Algorithms
6 https://github.com/lrleon/Aleph-w
7
8 This file is part of Aleph-w library
9
10 Copyright (c) 2002-2026 Leandro Rabindranath Leon
11
12 Permission is hereby granted, free of charge, to any person obtaining a copy
13 of this software and associated documentation files (the "Software"), to deal
14 in the Software without restriction, including without limitation the rights
15 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16 copies of the Software, and to permit persons to whom the Software is
17 furnished to do so, subject to the following conditions:
18
19 The above copyright notice and this permission notice shall be included in all
20 copies or substantial portions of the Software.
21
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 SOFTWARE.
29*/
30
102#ifndef AH_MDSPAN_H
103#define AH_MDSPAN_H
104
105#include <array>
106#include <cstddef>
107#include <type_traits>
108#include <utility>
109
110#include <ah-cpp-compat.H>
111#include <ah-errors.H>
112
113#if ALEPH_HAS_STD_MDSPAN
114# include <mdspan>
115#endif
116
117namespace Aleph
118{
119
120#if ALEPH_HAS_STD_MDSPAN
121
122inline constexpr size_t dynamic_extent = std::dynamic_extent;
123
124template <class IndexType, size_t... Exts>
125using extents = std::extents<IndexType, Exts...>;
126
127template <class IndexType, size_t Rank>
128using dextents = std::dextents<IndexType, Rank>;
129
130using layout_right = std::layout_right;
131using layout_left = std::layout_left;
132
133template <class ElementType>
134using default_accessor = std::default_accessor<ElementType>;
135
151template <class T, class Extents, class LayoutPolicy = std::layout_right,
152 class AccessorPolicy = std::default_accessor<T>>
158class mdspan
159{
160 using impl_type = std::mdspan<T, Extents, LayoutPolicy, AccessorPolicy>;
161
163
164 template <class, class, class, class>
165 friend class mdspan;
166
167public:
168 using extents_type = typename impl_type::extents_type;
169 using layout_type = typename impl_type::layout_type;
170 using accessor_type = typename impl_type::accessor_type;
171 using mapping_type = typename impl_type::mapping_type;
172 using element_type = typename impl_type::element_type;
173 using value_type = typename impl_type::value_type;
174 using index_type = typename impl_type::index_type;
175 using rank_type = typename impl_type::rank_type;
176 using data_handle_type = typename impl_type::data_handle_type;
177 using reference = typename impl_type::reference;
178
179 constexpr mdspan() noexcept = default;
184
190 : impl_(p, e)
191 {}
192
194 constexpr mdspan(data_handle_type p, const mapping_type &m) noexcept
195 : impl_(p, m)
196 {}
197
203 constexpr mdspan(data_handle_type p, const mapping_type &m, const accessor_type &a) noexcept
204 : impl_(p, m, a)
205 {}
206
211 template <class... IndexTypes>
212 requires(sizeof...(IndexTypes) >= 1 and
213 (std::is_convertible_v<IndexTypes, index_type> and ...))
214 constexpr explicit mdspan(data_handle_type p, IndexTypes... exts) noexcept
215 : impl_(p, static_cast<index_type>(exts)...)
216 {}
217
219 template <class OtherIndexType>
220 requires std::is_convertible_v<const OtherIndexType &, index_type>
221 constexpr mdspan(data_handle_type p,
222 const std::array<OtherIndexType, extents_type::rank_dynamic()> &dyn) noexcept
223 : impl_(p, dyn)
224 {}
225
227 template <class OtherT, class OtherAccessor>
228 requires(not std::is_same_v<OtherT, T> and std::is_convertible_v<OtherT (*)[], T (*)[]>)
230 : impl_(other.impl_)
231 {}
232
233 [[nodiscard]] static constexpr rank_type rank() noexcept { return impl_type::rank(); }
234 [[nodiscard]] constexpr index_type extent(rank_type r) const noexcept { return impl_.extent(r); }
235 [[nodiscard]] constexpr const extents_type &extents() const noexcept { return impl_.extents(); }
236 [[nodiscard]] constexpr const mapping_type &mapping() const noexcept { return impl_.mapping(); }
237 [[nodiscard]] constexpr const accessor_type &accessor() const noexcept { return impl_.accessor(); }
238 [[nodiscard]] constexpr data_handle_type data_handle() const noexcept { return impl_.data_handle(); }
239 [[nodiscard]] constexpr data_handle_type data() const noexcept { return impl_.data_handle(); }
240 [[nodiscard]] constexpr index_type size() const noexcept { return impl_.size(); }
241 [[nodiscard]] constexpr bool empty() const noexcept { return impl_.empty(); }
242
249 template <class... Indices>
250 requires(sizeof...(Indices) == extents_type::rank())
251 [[nodiscard]] constexpr reference operator()(Indices... idxs) const
252 {
253 return impl_[static_cast<index_type>(idxs)...];
254 }
255
261 template <class... Indices>
262 requires(sizeof...(Indices) == extents_type::rank())
263 [[nodiscard]] constexpr reference at(Indices... idxs) const
264 {
265 const index_type idx[]{static_cast<index_type>(idxs)...};
266 for (rank_type r = 0; r < rank(); ++r)
267 ah_out_of_range_error_if(std::cmp_less(idx[r], 0) or idx[r] >= extent(r))
268 << "Aleph::mdspan::at(): index[" << r << "]=" << idx[r] << " out of [0, "
269 << extent(r) << ")";
270 return impl_[static_cast<index_type>(idxs)...];
271 }
272};
273
274#else // !ALEPH_HAS_STD_MDSPAN: native C++20 polyfill
275
277inline constexpr size_t dynamic_extent = static_cast<size_t>(-1);
278
280namespace mdspan_detail
281{
282template <size_t... Exts>
283inline constexpr size_t count_dynamic = (size_t{0} + ... + (Exts == dynamic_extent ? 1 : 0));
284} // namespace mdspan_detail
286
301template <class IndexType, size_t... Exts>
303{
304 static_assert(std::is_integral_v<IndexType>,
305 "Aleph::extents: IndexType must be an integral type");
306
307 static constexpr std::array<size_t, sizeof...(Exts)> Static{Exts...};
308
309 std::array<IndexType, sizeof...(Exts)> values_{};
310
311public:
313 using size_type = std::make_unsigned_t<IndexType>;
314 using rank_type = size_t;
315
317 static constexpr rank_type rank() noexcept { return sizeof...(Exts); }
318
320 static constexpr rank_type rank_dynamic() noexcept
321 {
322 return mdspan_detail::count_dynamic<Exts...>;
323 }
324
326 static constexpr size_t static_extent(rank_type r) noexcept { return Static[r]; }
327
329 constexpr extents() noexcept
330 {
331 for (rank_type r = 0; r < rank(); ++r)
332 values_[r] = Static[r] == dynamic_extent ? IndexType{0} : static_cast<IndexType>(Static[r]);
333 }
334
341 template <class... IndexTypes>
342 requires(sizeof...(IndexTypes) == mdspan_detail::count_dynamic<Exts...> and
343 (std::is_convertible_v<IndexTypes, IndexType> and ...))
344 constexpr explicit extents(IndexTypes... dyn) noexcept
345 {
346 const std::array<IndexType, sizeof...(IndexTypes)> given{static_cast<IndexType>(dyn)...};
347 rank_type k = 0;
348 for (rank_type r = 0; r < rank(); ++r)
349 values_[r] = Static[r] == dynamic_extent ? given[k++] : static_cast<IndexType>(Static[r]);
350 }
351
357 template <class OtherIndexType>
358 requires std::is_convertible_v<const OtherIndexType &, IndexType>
359 constexpr explicit extents(
360 const std::array<OtherIndexType, mdspan_detail::count_dynamic<Exts...>> &dyn) noexcept
361 {
362 rank_type k = 0;
363 for (rank_type r = 0; r < rank(); ++r)
364 values_[r] = Static[r] == dynamic_extent ? static_cast<IndexType>(dyn[k++])
365 : static_cast<IndexType>(Static[r]);
366 }
367
372 [[nodiscard]] constexpr index_type extent(rank_type r) const noexcept { return values_[r]; }
373
374 [[nodiscard]] friend constexpr bool operator==(const extents &a, const extents &b) noexcept
375 {
376 return a.values_ == b.values_;
377 }
378};
379
381namespace mdspan_detail
382{
384template <class IndexType, size_t... Is>
385struct dextents_helper
386{
387 using type = extents<IndexType, ((void) Is, dynamic_extent)...>;
388};
389
395template <class IndexType, size_t... Is>
396dextents_helper<IndexType, Is...> dextents_of(std::index_sequence<Is...>);
397} // namespace mdspan_detail
399
401template <class IndexType, size_t Rank>
402using dextents =
403 typename decltype(mdspan_detail::dextents_of<IndexType>(
404 std::make_index_sequence<Rank>{}))::type;
405
413{
414 template <class Extents>
417 {
419
420 public:
422 using index_type = typename Extents::index_type;
423 using rank_type = typename Extents::rank_type;
425
426 constexpr mapping() noexcept = default;
428
429 [[nodiscard]] constexpr const extents_type &extents() const noexcept { return exts_; }
430
436 template <class... Indices>
437 requires(sizeof...(Indices) == Extents::rank())
438 [[nodiscard]] constexpr index_type operator()(Indices... idxs) const noexcept
439 {
440 const index_type idx[]{static_cast<index_type>(idxs)...};
441 index_type offset = 0;
442 for (rank_type r = 0; r < Extents::rank(); ++r)
443 offset = offset * exts_.extent(r) + idx[r];
444 return offset;
445 }
446
448 {
449 index_type total = 1;
450 for (rank_type r = 0; r < Extents::rank(); ++r)
451 total *= exts_.extent(r);
452 return total;
453 }
454
455 static constexpr bool is_always_unique() noexcept { return true; }
456 static constexpr bool is_always_exhaustive() noexcept { return true; }
457 static constexpr bool is_always_strided() noexcept { return true; }
458 };
459};
460
467{
468 template <class Extents>
471 {
473
474 public:
476 using index_type = typename Extents::index_type;
477 using rank_type = typename Extents::rank_type;
479
480 constexpr mapping() noexcept = default;
482
483 [[nodiscard]] constexpr const extents_type &extents() const noexcept { return exts_; }
484
490 template <class... Indices>
491 requires(sizeof...(Indices) == Extents::rank())
492 [[nodiscard]] constexpr index_type operator()(Indices... idxs) const noexcept
493 {
494 const index_type idx[]{static_cast<index_type>(idxs)...};
495 index_type offset = 0;
496 for (rank_type ri = 0; ri < Extents::rank(); ++ri)
497 {
498 const rank_type r = Extents::rank() - 1 - ri;
499 offset = offset * exts_.extent(r) + idx[r];
500 }
501 return offset;
502 }
503
505 {
506 index_type total = 1;
507 for (rank_type r = 0; r < Extents::rank(); ++r)
508 total *= exts_.extent(r);
509 return total;
510 }
511
512 static constexpr bool is_always_unique() noexcept { return true; }
513 static constexpr bool is_always_exhaustive() noexcept { return true; }
514 static constexpr bool is_always_strided() noexcept { return true; }
515 };
516};
517
524template <class ElementType>
526{
531
533
538
544 [[nodiscard]] constexpr reference access(data_handle_type p, size_t i) const noexcept
545 {
546 return p[i];
547 }
548
549 [[nodiscard]] constexpr data_handle_type offset(data_handle_type p, size_t i) const noexcept
550 {
551 return p + i;
552 }
553};
554
568template <class T, class Extents, class LayoutPolicy = layout_right,
569 class AccessorPolicy = default_accessor<T>>
576{
577public:
581 using mapping_type = typename layout_type::template mapping<extents_type>;
583 using value_type = std::remove_cv_t<T>;
584 using index_type = typename extents_type::index_type;
585 using rank_type = typename extents_type::rank_type;
586 using data_handle_type = typename accessor_type::data_handle_type;
587 using reference = typename accessor_type::reference;
588
589private:
593
594public:
596 constexpr mdspan() noexcept = default;
597
602
616
622 : ptr_(p), map_(e)
623 {}
624
630 : ptr_(p), map_(m)
631 {}
632
639 : ptr_(p), map_(m), acc_(a)
640 {}
641
648 template <class... IndexTypes>
649 requires(sizeof...(IndexTypes) >= 1 and
650 (std::is_convertible_v<IndexTypes, index_type> and ...))
652 : ptr_(p), map_(extents_type(static_cast<index_type>(exts)...))
653 {}
654
662 template <class OtherIndexType>
663 requires std::is_convertible_v<const OtherIndexType &, index_type>
665 const std::array<OtherIndexType, extents_type::rank_dynamic()> &dyn) noexcept
666 : ptr_(p), map_(extents_type(dyn))
667 {}
668
672 [[nodiscard]] static constexpr rank_type rank() noexcept { return extents_type::rank(); }
673
678 [[nodiscard]] constexpr index_type extent(rank_type r) const noexcept
679 {
680 return map_.extents().extent(r);
681 }
682
684 [[nodiscard]] constexpr const extents_type &extents() const noexcept { return map_.extents(); }
685
687 [[nodiscard]] constexpr const mapping_type &mapping() const noexcept { return map_; }
688
690 [[nodiscard]] constexpr const accessor_type &accessor() const noexcept { return acc_; }
691
694
696 [[nodiscard]] constexpr data_handle_type data() const noexcept { return ptr_; }
697
700 {
701 index_type total = 1;
702 for (rank_type r = 0; r < rank(); ++r)
703 total *= extent(r);
704 return total;
705 }
706
710 [[nodiscard]] constexpr bool empty() const noexcept
711 {
712 for (rank_type r = 0; r < rank(); ++r)
713 if (extent(r) == 0)
714 return true;
715 return false;
716 }
717
726 template <class... Indices>
727 requires(sizeof...(Indices) == extents_type::rank())
728 [[nodiscard]] constexpr reference operator()(Indices... idxs) const
729 {
730 return acc_.access(ptr_, map_(static_cast<index_type>(idxs)...));
731 }
732
739 template <class... Indices>
740 requires(sizeof...(Indices) == extents_type::rank())
741 [[nodiscard]] constexpr reference at(Indices... idxs) const
742 {
743 const index_type idx[]{static_cast<index_type>(idxs)...};
744 for (rank_type r = 0; r < rank(); ++r)
745 ah_out_of_range_error_if(std::cmp_less(idx[r], 0) or idx[r] >= extent(r))
746 << "Aleph::mdspan::at(): index[" << r << "]=" << idx[r] << " out of [0, "
747 << extent(r) << ")";
748 return acc_.access(ptr_, map_(static_cast<index_type>(idxs)...));
749 }
750};
751
752#endif // ALEPH_HAS_STD_MDSPAN
753
754} // namespace Aleph
755
756#endif // AH_MDSPAN_H
C++20/23 compatibility layer: feature detection + Aleph:: polyfills.
Exception handling system with formatted messages for Aleph-w.
#define ah_out_of_range_error_if(C)
Throws std::out_of_range if condition holds.
Definition ah-errors.H:584
Shape (per-axis sizes) of an mdspan, mixing compile-time and run-time extents.
Definition ah-mdspan.H:303
IndexType index_type
Definition ah-mdspan.H:312
static constexpr rank_type rank_dynamic() noexcept
Number of axes whose extent is dynamic_extent (compile-time constant).
Definition ah-mdspan.H:320
std::make_unsigned_t< IndexType > size_type
Definition ah-mdspan.H:313
constexpr index_type extent(rank_type r) const noexcept
Run-time size of axis r.
Definition ah-mdspan.H:372
static constexpr rank_type rank() noexcept
Number of axes (compile-time constant).
Definition ah-mdspan.H:317
std::array< IndexType, sizeof...(Exts)> values_
Definition ah-mdspan.H:309
constexpr extents(IndexTypes... dyn) noexcept
Construct providing a value for each dynamic axis, in rank order.
Definition ah-mdspan.H:344
friend constexpr bool operator==(const extents &a, const extents &b) noexcept
Definition ah-mdspan.H:374
size_t rank_type
Definition ah-mdspan.H:314
static constexpr std::array< size_t, sizeof...(Exts)> Static
Definition ah-mdspan.H:307
constexpr extents(const std::array< OtherIndexType, mdspan_detail::count_dynamic< Exts... > > &dyn) noexcept
Construct providing every dynamic axis's value packed in an array.
Definition ah-mdspan.H:359
static constexpr size_t static_extent(rank_type r) noexcept
Compile-time size of axis r, or dynamic_extent if axis r is dynamic.
Definition ah-mdspan.H:326
constexpr extents() noexcept
All-static-or-default-initialised extents (dynamic axes start at 0).
Definition ah-mdspan.H:329
Mapping from column-major multi-indices to linear offsets.
Definition ah-mdspan.H:471
constexpr index_type required_span_size() const noexcept
Definition ah-mdspan.H:504
typename Extents::index_type index_type
Definition ah-mdspan.H:476
static constexpr bool is_always_exhaustive() noexcept
Definition ah-mdspan.H:513
typename Extents::rank_type rank_type
Definition ah-mdspan.H:477
static constexpr bool is_always_unique() noexcept
Definition ah-mdspan.H:512
static constexpr bool is_always_strided() noexcept
Definition ah-mdspan.H:514
constexpr const extents_type & extents() const noexcept
Definition ah-mdspan.H:483
constexpr mapping() noexcept=default
Mapping from row-major multi-indices to linear offsets.
Definition ah-mdspan.H:417
static constexpr bool is_always_strided() noexcept
Definition ah-mdspan.H:457
constexpr mapping() noexcept=default
static constexpr bool is_always_exhaustive() noexcept
Definition ah-mdspan.H:456
constexpr index_type required_span_size() const noexcept
Definition ah-mdspan.H:447
constexpr const extents_type & extents() const noexcept
Definition ah-mdspan.H:429
typename Extents::index_type index_type
Definition ah-mdspan.H:422
static constexpr bool is_always_unique() noexcept
Definition ah-mdspan.H:455
typename Extents::rank_type rank_type
Definition ah-mdspan.H:423
Non-owning view of a contiguous buffer as a multidimensional grid.
Definition ah-mdspan.H:576
constexpr mdspan(data_handle_type p, const extents_type &e) noexcept
View p through the shape e.
Definition ah-mdspan.H:621
static constexpr rank_type rank() noexcept
Number of axes (compile-time constant).
Definition ah-mdspan.H:672
constexpr index_type extent(rank_type r) const noexcept
Run-time size of axis r.
Definition ah-mdspan.H:678
Extents extents_type
Definition ah-mdspan.H:578
constexpr mdspan(data_handle_type p, IndexTypes... exts) noexcept
View p as a grid with the given per-axis sizes.
Definition ah-mdspan.H:651
typename accessor_type::reference reference
Definition ah-mdspan.H:587
LayoutPolicy layout_type
Definition ah-mdspan.H:579
std::remove_cv_t< T > value_type
Definition ah-mdspan.H:583
constexpr mdspan(data_handle_type p, const mapping_type &m, const accessor_type &a) noexcept
View p through mapping m, reading via accessor a.
Definition ah-mdspan.H:638
typename extents_type::index_type index_type
Definition ah-mdspan.H:584
constexpr const accessor_type & accessor() const noexcept
The element-access policy of this view.
Definition ah-mdspan.H:690
constexpr mdspan(data_handle_type p, const std::array< OtherIndexType, extents_type::rank_dynamic()> &dyn) noexcept
View p as a grid whose dynamic axes are packed in an array.
Definition ah-mdspan.H:664
constexpr mdspan() noexcept=default
Empty view: data_handle() == nullptr, every extent is 0.
constexpr data_handle_type data() const noexcept
Definition ah-mdspan.H:696
typename accessor_type::data_handle_type data_handle_type
Definition ah-mdspan.H:586
constexpr const mapping_type & mapping() const noexcept
The index-to-offset mapping (layout + shape) of this view.
Definition ah-mdspan.H:687
data_handle_type ptr_
Definition ah-mdspan.H:590
accessor_type acc_
Definition ah-mdspan.H:592
constexpr data_handle_type data_handle() const noexcept
Underlying pointer to the first element (nullptr for a default-built view).
Definition ah-mdspan.H:693
AccessorPolicy accessor_type
Definition ah-mdspan.H:580
typename extents_type::rank_type rank_type
Definition ah-mdspan.H:585
constexpr mdspan(data_handle_type p, const mapping_type &m) noexcept
View p through an already-built mapping.
Definition ah-mdspan.H:629
constexpr reference at(Indices... idxs) const
Bounds-checked element access.
Definition ah-mdspan.H:741
constexpr bool empty() const noexcept
Checks if the view has no elements.
Definition ah-mdspan.H:710
typename layout_type::template mapping< extents_type > mapping_type
Definition ah-mdspan.H:581
mapping_type map_
Definition ah-mdspan.H:591
constexpr index_type size() const noexcept
Total element count: the product of every extent(r).
Definition ah-mdspan.H:699
constexpr const extents_type & extents() const noexcept
The shape of this view.
Definition ah-mdspan.H:684
size_t blossom_maximum_cardinality_matching(const GT &g, DynDlist< typename GT::Arc * > &matching, SA sa=SA())
Alias of compute_maximum_cardinality_general_matching().
Definition Blossom.H:466
const long double offset[]
Offset values indexed by symbol string length (bounded by MAX_OFFSET_INDEX)
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
constexpr size_t dynamic_extent
Sentinel marking an axis whose extent is only known at run time.
Definition ah-mdspan.H:277
and
Check uniqueness with explicit hash + equality functors.
std::decay_t< typename HeadC::Item_Type > T
Definition ah-zip.H:105
typename decltype(mdspan_detail::dextents_of< IndexType >(std::make_index_sequence< Rank >{}))::type dextents
extents<IndexType, ...> with all Rank axes dynamic — the common case.
Definition ah-mdspan.H:404
STL namespace.
Trivial accessor policy: access(p, i) is just p[i].
Definition ah-mdspan.H:526
ElementType element_type
Definition ah-mdspan.H:528
constexpr reference access(data_handle_type p, size_t i) const noexcept
Access an element from a pointer and an offset.
Definition ah-mdspan.H:544
ElementType * data_handle_type
Definition ah-mdspan.H:530
constexpr data_handle_type offset(data_handle_type p, size_t i) const noexcept
Definition ah-mdspan.H:549
ElementType & reference
Definition ah-mdspan.H:529
constexpr default_accessor() noexcept=default
Column-major layout: the first axis varies fastest (Fortran convention).
Definition ah-mdspan.H:467
Row-major layout: the last axis varies fastest (C convention).
Definition ah-mdspan.H:413
FooMap m(5, fst_unit_pair_hash, snd_unit_pair_hash)
static int * k
gsl_rng * r