LCOV - code coverage report
Current view: top level - src/AH/Containers - ArrayHelpers.hpp (source / functions) Coverage Total Hit
Test: 73449d9b107c772cf65493691543348214e5d5eb Lines: 84.4 % 45 38
Test Date: 2026-06-06 17:44:35 Functions: 60.5 % 38 23
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            5 : USE_CONSTEXPR_ARRAY_HELPERS Array<T, N> copyAs(const Array<U, N> &src) {
     106           17 :     Array<T, N> dest{{}};
     107           15 :     std::transform(std::begin(src), std::end(src), std::begin(dest),
     108           20 :                    [](const U &src) { return T(src); });
     109            5 :     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            3 :     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 2.4-beta