tetl 0.1.0
Embedded Template Library
Loading...
Searching...
No Matches
extents.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: BSL-1.0
2
3#ifndef TETL_MDSPAN_EXTENTS_HPP
4#define TETL_MDSPAN_EXTENTS_HPP
5
12#include <etl/_span/span.hpp>
18
19namespace etl {
20
21template <typename IndexType, etl::size_t... Extents>
22struct extents {
23 using index_type = IndexType;
26
27private:
28 static constexpr auto _rank = sizeof...(Extents);
29 static constexpr auto _rank_dynamic = ((rank_type(Extents == dynamic_extent)) + ... + 0);
30 static constexpr auto _static_extents = array<etl::size_t, sizeof...(Extents)>{Extents...};
31
32 [[nodiscard]] static constexpr auto _dynamic_index(rank_type i) noexcept -> rank_type
33 {
34 return []<etl::size_t... Idxs>(etl::size_t idx, etl::index_sequence<Idxs...> /*is*/) {
35 // NOLINTNEXTLINE(bugprone-misplaced-widening-cast)
36 return static_cast<rank_type>((((Idxs < idx) ? (Extents == dynamic_extent ? 1 : 0) : 0) + ... + 0));
38 }
39
40 [[nodiscard]] static constexpr auto _dynamic_index_inv(rank_type i) noexcept -> rank_type
41 {
42 // TODO: this is horrible!
43 auto result = rank_type{};
44 for (rank_type r{0}; r < rank(); ++r) {
45 if (_dynamic_index(r) == i) {
46 result = i;
47 }
48 }
49 return result;
50 }
51
52public:
53 [[nodiscard]] static constexpr auto rank() noexcept -> rank_type { return sizeof...(Extents); }
54
55 [[nodiscard]] static constexpr auto rank_dynamic() noexcept -> rank_type { return _rank_dynamic; }
56
57 [[nodiscard]] static constexpr auto static_extent(rank_type i) noexcept -> etl::size_t
58 {
59 return _static_extents[i];
60 }
61
62 [[nodiscard]] constexpr auto extent(rank_type i) const noexcept -> index_type
63 {
64 if constexpr (rank_dynamic() == 0) {
65 return static_cast<index_type>(static_extent(i));
66 } else if constexpr (rank_dynamic() == rank()) {
67 return _extents[static_cast<etl::size_t>(i)];
68 } else {
69 if (auto const ext = static_extent(i); ext != dynamic_extent) {
70 return static_cast<index_type>(ext);
71 }
72 return _extents[static_cast<etl::size_t>(_dynamic_index(i))];
73 }
74 }
75
76 // [mdspan.extents.ctor], Constructors
77 constexpr extents() noexcept = default;
78
79 template <typename OtherIndexType, etl::size_t... OtherExtents>
80 requires(
81 sizeof...(OtherExtents) == rank()
82 and ((OtherExtents == dynamic_extent or Extents == dynamic_extent or OtherExtents == Extents) and ...)
83 )
85 ((Extents != dynamic_extent and OtherExtents == dynamic_extent) or ...)
86 or (numeric_limits<IndexType>::max() < numeric_limits<OtherIndexType>::max())
87 ) constexpr extents(extents<OtherIndexType, OtherExtents...> const& e) noexcept
88 {
89 if constexpr (rank_dynamic() > 0) {
90 for (rank_type i{0}; i < rank(); ++i) {
91 if (e.static_extent(i) == dynamic_extent) {
92 _extents[_dynamic_index(i)] = static_cast<IndexType>(e.extent(i));
93 }
94 }
95 }
96 }
97
98 template <typename... OtherIndexTypes>
99 requires(
102 and (sizeof...(OtherIndexTypes) == rank_dynamic() or sizeof...(OtherIndexTypes) == rank())
103 )
104 explicit constexpr extents(OtherIndexTypes... es) noexcept
105 : extents{array<IndexType, sizeof...(OtherIndexTypes)>{static_cast<IndexType>(es)...}}
106 {
107 }
108
109 template <typename OtherIndexType, etl::size_t N>
110 requires(
113 )
114 explicit(N != rank_dynamic()) constexpr extents(span<OtherIndexType, N> ext) noexcept
115 {
116 if constexpr (rank_dynamic() != 0) {
117 transform(ext.begin(), ext.end(), _extents.begin(), [](auto e) { return static_cast<IndexType>(e); });
118 }
119 }
120
121 template <typename OtherIndexType, etl::size_t N>
122 requires(
125 )
126 explicit(N != rank_dynamic()) constexpr extents(array<OtherIndexType, N> const& e) noexcept
127 : extents{span{e}}
128 {
129 }
130
131 template <typename OtherIndexType, etl::size_t... OtherExtents>
132 friend constexpr auto operator==(extents const& lhs, extents<OtherIndexType, OtherExtents...> const& rhs) noexcept
133 -> bool
134 {
136 return false;
137 } else {
138 for (auto i = rank_type(0); i < rank(); ++i) {
139 if (cmp_not_equal(lhs.extent(i), rhs.extent(i))) {
140 return false;
141 }
142 }
143 return true;
144 }
145 }
146
147 template <typename OtherIndexType>
148 [[nodiscard]] static constexpr auto index_cast(OtherIndexType&& i) noexcept -> IndexType
149 {
150 return static_cast<IndexType>(i);
151 }
152
153 [[nodiscard]] constexpr auto fwd_prod_of_extents(rank_type i) const noexcept -> size_t
154 {
155 if constexpr (rank() == 0) {
156 return 1;
157 } else {
158 auto result = size_t(1);
159 for (auto e = rank_type(0); e < i; ++e) {
160 result *= static_cast<size_t>(extent(e));
161 }
162 return result;
163 }
164 }
165
166 [[nodiscard]] constexpr auto rev_prod_of_extents(rank_type i) const noexcept -> size_t
167 {
168 auto result = size_t(1);
169 for (auto e = i + 1; e < rank(); ++e) {
170 result *= static_cast<size_t>(extent(e));
171 }
172 return result;
173 }
174
175private:
176 TETL_NO_UNIQUE_ADDRESS array<IndexType, rank_dynamic()> _extents{};
177};
178
179namespace detail {
180
181template <typename IndexType, typename Integrals>
182struct dextents_impl;
183
184template <typename IndexType, etl::size_t... Integrals>
185struct dextents_impl<IndexType, etl::index_sequence<Integrals...>> {
186 using type = extents<IndexType, ((void)Integrals, dynamic_extent)...>;
187};
188
189} // namespace detail
190
191template <typename... Integrals>
193extents(Integrals...) -> extents<etl::size_t, etl::size_t((Integrals(), etl::dynamic_extent))...>;
194
195template <typename IndexType, etl::size_t Rank>
196using dextents = typename detail::dextents_impl<IndexType, etl::make_index_sequence<Rank>>::type;
197
198} // namespace etl
199
200#endif // TETL_MDSPAN_EXTENTS_HPP
#define TETL_NO_UNIQUE_ADDRESS
Definition attributes.hpp:41
constexpr auto transform(InputIt first, InputIt last, OutputIt dest, UnaryOp op) -> OutputIt
Applies the given function to a range and stores the result in another range, beginning at dest....
Definition transform.hpp:24
constexpr auto max(Type const &a, Type const &b, Compare comp) noexcept -> Type const &
Returns the greater of a and b, using a compare function.
Definition max.hpp:13
constexpr double e
Definition constants.hpp:29
constexpr auto dynamic_extent
etl::dynamic_extent is a constant of type etl::size_t that is used to differentiate etl::span of stat...
Definition dynamic_extent.hpp:14
constexpr auto cmp_not_equal(T t, U u) noexcept -> bool
Compare the values of two integers t and u. Unlike builtin comparison operators, negative signed inte...
Definition cmp_not_equal.hpp:20
Definition adjacent_find.hpp:8
constexpr auto operator==(inplace_function< R(Args...), Capacity, Alignment > const &f, nullptr_t) noexcept -> bool
Compares a etl::inplace_function with a null pointer. Empty functions (that is, functions without a c...
Definition inplace_function.hpp:262
etl::make_integer_sequence< etl::size_t, Size > make_index_sequence
Definition index_sequence.hpp:15
etl::integer_sequence< etl::size_t, Ints... > index_sequence
Definition index_sequence.hpp:12
extents(Integrals...) -> extents< etl::size_t, etl::size_t((Integrals(), etl::dynamic_extent))... >
typename make_unsigned< T >::type make_unsigned_t
Definition make_unsigned.hpp:75
span(c_array< Type, Extent > &) -> span< Type, Extent >
constexpr bool is_nothrow_constructible_v
Definition is_nothrow_constructible.hpp:50
typename detail::dextents_impl< IndexType, etl::make_index_sequence< Rank > >::type dextents
Definition extents.hpp:196
constexpr bool is_convertible_v
Definition is_convertible.hpp:46
TETL_BUILTIN_SIZET size_t
etl::size_t is the unsigned integer type of the result of the sizeof operator.
Definition size_t.hpp:14
A container that encapsulates fixed size arrays.
Definition array.hpp:48
array(T, U...) -> array< T, 1+sizeof...(U)>
One deduction guide is provided for array to provide an equivalent of experimental::make_array for co...
Definition extents.hpp:22
static constexpr auto rank() noexcept -> rank_type
Definition extents.hpp:53
static constexpr auto static_extent(rank_type i) noexcept -> etl::size_t
Definition extents.hpp:57
explicit(((Extents !=dynamic_extent and OtherExtents==dynamic_extent) or ...) or(numeric_limits< typename Extents::index_type >::max()< numeric_limits< OtherIndexType >::max())) const expr extents(extents< OtherIndexType
static constexpr auto rank_dynamic() noexcept -> rank_type
Definition extents.hpp:55
make_unsigned_t< typename Extents::index_type > size_type
Definition extents.hpp:24
constexpr extents() noexcept=default
constexpr auto extent(rank_type i) const noexcept -> index_type
Definition extents.hpp:62
Definition numeric_limits.hpp:17