tesseract++ 0.0.1
N-dimensional tensor library for embedded systems
Loading...
Searching...
No Matches
strided_layout_constexpr.h
Go to the documentation of this file.
1#pragma once
2
3#include "config.h"
4#include "containers/array.h"
5#include "helper_traits.h"
6
7template <bool Enabled, my_size_t... Vals>
9{
10 static constexpr bool unique = true;
11 static constexpr my_size_t max_val = 0;
12 static constexpr my_size_t min_val = 0;
13};
14
15template <my_size_t... Vals>
16struct PermValidation<true, Vals...>
17{
18 static constexpr bool unique = all_unique<Vals...>();
19 static constexpr my_size_t max_val = max_value<Vals...>();
20 static constexpr my_size_t min_val = min_value<Vals...>();
21};
22
36template <typename PadPolicy, my_size_t... Perm>
38{
39 static constexpr my_size_t NumDims = PadPolicy::NumDims;
40 static constexpr my_size_t LogicalSize = PadPolicy::LogicalSize;
41 static constexpr my_size_t PhysicalSize = PadPolicy::PhysicalSize;
42 static constexpr bool IsPermProvided = sizeof...(Perm) > 0;
43
44 using PadPolicyType = PadPolicy;
45
46private:
47 using PermCheck = PermValidation<IsPermProvided, Perm...>;
48
49 static_assert(!IsPermProvided || sizeof...(Perm) == NumDims,
50 "Permutation must match number of dimensions");
51
52 static_assert(!IsPermProvided || PermCheck::unique,
53 "Permutations must be unique");
54
55 static_assert(!IsPermProvided || PermCheck::max_val < NumDims,
56 "Max value of permutation pack must be less than number of dimensions");
57
58 static_assert(!IsPermProvided || PermCheck::min_val == 0,
59 "Min value of permutation pack is not equal to 0");
60
67 static constexpr Array<my_size_t, NumDims> computePermArray() noexcept
68 {
69 if constexpr (IsPermProvided)
70 {
71 return Array<my_size_t, NumDims>{Perm...};
72 }
73 else
74 {
76 for (my_size_t i = 0; i < NumDims; ++i)
77 {
78 result[i] = i;
79 }
80 return result;
81 }
82 }
83
88 static constexpr Array<my_size_t, NumDims> PermArray = computePermArray();
89
97 static constexpr Array<my_size_t, NumDims> computeInversePermArray() noexcept
98 {
100 for (my_size_t i = 0; i < NumDims; ++i)
101 {
102 result[PermArray[i]] = i;
103 }
104 return result;
105 }
106
111 static constexpr Array<my_size_t, NumDims> InversePermArray = computeInversePermArray();
112
118 static constexpr Array<my_size_t, NumDims> computeLogicalDims() noexcept
119 {
121 for (my_size_t i = 0; i < NumDims; ++i)
122 {
123 result[i] = PadPolicy::LogicalDims[PermArray[i]];
124 }
125 return result;
126 }
127
132 static constexpr Array<my_size_t, NumDims> LogicalDims = computeLogicalDims();
133
139 static constexpr Array<my_size_t, NumDims> computeBaseStrides() noexcept
140 {
142 result[NumDims - 1] = 1;
143 for (my_size_t i = NumDims - 1; i > 0; --i)
144 {
145 result[i - 1] = result[i] * PadPolicy::PhysicalDims[i];
146 }
147 return result;
148 }
149
154 static constexpr Array<my_size_t, NumDims> BaseStrides = computeBaseStrides();
155
161 static constexpr Array<my_size_t, NumDims> computeStrides() noexcept
162 {
163 // Permute the BaseStrides
165 for (my_size_t i = 0; i < NumDims; ++i)
166 {
167 result[i] = BaseStrides[PermArray[i]];
168 }
169 return result;
170 }
171
176 static constexpr Array<my_size_t, NumDims> Strides = computeStrides();
177
183 static constexpr Array<my_size_t, NumDims> computeLogicalStrides() noexcept
184 {
186 result[NumDims - 1] = 1;
187 for (my_size_t i = NumDims - 1; i > 0; --i)
188 {
189 result[i - 1] = result[i] * LogicalDims[i];
190 }
191 return result;
192 }
193
198 static constexpr Array<my_size_t, NumDims> LogicalStrides = computeLogicalStrides();
199
200public:
206 FORCE_INLINE static constexpr my_size_t num_dims() noexcept { return NumDims; }
207
216 {
217 return PermArray.at(i);
218 }
219
228 {
229 return InversePermArray.at(i);
230 }
231
240 {
241 return LogicalDims.at(i);
242 }
243
252 {
253 return BaseStrides.at(i);
254 }
255
264 {
265 return Strides.at(i);
266 }
267
276 {
277 return LogicalStrides.at(i);
278 }
279
280 // ========================================================================
281 // INDEX CONVERSION
282 // ========================================================================
283
291 {
292 if (logical_flat >= LogicalSize)
293 {
294 MyErrorHandler::error("logical_flat_to_physical_flat: logical_flat index out of bounds");
295 }
296 my_size_t offset = 0;
297 for (my_size_t i = 0; i < NumDims; ++i)
298 {
299 const my_size_t s = LogicalStrides[i];
300 const my_size_t idx = logical_flat / s;
301 logical_flat -= idx * s;
302 offset += idx * Strides[i];
303 }
304 return offset;
305 }
306
312 FORCE_INLINE static constexpr bool is_logical_index_in_bounds(const my_size_t (&indices)[NumDims]) noexcept
313 {
314 for (my_size_t i = 0; i < NumDims; ++i)
315 {
316 if (indices[i] >= LogicalDims[i])
317 return false;
318 }
319 return true;
320 }
321
329 {
330 if (!is_logical_index_in_bounds(indices))
331 {
332 MyErrorHandler::error("logical_coords_to_physical_flat: index out of bounds for logical dimension");
333 }
334
335 my_size_t flat = 0;
336 for (my_size_t i = 0; i < NumDims; ++i)
337 {
338 flat += indices[i] * Strides[i];
339 }
340 return flat;
341 }
342
351 template <typename... Indices>
353 {
354 static_assert(sizeof...(Indices) == NumDims, "Wrong number of indices");
355 my_size_t idx_arr[] = {static_cast<my_size_t>(indices)...};
356 return logical_coords_to_physical_flat(idx_arr);
357 }
358
379 {
380 // check logical_flat is in range
381 if (logical_flat >= LogicalSize)
382 {
383 MyErrorHandler::error("logical_flat_to_logical_coords: logical_flat index out of bounds");
384 }
385 for (my_size_t i = 0; i < NumDims; ++i)
386 {
387 const my_size_t s = LogicalStrides[i];
388 const my_size_t idx = logical_flat / s;
389 indices[i] = idx;
390 logical_flat -= idx * s;
391 }
392 }
393
417 {
418 // check physical_flat is in range
419 if (physical_flat >= PhysicalSize)
420 {
421 MyErrorHandler::error("physical_flat_to_physical_coords: physical_flat index out of bounds");
422 }
423
424 for (my_size_t i = 0; i < NumDims; ++i)
425 {
426 const my_size_t s = BaseStrides[i];
427 const my_size_t idx = physical_flat / s;
428 indices[i] = idx;
429 physical_flat -= idx * s;
430 }
431 }
432
433 // ========================================================================
434 // REVERSE CONVERSION
435 // ========================================================================
436
464 {
465 if (physical_flat >= PhysicalSize)
466 {
467 MyErrorHandler::error("physical_flat_to_logical_coords: physical_flat index out of bounds");
468 }
469 // Step 1: Decompose into physical (unpermuted) coords
470 my_size_t physical_coords[NumDims];
471 for (my_size_t i = 0; i < NumDims; ++i)
472 {
473 const my_size_t s = BaseStrides[i];
474 const my_size_t idx = physical_flat / s;
475 physical_coords[i] = idx;
476 physical_flat -= idx * s;
477 }
478
479 // Step 2: Apply forward permutation
480 // logical[i] = physical[PermArray[i]]
481 for (my_size_t i = 0; i < NumDims; ++i)
482 {
483 indices[i] = physical_coords[PermArray[i]];
484 }
485 }
486};
static void error(const T &msg)
Definition error_handler.h:30
Global configuration for the tesseract tensor library.
#define my_size_t
Size/index type used throughout the library.
Definition config.h:126
#define TESSERACT_CONDITIONAL_NOEXCEPT
Definition config.h:56
#define FORCE_INLINE
Hint the compiler to always inline a function.
Definition config.h:26
consteval my_size_t max_value()
Compile-time maximum of a non-type parameter pack.
Definition helper_traits.h:49
consteval my_size_t min_value()
Compile-time minimum of a non-type parameter pack.
Definition helper_traits.h:68
consteval bool all_unique()
Check if all values in a pack are unique.
Definition helper_traits.h:133
Fixed-size array container for embedded systems.
Definition array.h:21
constexpr T & at(my_size_t i)
Definition array.h:42
Definition strided_layout_constexpr.h:9
static constexpr bool unique
Definition strided_layout_constexpr.h:10
static constexpr my_size_t max_val
Definition strided_layout_constexpr.h:11
static constexpr my_size_t min_val
Definition strided_layout_constexpr.h:12
Compile-time strided layout with optional permutation.
Definition strided_layout_constexpr.h:38
static FORCE_INLINE constexpr my_size_t inverse_perm_array(my_size_t i) TESSERACT_CONDITIONAL_NOEXCEPT
Get inverse permutation at dimension i.
Definition strided_layout_constexpr.h:227
static FORCE_INLINE constexpr void logical_flat_to_logical_coords(my_size_t logical_flat, my_size_t(&indices)[NumDims]) TESSERACT_CONDITIONAL_NOEXCEPT
Logical flat index to logical coordinates.
Definition strided_layout_constexpr.h:378
static FORCE_INLINE constexpr my_size_t logical_stride(my_size_t i) TESSERACT_CONDITIONAL_NOEXCEPT
Get logical stride at dimension i (for flat index decomposition).
Definition strided_layout_constexpr.h:275
static constexpr bool IsPermProvided
Definition strided_layout_constexpr.h:42
static constexpr my_size_t NumDims
Definition strided_layout_constexpr.h:39
PadPolicy PadPolicyType
Definition strided_layout_constexpr.h:44
static FORCE_INLINE constexpr my_size_t num_dims() noexcept
Get number of dimensions.
Definition strided_layout_constexpr.h:206
static FORCE_INLINE constexpr my_size_t perm_array(my_size_t i) TESSERACT_CONDITIONAL_NOEXCEPT
Get permutation at dimension i.
Definition strided_layout_constexpr.h:215
static FORCE_INLINE constexpr my_size_t logical_coords_to_physical_flat(Indices... indices) TESSERACT_CONDITIONAL_NOEXCEPT
Logical coordinates (variadic multi-index) to physical flat index (bounds-checked).
Definition strided_layout_constexpr.h:352
static constexpr my_size_t PhysicalSize
Definition strided_layout_constexpr.h:41
static FORCE_INLINE constexpr void physical_flat_to_physical_coords(my_size_t physical_flat, my_size_t(&indices)[NumDims]) TESSERACT_CONDITIONAL_NOEXCEPT
Physical flat index to physical coordinates.
Definition strided_layout_constexpr.h:416
static FORCE_INLINE constexpr my_size_t logical_flat_to_physical_flat(my_size_t logical_flat) TESSERACT_CONDITIONAL_NOEXCEPT
Definition strided_layout_constexpr.h:290
static FORCE_INLINE constexpr my_size_t stride(my_size_t i) TESSERACT_CONDITIONAL_NOEXCEPT
Get physical stride at dimension i (with permutation applied).
Definition strided_layout_constexpr.h:263
static FORCE_INLINE constexpr bool is_logical_index_in_bounds(const my_size_t(&indices)[NumDims]) noexcept
Check if logical multi-index is in bounds.
Definition strided_layout_constexpr.h:312
static constexpr my_size_t LogicalSize
Definition strided_layout_constexpr.h:40
static FORCE_INLINE constexpr void physical_flat_to_logical_coords(my_size_t physical_flat, my_size_t(&indices)[NumDims]) TESSERACT_CONDITIONAL_NOEXCEPT
Physical flat index to logical coordinates.
Definition strided_layout_constexpr.h:463
static FORCE_INLINE constexpr my_size_t base_stride(my_size_t i) TESSERACT_CONDITIONAL_NOEXCEPT
Get base stride at dimension i (unpermuted, for physical decomposition).
Definition strided_layout_constexpr.h:251
static FORCE_INLINE constexpr my_size_t logical_coords_to_physical_flat(const my_size_t(&indices)[NumDims]) TESSERACT_CONDITIONAL_NOEXCEPT
Logical coordinates (Array multi-index) to physical flat index (bounds-checked).
Definition strided_layout_constexpr.h:328
static FORCE_INLINE constexpr my_size_t logical_dim(my_size_t i) TESSERACT_CONDITIONAL_NOEXCEPT
Get logical dimension at index i (with permutation applied).
Definition strided_layout_constexpr.h:239