Arduino Helpers master
Utility library for Arduino
Array.hpp
Go to the documentation of this file.
1/* ✔ */
2
3#pragma once
4
5#include <AH/Error/Error.hpp>
6#include <AH/STL/iterator>
7#include <AH/STL/type_traits> // conditional
8#include <stddef.h> // size_t
9
11
12template <class T>
13constexpr T abs_diff(const T &a, const T &b) {
14 return a < b ? b - a : a - b;
15}
16
19
20template <class T, size_t N, bool Reverse, bool Const>
21class ArraySlice;
22
31template <class T, size_t N>
32struct Array {
33 T data[N];
34 using type = T;
35 constexpr static size_t length = N;
36
46 T &operator[](size_t index) {
47 if (index >= N) { // TODO
48 ERROR(F("Index out of bounds: ") << index << F(" ≥ ") << N, 0xEDED);
49 index = N - 1; // LCOV_EXCL_LINE
50 } // LCOV_EXCL_LINE
51 return data[index];
52 }
53
63 const T &operator[](size_t index) const {
64 if (index >= N) { // TODO
65 ERROR(F("Index out of bounds: ") << index << F(" ≥ ") << N, 0xEDED);
66 index = N - 1; // LCOV_EXCL_LINE
67 } // LCOV_EXCL_LINE
68 return data[index];
69 }
70
74 T *begin() { return &data[0]; }
75
79 const T *begin() const { return &data[0]; }
80
84 T *end() { return &data[N]; }
85
89 const T *end() const { return &data[N]; }
90
97 bool operator==(const Array<T, N> &rhs) const {
98 if (this == &rhs)
99 return true;
100 for (size_t i = 0; i < N; i++)
101 if ((*this)[i] != rhs[i])
102 return false;
103 return true;
104 }
105
112 bool operator!=(const Array<T, N> &rhs) const { return !(*this == rhs); }
113
114 public:
126 template <size_t Start = 0, size_t End = N - 1>
127 ArraySlice<T, abs_diff(Start, End) + 1, (End < Start), false> slice();
128
133 template <size_t Start = 0, size_t End = N - 1>
134 ArraySlice<T, abs_diff(Start, End) + 1, (End < Start), true> slice() const;
135
140 template <size_t Start = 0, size_t End = N - 1>
141 ArraySlice<T, abs_diff(Start, End) + 1, (End < Start), true>
142 cslice() const {
143 const Array<T, N> *This = this;
144 return This->template slice<Start, End>();
145 }
146};
147
163template <class T, size_t N, bool Reverse = false, bool Const = true>
166 typename std::conditional<Const, const T &, T &>::type;
168 typename std::conditional<Const, const T *, T *>::type;
169
170 public:
173
175 operator Array<T, N>() const { return asArray(); }
176
178 Array<T, N> slice = {{}};
179 for (size_t i = 0; i < N; ++i)
180 slice[i] = (*this)[i];
181 return slice;
182 }
183
184 using iterator = typename std::conditional<
185 Reverse, std::reverse_iterator<ElementPtrType>, ElementPtrType>::type;
186
196 ElementRefType operator[](size_t index) const {
197 if (index >= N) { // TODO
198 ERROR(F("Index out of bounds: ") << index << F(" ≥ ") << N, 0xEDEF);
199 index = N - 1; // LCOV_EXCL_LINE
200 } // LCOV_EXCL_LINE
201 if (Reverse)
202 return *(array - index);
203 else
204 return *(array + index);
205 }
206
207 iterator begin() const {
208 if (Reverse)
209 return iterator {array + 1};
210 else
211 return iterator {array};
212 }
213
214 iterator end() const {
215 if (Reverse)
216 return iterator {array + 1 - N};
217 else
218 return iterator {array + N};
219 }
220
221 template <size_t Start, size_t End>
222 ArraySlice<T, abs_diff(End, Start) + 1, Reverse ^ (End < Start), Const>
223 slice() const;
224
225 private:
227};
228
229template <class T, size_t N>
230template <size_t Start, size_t End>
231inline ArraySlice<T, abs_diff(Start, End) + 1, (End < Start), false>
233 static_assert(Start < N, "");
234 static_assert(End < N, "");
235 return &(*this)[Start];
236}
237
238template <class T, size_t N>
239template <size_t Start, size_t End>
240inline ArraySlice<T, abs_diff(Start, End) + 1, (End < Start), true>
242 static_assert(Start < N, "");
243 static_assert(End < N, "");
244 return &(*this)[Start];
245}
246
247template <class T, size_t N, bool Reverse, bool Const>
248template <size_t Start, size_t End>
249ArraySlice<T, abs_diff(End, Start) + 1, Reverse ^ (End < Start), Const>
251 static_assert(Start < N, "");
252 static_assert(End < N, "");
253 return &(*this)[Start];
254}
255
257template <class T, size_t N, bool Reverse, bool Const>
261 return a + n;
262}
263
264// Equality ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
265
268template <class T1, class T2, size_t N1, size_t N2, bool Reverse1,
269 bool Reverse2, bool Const1, bool Const2>
272 static_assert(N1 == N2, "Error: sizes do not match");
273 for (size_t i = 0; i < N1; ++i)
274 if (a[i] != b[i])
275 return false;
276 return true;
277}
278
281template <class T1, class T2, size_t N1, size_t N2, bool Reverse2, bool Const2>
284 return a.slice() == b;
285}
286
289template <class T1, class T2, size_t N1, size_t N2, bool Reverse1, bool Const1>
291 const Array<T2, N2> &b) {
292 return a == b.slice();
293}
294
295// Inequality ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
296
299template <class T1, class T2, size_t N1, size_t N2, bool Reverse1,
300 bool Reverse2, bool Const1, bool Const2>
303 return !(a == b);
304}
305
308template <class T1, class T2, size_t N1, size_t N2, bool Reverse2, bool Const2>
311 return a.slice() != b;
312}
313
316template <class T1, class T2, size_t N1, size_t N2, bool Reverse1, bool Const1>
318 const Array<T2, N2> &b) {
319 return a != b.slice();
320}
321
322// Addition ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
323
326template <class T1, class T2, size_t N1, size_t N2, bool Reverse1,
327 bool Reverse2, bool Const1, bool Const2>
328Array<decltype(T1 {} + T2 {}), N1>
331 static_assert(N1 == N2, "Error: sizes do not match");
332 Array<decltype(T1 {} + T2 {}), N1> result = {{}};
333 for (size_t i = 0; i < N1; ++i)
334 result[i] = a[i] + b[i];
335 return result;
336}
337
340template <class T1, class T2, size_t N1, size_t N2>
341Array<decltype(T1 {} + T2 {}), N1> operator+(const Array<T1, N1> &a,
342 const Array<T2, N2> &b) {
343 return a.slice() + b.slice();
344}
345
348template <class T1, class T2, size_t N1, size_t N2, bool Reverse1,
349 bool Reverse2, bool Const1, bool Const2>
353 static_assert(N1 == N2, "Error: sizes do not match");
354 for (size_t i = 0; i < N1; ++i)
355 a[i] += b[i];
356 return a;
357}
358
361template <class T1, class T2, size_t N1, size_t N2>
363 a.slice() += b.slice();
364 return a;
365}
366
367// Subtraction :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
368
371template <class T1, class T2, size_t N1, size_t N2, bool Reverse1,
372 bool Reverse2, bool Const1, bool Const2>
373Array<decltype(T1 {} - T2 {}), N1>
376 static_assert(N1 == N2, "Error: sizes do not match");
377 Array<decltype(T1 {} - T2 {}), N1> result = {{}};
378 for (size_t i = 0; i < N1; ++i)
379 result[i] = a[i] - b[i];
380 return result;
381}
382
385template <class T1, class T2, size_t N1, size_t N2>
386Array<decltype(T1 {} - T2 {}), N1> operator-(const Array<T1, N1> &a,
387 const Array<T2, N2> &b) {
388 return a.slice() - b.slice();
389}
390
393template <class T1, class T2, size_t N1, size_t N2, bool Reverse1,
394 bool Reverse2, bool Const1, bool Const2>
398 static_assert(N1 == N2, "Error: sizes do not match");
399 for (size_t i = 0; i < N1; ++i)
400 a[i] -= b[i];
401 return a;
402}
403
406template <class T1, class T2, size_t N1, size_t N2>
408 a.slice() -= b.slice();
409 return a;
410}
411
412// Scalar Multiplication :::::::::::::::::::::::::::::::::::::::::::::::::::::::
413
416template <class T1, class T2, size_t N1, bool Reverse1, bool Const1>
417Array<decltype(T1 {} * T2 {}), N1>
419 Array<decltype(T1 {} * T2 {}), N1> result = {{}};
420 for (size_t i = 0; i < N1; ++i)
421 result[i] = a[i] * b;
422 return result;
423}
424
427template <class T1, class T2, size_t N1>
428Array<decltype(T1 {} * T2 {}), N1> operator*(const Array<T1, N1> &a, T2 b) {
429 return a.slice() * b;
430}
431
434template <class T1, class T2, size_t N2, bool Reverse2, bool Const2>
435Array<decltype(T1 {} * T2 {}), N2>
437 Array<decltype(T1 {} * T2 {}), N2> result = {{}};
438 for (size_t i = 0; i < N2; ++i)
439 result[i] = a * b[i];
440 return result;
441}
442
445template <class T1, class T2, size_t N2>
446Array<decltype(T1 {} * T2 {}), N2> operator*(T1 a, const Array<T2, N2> &b) {
447 return a * b.slice();
448}
449
452template <class T1, class T2, size_t N1, bool Reverse1, bool Const1>
455 for (size_t i = 0; i < N1; ++i)
456 a[i] *= b;
457 return a;
458}
459
462template <class T1, class T2, size_t N1>
464 a.slice() *= b;
465 return a;
466}
467
468// Scalar Division :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
469
472template <class T1, class T2, size_t N1, bool Reverse1, bool Const1>
473Array<decltype(T1 {} / T2 {}), N1>
475 Array<decltype(T1 {} / T2 {}), N1> result = {{}};
476 for (size_t i = 0; i < N1; ++i)
477 result[i] = a[i] / b;
478 return result;
479}
480
483template <class T1, class T2, size_t N1>
484Array<decltype(T1 {} / T2 {}), N1> operator/(const Array<T1, N1> &a, T2 b) {
485 return a.slice() / b;
486}
487
490template <class T1, class T2, size_t N1, bool Reverse1, bool Const1>
493 for (size_t i = 0; i < N1; ++i)
494 a[i] /= b;
495 return a;
496}
497
500template <class T1, class T2, size_t N1>
502 a.slice() /= b;
503 return a;
504}
505
506// Negation ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
507
510template <class T, size_t N, bool Reverse, bool Const>
511Array<decltype(-T {}), N> operator-(ArraySlice<T, N, Reverse, Const> a) {
512 Array<decltype(-T {}), N> result = {{}};
513 for (size_t i = 0; i < N; ++i)
514 result[i] = -a[i];
515 return result;
516}
517
520template <class T, size_t N>
521Array<decltype(-T {}), N> operator-(const Array<T, N> &a) {
522 return -a.slice();
523}
524
525// Type aliases ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
526
528template <class T, size_t NumRows, size_t NumCols>
530
532
constexpr T abs_diff(const T &a, const T &b)
Definition: Array.hpp:13
#define END_AH_NAMESPACE
#define BEGIN_AH_NAMESPACE
Class for a view on a slice of an array.
Definition: Array.hpp:164
iterator begin() const
Definition: Array.hpp:207
ElementPtrType array
Definition: Array.hpp:226
ArraySlice(ElementPtrType array)
Constructor.
Definition: Array.hpp:172
typename std::conditional< Const, const T &, T & >::type ElementRefType
Definition: Array.hpp:166
typename std::conditional< Reverse, std::reverse_iterator< ElementPtrType >, ElementPtrType >::type iterator
Definition: Array.hpp:185
iterator end() const
Definition: Array.hpp:214
typename std::conditional< Const, const T *, T * >::type ElementPtrType
Definition: Array.hpp:168
ElementRefType operator[](size_t index) const
Get the element at the given index.
Definition: Array.hpp:196
Array< T, N > asArray() const
Definition: Array.hpp:177
Array< T1, N1 > & operator*=(Array< T1, N1 > &a, T2 b)
Array *= Scalar.
Definition: Array.hpp:463
bool operator!=(ArraySlice< T1, N1, Reverse1, Const1 > a, ArraySlice< T2, N2, Reverse2, Const2 > b)
Slice != Slice.
Definition: Array.hpp:301
const ArraySlice< T1, N1, Reverse1, Const1 > & operator+=(const ArraySlice< T1, N1, Reverse1, Const1 > &a, const ArraySlice< T2, N2, Reverse2, Const2 > &b)
Slice += Slice.
Definition: Array.hpp:351
const ArraySlice< T1, N1, Reverse1, Const1 > & operator*=(const ArraySlice< T1, N1, Reverse1, Const1 > &a, T2 b)
Slice *= Scalar.
Definition: Array.hpp:454
const ArraySlice< T1, N1, Reverse1, Const1 > & operator/=(const ArraySlice< T1, N1, Reverse1, Const1 > &a, T2 b)
Slice /= Scalar.
Definition: Array.hpp:492
bool operator!=(const Array< T1, N1 > &a, ArraySlice< T2, N2, Reverse2, Const2 > b)
Array != Slice.
Definition: Array.hpp:309
bool operator==(const Array< T1, N1 > &a, ArraySlice< T2, N2, Reverse2, Const2 > b)
Array == Slice.
Definition: Array.hpp:282
Array< T1, N1 > & operator+=(Array< T1, N1 > &a, const Array< T2, N2 > &b)
Array += Array.
Definition: Array.hpp:362
bool operator==(ArraySlice< T1, N1, Reverse1, Const1 > a, ArraySlice< T2, N2, Reverse2, Const2 > b)
Slice == Slice.
Definition: Array.hpp:270
bool operator==(ArraySlice< T1, N1, Reverse1, Const1 > a, const Array< T2, N2 > &b)
Slice == Array.
Definition: Array.hpp:290
const ArraySlice< T1, N1, Reverse1, Const1 > & operator-=(const ArraySlice< T1, N1, Reverse1, Const1 > &a, const ArraySlice< T2, N2, Reverse2, Const2 > &b)
Slice -= Slice.
Definition: Array.hpp:396
ArraySlice< T, abs_diff(End, Start)+1, Reverse ^(End< Start), Const > slice() const
Definition: Array.hpp:250
ArraySlice< T, abs_diff(Start, End)+1,(End< Start), true > slice() const
Get a read-only view on a slice of the Array.
Definition: Array.hpp:241
Array< T1, N1 > & operator/=(Array< T1, N1 > &a, T2 b)
Array /= Scalar.
Definition: Array.hpp:501
bool operator!=(ArraySlice< T1, N1, Reverse1, Const1 > a, const Array< T2, N2 > &b)
Slice != Array.
Definition: Array.hpp:317
Array< T1, N1 > & operator-=(Array< T1, N1 > &a, const Array< T2, N2 > &b)
Array -= Array.
Definition: Array.hpp:407
ArraySlice< T, abs_diff(Start, End)+1,(End< Start), false > slice()
Get a view on a slice of the Array.
Definition: Array.hpp:232
ArraySlice< T, N, Reverse, Const >::iterator operator+(typename ArraySlice< T, N, Reverse, Const >::iterator::difference_type n, typename ArraySlice< T, N, Reverse, Const >::iterator a)
<T, N, Reverse, Const>::iterator
Definition: Array.hpp:258
#define ERROR(msg, errc)
Print the error message and error code, and stop the execution if FATAL_ERRORS are enabled.
Definition: Error.hpp:39
An array wrapper for easy copying, comparing, and iterating.
Definition: Array.hpp:32
static constexpr size_t length
Definition: Array.hpp:35
const T * end() const
Get a pointer to the memory beyond the array.
Definition: Array.hpp:89
T & operator[](size_t index)
Get the element at the given index.
Definition: Array.hpp:46
bool operator==(const Array< T, N > &rhs) const
Check the equality of all elements in two arrays.
Definition: Array.hpp:97
bool operator!=(const Array< T, N > &rhs) const
Check the inequality of all elements in two arrays.
Definition: Array.hpp:112
T data[N]
Definition: Array.hpp:33
T type
Definition: Array.hpp:34
T * begin()
Get a pointer to the first element.
Definition: Array.hpp:74
T * end()
Get a pointer to the memory beyond the array.
Definition: Array.hpp:84
ArraySlice< T, abs_diff(Start, End)+1,(End< Start), true > cslice() const
Get a read-only view on a slice of the Array.
Definition: Array.hpp:142
const T * begin() const
Get a pointer to the first element.
Definition: Array.hpp:79
const T & operator[](size_t index) const
Get the element at the given index.
Definition: Array.hpp:63