168 lines
4.8 KiB
C++
168 lines
4.8 KiB
C++
#pragma once
|
|
|
|
#include "Array.hpp"
|
|
#include <AH/STL/algorithm>
|
|
|
|
#if __cplusplus >= 201400L
|
|
#define USE_CONSTEXPR_ARRAY_HELPERS constexpr
|
|
#else
|
|
#define USE_CONSTEXPR_ARRAY_HELPERS
|
|
#endif
|
|
|
|
BEGIN_AH_NAMESPACE
|
|
|
|
namespace detail {
|
|
|
|
template <class T, class V>
|
|
class Incrementor {
|
|
public:
|
|
USE_CONSTEXPR_ARRAY_HELPERS Incrementor(T start = 0, V increment = 1)
|
|
: value(start), increment(increment) {}
|
|
USE_CONSTEXPR_ARRAY_HELPERS T operator()() {
|
|
T temp = value;
|
|
value += increment;
|
|
return temp;
|
|
}
|
|
|
|
private:
|
|
T value;
|
|
const V increment;
|
|
};
|
|
|
|
} // namespace detail
|
|
|
|
template <class T, size_t N, class G>
|
|
USE_CONSTEXPR_ARRAY_HELPERS Array<T, N> generateArray(G generator) {
|
|
Array<T, N> array{{}};
|
|
std::generate(array.begin(), array.end(), generator);
|
|
return array;
|
|
}
|
|
|
|
template <size_t N, class G>
|
|
USE_CONSTEXPR_ARRAY_HELPERS auto generateArray(G generator)
|
|
-> Array<decltype(generator()), N> {
|
|
Array<decltype(generator()), N> array{{}};
|
|
std::generate(array.begin(), array.end(), generator);
|
|
return array;
|
|
}
|
|
|
|
template <class T, size_t N, class U>
|
|
USE_CONSTEXPR_ARRAY_HELPERS Array<T, N> copyAs(const Array<U, N> &src) {
|
|
Array<T, N> dest{{}};
|
|
std::transform(std::begin(src), std::end(src), std::begin(dest),
|
|
[](const U &src) { return T(src); });
|
|
return dest;
|
|
}
|
|
|
|
template <class F, class U, size_t N>
|
|
USE_CONSTEXPR_ARRAY_HELPERS Array<decltype(F{}(U{})), N>
|
|
apply(const Array<U, N> &src, F f) {
|
|
Array<decltype(F{}(U{})), N> dest{{}};
|
|
std::transform(std::begin(src), std::end(src), std::begin(dest), f);
|
|
return dest;
|
|
}
|
|
|
|
template <class T, size_t N, class... Args>
|
|
USE_CONSTEXPR_ARRAY_HELPERS Array<T, N> fillArray(Args... args) {
|
|
return generateArray<N>([&]() { return T{args...}; });
|
|
}
|
|
|
|
template <class T, size_t N, class U, class V = U>
|
|
USE_CONSTEXPR_ARRAY_HELPERS Array<T, N>
|
|
generateIncrementalArray(U start = 0, V increment = V(1)) {
|
|
detail::Incrementor<U, V> g(start, increment);
|
|
return generateArray<T, N>(g);
|
|
}
|
|
|
|
template <class T, size_t M, size_t N>
|
|
USE_CONSTEXPR_ARRAY_HELPERS Array<T, M + N> cat(const Array<T, M> &a,
|
|
const Array<T, N> &b) {
|
|
Array<T, M + N> result{{}};
|
|
size_t r = 0;
|
|
for (size_t i = 0; i < M; ++i, ++r)
|
|
result[r] = a[i];
|
|
for (size_t i = 0; i < N; ++i, ++r)
|
|
result[r] = b[i];
|
|
return result;
|
|
}
|
|
|
|
template <class T1, class T2, size_t N1, size_t N2, bool Reverse1,
|
|
bool Reverse2, bool Const1, bool Const2>
|
|
USE_CONSTEXPR_ARRAY_HELPERS Array<decltype(T1() * T2()), N1 + N2 - 1>
|
|
distribute(const ArraySlice<T1, N1, Reverse1, Const1> &a,
|
|
const ArraySlice<T2, N2, Reverse2, Const2> &b) {
|
|
Array<decltype(T1() * T2()), N1 + N2 - 1> result = {{}};
|
|
for (size_t i = 0; i < N1; ++i)
|
|
for (size_t j = 0; j < N2; ++j)
|
|
result[i + j] += a[i] * b[j];
|
|
return result;
|
|
}
|
|
|
|
template <class T1, class T2, size_t N1, size_t N2, bool Reverse1, bool Const1>
|
|
USE_CONSTEXPR_ARRAY_HELPERS Array<decltype(T1() * T2()), N1 + N2 - 1>
|
|
distribute(const ArraySlice<T1, N1, Reverse1, Const1> &a,
|
|
const Array<T2, N2> &b) {
|
|
return distribute(a, b.slice());
|
|
}
|
|
|
|
template <class T1, class T2, size_t N1, size_t N2, bool Reverse2, bool Const2>
|
|
USE_CONSTEXPR_ARRAY_HELPERS Array<decltype(T1() * T2()), N1 + N2 - 1>
|
|
distribute(const Array<T1, N1> &a,
|
|
const ArraySlice<T2, N2, Reverse2, Const2> &b) {
|
|
return distribute(a.slice(), b);
|
|
}
|
|
|
|
template <class T1, class T2, size_t N1, size_t N2>
|
|
USE_CONSTEXPR_ARRAY_HELPERS Array<decltype(T1() * T2()), N1 + N2 - 1>
|
|
distribute(const Array<T1, N1> &a, const Array<T2, N2> &b) {
|
|
return distribute(a.slice(), b.slice());
|
|
}
|
|
|
|
END_AH_NAMESPACE
|
|
|
|
#ifndef ARDUINO
|
|
|
|
#include <ostream>
|
|
|
|
BEGIN_AH_NAMESPACE
|
|
|
|
template <class T, size_t N, bool Reverse, bool Const>
|
|
std::enable_if_t<std::is_arithmetic<T>::value, std::ostream &>
|
|
operator<<(std::ostream &os, const AH::ArraySlice<T, N, Reverse, Const> &a) {
|
|
for (const T &el : a.template slice<0, N - 2>())
|
|
os << el << ", ";
|
|
os << a[N - 1];
|
|
return os;
|
|
}
|
|
|
|
template <class T, size_t N>
|
|
std::enable_if_t<std::is_arithmetic<T>::value, std::ostream &>
|
|
operator<<(std::ostream &os, const AH::Array<T, N> &a) {
|
|
return os << a.slice();
|
|
}
|
|
|
|
END_AH_NAMESPACE
|
|
|
|
#endif
|
|
|
|
#include <AH/PrintStream/PrintStream.hpp>
|
|
|
|
BEGIN_AH_NAMESPACE
|
|
|
|
template <class T, size_t N, bool Reverse, bool Const>
|
|
std::enable_if_t<std::is_arithmetic<T>::value, Print &>
|
|
operator<<(Print &os, const AH::ArraySlice<T, N, Reverse, Const> &a) {
|
|
for (const T &el : a.template slice<0, N - 2>())
|
|
os << el << ", ";
|
|
os << a[N - 1];
|
|
return os;
|
|
}
|
|
|
|
template <class T, size_t N>
|
|
std::enable_if_t<std::is_arithmetic<T>::value, Print &>
|
|
operator<<(Print &os, const AH::Array<T, N> &a) {
|
|
return os << a.slice();
|
|
}
|
|
|
|
END_AH_NAMESPACE
|