LCOV - code coverage report
Current view: top level - src/AH/Containers - ArrayHelpers.hpp (source / functions) Hit Total Coverage
Test: e224b347cd670555e44f06608ac41bd1ace9d9d8 Lines: 43 43 100.0 %
Date: 2020-09-08 17:44:46 Functions: 19 19 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           8 :         return temp;
      40           4 :     }
      41             : 
      42             :   private:
      43             :     T value;
      44             :     const V increment;
      45             : };
      46             : 
      47             : } // namespace detail
      48             : 
      49             : END_AH_NAMESPACE
      50             : /// @addtogroup AH_Containers
      51             : /// @{
      52             : 
      53             : BEGIN_AH_NAMESPACE
      54             : 
      55             : /**
      56             :  * @brief   Generate an array using the given generator.
      57             :  * 
      58             :  * @tparam  T 
      59             :  *          The type of the elements in the array.
      60             :  * @tparam  N 
      61             :  *          The number of elements in the array.
      62             :  * @tparam  G
      63             :  *          The generator functor type.
      64             :  * 
      65             :  * @param   generator
      66             :  *          A functor that will be called to create each element.
      67             :  * 
      68             :  * @return  The generated array.
      69             :  */
      70             : template <class T, size_t N, class G>
      71           2 : USE_CONSTEXPR_ARRAY_HELPERS Array<T, N> generateArray(G generator) {
      72           2 :     Array<T, N> array{{}};
      73           2 :     std::generate(array.begin(), array.end(), generator);
      74           2 :     return array;
      75             : }
      76             : 
      77             : /**
      78             :  * @brief   Generate an array using the given generator.
      79             :  * 
      80             :  * @tparam  N 
      81             :  *          The number of elements in the array.
      82             :  * @tparam  G
      83             :  *          The generator functor type.
      84             :  * 
      85             :  * @param   generator
      86             :  *          A functor that will be called to create each element.
      87             :  * 
      88             :  * @return  The generated array.
      89             :  */
      90             : template <size_t N, class G>
      91           1 : USE_CONSTEXPR_ARRAY_HELPERS auto generateArray(G generator)
      92             :     -> Array<decltype(generator()), N> {
      93           1 :     Array<decltype(generator()), N> array{{}};
      94           1 :     std::generate(array.begin(), array.end(), generator);
      95           1 :     return array;
      96             : }
      97             : 
      98             : /**
      99             :  * @brief   Copy an Array to an Array of a different type.
     100             :  * 
     101             :  * @tparam  T 
     102             :  *          The type of the new array.
     103             :  * @tparam  N 
     104             :  *          The number of elements in the arrays.
     105             :  * @tparam  U 
     106             :  *          The type of the source array.
     107             :  * 
     108             :  * @param   src 
     109             :  *          The source array to be copied.
     110             :  */
     111             : template <class T, size_t N, class U>
     112           1 : USE_CONSTEXPR_ARRAY_HELPERS Array<T, N> copyAs(const Array<U, N> &src) {
     113           4 :     Array<T, N> dest{{}};
     114           1 :     std::transform(std::begin(src), std::end(src), std::begin(dest),
     115           4 :                    [](const U &src) { return T(src); });
     116           1 :     return dest;
     117             : }
     118             : 
     119             : /**
     120             :  * @brief   Apply a function to all elements of the array and return a copy.
     121             :  */
     122             : template <class F, class U, size_t N>
     123             : USE_CONSTEXPR_ARRAY_HELPERS Array<decltype(F{}(U{})), N>
     124           1 : apply(const Array<U, N> &src, F f) {
     125           1 :     Array<decltype(F{}(U{})), N> dest{{}};
     126           1 :     std::transform(std::begin(src), std::end(src), std::begin(dest), f);
     127           1 :     return dest;
     128             : }
     129             : 
     130             : #if !defined(__GNUC__) || (__GNUC__ > 7) ||                                    \
     131             :     (__GNUC__ == 7 && __GNUC_MINOR__ >= 3) || defined(DOXYGEN)
     132             : /** 
     133             :  * @brief   Fill the array with the same value for each element.
     134             :  */
     135             : template <class T, size_t N, class... Args>
     136             : USE_CONSTEXPR_ARRAY_HELPERS Array<T, N> fillArray(Args... args) {
     137             :     return generateArray<N>([&]() { return T{args...}; });
     138             : }
     139             : #else
     140             : template <class T, size_t N, class... Args>
     141           1 : USE_CONSTEXPR_ARRAY_HELPERS Array<T, N> fillArray(Args... args) {
     142           1 :     Array<T, N> array{{}};
     143           5 :     for (auto &el : array)
     144           4 :         el = T{args...};
     145           1 :     return array;
     146             : }
     147             : #endif
     148             : 
     149             : /**
     150             :  * @brief   Generate an array where the first value is given, and the subsequent
     151             :  *          values are calculated as the previous value incremented with a given
     152             :  *          value:  
     153             :  *          @f$ x[0] = \mathrm{start} @f$  
     154             :  *          @f$ x[k+1] = x[k] + \mathrm{increment} @f$ .
     155             :  * 
     156             :  * For example:  
     157             :  * ```
     158             :  * auto x = generateIncrementalArray<unsigned int, 4>(2, 3);
     159             :  * ```
     160             :  * is equivalent to  
     161             :  * ```
     162             :  * Array<unsigned int, 4> x = {2, 5, 8, 11};
     163             :  * ```
     164             :  * 
     165             :  * @tparam  T 
     166             :  *          The type of the elements in the array.
     167             :  * @tparam  N 
     168             :  *          The number of elements in the array.
     169             :  * @tparam  U 
     170             :  *          The type of the initial value.
     171             :  * @tparam  V
     172             :  *          The type of the value that will be added to each subsequent element.
     173             :  * 
     174             :  * @param   start
     175             :  *          The first value in the array.
     176             :  * @param   increment
     177             :  *          The value to add to each subsequent element of the array.
     178             :  * 
     179             :  * @return  The generated array.
     180             :  */
     181             : template <class T, size_t N, class U, class V = U>
     182             : USE_CONSTEXPR_ARRAY_HELPERS Array<T, N>
     183           1 : generateIncrementalArray(U start = 0, V increment = V(1)) {
     184           1 :     detail::Incrementor<U, V> g(start, increment);
     185           1 :     return generateArray<T, N>(g);
     186           1 : }
     187             : 
     188             : /**
     189             :  * @brief   Concatenate two arrays.
     190             :  * 
     191             :  * @tparam  T
     192             :  *          The type of the elements in the array. 
     193             :  * @tparam  M
     194             :  *          The number of elements in the first array.
     195             :  * @tparam  N 
     196             :  *          The number of elements in the second array.
     197             :  * @param   a 
     198             :  *          The first array.
     199             :  * @param   b 
     200             :  *          The second array.
     201             :  * @return  A new array containing the elements of both input arrays (in order). 
     202             :  */
     203             : template <class T, size_t M, size_t N>
     204             : USE_CONSTEXPR_ARRAY_HELPERS Array<T, M + N> cat(const Array<T, M> &a,
     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>
     218           5 : distribute(const ArraySlice<T1, N1, Reverse1, Const1> &a,
     219             :            const ArraySlice<T2, N2, Reverse2, Const2> &b) {
     220           5 :     Array<decltype(T1() * T2()), N1 + N2 - 1> result = {{}};
     221          22 :     for (size_t i = 0; i < N1; ++i)
     222          77 :         for (size_t j = 0; j < N2; ++j)
     223          77 :             result[i + j] += a[i] * b[j];
     224           5 :     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>
     229           2 : distribute(const ArraySlice<T1, N1, Reverse1, Const1> &a,
     230             :            const Array<T2, N2> &b) {
     231           2 :     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>
     236             : distribute(const Array<T1, N1> &a,
     237             :            const ArraySlice<T2, N2, Reverse2, Const2> &b) {
     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>
     243           2 : distribute(const Array<T1, N1> &a, const Array<T2, N2> &b) {
     244           2 :     return distribute(a.slice(), b.slice());
     245             : }
     246             : 
     247             : END_AH_NAMESPACE
     248             : 
     249             : /// @}
     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             : 
     272             : #include <AH/PrintStream/PrintStream.hpp>
     273             : 
     274             : template <class T, size_t N, bool Reverse, bool Const>
     275             : std::enable_if_t<std::is_arithmetic<T>::value, Print &>
     276             : operator<<(Print &os, const AH::ArraySlice<T, N, Reverse, Const> &a) {
     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             : 
     289             : AH_DIAGNOSTIC_POP()

Generated by: LCOV version 1.14-6-g40580cd