LCOV - code coverage report
Current view: top level - gcore - gdal_vectorx.h (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 100 100 100.0 %
Date: 2024-11-21 22:18:42 Functions: 99 99 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  * Project:  GDAL Vector abstraction
       3             :  * Purpose:
       4             :  * Author:   Javier Jimenez Shaw
       5             :  *
       6             :  ******************************************************************************
       7             :  * Copyright (c) 2024, Javier Jimenez Shaw
       8             :  *
       9             :  * SPDX-License-Identifier: MIT
      10             :  ****************************************************************************/
      11             : 
      12             : #ifndef GDAL_VECTORX_H_INCLUDED
      13             : #define GDAL_VECTORX_H_INCLUDED
      14             : 
      15             : /*! @cond Doxygen_Suppress */
      16             : 
      17             : #include <algorithm>
      18             : #include <array>
      19             : #include <functional>
      20             : 
      21             : namespace gdal
      22             : {
      23             : 
      24             : /**
      25             :  * @brief Template class to abstract a vector
      26             :  *
      27             :  * Inspired by Eigen3 Vector class, but much simpler.
      28             :  * For GDAL internal use for now.
      29             :  *
      30             :  * @tparam T type of the values stored
      31             :  * @tparam N size of the container/vector
      32             :  */
      33             : template <typename T, std::size_t N> class VectorX
      34             : {
      35             :   public:
      36             :     using value_type = T;
      37             :     using size_type = std::size_t;
      38             :     using self_type = VectorX<T, N>;
      39             : 
      40             :     /** Size of the container */
      41           7 :     static constexpr size_type size() noexcept
      42             :     {
      43           7 :         return N;
      44             :     }
      45             : 
      46     1776605 :     VectorX()
      47     1776605 :     {
      48     1776605 :     }
      49             : 
      50             :     // cppcheck-suppress noExplicitConstructor
      51     1121236 :     template <typename... Args> VectorX(Args... args) : _values({args...})
      52             :     {
      53             :         static_assert(N == sizeof...(Args),
      54             :                       "Invalid number of constructor params");
      55     1121236 :     }
      56             : 
      57             :     /** Container as an std::array */
      58           1 :     const std::array<T, N> &array() const
      59             :     {
      60           1 :         return _values;
      61             :     }
      62             : 
      63     3046076 :     T &operator[](const size_type &pos)
      64             :     {
      65     3046076 :         return _values[pos];
      66             :     }
      67             : 
      68     1015706 :     const T &operator[](const size_type &pos) const
      69             :     {
      70     1015706 :         return _values[pos];
      71             :     }
      72             : 
      73     2134855 :     T x() const
      74             :     {
      75             :         static_assert(N >= 1, "Invalid template size for x()");
      76     2134855 :         return _values[0];
      77             :     }
      78             : 
      79     1796551 :     T y() const
      80             :     {
      81             :         static_assert(N >= 2, "Invalid template size for y()");
      82     1796551 :         return _values[1];
      83             :     }
      84             : 
      85             :     T z() const
      86             :     {
      87             :         static_assert(N >= 3, "Invalid template size for z()");
      88             :         return _values[2];
      89             :     }
      90             : 
      91     1521727 :     T &x()
      92             :     {
      93             :         static_assert(N >= 1, "Invalid template size for x()");
      94     1521727 :         return _values[0];
      95             :     }
      96             : 
      97     1268156 :     T &y()
      98             :     {
      99             :         static_assert(N >= 2, "Invalid template size for y()");
     100     1268156 :         return _values[1];
     101             :     }
     102             : 
     103           6 :     T &z()
     104             :     {
     105             :         static_assert(N >= 3, "Invalid template size for z()");
     106           6 :         return _values[2];
     107             :     }
     108             : 
     109             :     /** Fill all elements of the vector with the same value
     110             :      * @return this
     111             :      */
     112           2 :     self_type &fill(T arg)
     113             :     {
     114           8 :         for (size_t i = 0; i < N; i++)
     115           6 :             (*this)[i] = arg;
     116             : 
     117           2 :         return *this;
     118             :     }
     119             : 
     120             :     /** Apply the unary operator to all the elements
     121             :      * @param op unary operator to apply to every element
     122             :      * @return a new object with the computed values
     123             :      */
     124      253616 :     template <class UnaryOp> self_type apply(UnaryOp op) const
     125             :     {
     126      253616 :         self_type res;
     127      760848 :         for (size_t i = 0; i < N; i++)
     128      507232 :             res[i] = op(_values[i]);
     129      253616 :         return res;
     130             :     }
     131             : 
     132      253613 :     self_type floor() const
     133             :     {
     134      760839 :         return apply([](const value_type &v) { return std::floor(v); });
     135             :     }
     136             : 
     137           1 :     self_type ceil() const
     138             :     {
     139           3 :         return apply([](const value_type &v) { return std::ceil(v); });
     140             :     }
     141             : 
     142             :     /** Compute the scalar product of two vectors */
     143           2 :     T scalarProd(const self_type &arg) const
     144             :     {
     145           2 :         T accum{};
     146           6 :         for (size_t i = 0; i < N; i++)
     147           4 :             accum += _values[i] * arg[i];
     148           2 :         return accum;
     149             :     }
     150             : 
     151             :     /** Compute the norm squared of the vector */
     152           1 :     T norm2() const
     153             :     {
     154           1 :         return scalarProd(*this);
     155             :     }
     156             : 
     157             :     /**
     158             :      * @brief cast the type to a different one, and convert the elements
     159             :      *
     160             :      * @tparam U output value type
     161             :      * @return VectorX<U, N> object of new type, where all elements are casted
     162             :      */
     163      507911 :     template <typename U> VectorX<U, N> cast() const
     164             :     {
     165      507911 :         VectorX<U, N> res;
     166     1523733 :         for (size_t i = 0; i < N; i++)
     167     1015822 :             res[i] = static_cast<U>(_values[i]);
     168      507911 :         return res;
     169             :     }
     170             : 
     171           1 :     self_type operator+(T arg) const
     172             :     {
     173           1 :         return operatorImpl(arg, std::plus());
     174             :     }
     175             : 
     176           2 :     self_type &operator+=(T arg)
     177             :     {
     178           2 :         return operatorEqImpl(arg, std::plus());
     179             :     }
     180             : 
     181      253651 :     self_type operator-(T arg) const
     182             :     {
     183      253651 :         return operatorImpl(arg, std::minus());
     184             :     }
     185             : 
     186           2 :     self_type &operator-=(T arg)
     187             :     {
     188           2 :         return operatorEqImpl(arg, std::minus());
     189             :     }
     190             : 
     191           1 :     self_type operator-() const
     192             :     {
     193           3 :         return apply([](const value_type &v) { return -v; });
     194             :     }
     195             : 
     196           1 :     template <typename U> self_type operator*(U arg) const
     197             :     {
     198           1 :         self_type res;
     199           3 :         for (size_t i = 0; i < N; i++)
     200           2 :             res[i] = T(_values[i] * arg);
     201           1 :         return res;
     202             :     }
     203             : 
     204           1 :     self_type operator*(T arg) const
     205             :     {
     206           1 :         return operatorImpl(arg, std::multiplies());
     207             :     }
     208             : 
     209           1 :     template <typename U> self_type operator/(U arg) const
     210             :     {
     211           1 :         self_type res;
     212           3 :         for (size_t i = 0; i < N; i++)
     213           2 :             res[i] = T(_values[i] / arg);
     214           1 :         return res;
     215             :     }
     216             : 
     217           1 :     self_type operator/(T arg) const
     218             :     {
     219           1 :         return operatorImpl(arg, std::divides());
     220             :     }
     221             : 
     222           1 :     self_type operator+(const self_type &arg) const
     223             :     {
     224           1 :         return operatorImpl(arg, std::plus());
     225             :     }
     226             : 
     227      507847 :     self_type operator-(const self_type &arg) const
     228             :     {
     229      507847 :         return operatorImpl(arg, std::minus());
     230             :     }
     231             : 
     232           1 :     friend VectorX<T, N> operator+(T t, const VectorX<T, N> &arg)
     233             :     {
     234           1 :         VectorX<T, N> res;
     235           3 :         for (size_t i = 0; i < N; i++)
     236           2 :             res._values[i] = t + arg._values[i];
     237           1 :         return res;
     238             :     }
     239             : 
     240      253569 :     friend VectorX<T, N> operator-(T t, const VectorX<T, N> &arg)
     241             :     {
     242      253569 :         VectorX<T, N> res;
     243      760707 :         for (size_t i = 0; i < N; i++)
     244      507138 :             res._values[i] = t - arg._values[i];
     245      253569 :         return res;
     246             :     }
     247             : 
     248             :   private:
     249             :     std::array<T, N> _values{};
     250             : 
     251      253654 :     template <class Op> self_type operatorImpl(T arg, Op op) const
     252             :     {
     253      253654 :         self_type res;
     254      760962 :         for (size_t i = 0; i < N; i++)
     255      507308 :             res[i] = op(_values[i], arg);
     256      253654 :         return res;
     257             :     }
     258             : 
     259           4 :     template <class Op> self_type &operatorEqImpl(T arg, Op op)
     260             :     {
     261          12 :         for (size_t i = 0; i < N; i++)
     262           8 :             _values[i] = op(_values[i], arg);
     263           4 :         return *this;
     264             :     }
     265             : 
     266             :     template <class Op>
     267      507848 :     self_type operatorImpl(const self_type &arg, Op op) const
     268             :     {
     269      507848 :         self_type res;
     270     1523544 :         for (size_t i = 0; i < N; i++)
     271     1015696 :             res[i] = op(_values[i], arg[i]);
     272      507848 :         return res;
     273             :     }
     274             : 
     275             :     template <class Op> self_type &operatorEqImpl(const self_type &arg, Op op)
     276             :     {
     277             :         for (size_t i = 0; i < N; i++)
     278             :             _values[i] = op(_values[i], arg[i]);
     279             :         return *this;
     280             :     }
     281             : };
     282             : 
     283             : using Vector2d = VectorX<double, 2>;
     284             : using Vector2i = VectorX<int, 2>;
     285             : using Vector3d = VectorX<double, 3>;
     286             : using Vector3i = VectorX<int, 3>;
     287             : }  // namespace gdal
     288             : 
     289             : /*! @endcond */
     290             : 
     291             : #endif /* ndef GDAL_VECTORX_H_INCLUDED */

Generated by: LCOV version 1.14