Expression Templates Library (ETL)
index.hpp
Go to the documentation of this file.
1 //=======================================================================
2 // Copyright (c) 2014-2023 Baptiste Wicht
3 // Distributed under the terms of the MIT License.
4 // (See accompanying file LICENSE or copy at
5 // http://opensource.org/licenses/MIT)
6 //=======================================================================
7 
13 #pragma once
14 
15 namespace etl {
16 
17 namespace detail {
18 
19 template <typename M, size_t I>
20 inline constexpr size_t matrix_subsize() {
21  if constexpr (I < decay_traits<M>::dimensions() - 1) {
22  return decay_traits<M>::template dim<I + 1>() * matrix_subsize<M, I + 1>();
23  } else {
24  return 1;
25  }
26 }
27 
28 template <typename M, size_t I>
29 inline constexpr size_t matrix_leadingsize() {
30  if constexpr (I > 0) {
31  return decay_traits<M>::template dim<I - 1>() * matrix_leadingsize<M, I - 1>();
32  } else {
33  return 1;
34  }
35 }
36 
40 template <typename M, size_t I>
41 constexpr size_t rm_compute_index(size_t first) noexcept(assert_nothrow) {
42  cpp_assert(first < decay_traits<M>::template dim<I>(), "Out of bounds");
43  return first;
44 }
45 
49 template <typename M, size_t I, typename... S>
50 constexpr size_t rm_compute_index(size_t first, size_t second, S... args) noexcept(assert_nothrow) {
51  cpp_assert(first < decay_traits<M>::template dim<I>(), "Out of bounds");
52  return matrix_subsize<M, I>() * first + rm_compute_index<M, I + 1>(second, args...);
53 }
54 
58 template <typename M, size_t I>
59 constexpr size_t cm_compute_index(size_t first) noexcept(assert_nothrow) {
60  cpp_assert(first < M::template dim<I>(), "Out of bounds");
61  return matrix_leadingsize<M, I>() * first;
62 }
63 
67 template <typename M, size_t I, typename... S>
68 constexpr size_t cm_compute_index(size_t first, size_t second, S... args) noexcept(assert_nothrow) {
69  cpp_assert(first < M::template dim<I>(), "Out of bounds");
70  return matrix_leadingsize<M, I>() * first + cm_compute_index<M, I + 1>(second, args...);
71 }
72 
73 } // end of namespace detail
74 
75 //Note: Version with sizes moved to a std::array and accessed with
76 //standard loop may be faster, but need some stack space (relevant ?)
77 
83 template <etl_1d T>
84 constexpr size_t fast_index(size_t i) noexcept(assert_nothrow) {
85  cpp_assert(i < decay_traits<T>::template dim<0>(), "Out of bounds");
86 
87  return i;
88 }
89 
96 template <etl_2d T>
97 constexpr size_t fast_index(size_t i, size_t j) noexcept(assert_nothrow) {
99  cpp_assert(i < decay_traits<T>::template dim<0>(), "Out of bounds");
100  cpp_assert(j < decay_traits<T>::template dim<1>(), "Out of bounds");
101 
102  return i * decay_traits<T>::template dim<1>() + j;
103  } else {
104  cpp_assert(i < decay_traits<T>::template dim<0>(), "Out of bounds");
105  cpp_assert(j < decay_traits<T>::template dim<1>(), "Out of bounds");
106 
107  return i + j * decay_traits<T>::template dim<0>();
108  }
109 }
110 
118 template <etl_3d T>
119 constexpr size_t fast_index(size_t i, size_t j, size_t k) noexcept(assert_nothrow) {
121  cpp_assert(i < decay_traits<T>::template dim<0>(), "Out of bounds");
122  cpp_assert(j < decay_traits<T>::template dim<1>(), "Out of bounds");
123  cpp_assert(k < decay_traits<T>::template dim<2>(), "Out of bounds");
124 
125  return i * decay_traits<T>::template dim<1>() * decay_traits<T>::template dim<2>() + j * decay_traits<T>::template dim<2>() + k;
126  } else {
127  cpp_assert(i < decay_traits<T>::template dim<0>(), "Out of bounds");
128  cpp_assert(j < decay_traits<T>::template dim<1>(), "Out of bounds");
129  cpp_assert(k < decay_traits<T>::template dim<2>(), "Out of bounds");
130 
131  return i + j * decay_traits<T>::template dim<0>() + k * decay_traits<T>::template dim<0>() * decay_traits<T>::template dim<1>();
132  }
133 }
134 
143 template <etl_4d T>
144 constexpr size_t fast_index(size_t i, size_t j, size_t k, size_t l) noexcept(assert_nothrow) {
146  cpp_assert(i < decay_traits<T>::template dim<0>(), "Out of bounds");
147  cpp_assert(j < decay_traits<T>::template dim<1>(), "Out of bounds");
148  cpp_assert(k < decay_traits<T>::template dim<2>(), "Out of bounds");
149  cpp_assert(l < decay_traits<T>::template dim<3>(), "Out of bounds");
150 
151  return i * decay_traits<T>::template dim<1>() * decay_traits<T>::template dim<2>() * decay_traits<T>::template dim<3>()
152  + j * decay_traits<T>::template dim<2>() * decay_traits<T>::template dim<3>() + k * decay_traits<T>::template dim<3>() + l;
153  } else {
154  cpp_assert(i < decay_traits<T>::template dim<0>(), "Out of bounds");
155  cpp_assert(j < decay_traits<T>::template dim<1>(), "Out of bounds");
156  cpp_assert(k < decay_traits<T>::template dim<2>(), "Out of bounds");
157  cpp_assert(l < decay_traits<T>::template dim<3>(), "Out of bounds");
158 
159  return i + j * decay_traits<T>::template dim<0>() + k * decay_traits<T>::template dim<0>() * decay_traits<T>::template dim<1>()
161  }
162 }
163 
169 template <typename T, typename... S>
170 constexpr size_t fast_index(S... sizes) noexcept(assert_nothrow) requires(sizeof...(S) > 4 && decay_traits<T>::dimensions() == sizeof...(S)) {
172  return detail::rm_compute_index<T, 0>(sizes...);
173  } else {
174  return detail::cm_compute_index<T, 0>(sizes...);
175  }
176 }
177 
178 // Dynamic index (row major)
179 
186 template <etl_1d T>
187 size_t dyn_index([[maybe_unused]] const T& expression, size_t i) noexcept(assert_nothrow) {
188  cpp_assert(i < decay_traits<T>::dim(expression, 0), "Out of bounds");
189 
190  return i;
191 }
192 
200 template <etl_2d T>
201 size_t dyn_index(const T& expression, size_t i, size_t j) noexcept(assert_nothrow) {
203  cpp_assert(i < decay_traits<T>::dim(expression, 0), "Out of bounds");
204  cpp_assert(j < decay_traits<T>::dim(expression, 1), "Out of bounds");
205 
206  return i * decay_traits<T>::dim(expression, 1) + j;
207  } else {
208  cpp_assert(i < decay_traits<T>::dim(expression, 0), "Out of bounds");
209  cpp_assert(j < decay_traits<T>::dim(expression, 1), "Out of bounds");
210 
211  return i + j * decay_traits<T>::dim(expression, 0);
212  }
213 }
214 
223 template <etl_3d T>
224 size_t dyn_index(const T& expression, size_t i, size_t j, size_t k) noexcept(assert_nothrow) {
226  cpp_assert(i < decay_traits<T>::dim(expression, 0), "Out of bounds");
227  cpp_assert(j < decay_traits<T>::dim(expression, 1), "Out of bounds");
228  cpp_assert(k < decay_traits<T>::dim(expression, 2), "Out of bounds");
229 
230  return i * decay_traits<T>::dim(expression, 1) * decay_traits<T>::dim(expression, 2) + j * decay_traits<T>::dim(expression, 2) + k;
231  } else {
232  cpp_assert(i < decay_traits<T>::dim(expression, 0), "Out of bounds");
233  cpp_assert(j < decay_traits<T>::dim(expression, 1), "Out of bounds");
234  cpp_assert(k < decay_traits<T>::dim(expression, 2), "Out of bounds");
235 
236  return i + j * decay_traits<T>::dim(expression, 0) + k * decay_traits<T>::dim(expression, 0) * decay_traits<T>::dim(expression, 1);
237  }
238 }
239 
249 template <etl_4d T>
250 size_t dyn_index(const T& expression, size_t i, size_t j, size_t k, size_t l) noexcept(assert_nothrow) {
252  cpp_assert(i < decay_traits<T>::dim(expression, 0), "Out of bounds");
253  cpp_assert(j < decay_traits<T>::dim(expression, 1), "Out of bounds");
254  cpp_assert(k < decay_traits<T>::dim(expression, 2), "Out of bounds");
255  cpp_assert(l < decay_traits<T>::dim(expression, 3), "Out of bounds");
256 
257  return i * decay_traits<T>::dim(expression, 1) * decay_traits<T>::dim(expression, 2) * decay_traits<T>::dim(expression, 3)
258  + j * decay_traits<T>::dim(expression, 2) * decay_traits<T>::dim(expression, 3) + k * decay_traits<T>::dim(expression, 3) + l;
259  } else {
260  cpp_assert(i < decay_traits<T>::dim(expression, 0), "Out of bounds");
261  cpp_assert(j < decay_traits<T>::dim(expression, 1), "Out of bounds");
262  cpp_assert(k < decay_traits<T>::dim(expression, 2), "Out of bounds");
263  cpp_assert(l < decay_traits<T>::dim(expression, 3), "Out of bounds");
264 
265  return i + j * decay_traits<T>::dim(expression, 0) + k * decay_traits<T>::dim(expression, 0) * decay_traits<T>::dim(expression, 1)
266  + l * decay_traits<T>::dim(expression, 0) * decay_traits<T>::dim(expression, 1) * decay_traits<T>::dim(expression, 2);
267  }
268 }
269 
276 template <typename T, typename... S>
277 size_t dyn_index(const T& expression, S... sizes) noexcept(assert_nothrow) requires(sizeof...(S) > 4 && decay_traits<T>::dimensions() == sizeof...(S)) {
279  size_t index = 0;
280  size_t subsize = decay_traits<T>::size(expression);
281  size_t i = 0;
282 
283  cpp::for_each_in(
284  [&subsize, &index, &i, &expression](size_t s) {
285  cpp_assert(s < decay_traits<T>::dim(expression, i), "Out of bounds");
286  subsize /= decay_traits<T>::dim(expression, i++);
287  index += subsize * s;
288  },
289  sizes...);
290 
291  return index;
292  } else {
293  size_t index = 0;
294  size_t subsize = 1;
295  size_t i = 0;
296 
297  cpp::for_each_in(
298  [&subsize, &index, &i, &expression](size_t s) {
299  cpp_assert(s < decay_traits<T>::dim(expression, i), "Out of bounds");
300  index += subsize * s;
301  subsize *= decay_traits<T>::dim(expression, i++);
302  },
303  sizes...);
304 
305  return index;
306  }
307 }
308 
309 } //end of namespace etl
auto s(T &&value)
Force the evaluation of the given expression.
Definition: stop.hpp:18
constexpr size_t fast_index(size_t i) noexcept(assert_nothrow)
Compute the index for a 1D fast matrix.
Definition: index.hpp:84
Traits to get information about ETL types.
Definition: tmp.hpp:68
Root namespace for the ETL library.
Definition: adapter.hpp:15
static constexpr size_t dimensions()
Return the number of dimensions of the expression.
Definition: traits_base.hpp:31
auto dim(E &&value, size_t i) -> detail::identity_helper< E, dim_view< detail::build_identity_type< E >, D >>
Return a view representing the ith Dth dimension.
Definition: view_expression_builder.hpp:25
requires(D > 0) struct dyn_base
Matrix with run-time fixed dimensions.
Definition: dyn_base.hpp:113
constexpr size_t rm_compute_index(size_t first) noexcept(assert_nothrow)
Compute the index inside the row major matrix.
Definition: index.hpp:41
constexpr size_t cm_compute_index(size_t first) noexcept(assert_nothrow)
Compute the index inside the column major matrix.
Definition: index.hpp:59
Row-Major storage.
size_t subsize(const E &expr)
Returns the sub-size of the given ETL expression, i.e. the size not considering the first dimension...
Definition: helpers.hpp:118
size_t dyn_index([[maybe_unused]] const T &expression, size_t i) noexcept(assert_nothrow)
Compute the index for a 1D dynamic matrix.
Definition: index.hpp:187