LCOV - code coverage report
Current view: top level - src/AH/Containers - ArrayHelpers.hpp (source / functions) Hit Total Coverage
Test: 00f463b534fbea22f0b596e091a60715679e3064 Lines: 33 40 82.5 %
Date: 2024-11-03 16:33:35 Functions: 19 34 55.9 %
Legend: Lines: hit not hit

          Line data    Source code
       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             : 
      14             : BEGIN_AH_NAMESPACE
      15             : 
      16             : namespace detail {
      17             : 
      18             : /** 
      19             :  * @brief   Utility class that acts as a functor to return incremental values.
      20             :  * 
      21             :  * @tparam  T
      22             :  *          The type that will be returned by the functor, as well as the type
      23             :  *          of the initial value.
      24             :  * @tparam  V
      25             :  *          The type of the object that is added to the value on each call.
      26             :  */
      27             : template <class T, class V>
      28             : class Incrementor {
      29             :   public:
      30           1 :     USE_CONSTEXPR_ARRAY_HELPERS Incrementor(T start = 0, V increment = 1)
      31           1 :         : value(start), increment(increment) {}
      32           4 :     USE_CONSTEXPR_ARRAY_HELPERS T operator()() {
      33           4 :         T temp = value;
      34           4 :         value += increment;
      35           4 :         return temp;
      36             :     }
      37             : 
      38             :   private:
      39             :     T value;
      40             :     const V increment;
      41             : };
      42             : 
      43             : } // namespace detail
      44             : 
      45             : /// @addtogroup AH_Containers
      46             : /// @{
      47             : 
      48             : /**
      49             :  * @brief   Generate an array using the given generator.
      50             :  * 
      51             :  * @tparam  T 
      52             :  *          The type of the elements in the array.
      53             :  * @tparam  N 
      54             :  *          The number of elements in the array.
      55             :  * @tparam  G
      56             :  *          The generator functor type.
      57             :  * 
      58             :  * @param   generator
      59             :  *          A functor that will be called to create each element.
      60             :  * 
      61             :  * @return  The generated array.
      62             :  */
      63             : template <class T, size_t N, class G>
      64           2 : USE_CONSTEXPR_ARRAY_HELPERS Array<T, N> generateArray(G generator) {
      65           2 :     Array<T, N> array{{}};
      66           2 :     std::generate(array.begin(), array.end(), generator);
      67           2 :     return array;
      68             : }
      69             : 
      70             : /**
      71             :  * @brief   Generate an array using the given generator.
      72             :  * 
      73             :  * @tparam  N 
      74             :  *          The number of elements in the array.
      75             :  * @tparam  G
      76             :  *          The generator functor type.
      77             :  * 
      78             :  * @param   generator
      79             :  *          A functor that will be called to create each element.
      80             :  * 
      81             :  * @return  The generated array.
      82             :  */
      83             : template <size_t N, class G>
      84           2 : USE_CONSTEXPR_ARRAY_HELPERS auto generateArray(G generator)
      85             :     -> Array<decltype(generator()), N> {
      86           2 :     Array<decltype(generator()), N> array{{}};
      87           2 :     std::generate(array.begin(), array.end(), generator);
      88           2 :     return array;
      89             : }
      90             : 
      91             : /**
      92             :  * @brief   Copy an Array to an Array of a different type.
      93             :  * 
      94             :  * @tparam  T 
      95             :  *          The type of the new array.
      96             :  * @tparam  N 
      97             :  *          The number of elements in the arrays.
      98             :  * @tparam  U 
      99             :  *          The type of the source array.
     100             :  * 
     101             :  * @param   src 
     102             :  *          The source array to be copied.
     103             :  */
     104             : template <class T, size_t N, class U>
     105             : USE_CONSTEXPR_ARRAY_HELPERS Array<T, N> copyAs(const Array<U, N> &src) {
     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             : 
     112             : /**
     113             :  * @brief   Apply a function to all elements of the array and return a copy.
     114             :  */
     115             : template <class F, class U, size_t N>
     116             : USE_CONSTEXPR_ARRAY_HELPERS Array<decltype(F{}(U{})), N>
     117           1 : apply(const Array<U, N> &src, F f) {
     118           1 :     Array<decltype(F{}(U{})), N> dest{{}};
     119           1 :     std::transform(std::begin(src), std::end(src), std::begin(dest), f);
     120           1 :     return dest;
     121             : }
     122             : 
     123             : #if !defined(__GNUC__) || (__GNUC__ > 7) ||                                    \
     124             :     (__GNUC__ == 7 && __GNUC_MINOR__ >= 3) || defined(DOXYGEN)
     125             : /** 
     126             :  * @brief   Fill the array with the same value for each element.
     127             :  */
     128             : template <class T, size_t N, class... Args>
     129           1 : USE_CONSTEXPR_ARRAY_HELPERS Array<T, N> fillArray(Args... args) {
     130           5 :     return generateArray<N>([&]() { return T{args...}; });
     131             : }
     132             : #else
     133             : template <class T, size_t N, class... Args>
     134             : USE_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             : 
     142             : /**
     143             :  * @brief   Generate an array where the first value is given, and the subsequent
     144             :  *          values are calculated as the previous value incremented with a given
     145             :  *          value:  
     146             :  *          @f$ x[0] = \mathrm{start} @f$  
     147             :  *          @f$ x[k+1] = x[k] + \mathrm{increment} @f$ .
     148             :  * 
     149             :  * For example:  
     150             :  * ```
     151             :  * auto x = generateIncrementalArray<unsigned int, 4>(2, 3);
     152             :  * ```
     153             :  * is equivalent to  
     154             :  * ```
     155             :  * Array<unsigned int, 4> x = {2, 5, 8, 11};
     156             :  * ```
     157             :  * 
     158             :  * @tparam  T 
     159             :  *          The type of the elements in the array.
     160             :  * @tparam  N 
     161             :  *          The number of elements in the array.
     162             :  * @tparam  U 
     163             :  *          The type of the initial value.
     164             :  * @tparam  V
     165             :  *          The type of the value that will be added to each subsequent element.
     166             :  * 
     167             :  * @param   start
     168             :  *          The first value in the array.
     169             :  * @param   increment
     170             :  *          The value to add to each subsequent element of the array.
     171             :  * 
     172             :  * @return  The generated array.
     173             :  */
     174             : template <class T, size_t N, class U, class V = U>
     175             : USE_CONSTEXPR_ARRAY_HELPERS Array<T, N>
     176           1 : generateIncrementalArray(U start = 0, V increment = V(1)) {
     177           1 :     detail::Incrementor<U, V> g(start, increment);
     178           2 :     return generateArray<T, N>(g);
     179             : }
     180             : 
     181             : /**
     182             :  * @brief   Concatenate two arrays.
     183             :  * 
     184             :  * @tparam  T
     185             :  *          The type of the elements in the array. 
     186             :  * @tparam  M
     187             :  *          The number of elements in the first array.
     188             :  * @tparam  N 
     189             :  *          The number of elements in the second array.
     190             :  * @param   a 
     191             :  *          The first array.
     192             :  * @param   b 
     193             :  *          The second array.
     194             :  * @return  A new array containing the elements of both input arrays (in order). 
     195             :  */
     196             : template <class T, size_t M, size_t N>
     197             : USE_CONSTEXPR_ARRAY_HELPERS Array<T, M + N> cat(const Array<T, M> &a,
     198             :                                                 const Array<T, N> &b) {
     199             :     Array<T, M + N> result{{}};
     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             : 
     208             : template <class T1, class T2, size_t N1, size_t N2, bool Reverse1,
     209             :           bool Reverse2, bool Const1, bool Const2>
     210             : USE_CONSTEXPR_ARRAY_HELPERS Array<decltype(T1() * T2()), N1 + N2 - 1>
     211           5 : distribute(const ArraySlice<T1, N1, Reverse1, Const1> &a,
     212             :            const ArraySlice<T2, N2, Reverse2, Const2> &b) {
     213           5 :     Array<decltype(T1() * T2()), N1 + N2 - 1> result = {{}};
     214          22 :     for (size_t i = 0; i < N1; ++i)
     215          77 :         for (size_t j = 0; j < N2; ++j)
     216          60 :             result[i + j] += a[i] * b[j];
     217           5 :     return result;
     218             : }
     219             : 
     220             : template <class T1, class T2, size_t N1, size_t N2, bool Reverse1, bool Const1>
     221             : USE_CONSTEXPR_ARRAY_HELPERS Array<decltype(T1() * T2()), N1 + N2 - 1>
     222           2 : distribute(const ArraySlice<T1, N1, Reverse1, Const1> &a,
     223             :            const Array<T2, N2> &b) {
     224           2 :     return distribute(a, b.slice());
     225             : }
     226             : 
     227             : template <class T1, class T2, size_t N1, size_t N2, bool Reverse2, bool Const2>
     228             : USE_CONSTEXPR_ARRAY_HELPERS Array<decltype(T1() * T2()), N1 + N2 - 1>
     229             : distribute(const Array<T1, N1> &a,
     230             :            const ArraySlice<T2, N2, Reverse2, Const2> &b) {
     231             :     return distribute(a.slice(), b);
     232             : }
     233             : 
     234             : template <class T1, class T2, size_t N1, size_t N2>
     235             : USE_CONSTEXPR_ARRAY_HELPERS Array<decltype(T1() * T2()), N1 + N2 - 1>
     236           2 : distribute(const Array<T1, N1> &a, const Array<T2, N2> &b) {
     237           2 :     return distribute(a.slice(), b.slice());
     238             : }
     239             : 
     240             : /// @}
     241             : 
     242             : END_AH_NAMESPACE
     243             : 
     244             : #ifndef ARDUINO
     245             : 
     246             : #include <ostream>
     247             : 
     248             : BEGIN_AH_NAMESPACE
     249             : 
     250             : template <class T, size_t N, bool Reverse, bool Const>
     251             : std::enable_if_t<std::is_arithmetic<T>::value, std::ostream &>
     252           0 : operator<<(std::ostream &os, const AH::ArraySlice<T, N, Reverse, Const> &a) {
     253           0 :     for (const T &el : a.template slice<0, N - 2>())
     254           0 :         os << el << ", ";
     255           0 :     os << a[N - 1];
     256           0 :     return os;
     257             : }
     258             : 
     259             : template <class T, size_t N>
     260             : std::enable_if_t<std::is_arithmetic<T>::value, std::ostream &>
     261           0 : operator<<(std::ostream &os, const AH::Array<T, N> &a) {
     262           0 :     return os << a.slice();
     263             : }
     264             : 
     265             : END_AH_NAMESPACE
     266             : 
     267             : #endif
     268             : 
     269             : #include <AH/PrintStream/PrintStream.hpp>
     270             : 
     271             : BEGIN_AH_NAMESPACE
     272             : 
     273             : template <class T, size_t N, bool Reverse, bool Const>
     274             : std::enable_if_t<std::is_arithmetic<T>::value, Print &>
     275             : operator<<(Print &os, const AH::ArraySlice<T, N, Reverse, Const> &a) {
     276             :     for (const T &el : a.template slice<0, N - 2>())
     277             :         os << el << ", ";
     278             :     os << a[N - 1];
     279             :     return os;
     280             : }
     281             : 
     282             : template <class T, size_t N>
     283             : std::enable_if_t<std::is_arithmetic<T>::value, Print &>
     284             : operator<<(Print &os, const AH::Array<T, N> &a) {
     285             :     return os << a.slice();
     286             : }
     287             : 
     288             : END_AH_NAMESPACE

Generated by: LCOV version 1.15