LCOV - code coverage report
Current view: top level - math/linalg - matrix.hpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 100.0 % 170 170
Test Date: 2026-04-26 21:52:20 Functions: 99.7 % 335 334
Legend: Lines: hit not hit

            Line data    Source code
       1              : #ifndef E4BF6CCD_1BFD_497E_A5CD_75BCD8DD1ED3
       2              : #define E4BF6CCD_1BFD_497E_A5CD_75BCD8DD1ED3
       3              : 
       4              : #include "math/linalg/matrix.h"
       5              : 
       6              : #include <algorithm>
       7              : #include <cmath>
       8              : #include <functional>
       9              : #include <limits>
      10              : #include <stdexcept>
      11              : #include <string>
      12              : #include <type_traits>
      13              : 
      14              : namespace tracking
      15              : {
      16              : namespace math
      17              : {
      18              : 
      19              : template <typename ValueType_, sint32 Rows_, sint32 Cols_, bool IsRowMajor_>
      20          263 : inline void Matrix<ValueType_, Rows_, Cols_, IsRowMajor_>::setZeros()
      21              : {
      22          866 :   data().fill(static_cast<ValueType_>(0));
      23              : }
      24              : 
      25              : template <typename ValueType_, sint32 Rows_, sint32 Cols_, bool IsRowMajor_>
      26           88 : inline auto Matrix<ValueType_, Rows_, Cols_, IsRowMajor_>::Zeros() -> Matrix
      27              : {
      28          653 :   Matrix tmp;
      29         3590 :   tmp.setZeros();
      30              :   return tmp;
      31              : }
      32              : 
      33              : template <typename ValueType_, sint32 Rows_, sint32 Cols_, bool IsRowMajor_>
      34          673 : inline void Matrix<ValueType_, Rows_, Cols_, IsRowMajor_>::setOnes()
      35              : {
      36         1021 :   data().fill(static_cast<ValueType_>(1));
      37              : }
      38              : 
      39              : template <typename ValueType_, sint32 Rows_, sint32 Cols_, bool IsRowMajor_>
      40           20 : inline auto Matrix<ValueType_, Rows_, Cols_, IsRowMajor_>::Ones() -> Matrix
      41              : {
      42           20 :   Matrix tmp;
      43          228 :   tmp.setOnes();
      44              :   return tmp;
      45              : }
      46              : 
      47              : template <typename ValueType_, sint32 Rows_, sint32 Cols_, bool IsRowMajor_>
      48          643 : inline auto Matrix<ValueType_, Rows_, Cols_, IsRowMajor_>::FromList(
      49              :     const std::initializer_list<std::initializer_list<ValueType_>>& list) -> Matrix
      50              : {
      51          643 :   Matrix result{};
      52              : 
      53              :   // Validate row count - input is always in logical row-major format
      54          643 :   if (list.size() != static_cast<std::size_t>(Rows))
      55              :   {
      56           28 :     throw std::runtime_error("Matrix::FromList: expected " + std::to_string(Rows) + " rows, got " + std::to_string(list.size()));
      57              :   }
      58              : 
      59              :   // Validate column count for each row - input is always in logical row-major format
      60         2441 :   for (const auto& row : list)
      61              :   {
      62         1806 :     if (row.size() != static_cast<std::size_t>(Cols))
      63              :     {
      64           28 :       throw std::runtime_error("Matrix::FromList: expected " + std::to_string(Cols) + " columns, got " +
      65              :                                std::to_string(row.size()));
      66              :     }
      67              :   }
      68              : 
      69              :   if constexpr (IsRowMajor_)
      70              :   {
      71              :     // For row-major storage, copy data directly
      72          503 :     auto iter = result.data().begin();
      73         1988 :     for (const auto& row : list)
      74              :     {
      75         1485 :       std::copy(row.begin(), row.end(), iter);
      76         1485 :       iter += row.size();
      77              :     }
      78              :   }
      79              :   else
      80              :   {
      81              :     // For column-major storage, transpose the input data
      82          569 :     for (sint32 col = 0; col < Cols; ++col)
      83              :     {
      84         1492 :       for (sint32 row = 0; row < Rows; ++row)
      85              :       {
      86              :         // Get element from row-major input
      87         1055 :         auto row_iter = list.begin();
      88         1055 :         std::advance(row_iter, row);
      89         1055 :         auto col_iter = row_iter->begin();
      90         1055 :         std::advance(col_iter, col);
      91              : 
      92              :         // Store in column-major order
      93         1055 :         result.data()[col * Rows + row] = *col_iter;
      94              :       }
      95              :     }
      96              :   }
      97          635 :   return result;
      98            8 : }
      99              : 
     100              : template <typename ValueType_, sint32 Rows_, sint32 Cols_, bool IsRowMajor_>
     101       308140 : inline auto Matrix<ValueType_, Rows_, Cols_, IsRowMajor_>::at_unsafe(sint32 row, sint32 col) const -> ValueType_
     102              : {
     103       308036 :   assert((0 <= row) && (row < Rows));
     104       308036 :   assert((0 <= col) && (col < Cols));
     105       308142 :   const auto idx = IsRowMajor_ ? (row * ColsInMem) + col : (col * ColsInMem) + row;
     106       308142 :   return data()[idx];
     107              : }
     108              : 
     109              : template <typename ValueType_, sint32 Rows_, sint32 Cols_, bool IsRowMajor_>
     110       200749 : inline auto Matrix<ValueType_, Rows_, Cols_, IsRowMajor_>::at_unsafe(sint32 row, sint32 col) -> ValueType_&
     111              : {
     112       200749 :   assert((0 <= row) && (row < Rows));
     113       200749 :   assert((0 <= col) && (col < Cols));
     114       200925 :   const auto idx = IsRowMajor_ ? (row * ColsInMem) + col : (col * ColsInMem) + row;
     115       200926 :   return data()[idx];
     116              : }
     117              : 
     118              : template <typename ValueType_, sint32 Rows_, sint32 Cols_, bool IsRowMajor_>
     119            8 : inline auto Matrix<ValueType_, Rows_, Cols_, IsRowMajor_>::operator()(sint32 row,
     120              :                                                                       sint32 col) const -> tl::expected<ValueType_, Errors>
     121              : {
     122            4 :   if (!(row >= 0 && row < Rows))
     123              :   {
     124            3 :     return tl::unexpected<Errors>{Errors::invalid_access_row};
     125              :   }
     126            3 :   if (!(col >= 0 && col < Cols))
     127              :   {
     128            2 :     return tl::unexpected<Errors>{Errors::invalid_access_col};
     129              :   }
     130            3 :   return at_unsafe(row, col);
     131              : }
     132              : 
     133              : template <typename ValueType_, sint32 Rows_, sint32 Cols_, bool IsRowMajor_>
     134           20 : inline auto Matrix<ValueType_, Rows_, Cols_, IsRowMajor_>::operator()(sint32 row, sint32 col)
     135              :     -> tl::expected<std::reference_wrapper<ValueType_>, Errors>
     136              : {
     137           12 :   if (!(row >= 0 && row < Rows))
     138              :   {
     139            4 :     return tl::unexpected<Errors>{Errors::invalid_access_row};
     140              :   }
     141           12 :   if (!(col >= 0 && col < Cols))
     142              :   {
     143            4 :     return tl::unexpected<Errors>{Errors::invalid_access_col};
     144              :   }
     145           12 :   return at_unsafe(row, col);
     146              : }
     147              : 
     148              : template <typename ValueType_, sint32 Rows_, sint32 Cols_, bool IsRowMajor_>
     149              : template <bool IsRowMajor2_>
     150           49 : inline auto Matrix<ValueType_, Rows_, Cols_, IsRowMajor_>::operator==(
     151              :     const Matrix<ValueType_, Rows_, Cols_, IsRowMajor2_>& other) const -> bool
     152              : {
     153              :   if constexpr (IsRowMajor_ == IsRowMajor2_)
     154              :   {
     155              :     // same memory layout: can compare underlying data arrays directly
     156              :     // TODO(matthias): check whether this only checks pointers or also the elements
     157           39 :     return this->data() == other.data();
     158              :   }
     159              :   else
     160              :   {
     161              :     // different memory layouts: compare element-wise
     162           24 :     bool isEqual = true;
     163           90 :     for (auto row = 0; row < Rows; ++row)
     164              :     {
     165          264 :       for (auto col = 0; col < Cols; ++col)
     166              :       {
     167          216 :         isEqual = isEqual && (at_unsafe(row, col) == other.at_unsafe(row, col));
     168              :       }
     169              :     }
     170           24 :     return isEqual;
     171              :   }
     172              : }
     173              : 
     174              : template <typename ValueType_, sint32 Rows_, sint32 Cols_, bool IsRowMajor_>
     175              : template <bool IsRowMajor2_>
     176            3 : inline auto Matrix<ValueType_, Rows_, Cols_, IsRowMajor_>::operator!=(
     177              :     const Matrix<ValueType_, Rows_, Cols_, IsRowMajor2_>& other) const -> bool
     178              : {
     179            3 :   return !(*this == other);
     180              : }
     181              : 
     182              : template <typename ValueType_, sint32 Rows_, sint32 Cols_, bool IsRowMajor_>
     183              : template <bool IsRowMajor2_>
     184           41 : inline void Matrix<ValueType_, Rows_, Cols_, IsRowMajor_>::operator+=(const Matrix<ValueType_, Rows_, Cols_, IsRowMajor2_>& other)
     185              : {
     186              :   if constexpr (IsRowMajor_ == IsRowMajor2_)
     187              :   {
     188              :     // same memory layout: can add underlying data arrays directly
     189           74 :     const auto&  otherData = other.data();
     190           74 :     const sint32 size      = data().size();
     191         1736 :     for (sint32 idx = 0; idx < size; ++idx)
     192              :     {
     193         1662 :       data()[idx] += otherData[idx];
     194              :     }
     195              :   }
     196              :   else
     197              :   {
     198              :     // different memory layouts: add element-wise
     199              :     // When both matrixes share the same underlying data and are square Matrixes (e.g., transposed view),
     200              :     // we must make a copy to avoid read-after-write corruption.
     201              :     // Example: a += a.transpose() would overwrite a[0][1] before reading it as a.transpose()[1][0]
     202              :     // clang-format off
     203           40 :     const auto&& tmp = ((*this==other) && (Rows_ == Cols_)) 
     204           18 :                      ? Matrix<ValueType_, Rows_, Cols_, IsRowMajor2_>{other}
     205              :                      : std::move(other);
     206              :     // clang-format on
     207           84 :     for (auto row = 0; row < Rows; ++row)
     208              :     {
     209          248 :       for (auto col = 0; col < Cols; ++col)
     210              :       {
     211          186 :         at_unsafe(row, col) += tmp.at_unsafe(row, col);
     212              :       }
     213              :     }
     214           22 :   }
     215           22 : }
     216              : 
     217              : template <typename ValueType_, sint32 Rows_, sint32 Cols_, bool IsRowMajor_>
     218              : template <bool IsRowMajor2_>
     219           66 : inline void Matrix<ValueType_, Rows_, Cols_, IsRowMajor_>::operator-=(const Matrix<ValueType_, Rows_, Cols_, IsRowMajor2_>& other)
     220              : {
     221              :   if constexpr (IsRowMajor_ == IsRowMajor2_)
     222              :   {
     223           61 :     if (this->data().data() == other.data().data())
     224              :     {
     225              :       // case: A -= A
     226           61 :       this->setZeros();
     227              :     }
     228              :     else
     229              :     {
     230              :       // case: A -= B
     231              :       const auto&  otherData = other.data();
     232              :       const sint32 size      = data().size();
     233          428 :       for (sint32 idx = 0; idx < size; ++idx)
     234              :       {
     235          370 :         data()[idx] -= otherData[idx];
     236              :       }
     237              :     }
     238              :   }
     239              :   else
     240              :   {
     241              :     // different memory layouts: subtract element-wise
     242              :     // When both matrixes share the same underlying data and are square Matrixes (e.g., transposed view),
     243              :     // we must make a copy to avoid read-after-write corruption.
     244              :     // Example: a -= a.transpose() would overwrite a[0][1] before reading it as a.transpose()[1][0]
     245            5 :     auto&& tmp = ((this->data().data() == other.data().data()) && (Rows_ == Cols_))
     246            1 :                      ? Matrix<ValueType_, Rows_, Cols_, IsRowMajor2_>{other}
     247              :                      : std::move(other);
     248           16 :     for (auto row = 0; row < Rows; ++row)
     249              :     {
     250           44 :       for (auto col = 0; col < Cols; ++col)
     251              :       {
     252           33 :         at_unsafe(row, col) -= tmp.at_unsafe(row, col);
     253              :       }
     254              :     }
     255            5 :   }
     256           66 : }
     257              : 
     258              : template <typename ValueType_, sint32 Rows_, sint32 Cols_, bool IsRowMajor_>
     259          766 : inline void Matrix<ValueType_, Rows_, Cols_, IsRowMajor_>::operator*=(ValueType_ scalar)
     260              : {
     261         7460 :   for (auto& val : data())
     262              :   {
     263         6681 :     val *= scalar;
     264              :   }
     265              : }
     266              : 
     267              : template <typename ValueType_, sint32 Rows_, sint32 Cols_, bool IsRowMajor_>
     268              : template <typename T, typename std::enable_if_t<std::is_integral<T>::value, bool>>
     269            3 : inline auto Matrix<ValueType_, Rows_, Cols_, IsRowMajor_>::operator/=(T scalar) -> tl::expected<void, Errors>
     270              : {
     271            2 :   if (std::abs(scalar) > static_cast<T>(0))
     272              :   {
     273            2 :     inplace_div_by_int_unsafe(scalar);
     274            2 :     return {};
     275              :   }
     276            1 :   return tl::unexpected<Errors>{Errors::divide_by_zero};
     277              : }
     278              : 
     279              : template <typename ValueType_, sint32 Rows_, sint32 Cols_, bool IsRowMajor_>
     280              : template <typename T, typename std::enable_if_t<std::is_floating_point<T>::value, bool>>
     281          758 : inline auto Matrix<ValueType_, Rows_, Cols_, IsRowMajor_>::operator/=(T scalar) -> tl::expected<void, Errors>
     282              : {
     283          758 :   if (std::abs(scalar) > std::numeric_limits<value_type>::min())
     284              :   {
     285          757 :     inplace_mul_by_inverse_factor_unsafe(scalar);
     286          757 :     return {};
     287              :   }
     288            1 :   return tl::unexpected<Errors>{Errors::divide_by_zero};
     289              : }
     290              : 
     291              : template <typename ValueType_, sint32 Rows_, sint32 Cols_, bool IsRowMajor_>
     292              : template <bool IsRowMajor2_>
     293           60 : inline auto Matrix<ValueType_, Rows_, Cols_, IsRowMajor_>::operator+(
     294              :     const Matrix<ValueType_, Rows_, Cols_, IsRowMajor2_>& other) const -> Matrix
     295              : {
     296           60 :   Matrix res{*this};
     297           59 :   res += other;
     298           45 :   return res;
     299              : }
     300              : 
     301              : template <typename ValueType_, sint32 Rows_, sint32 Cols_, bool IsRowMajor_>
     302              : template <bool IsRowMajor2_>
     303           47 : inline auto Matrix<ValueType_, Rows_, Cols_, IsRowMajor_>::operator-(
     304              :     const Matrix<ValueType_, Rows_, Cols_, IsRowMajor2_>& other) const -> Matrix
     305              : {
     306           47 :   Matrix res{*this};
     307           47 :   res -= other;
     308              :   return res;
     309              : }
     310              : 
     311              : template <typename ValueType_, sint32 Rows_, sint32 Cols_, bool IsRowMajor_>
     312            6 : inline auto Matrix<ValueType_, Rows_, Cols_, IsRowMajor_>::operator+(ValueType_ scalar) const -> Matrix
     313              : {
     314            6 :   Matrix res{*this};
     315           31 :   for (auto& val : res.data())
     316              :   {
     317           25 :     val += scalar;
     318              :   }
     319              :   return res;
     320              : }
     321              : 
     322              : template <typename ValueType_, sint32 Rows_, sint32 Cols_, bool IsRowMajor_>
     323            5 : inline auto Matrix<ValueType_, Rows_, Cols_, IsRowMajor_>::operator-(ValueType_ scalar) const -> Matrix
     324              : {
     325            5 :   Matrix res{*this};
     326           26 :   for (auto& val : res.data())
     327              :   {
     328           21 :     val -= scalar;
     329              :   }
     330              :   return res;
     331              : }
     332              : 
     333              : template <typename ValueType_, sint32 Rows_, sint32 Cols_, bool IsRowMajor_>
     334            6 : inline auto Matrix<ValueType_, Rows_, Cols_, IsRowMajor_>::operator*(ValueType_ scalar) const -> Matrix
     335              : {
     336            6 :   Matrix res{*this};
     337            6 :   res *= scalar;
     338              :   return res;
     339              : }
     340              : 
     341              : template <typename ValueType_, sint32 Rows_, sint32 Cols_, bool IsRowMajor_>
     342              : template <typename T, typename std::enable_if_t<std::is_integral<T>::value, bool>>
     343            4 : inline auto Matrix<ValueType_, Rows_, Cols_, IsRowMajor_>::operator/(T scalar) const -> tl::expected<Matrix, Errors>
     344              : {
     345            2 :   if (std::abs(scalar) > static_cast<T>(0))
     346              :   {
     347            2 :     Matrix res{*this};
     348            2 :     res.inplace_div_by_int_unsafe(scalar);
     349            2 :     return res;
     350            2 :   }
     351            2 :   return tl::unexpected<Errors>{Errors::divide_by_zero};
     352              : }
     353              : 
     354              : template <typename ValueType_, sint32 Rows_, sint32 Cols_, bool IsRowMajor_>
     355              : template <typename T, typename std::enable_if_t<std::is_floating_point<T>::value, bool>>
     356            5 : inline auto Matrix<ValueType_, Rows_, Cols_, IsRowMajor_>::operator/(T scalar) const -> tl::expected<Matrix, Errors>
     357              : {
     358            5 :   if (std::abs(scalar) > std::numeric_limits<T>::min())
     359              :   {
     360            2 :     Matrix res{*this};
     361            2 :     res.inplace_mul_by_inverse_factor_unsafe(scalar);
     362            2 :     return res;
     363            2 :   }
     364            3 :   return tl::unexpected<Errors>{Errors::divide_by_zero};
     365              : }
     366              : 
     367              : template <typename ValueType_, sint32 Rows_, sint32 Cols_, bool IsRowMajor_>
     368              : template <sint32 Cols2_, bool IsRowMajor2_>
     369          633 : inline auto Matrix<ValueType_, Rows_, Cols_, IsRowMajor_>::operator*(
     370              :     const Matrix<ValueType_, Cols_, Cols2_, IsRowMajor2_>& other) const -> Matrix<ValueType_, Rows_, Cols2_, IsRowMajor_>
     371              : {
     372              :   using ResultMatrix = Matrix<ValueType_, Rows_, Cols2_, IsRowMajor_>;
     373         3589 :   ResultMatrix result{ResultMatrix::Zeros()};
     374              : 
     375              :   // Optimized loop order (i-j-k) for cache-friendly row-major access (4-8x faster)
     376         3589 :   for (auto i = 0; i < ResultMatrix::Rows; ++i)
     377              :   {
     378        14348 :     for (auto j = 0; j < ResultMatrix::Cols; ++j)
     379              :     {
     380        63216 :       for (auto k = 0; k < Cols; ++k)
     381              :       {
     382        51824 :         result.at_unsafe(i, j) += at_unsafe(i, k) * other.at_unsafe(k, j);
     383              :       }
     384              :     }
     385              :   }
     386          633 :   return result;
     387              : }
     388              : 
     389              : 
     390              : template <typename ValueType_, sint32 Rows_, sint32 Cols_, bool IsRowMajor_>
     391          140 : inline auto Matrix<ValueType_, Rows_, Cols_, IsRowMajor_>::isZeros() const -> bool
     392              : {
     393          140 :   const auto [min, max] = minmax();
     394          140 :   return (min == static_cast<ValueType_>(0)) && (max == static_cast<ValueType_>(0));
     395              : }
     396              : 
     397              : template <typename ValueType_, sint32 Rows_, sint32 Cols_, bool IsRowMajor_>
     398          274 : inline auto Matrix<ValueType_, Rows_, Cols_, IsRowMajor_>::minmax() const -> std::tuple<ValueType_, ValueType_>
     399              : {
     400          274 :   const auto [min, max] = std::minmax_element(data().begin(), data().end());
     401          274 :   return std::make_tuple(*min, *max);
     402              : }
     403              : 
     404              : template <typename ValueType_, sint32 Rows_, sint32 Cols_, bool IsRowMajor_>
     405              : template <typename T, typename std::enable_if_t<std::is_floating_point<T>::value, bool>>
     406            4 : inline auto Matrix<ValueType_, Rows_, Cols_, IsRowMajor_>::frobenius_norm() const -> ValueType_
     407              : {
     408            4 :   ValueType_ sum_of_squares = static_cast<ValueType_>(0);
     409           22 :   for (const auto& val : data())
     410              :   {
     411           18 :     sum_of_squares += val * val;
     412              :   }
     413            4 :   return std::sqrt(sum_of_squares);
     414              : }
     415              : 
     416              : template <typename ValueType_, sint32 Rows_, sint32 Cols_, bool IsRowMajor_>
     417              : inline auto Matrix<ValueType_, Rows_, Cols_, IsRowMajor_>::transpose() const -> const transpose_type& // LCOV_EXCL_LINE
     418              : {
     419              :   return reinterpret_cast<const transpose_type&>(*this);
     420              : }
     421              : 
     422              : template <typename ValueType_, sint32 Rows_, sint32 Cols_, bool IsRowMajor_>
     423              : inline auto Matrix<ValueType_, Rows_, Cols_, IsRowMajor_>::transpose() -> transpose_type& // LCOV_EXCL_LINE
     424              : {
     425              :   return reinterpret_cast<transpose_type&>(*this);
     426              : }
     427              : 
     428              : template <typename ValueType_, sint32 Rows_, sint32 Cols_, bool IsRowMajor_>
     429          300 : inline auto Matrix<ValueType_, Rows_, Cols_, IsRowMajor_>::transpose_rvalue() && -> transpose_type
     430              : {
     431          300 :   return reinterpret_cast<transpose_type&>(*this);
     432              : }
     433              : 
     434              : template <typename ValueType_, sint32 Rows_, sint32 Cols_, bool IsRowMajor_>
     435              : template <sint32 SrcRowSize_,
     436              :           sint32 SrcColSize_,
     437              :           sint32 SrcRowCount_,
     438              :           sint32 SrcColCount_,
     439              :           sint32 SrcRowBeg_,
     440              :           sint32 SrcColBeg_,
     441              :           bool   SrcIsRowMajor_,
     442              :           sint32 DstRowBeg_,
     443              :           sint32 DstColBeg_>
     444           99 : inline void Matrix<ValueType_, Rows_, Cols_, IsRowMajor_>::setBlock(
     445              :     const Matrix<ValueType_, SrcRowSize_, SrcColSize_, SrcIsRowMajor_>& block)
     446              : {
     447              :   static_assert(SrcRowBeg_ + SrcRowCount_ <= SrcRowSize_, "copy to many rows from src");
     448              :   static_assert(SrcColBeg_ + SrcColCount_ <= SrcColSize_, "copy to many cols from src");
     449              : 
     450              :   static_assert(DstRowBeg_ + SrcRowCount_ <= Rows_, "copy to many rows to dst");
     451              :   static_assert(DstColBeg_ + SrcColCount_ <= Cols_, "copy to many cols to dst");
     452              : 
     453          537 :   for (sint32 row = 0; row < SrcRowCount_; ++row)
     454              :   {
     455         1498 :     for (sint32 col = 0; col < SrcColCount_; ++col)
     456              :     {
     457         1060 :       this->at_unsafe(DstRowBeg_ + row, DstColBeg_ + col) = block.at_unsafe(SrcRowBeg_ + row, SrcColBeg_ + col);
     458              :     }
     459              :   }
     460           99 : }
     461              : 
     462              : template <typename ValueType_, sint32 Rows_, sint32 Cols_, bool IsRowMajor_>
     463              : template <sint32 SrcRowSize_, sint32 SrcColSize_, bool SrcIsRowMajor_>
     464          626 : inline void Matrix<ValueType_, Rows_, Cols_, IsRowMajor_>::setBlock(
     465              :     const sint32                                                        srcRowCount,
     466              :     const sint32                                                        srcColCount,
     467              :     const sint32                                                        srcRowBeg,
     468              :     const sint32                                                        srcColBeg,
     469              :     const sint32                                                        dstRowBeg,
     470              :     const sint32                                                        dstColBeg,
     471              :     const Matrix<ValueType_, SrcRowSize_, SrcColSize_, SrcIsRowMajor_>& block)
     472              : {
     473          626 :   assert((srcRowBeg + srcRowCount <= SrcRowSize_) && "copy to many rows from src");
     474          626 :   assert((srcColBeg + srcColCount <= SrcColSize_) && "copy to many cols from src");
     475              : 
     476          626 :   assert((dstRowBeg + srcRowCount <= Rows) && "copy to many rows to dst");
     477          626 :   assert((dstColBeg + srcColCount <= Cols) && "copy to many cols to dst");
     478              : 
     479         2540 :   for (sint32 row = 0; row < srcRowCount; ++row)
     480              :   {
     481         3830 :     for (sint32 col = 0; col < srcColCount; ++col)
     482              :     {
     483         1916 :       this->at_unsafe(dstRowBeg + row, dstColBeg + col) = block.at_unsafe(srcRowBeg + row, srcColBeg + col);
     484              :     }
     485              :   }
     486          626 : }
     487              : 
     488              : template <typename ValueType_, sint32 Rows_, sint32 Cols_, bool IsRowMajor_>
     489              : template <typename T, typename std::enable_if_t<std::is_integral<T>::value, bool>>
     490            4 : inline void Matrix<ValueType_, Rows_, Cols_, IsRowMajor_>::inplace_div_by_int_unsafe(T scalar)
     491              : {
     492           28 :   for (auto& val : data())
     493              :   {
     494           24 :     val /= scalar;
     495              :   }
     496              : }
     497              : 
     498              : template <typename ValueType_, sint32 Rows_, sint32 Cols_, bool IsRowMajor_>
     499              : template <typename T, typename std::enable_if_t<std::is_floating_point<T>::value, bool>>
     500          759 : inline void Matrix<ValueType_, Rows_, Cols_, IsRowMajor_>::inplace_mul_by_inverse_factor_unsafe(T scalar)
     501              : {
     502          759 :   const T factor = 1 / scalar;
     503          759 :   this->operator*=(factor);
     504              : }
     505              : 
     506              : } // namespace math
     507              : } // namespace tracking
     508              : 
     509              : #endif // E4BF6CCD_1BFD_497E_A5CD_75BCD8DD1ED3
        

Generated by: LCOV version 2.0-1