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

            Line data    Source code
       1              : #ifndef EDCA948E_6A98_4AF3_8A01_916736E1577B
       2              : #define EDCA948E_6A98_4AF3_8A01_916736E1577B
       3              : 
       4              : #include "base/first_include.h" // IWYU pragma: keep
       5              : #include "math/linalg/errors.h"
       6              : #include "math/linalg/matrix_io.h"
       7              : #include <initializer_list>
       8              : 
       9              : namespace tracking
      10              : {
      11              : namespace math
      12              : {
      13              : 
      14              : template <typename ValueType_, sint32 Rows_, sint32 Cols_, bool IsRowMajor_>
      15              : class Matrix;
      16              : 
      17              : template <typename ValueType_, sint32 Size_, bool IsRowMajor_>
      18              : class SquareMatrix;
      19              : 
      20              : template <typename ValueType_, sint32 Size_, bool IsLower_, bool IsRowMajor_>
      21              : class TriangularMatrix;
      22              : 
      23              : template <typename ValueType_, sint32 Size_>
      24              : class Vector;
      25              : 
      26              : // TODO(matthias): add interface contract
      27              : 
      28              : /// \brief A diagonal matrix that stores only the diagonal elements for memory efficiency.
      29              : ///
      30              : /// This class represents diagonal matrixes where only the diagonal elements are stored
      31              : /// and manipulated. All off-diagonal elements are implicitly zero. Provides optimized
      32              : /// operations for diagonal-specific computations like inversion and multiplication.
      33              : ///
      34              : /// \tparam ValueType_ The atomic data type of internal elements
      35              : /// \tparam Size_ The dimension of the diagonal matrix (compile-time constant)
      36              : ///
      37              : /// \note Memory efficient: stores only Size_ elements instead of Size_²
      38              : /// \note All operations are O(Size_) instead of O(Size_²) for general matrixes
      39              : ///
      40              : /// \see SquareMatrix for general square matrix operations
      41              : /// \see TriangularMatrix for triangular matrix operations
      42              : template <typename ValueType_, sint32 Size_>
      43          399 : class DiagonalMatrix TEST_REMOVE_FINAL
      44              : {
      45              : public:
      46              :   // rule of 5 declarations
      47            2 :   DiagonalMatrix()                                             = default;
      48          311 :   DiagonalMatrix(const DiagonalMatrix& other)                  = default;
      49          111 :   DiagonalMatrix(DiagonalMatrix&&) noexcept                    = default;
      50              :   auto operator=(const DiagonalMatrix&) -> DiagonalMatrix&     = default;
      51           28 :   auto operator=(DiagonalMatrix&&) noexcept -> DiagonalMatrix& = default;
      52              : 
      53              :   /// \brief Construct an identity diagonal matrix.
      54              :   ///
      55              :   /// Creates a diagonal matrix with ones on the diagonal (identity matrix).
      56              :   ///
      57              :   /// \return DiagonalMatrix An identity matrix with ones on the diagonal
      58              :   ///
      59              :   /// \note This is equivalent to a diagonal matrix with all diagonal elements equal to 1
      60              :   [[nodiscard]] static auto Identity() -> DiagonalMatrix;
      61              : 
      62              :   /// \brief Set the diagonal matrix to identity in-place.
      63              :   ///
      64              :   /// Modifies the diagonal elements to all be 1, creating an identity matrix.
      65              :   ///
      66              :   /// \note This operation modifies the matrix in-place and does not change its size
      67              :   void setIdentity();
      68              : 
      69              :   /// \brief Creates a DiagonalMatrix from a flat initializer list
      70              :   ///
      71              :   /// This function creates a diagonal matrix where the diagonal elements are taken from
      72              :   /// a flat initializer list. The list size must exactly match the matrix dimension.
      73              :   ///
      74              :   /// \param[in] list Initializer list containing the diagonal values
      75              :   /// \return DiagonalMatrix with the specified diagonal elements
      76              :   /// \note The list size must equal Size_, otherwise assertion fails
      77              :   [[nodiscard]] static auto FromList(const std::initializer_list<ValueType_>& list) -> DiagonalMatrix;
      78              : 
      79              :   /// \brief Creates a DiagonalMatrix from the diagonal of a nested initializer list
      80              :   ///
      81              :   /// This function creates a diagonal matrix by extracting the diagonal elements from
      82              :   /// a nested initializer list representing a full matrix. Only the diagonal elements
      83              :   /// (where row index equals column index) are used.
      84              :   ///
      85              :   /// \param[in] list Nested initializer list representing a square matrix
      86              :   /// \return DiagonalMatrix containing the diagonal elements from the input list
      87              :   /// \note The outer list size must equal Size_, and each inner list size must equal Size_
      88              :   [[nodiscard]] static auto FromList(const std::initializer_list<std::initializer_list<ValueType_>>& list) -> DiagonalMatrix;
      89              : 
      90              :   /// \brief Set a diagonal block matrix at given position
      91              :   /// \tparam SrcSize_    Size_ of the source block
      92              :   /// \tparam SrcCount   Number of diagonal elements to copy from source
      93              :   /// \tparam SrcIdxBeg  Begin diagonal element index in source
      94              :   /// \tparam DstIdxBeg  Begin diagonal element index in dest
      95              :   /// \param[in] block   Source block matrix to copy from
      96              :   template <sint32 SrcSize_, sint32 SrcCount_, sint32 SrcIdxBeg_, sint32 DstIdxBeg_>
      97              :   void setBlock(const DiagonalMatrix<ValueType_, SrcSize_>& block);
      98              : 
      99              :   /// \brief Multiplication with generic matrix: D * Matrix
     100              :   /// \tparam Cols_
     101              :   /// \tparam IsRowMajor_
     102              :   /// \param[in] mat
     103              :   /// \return Matrix<ValueType_, Size_, Cols_, IsRowMajor_>
     104              :   template <sint32 Cols_, bool IsRowMajor_>
     105              :   [[nodiscard]] auto operator*(const Matrix<ValueType_, Size_, Cols_, IsRowMajor_>& mat) const
     106              :       -> Matrix<ValueType_, Size_, Cols_, IsRowMajor_>;
     107              : 
     108              :   /// \brief Multiplication with triangular matrix: D * Matrix
     109              :   /// \tparam isLower_
     110              :   /// \tparam isRowMajor_
     111              :   /// \param[in] mat  A triangular matrix
     112              :   /// \return TriangularMatrix<ValueType_, Size_, isLower_, isRowMajor_>
     113              :   template <bool IsLower_, bool IsRowMajor_>
     114              :   [[nodiscard]] auto operator*(const TriangularMatrix<ValueType_, Size_, IsLower_, IsRowMajor_>& mat) const
     115              :       -> TriangularMatrix<ValueType_, Size_, IsLower_, IsRowMajor_>;
     116              : 
     117              :   /// \brief Multiplication with diagonal matrix: D * Matrix
     118              :   /// \param[in] mat  A diagonal matrix
     119              :   /// \return DiagonalMatrix<ValueType_, Size_>
     120              :   [[nodiscard]] auto operator*(const DiagonalMatrix& mat) const -> DiagonalMatrix;
     121              : 
     122              :   /// \brief Multiplication with scalar: D * scalar
     123              :   /// \param[in] scalar  A scalar value
     124              :   /// \return DiagonalMatrix<ValueType_, Size_>
     125              :   [[nodiscard]] auto operator*(const ValueType_ scalar) const -> DiagonalMatrix;
     126              : 
     127              :   /// \brief Inplace Multiplication with diagonal matrix: D * Matrix
     128              :   /// \param[in] mat  A diagonal matrix
     129              :   void operator*=(const DiagonalMatrix& mat);
     130              : 
     131              :   /// \brief Inplace Multiplication with scalar: D * scalar
     132              :   /// \param[in] scalar  A scalar value
     133              :   void operator*=(const ValueType_ scalar);
     134              : 
     135              :   /// \brief Element access to a scalar diagonal value
     136              :   /// \param[in] idx  Row/Col index of the element
     137              :   /// \return tl::expected<std::reference_wrapper<ValueType_>, Errors>   either the reference at (idx) or an Error descriptor
     138              :   [[nodiscard]] auto operator[](const sint32 idx) -> tl::expected<std::reference_wrapper<ValueType_>, Errors>
     139              :   { // implemented here to solve cyclic includes
     140              :     if (!(idx >= 0 && idx < Size_))
     141              :     {
     142              :       return tl::unexpected<Errors>{Errors::invalid_access_idx};
     143              :     }
     144              :     return at_unsafe(idx);
     145              :   }
     146              : 
     147              :   /// \brief Element read-only access to a scalar diagonal value
     148              :   /// \param[in] idx  Row/Col index of the element
     149              :   /// \return tl::expected<ValueType_, Errors>   either the value at (idx) or an Error descriptor
     150              :   [[nodiscard]] auto operator[](const sint32 idx) const -> tl::expected<ValueType_, Errors>
     151              :   { // implemented here to solve cyclic includes
     152              :     if (!(idx >= 0 && idx < Size_))
     153              :     {
     154              :       return tl::unexpected<Errors>{Errors::invalid_access_idx};
     155              :     }
     156              :     return at_unsafe(idx);
     157              :   }
     158              : 
     159              :   /// \brief Compute the inverse of the diagonal matrix.
     160              :   ///
     161              :   /// Calculates the inverse by taking the reciprocal of each diagonal element.
     162              :   /// The result is also a diagonal matrix.
     163              :   ///
     164              :   /// \return DiagonalMatrix The inverse matrix such that D * D^(-1) = I
     165              :   ///
     166              :   /// \warning Fails if any diagonal element is zero (singular matrix)
     167              :   /// \note O(Size_) complexity, very efficient for diagonal matrixes
     168              :   [[nodiscard]] auto inverse() const -> DiagonalMatrix;
     169              : 
     170              :   /// \brief Compute the inverse in-place.
     171              :   ///
     172              :   /// Modifies this matrix to contain its inverse by taking reciprocals of diagonal elements.
     173              :   ///
     174              :   /// \warning Fails if any diagonal element is zero (singular matrix)
     175              :   /// \note More memory efficient than the const version for large matrixes
     176              :   void inverse();
     177              : 
     178              :   /// \brief Calculate the trace of the diagonal matrix.
     179              :   ///
     180              :   /// Computes the sum of all diagonal elements of the matrix.
     181              :   /// The trace is defined as the sum of elements A_ii for i = 1 to n.
     182              :   ///
     183              :   /// \return ValueType_ The trace of the matrix(sum of diagonal elements)
     184              :   [[nodiscard]] auto trace() const -> ValueType_;
     185              : 
     186              :   /// \brief Calculate the determinant of the diagonal matrix.
     187              :   ///
     188              :   /// Computes the determinant as the product of the diagonal elements.
     189              :   ///
     190              :   /// \return ValueType_ The determinant of the matrix
     191              :   /// \note Time complexity: O(n) where n is the matrix dimension
     192              :   /// \note For singular matrixes, the determinant will be zero or very close to zero
     193              :   [[nodiscard]] auto determinant() const -> ValueType_;
     194              : 
     195              :   /// \brief Check if the diagonal matrix is positive definite.
     196              :   ///
     197              :   /// A diagonal matrix is positive definite if all diagonal elements are positive.
     198              :   ///
     199              :   /// \return true if all diagonal elements are > 0, false otherwise
     200              :   ///
     201              :   /// \note For diagonal matrixes, positive definiteness is equivalent to all elements > 0
     202              :   [[nodiscard]] auto isPositiveDefinite() const -> bool;
     203              : 
     204              :   /// \brief Check if the diagonal matrix is positive semi-definite.
     205              :   ///
     206              :   /// A diagonal matrix is positive semi-definite if all diagonal elements are non-negative.
     207              :   ///
     208              :   /// \return true if all diagonal elements are >= 0, false otherwise
     209              :   ///
     210              :   /// \note For diagonal matrixes, positive semi-definiteness means all elements >= 0
     211              :   [[nodiscard]] auto isPositiveSemiDefinite() const -> bool;
     212              : 
     213              :   //////////////////////////////////////////////////
     214              :   // unsafe access operators  --->
     215              :   /// \brief Element read-only access to a scalar vector value
     216              :   /// \param[in] idx  Row index of the element
     217              :   /// \return ValueType_  Scalar vector value
     218        10101 :   [[nodiscard]] auto at_unsafe(sint32 idx) const -> ValueType_ { return _data.at_unsafe(idx); }
     219              : 
     220              :   /// \brief Element access to a scalar vector value
     221              :   /// \param[in] idx  Row index of the element
     222              :   /// \return ValueType_&  Reference to the scalar vector value
     223         8480 :   [[nodiscard]] auto at_unsafe(sint32 idx) -> ValueType_& { return _data.at_unsafe(idx); }
     224              :   // <---
     225              : 
     226              :   // clang-format off
     227              : TEST_REMOVE_PRIVATE:
     228              :   ; // workaround for correct indentation
     229              :   // clang-format on
     230              :   Vector<ValueType_, Size_> _data{};
     231              : };
     232              : 
     233              : template <typename ValueType_, sint32 Rows_, sint32 Cols_, bool IsRowMajor_>
     234              : [[nodiscard]] auto operator*(const Matrix<ValueType_, Rows_, Cols_, IsRowMajor_>& mat,
     235              :                              const DiagonalMatrix<ValueType_, Cols_>& diag) -> Matrix<ValueType_, Rows_, Cols_, IsRowMajor_>;
     236              : 
     237              : } // namespace math
     238              : } // namespace tracking
     239              : 
     240              : #endif // EDCA948E_6A98_4AF3_8A01_916736E1577B
        

Generated by: LCOV version 2.0-1