Control Surface main
MIDI Control Surface library for Arduino
Loading...
Searching...
No Matches
ArrayHelpers.hpp
Go to the documentation of this file.
1/* ✔ */
2
3#pragma once
4
5#include "Array.hpp"
6#include <AH/STL/algorithm>
7
8#if __cplusplus >= 201400L
9#define USE_CONSTEXPR_ARRAY_HELPERS constexpr
10#else
11#define USE_CONSTEXPR_ARRAY_HELPERS
12#endif
13
15
16namespace detail {
17
27template <class T, class V>
29 public:
30 USE_CONSTEXPR_ARRAY_HELPERS Incrementor(T start = 0, V increment = 1)
31 : value(start), increment(increment) {}
33 T temp = value;
34 value += increment;
35 return temp;
36 }
37
38 private:
40 const V increment;
41};
42
43} // namespace detail
44
47
63template <class T, size_t N, class G>
65 Array<T, N> array{{}};
66 std::generate(array.begin(), array.end(), generator);
67 return array;
68}
69
83template <size_t N, class G>
85 -> Array<decltype(generator()), N> {
86 Array<decltype(generator()), N> array{{}};
87 std::generate(array.begin(), array.end(), generator);
88 return array;
89}
90
104template <class T, size_t N, class U>
106 Array<T, N> dest{{}};
107 std::transform(std::begin(src), std::end(src), std::begin(dest),
108 [](const U &src) { return T(src); });
109 return dest;
110}
111
115template <class F, class U, size_t N>
116USE_CONSTEXPR_ARRAY_HELPERS Array<decltype(F{}(U{})), N>
117apply(const Array<U, N> &src, F f) {
118 Array<decltype(F{}(U{})), N> dest{{}};
119 std::transform(std::begin(src), std::end(src), std::begin(dest), f);
120 return dest;
121}
122
123#if !defined(__GNUC__) || (__GNUC__ > 7) || \
124 (__GNUC__ == 7 && __GNUC_MINOR__ >= 3) || defined(DOXYGEN)
128template <class T, size_t N, class... Args>
130 return generateArray<N>([&]() { return T{args...}; });
131}
132#else
133template <class T, size_t N, class... Args>
134USE_CONSTEXPR_ARRAY_HELPERS Array<T, N> fillArray(Args... args) {
135 Array<T, N> array{{}};
136 for (auto &el : array)
137 el = T{args...};
138 return array;
139}
140#endif
141
174template <class T, size_t N, class U, class V = U>
176generateIncrementalArray(U start = 0, V increment = V(1)) {
177 detail::Incrementor<U, V> g(start, increment);
178 return generateArray<T, N>(g);
179}
180
196template <class T, size_t M, size_t N>
198 const Array<T, N> &b) {
200 size_t r = 0;
201 for (size_t i = 0; i < M; ++i, ++r)
202 result[r] = a[i];
203 for (size_t i = 0; i < N; ++i, ++r)
204 result[r] = b[i];
205 return result;
206}
207
208template <class T1, class T2, size_t N1, size_t N2, bool Reverse1,
209 bool Reverse2, bool Const1, bool Const2>
210USE_CONSTEXPR_ARRAY_HELPERS Array<decltype(T1() * T2()), N1 + N2 - 1>
213 Array<decltype(T1() * T2()), N1 + N2 - 1> result = {{}};
214 for (size_t i = 0; i < N1; ++i)
215 for (size_t j = 0; j < N2; ++j)
216 result[i + j] += a[i] * b[j];
217 return result;
218}
219
220template <class T1, class T2, size_t N1, size_t N2, bool Reverse1, bool Const1>
221USE_CONSTEXPR_ARRAY_HELPERS Array<decltype(T1() * T2()), N1 + N2 - 1>
223 const Array<T2, N2> &b) {
224 return distribute(a, b.slice());
225}
226
227template <class T1, class T2, size_t N1, size_t N2, bool Reverse2, bool Const2>
228USE_CONSTEXPR_ARRAY_HELPERS Array<decltype(T1() * T2()), N1 + N2 - 1>
231 return distribute(a.slice(), b);
232}
233
234template <class T1, class T2, size_t N1, size_t N2>
235USE_CONSTEXPR_ARRAY_HELPERS Array<decltype(T1() * T2()), N1 + N2 - 1>
237 return distribute(a.slice(), b.slice());
238}
239
241
243
244#ifndef ARDUINO
245
246#include <ostream>
247
249
250template <class T, size_t N, bool Reverse, bool Const>
251std::enable_if_t<std::is_arithmetic<T>::value, std::ostream &>
252operator<<(std::ostream &os, const AH::ArraySlice<T, N, Reverse, Const> &a) {
253 for (const T &el : a.template slice<0, N - 2>())
254 os << el << ", ";
255 os << a[N - 1];
256 return os;
257}
258
259template <class T, size_t N>
260std::enable_if_t<std::is_arithmetic<T>::value, std::ostream &>
261operator<<(std::ostream &os, const AH::Array<T, N> &a) {
262 return os << a.slice();
263}
264
266
267#endif
268
270
272
273template <class T, size_t N, bool Reverse, bool Const>
274std::enable_if_t<std::is_arithmetic<T>::value, Print &>
276 for (const T &el : a.template slice<0, N - 2>())
277 os << el << ", ";
278 os << a[N - 1];
279 return os;
280}
281
282template <class T, size_t N>
283std::enable_if_t<std::is_arithmetic<T>::value, Print &>
284operator<<(Print &os, const AH::Array<T, N> &a) {
285 return os << a.slice();
286}
287
#define END_AH_NAMESPACE
#define BEGIN_AH_NAMESPACE
#define USE_CONSTEXPR_ARRAY_HELPERS
Print & operator<<(Print &os, Cable c)
Definition Cable.cpp:6
Utility class that acts as a functor to return incremental values.
Incrementor(T start=0, V increment=1)
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...
Array< decltype(T1() *T2()), N1+N2 - 1 > distribute(const ArraySlice< T1, N1, Reverse1, Const1 > &a, const ArraySlice< T2, N2, Reverse2, Const2 > &b)
Array< T, N > copyAs(const Array< U, N > &src)
Copy an Array to an Array of a different type.
Array< T, N > fillArray(Args... args)
Fill the array with the same value for each element.
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< T, N > generateArray(G generator)
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.
An array wrapper for easy copying, comparing, and iterating.
Definition Array.hpp:32
ArraySlice< T, abs_diff(Start, End)+1,(End< Start), false > slice()
Get a view on a slice of the Array.