Control Surface  1.1.1
MIDI Control Surface library for Arduino
ArrayHelpers.hpp
Go to the documentation of this file.
1 /* ✔ */
2 
3 #pragma once
4 
6 
7 AH_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 
20 namespace detail {
21 
31 template <class T, class V>
32 class Incrementor {
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:
43  T value;
44  const V increment;
45 };
46 
47 } // namespace detail
48 
52 
54 
70 template <class T, size_t N, class G>
72  Array<T, N> array{{}};
73  std::generate(array.begin(), array.end(), generator);
74  return array;
75 }
76 
90 template <size_t N, class G>
92  -> Array<decltype(generator()), N> {
93  Array<decltype(generator()), N> array{{}};
94  std::generate(array.begin(), array.end(), generator);
95  return array;
96 }
97 
111 template <class T, size_t N, class U>
113  Array<T, N> dest{{}};
114  std::transform(std::begin(src), std::end(src), std::begin(dest),
115  [](const U &src) { return T(src); });
116  return dest;
117 }
118 
122 template <class F, class U, size_t N>
123 USE_CONSTEXPR_ARRAY_HELPERS Array<decltype(F{}(U{})), N>
124 apply(const Array<U, N> &src, F f) {
125  Array<decltype(F{}(U{})), N> dest{{}};
126  std::transform(std::begin(src), std::end(src), std::begin(dest), f);
127  return dest;
128 }
129 
130 #if !defined(__GNUC__) || (__GNUC__ > 7) || \
131  (__GNUC__ == 7 && __GNUC_MINOR__ >= 3) || defined(DOXYGEN)
132 
135 template <class T, size_t N, class... Args>
137  return generateArray<N>([&]() { return T{args...}; });
138 }
139 #else
140 template <class T, size_t N, class... Args>
141 USE_CONSTEXPR_ARRAY_HELPERS Array<T, N> fillArray(Args... args) {
142  Array<T, N> array{{}};
143  for (auto &el : array)
144  el = T{args...};
145  return array;
146 }
147 #endif
148 
181 template <class T, size_t N, class U, class V = U>
182 USE_CONSTEXPR_ARRAY_HELPERS Array<T, N>
183 generateIncrementalArray(U start = 0, V increment = V(1)) {
184  detail::Incrementor<U, V> g(start, increment);
185  return generateArray<T, N>(g);
186 }
187 
203 template <class T, size_t M, size_t N>
205  const Array<T, N> &b) {
206  Array<T, M + N> result{{}};
207  size_t r = 0;
208  for (size_t i = 0; i < M; ++i, ++r)
209  result[r] = a[i];
210  for (size_t i = 0; i < N; ++i, ++r)
211  result[r] = b[i];
212  return result;
213 }
214 
215 template <class T1, class T2, size_t N1, size_t N2, bool Reverse1,
216  bool Reverse2, bool Const1, bool Const2>
217 USE_CONSTEXPR_ARRAY_HELPERS Array<decltype(T1() * T2()), N1 + N2 - 1>
220  Array<decltype(T1() * T2()), N1 + N2 - 1> result = {{}};
221  for (size_t i = 0; i < N1; ++i)
222  for (size_t j = 0; j < N2; ++j)
223  result[i + j] += a[i] * b[j];
224  return result;
225 }
226 
227 template <class T1, class T2, size_t N1, size_t N2, bool Reverse1, bool Const1>
228 USE_CONSTEXPR_ARRAY_HELPERS Array<decltype(T1() * T2()), N1 + N2 - 1>
230  const Array<T2, N2> &b) {
231  return distribute(a, b.slice());
232 }
233 
234 template <class T1, class T2, size_t N1, size_t N2, bool Reverse2, bool Const2>
235 USE_CONSTEXPR_ARRAY_HELPERS Array<decltype(T1() * T2()), N1 + N2 - 1>
238  return distribute(a.slice(), b);
239 }
240 
241 template <class T1, class T2, size_t N1, size_t N2>
242 USE_CONSTEXPR_ARRAY_HELPERS Array<decltype(T1() * T2()), N1 + N2 - 1>
244  return distribute(a.slice(), b.slice());
245 }
246 
248 
250 
251 #ifndef ARDUINO
252 
253 #include <ostream>
254 
255 template <class T, size_t N, bool Reverse, bool Const>
256 std::enable_if_t<std::is_arithmetic<T>::value, std::ostream &>
257 operator<<(std::ostream &os, const AH::ArraySlice<T, N, Reverse, Const> &a) {
258  for (const T &el : a.template slice<0, N - 2>())
259  os << el << ", ";
260  os << a[N - 1];
261  return os;
262 }
263 
264 template <class T, size_t N>
265 std::enable_if_t<std::is_arithmetic<T>::value, std::ostream &>
266 operator<<(std::ostream &os, const AH::Array<T, N> &a) {
267  return os << a.slice();
268 }
269 
270 #endif
271 
273 
274 template <class T, size_t N, bool Reverse, bool Const>
275 std::enable_if_t<std::is_arithmetic<T>::value, Print &>
277  for (const T &el : a.template slice<0, N - 2>())
278  os << el << ", ";
279  os << a[N - 1];
280  return os;
281 }
282 
283 template <class T, size_t N>
284 std::enable_if_t<std::is_arithmetic<T>::value, Print &>
285 operator<<(Print &os, const AH::Array<T, N> &a) {
286  return os << a.slice();
287 }
288 
AH::generateArray
auto generateArray(G generator) -> Array< decltype(generator()), N >
Generate an array using the given generator.
Definition: ArrayHelpers.hpp:91
MIDI_Notes::G
constexpr int8_t G
Definition: Notes.hpp:25
Warnings.hpp
operator<<
std::enable_if_t< std::is_arithmetic< T >::value, Print & > operator<<(Print &os, const AH::ArraySlice< T, N, Reverse, Const > &a)
Definition: ArrayHelpers.hpp:276
AH::copyAs
Array< T, N > copyAs(const Array< U, N > &src)
Copy an Array to an Array of a different type.
Definition: ArrayHelpers.hpp:112
AH::detail::Incrementor::Incrementor
Incrementor(T start=0, V increment=1)
Definition: ArrayHelpers.hpp:34
AH::generateIncrementalArray
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...
Definition: ArrayHelpers.hpp:183
AH::apply
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.
Definition: ArrayHelpers.hpp:124
AH::Array::slice
ArraySlice< T, abs_diff(Start, End)+1,(End< Start), false > slice()
Get a view on a slice of the Array.
AH_DIAGNOSTIC_POP
#define AH_DIAGNOSTIC_POP()
Definition: Warnings.hpp:17
USE_CONSTEXPR_ARRAY_HELPERS
#define USE_CONSTEXPR_ARRAY_HELPERS
Definition: ArrayHelpers.hpp:15
AH::cat
Array< T, M+N > cat(const Array< T, M > &a, const Array< T, N > &b)
Concatenate two arrays.
Definition: ArrayHelpers.hpp:204
AH::Array
An array wrapper for easy copying, comparing, and iterating.
Definition: Array.hpp:36
AH::detail::Incrementor::value
T value
Definition: ArrayHelpers.hpp:43
AH::distribute
Array< decltype(T1() *T2()), N1+N2 - 1 > distribute(const Array< T1, N1 > &a, const Array< T2, N2 > &b)
Definition: ArrayHelpers.hpp:243
AH::ArraySlice
Class for a view on a slice of an array.
Definition: Array.hpp:25
MIDI_Notes::F
constexpr int8_t F
Definition: Notes.hpp:23
PrintStream.hpp
AH_DIAGNOSTIC_WERROR
#define AH_DIAGNOSTIC_WERROR()
Definition: Warnings.hpp:16
BEGIN_AH_NAMESPACE
#define BEGIN_AH_NAMESPACE
Definition: AH/Settings/NamespaceSettings.hpp:9
END_AH_NAMESPACE
#define END_AH_NAMESPACE
Definition: AH/Settings/NamespaceSettings.hpp:10
AH::detail::Incrementor::operator()
T operator()()
Definition: ArrayHelpers.hpp:36
AH::detail::Incrementor::increment
const V increment
Definition: ArrayHelpers.hpp:44
AH::detail::Incrementor
Utility class that acts as a functor to return incremental values.
Definition: ArrayHelpers.hpp:32
AH::fillArray
Array< T, N > fillArray(Args... args)
Fill the array with the same value for each element.
Definition: ArrayHelpers.hpp:136