Iros
 
Loading...
Searching...
No Matches
extents.h
Go to the documentation of this file.
1#pragma once
2
7#include "di/types/prelude.h"
9
10namespace di::vocab {
11template<concepts::Integer T, size_t... extents>
12requires((extents == dynamic_extent || extents <= math::to_unsigned(math::NumericLimits<T>::max)) && ...)
13class Extents {
14public:
15 constexpr static auto static_extent(size_t index) -> size_t {
16 auto result = Array { extents... };
17 return result.data()[index];
18 }
19
20private:
21 constexpr static auto dynamic_index(size_t index) -> size_t {
22 auto result = Array<size_t, rank() + 1> {};
23 size_t count = 0;
24 for (auto i : container::view::range(1ZU, rank() + 1)) {
25 if (static_extent(i - 1) == dynamic_extent) {
26 ++count;
27 }
28 result.data()[i] = count;
29 }
30
31 return result.data()[index];
32 }
33
34 constexpr static auto dynamic_index_inv(size_t index) -> size_t {
35 constexpr auto result = [] {
36 auto answer = Array<size_t, rank_dynamic()> {};
37 for (auto i : container::view::range(rank())) {
38 for (auto r : container::view::range(rank())) {
39 if (dynamic_index(r + 1) == i + 1) {
40 answer.data()[i] = r;
41 break;
42 }
43 }
44 }
45 return answer;
46 }();
47
48 return result.data()[index];
49 }
50
51public:
52 using SizeType = T;
54
55 constexpr static auto rank() -> size_t { return sizeof...(extents); }
56 constexpr static auto rank_dynamic() -> size_t { return dynamic_index(rank()); }
57
58 constexpr Extents() { m_dynamic_extents.fill(0); }
59
60 template<typename OtherSizeType, size_t... other_extents>
61 requires(sizeof...(other_extents) == rank() &&
62 ((other_extents == dynamic_extent || extents == dynamic_extent || other_extents == extents) && ...))
63 constexpr explicit((((extents != dynamic_extent) && (other_extents == dynamic_extent)) || ...) ||
67 for (auto i : container::view::range(rank())) {
68 if (static_extent(i) == dynamic_extent) {
69 m_dynamic_extents[dynamic_index(i)] = other.extent(i);
70 } else {
71 DI_ASSERT(this->extent(i) == other.extent(i));
72 }
73 }
74 }
75
76 template<typename... OtherSizeType>
78 (sizeof...(OtherSizeType) == rank_dynamic() || sizeof...(OtherSizeType) == rank()))
79 constexpr explicit Extents(OtherSizeType... values) {
80 if constexpr (sizeof...(OtherSizeType) == rank_dynamic()) {
81 DI_ASSERT(((values >= 0) && ...));
83 m_dynamic_extents = { static_cast<SizeType>(util::move(values))... };
84 } else {
85 auto as_extents = Extents<SizeType, (values, dynamic_extent)...> { values... };
86 auto new_extents = Extents(as_extents);
87 *this = new_extents;
88 }
89 }
90
91 template<typename OtherSizeType, size_t N>
92 requires(concepts::ConvertibleTo<OtherSizeType const&, SizeType> && (N == rank_dynamic() || N == rank()))
93 constexpr explicit(N != rank_dynamic()) Extents(Span<OtherSizeType, N> extents_array) {
94 function::unpack<meta::MakeIndexSequence<rank_dynamic()>>([&]<size_t... indices>(meta::ListV<indices...>) {
95 if constexpr (N == rank_dynamic()) {
96 m_dynamic_extents = { util::as_const(extents_array[indices])... };
97 } else {
98 m_dynamic_extents = { util::as_const(extents_array[dynamic_index_inv(indices)])... };
99 }
100 });
101 }
102
103 template<typename OtherSizeType, size_t N>
104 requires(concepts::ConvertibleTo<OtherSizeType const&, SizeType> && (N == rank_dynamic() || N == rank()))
105 constexpr explicit(N != rank_dynamic()) Extents(Array<OtherSizeType, N> const& extents_array)
106 : Extents(extents_array.span()) {}
107
108 constexpr auto extent(size_t index) const -> size_t {
109 auto extent = static_extent(index);
110 if (extent != dynamic_extent) {
111 return extent;
112 }
113 if constexpr (rank_dynamic() != 0) {
114 return m_dynamic_extents[dynamic_index(index)];
115 } else {
117 }
118 }
119
120 constexpr auto fwd_prod_of_extents(size_t i) const -> size_t {
121 size_t result = 1;
122 for (auto i : container::view::range(i)) {
123 result *= extent(i);
124 }
125 return result;
126 }
127
128 constexpr auto rev_prod_of_extents(size_t i) const -> size_t {
129 size_t result = 1;
130 for (auto i : container::view::range(i + 1, rank())) {
131 result *= extent(i);
132 }
133 return result;
134 }
135
136 template<typename OtherSizeType>
137 constexpr static auto index_cast(OtherSizeType&& i) {
138 if constexpr (concepts::Integral<OtherSizeType> && !concepts::SameAs<OtherSizeType, bool>) {
139 return i;
140 } else {
141 return static_cast<SizeType>(i);
142 }
143 }
144
145private:
146 template<typename OtherSizeType, size_t... other_extents>
147 constexpr friend auto operator==(Extents const& a, Extents<OtherSizeType, other_extents...> const& b) -> bool {
148 if (a.rank() != b.rank()) {
149 return false;
150 }
151 return di::all_of(container::view::range(rank()), [&](usize i) {
152 return a.extent(i) == b.extent(i);
153 });
154 }
155
156 [[no_unique_address]] Array<SizeType, rank_dynamic()> m_dynamic_extents {};
157};
158
159template<typename... Integrals>
160requires(concepts::ConvertibleTo<Integrals, size_t> && ...)
161explicit Extents(Integrals...) -> Extents<size_t, (Integrals {}, dynamic_extent)...>;
162}
#define DI_ASSERT(...)
Definition assert_bool.h:7
Definition extents_forward_declaration.h:11
constexpr other_extents const & other
Definition extents.h:66
static constexpr auto static_extent(size_t index) -> size_t
Definition extents.h:15
static constexpr auto rank() -> size_t
Definition extents.h:55
size_t RankType
Definition extents.h:53
static constexpr auto rank_dynamic() -> size_t
Definition extents.h:56
T SizeType
Definition extents.h:52
constexpr Extents()
Definition extents.h:58
Definition span_forward_declaration.h:10
Definition operations.h:99
constexpr auto range
Definition range.h:22
constexpr auto unpack
Definition unpack.h:24
constexpr auto extent
Definition vec.h:39
constexpr auto to_unsigned
Definition to_unsigned.h:16
MakeIntegerSequence< usize, count > MakeIndexSequence
Definition algorithm.h:285
size_t usize
Definition integers.h:33
std::size_t size_t
Definition size_t.h:12
void unreachable()
Definition unreachable.h:4
Definition lazy.h:165
Extents(Integrals...) -> Extents< size_t,(Integrals {}, dynamic_extent)... >
constexpr auto dynamic_extent
Definition span_forward_declaration.h:7
constexpr auto operator==(StatusCode< T > const &a, StatusCode< U > const &b) -> bool
Definition status_code_equality.h:7
constexpr auto all_of
Definition all_of.h:24
constexpr auto count
Definition count.h:37
constexpr auto dynamic_extent
Definition span_forward_declaration.h:7
@ N
Definition key.h:23
@ T
Definition key.h:29
Definition numeric_limits.h:7
Definition span_fixed_size.h:37
constexpr auto data() -> T *
Definition array.h:75