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

            Line data    Source code
       1              : #ifndef BB251A7C_F2DC_4075_B478_BA5931DF6CEC
       2              : #define BB251A7C_F2DC_4075_B478_BA5931DF6CEC
       3              : 
       4              : #include "math/linalg/modified_gram_schmidt.h"
       5              : 
       6              : #include "math/linalg/diagonal_matrix.hpp"   // IWYU pragma: keep
       7              : #include "math/linalg/matrix.hpp"            // IWYU pragma: keep
       8              : #include "math/linalg/square_matrix.hpp"     // IWYU pragma: keep
       9              : #include "math/linalg/triangular_matrix.hpp" // IWYU pragma: keep
      10              : 
      11              : namespace tracking
      12              : {
      13              : namespace math
      14              : {
      15              : template <typename ValueType_, sint32 Size_>
      16           46 : void ModifiedGramSchmidt<ValueType_, Size_>::run(TriangularMatrix<ValueType_, Size_, false, true>& u,
      17              :                                                  DiagonalMatrix<ValueType_, Size_>&                d,
      18              :                                                  const SquareMatrix<ValueType_, Size_, true>&      Phi)
      19              : {
      20              :   // M. S. Grewal and A. P. Andrews
      21              :   // Kalman Filtering: Theory and Practice Using MATLAB, 4th Edition
      22              :   // Wiley, 2014.
      23              :   //
      24              :   // Catherine Thornton's modified weighted Gram-Schmidt orthogonalization method
      25              :   // TODO(matthias): Grewal, p. 260 -> inplace product Phi*U
      26              :   // TODO(matthias): optimization - eliminate allocations in modified Gram-Schmidt for in-place updates
      27              :   // beneficial for small n without complexity overhead; add template-based loop unrolling for Size_ <= 10
      28           46 :   auto PhiU = Phi * u;
      29           46 :   auto Din  = d;
      30           46 :   u.setIdentity();
      31              :   ValueType_ sigma;
      32          240 :   for (sint32 i = Size_ - 1; i >= 0; --i)
      33              :   {
      34          194 :     sigma = static_cast<ValueType_>(0.0);
      35         1080 :     for (sint32 j = 0; j < Size_; ++j)
      36              :     {
      37          886 :       sigma += (PhiU.at_unsafe(i, j) * PhiU.at_unsafe(i, j)) * Din.at_unsafe(j);
      38              :     }
      39          222 :     d.at_unsafe(i) = std::max(sigma, std::numeric_limits<ValueType_>::epsilon());
      40          540 :     for (sint32 j = 0; j < i; ++j)
      41              :     {
      42          346 :       sigma = static_cast<ValueType_>(0.0);
      43         2076 :       for (sint32 k = 0; k < Size_; ++k)
      44              :       {
      45         1730 :         sigma += PhiU.at_unsafe(i, k) * Din.at_unsafe(k) * PhiU.at_unsafe(j, k);
      46              :       }
      47              : 
      48          346 :       u.at_unsafe(j, i) = sigma / d.at_unsafe(i);
      49              : 
      50         2076 :       for (sint32 k = 0; k < Size_; ++k)
      51              :       {
      52         1730 :         PhiU.at_unsafe(j, k) -= u.at_unsafe(j, i) * PhiU.at_unsafe(i, k);
      53              :       }
      54              :     }
      55              :   }
      56           46 : }
      57              : 
      58              : template <typename ValueType_, sint32 Size_>
      59              : template <sint32 SizeQ_>
      60           29 : void ModifiedGramSchmidt<ValueType_, Size_>::run(TriangularMatrix<ValueType_, Size_, false, true>& u,
      61              :                                                  DiagonalMatrix<ValueType_, Size_>&                d,
      62              :                                                  const SquareMatrix<ValueType_, Size_, true>&      Phi,
      63              :                                                  const Matrix<ValueType_, Size_, SizeQ_, true>&    G,
      64              :                                                  const DiagonalMatrix<ValueType_, SizeQ_>&         Q)
      65              : {
      66              :   // M. S. Grewal and A. P. Andrews
      67              :   // Kalman Filtering: Theory and Practice Using MATLAB, 4th Edition
      68              :   // Wiley, 2014.
      69              :   //
      70              :   // Catherine Thornton's modified weighted Gram-Schmidt orthogonalization method
      71              :   // for the predictor update of the U-D factors of the covariance matrix
      72              :   // of estimation uncertainty in Kalman filtering
      73              : 
      74              :   // TODO(matthias): Grewal, p. 260 -> inplace product Phi*U
      75              :   // TODO(matthias): optimization - eliminate allocations in modified Gram-Schmidt for in-place updates
      76              :   // beneficial for small n without complexity overhead; add template-based loop unrolling for Size_ <= 10
      77           29 :   auto PhiU = Phi * u;
      78           29 :   auto Din  = d;
      79           29 :   auto Gin  = G;
      80           29 :   u.setIdentity();
      81              :   ValueType_ sigma;
      82          160 :   for (sint32 i = Size_ - 1; i >= 0; --i)
      83              :   {
      84          131 :     sigma = static_cast<ValueType_>(0.0);
      85              :     // process all state columns
      86          770 :     for (sint32 j = 0; j < Size_; ++j)
      87              :     {
      88          639 :       sigma += (PhiU.at_unsafe(i, j) * PhiU.at_unsafe(i, j)) * Din.at_unsafe(j);
      89              :     }
      90              :     // process all process noise columns
      91          539 :     for (sint32 j = 0; j < SizeQ_; ++j)
      92              :     {
      93          408 :       sigma += Gin.at_unsafe(i, j) * Gin.at_unsafe(i, j) * Q.at_unsafe(j);
      94              :     }
      95          131 :     d.at_unsafe(i) = std::max(sigma, std::numeric_limits<ValueType_>::epsilon());
      96          385 :     for (sint32 j = 0; j < i; ++j)
      97              :     {
      98          254 :       sigma = static_cast<ValueType_>(0.0);
      99         1587 :       for (sint32 k = 0; k < Size_; ++k)
     100              :       {
     101         1333 :         sigma += PhiU.at_unsafe(i, k) * Din.at_unsafe(k) * PhiU.at_unsafe(j, k);
     102              :       }
     103         1084 :       for (sint32 k = 0; k < SizeQ_; ++k)
     104              :       {
     105          830 :         sigma += Gin.at_unsafe(i, k) * Q.at_unsafe(k) * Gin.at_unsafe(j, k);
     106              :       }
     107              : 
     108          254 :       u.at_unsafe(j, i) = sigma / d.at_unsafe(i);
     109              : 
     110         1587 :       for (sint32 k = 0; k < Size_; ++k)
     111              :       {
     112         1333 :         PhiU.at_unsafe(j, k) -= u.at_unsafe(j, i) * PhiU.at_unsafe(i, k);
     113              :       }
     114         1084 :       for (sint32 k = 0; k < SizeQ_; ++k)
     115              :       {
     116          830 :         Gin.at_unsafe(j, k) -= u.at_unsafe(j, i) * Gin.at_unsafe(i, k);
     117              :       }
     118              :     }
     119              :   }
     120           29 : }
     121              : 
     122              : } // namespace math
     123              : } // namespace tracking
     124              : 
     125              : #endif // BB251A7C_F2DC_4075_B478_BA5931DF6CEC
        

Generated by: LCOV version 2.0-1