LCOV - code coverage report
Current view: top level - src/AH/Containers - ArrayHelpers.hpp (source / functions) Hit Total Coverage
Test: ffed98f648fe78e7aa7bdd228474317d40dadbec Lines: 38 38 100.0 %
Date: 2022-05-28 15:22:59 Functions: 23 23 100.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.15