Control Surface master
MIDI Control Surface library for Arduino
ArrayHelpers.hpp
Go to the documentation of this file.
1/* ✔ */
2
3#pragma once
4
6
7AH_DIAGNOSTIC_WERROR() // Enable errors on warnings
8
9#include "Array.hpp"
10#include <AH/STL/algorithm>
11
12#if __cplusplus >= 201400L
13#define USE_CONSTEXPR_ARRAY_HELPERS constexpr
14#else
15#define USE_CONSTEXPR_ARRAY_HELPERS
16#endif
17
19
20namespace detail {
21
31template <class T, class V>
33 public:
34 USE_CONSTEXPR_ARRAY_HELPERS Incrementor(T start = 0, V increment = 1)
35 : value(start), increment(increment) {}
37 T temp = value;
38 value += increment;
39 return temp;
40 }
41
42 private:
44 const V increment;
45};
46
47} // namespace detail
48
51
67template <class T, size_t N, class G>
69 Array<T, N> array{{}};
70 std::generate(array.begin(), array.end(), generator);
71 return array;
72}
73
87template <size_t N, class G>
89 -> Array<decltype(generator()), N> {
90 Array<decltype(generator()), N> array{{}};
91 std::generate(array.begin(), array.end(), generator);
92 return array;
93}
94
108template <class T, size_t N, class U>
110 Array<T, N> dest{{}};
111 std::transform(std::begin(src), std::end(src), std::begin(dest),
112 [](const U &src) { return T(src); });
113 return dest;
114}
115
119template <class F, class U, size_t N>
120USE_CONSTEXPR_ARRAY_HELPERS Array<decltype(F{}(U{})), N>
121apply(const Array<U, N> &src, F f) {
122 Array<decltype(F{}(U{})), N> dest{{}};
123 std::transform(std::begin(src), std::end(src), std::begin(dest), f);
124 return dest;
125}
126
127#if !defined(__GNUC__) || (__GNUC__ > 7) || \
128 (__GNUC__ == 7 && __GNUC_MINOR__ >= 3) || defined(DOXYGEN)
132template <class T, size_t N, class... Args>
134 return generateArray<N>([&]() { return T{args...}; });
135}
136#else
137template <class T, size_t N, class... Args>
138USE_CONSTEXPR_ARRAY_HELPERS Array<T, N> fillArray(Args... args) {
139 Array<T, N> array{{}};
140 for (auto &el : array)
141 el = T{args...};
142 return array;
143}
144#endif
145
178template <class T, size_t N, class U, class V = U>
180generateIncrementalArray(U start = 0, V increment = V(1)) {
181 detail::Incrementor<U, V> g(start, increment);
182 return generateArray<T, N>(g);
183}
184
200template <class T, size_t M, size_t N>
202 const Array<T, N> &b) {
203 Array<T, M + N> result{{}};
204 size_t r = 0;
205 for (size_t i = 0; i < M; ++i, ++r)
206 result[r] = a[i];
207 for (size_t i = 0; i < N; ++i, ++r)
208 result[r] = b[i];
209 return result;
210}
211
212template <class T1, class T2, size_t N1, size_t N2, bool Reverse1,
213 bool Reverse2, bool Const1, bool Const2>
214USE_CONSTEXPR_ARRAY_HELPERS Array<decltype(T1() * T2()), N1 + N2 - 1>
217 Array<decltype(T1() * T2()), N1 + N2 - 1> result = {{}};
218 for (size_t i = 0; i < N1; ++i)
219 for (size_t j = 0; j < N2; ++j)
220 result[i + j] += a[i] * b[j];
221 return result;
222}
223
224template <class T1, class T2, size_t N1, size_t N2, bool Reverse1, bool Const1>
225USE_CONSTEXPR_ARRAY_HELPERS Array<decltype(T1() * T2()), N1 + N2 - 1>
227 const Array<T2, N2> &b) {
228 return distribute(a, b.slice());
229}
230
231template <class T1, class T2, size_t N1, size_t N2, bool Reverse2, bool Const2>
232USE_CONSTEXPR_ARRAY_HELPERS Array<decltype(T1() * T2()), N1 + N2 - 1>
235 return distribute(a.slice(), b);
236}
237
238template <class T1, class T2, size_t N1, size_t N2>
239USE_CONSTEXPR_ARRAY_HELPERS Array<decltype(T1() * T2()), N1 + N2 - 1>
241 return distribute(a.slice(), b.slice());
242}
243
245
247
248#ifndef ARDUINO
249
250#include <ostream>
251
253
254template <class T, size_t N, bool Reverse, bool Const>
255std::enable_if_t<std::is_arithmetic<T>::value, std::ostream &>
256operator<<(std::ostream &os, const AH::ArraySlice<T, N, Reverse, Const> &a) {
257 for (const T &el : a.template slice<0, N - 2>())
258 os << el << ", ";
259 os << a[N - 1];
260 return os;
261}
262
263template <class T, size_t N>
264std::enable_if_t<std::is_arithmetic<T>::value, std::ostream &>
265operator<<(std::ostream &os, const AH::Array<T, N> &a) {
266 return os << a.slice();
267}
268
270
271#endif
272
274
276
277template <class T, size_t N, bool Reverse, bool Const>
278std::enable_if_t<std::is_arithmetic<T>::value, Print &>
280 for (const T &el : a.template slice<0, N - 2>())
281 os << el << ", ";
282 os << a[N - 1];
283 return os;
284}
285
286template <class T, size_t N>
287std::enable_if_t<std::is_arithmetic<T>::value, Print &>
288operator<<(Print &os, const AH::Array<T, N> &a) {
289 return os << a.slice();
290}
291
293
#define END_AH_NAMESPACE
#define BEGIN_AH_NAMESPACE
#define USE_CONSTEXPR_ARRAY_HELPERS
#define AH_DIAGNOSTIC_POP()
Definition: Warnings.hpp:36
#define AH_DIAGNOSTIC_WERROR()
Definition: Warnings.hpp:35
Class for a view on a slice of an array.
Definition: Array.hpp:168
Utility class that acts as a functor to return incremental values.
Incrementor(T start=0, V increment=1)
Array< T, N > copyAs(const Array< U, N > &src)
Copy an Array to an Array of a different type.
Array< decltype(F{}(U{})), N > apply(const Array< U, N > &src, F f)
Apply a function to all elements of the array and return a copy.
Array< decltype(T1() *T2()), N1+N2 - 1 > distribute(const Array< T1, N1 > &a, const Array< T2, N2 > &b)
Array< T, N > fillArray(Args... args)
Fill the array with the same value for each element.
Array< T, N > generateIncrementalArray(U start=0, V increment=V(1))
Generate an array where the first value is given, and the subsequent values are calculated as the pre...
auto generateArray(G generator) -> Array< decltype(generator()), N >
Generate an array using the given generator.
Array< T, M+N > cat(const Array< T, M > &a, const Array< T, N > &b)
Concatenate two arrays.
ArraySlice< T, abs_diff(Start, End)+1,(End< Start), false > slice()
Get a view on a slice of the Array.
Definition: Array.hpp:309
Print & operator<<(Print &os, Quaternion e)
Printing.
Definition: Quaternion.cpp:28
constexpr Note G
G (Sol)
Definition: Notes.hpp:47
An array wrapper for easy copying, comparing, and iterating.
Definition: Array.hpp:36