numerics 0.1.0
Loading...
Searching...
No Matches
matrix_properties.hpp
Go to the documentation of this file.
1/// @file linalg/matrix_properties.hpp
2/// @brief Declared mathematical properties for stored matrices.
3#pragma once
4
5#include "core/matrix.hpp"
6#include <cmath>
7#include <stdexcept>
8#include <utility>
9
10namespace num::linalg {
11
12[[nodiscard]] inline bool is_symmetric(const Matrix& A, real tol = 1e-12) {
13 if (A.rows() != A.cols()) {
14 return false;
15 }
16 const idx n = A.rows();
17 for (idx i = 0; i < n; ++i) {
18 for (idx j = 0; j < i; ++j) {
19 if (std::abs(A(i, j) - A(j, i)) > tol) {
20 return false;
21 }
22 }
23 }
24 return true;
25}
26
27[[nodiscard]] inline bool is_spd(const Matrix& A, real tol = 1e-12) {
28 if (!is_symmetric(A, tol)) {
29 return false;
30 }
31
32 const idx n = A.rows();
33 Matrix L(n, n, 0.0);
34 for (idx i = 0; i < n; ++i) {
35 for (idx j = 0; j <= i; ++j) {
36 real sum = A(i, j);
37 for (idx k = 0; k < j; ++k) {
38 sum -= L(i, k) * L(j, k);
39 }
40
41 if (i == j) {
42 if (sum <= tol) {
43 return false;
44 }
45 L(i, j) = std::sqrt(sum);
46 } else {
47 L(i, j) = sum / L(j, j);
48 }
49 }
50 }
51 return true;
52}
53
54template<class Mat>
55class SymmetricMatrix final {
56public:
58
59 explicit SymmetricMatrix(Mat A)
60 : A_(std::move(A)) {}
61
62 [[nodiscard]] const Mat& base() const noexcept { return A_; }
63 [[nodiscard]] idx rows() const noexcept { return A_.rows(); }
64 [[nodiscard]] idx cols() const noexcept { return A_.cols(); }
65
66private:
67 Mat A_;
68};
69
70template<class Mat>
71class SPDMatrix final {
72public:
74 using spd_matrix_tag = void;
75
76 explicit SPDMatrix(Mat A)
77 : A_(std::move(A)) {}
78
79 [[nodiscard]] const Mat& base() const noexcept { return A_; }
80 [[nodiscard]] idx rows() const noexcept { return A_.rows(); }
81 [[nodiscard]] idx cols() const noexcept { return A_.cols(); }
82
83private:
84 Mat A_;
85};
86
88 return SymmetricMatrix<Matrix>(std::move(A));
89}
90
91[[nodiscard]] inline SPDMatrix<Matrix> assume_spd(Matrix A) {
92 return SPDMatrix<Matrix>(std::move(A));
93}
94
95[[nodiscard]] inline SymmetricMatrix<Matrix> make_symmetric(Matrix A, real tol = 1e-12) {
96 if (!is_symmetric(A, tol)) {
97 throw std::invalid_argument("make_symmetric: matrix is not symmetric");
98 }
99 return SymmetricMatrix<Matrix>(std::move(A));
100}
101
102[[nodiscard]] inline SPDMatrix<Matrix> make_spd(Matrix A, real tol = 1e-12) {
103 if (!is_spd(A, tol)) {
104 throw std::invalid_argument("make_spd: matrix is not symmetric positive definite");
105 }
106 return SPDMatrix<Matrix>(std::move(A));
107}
108
109} // namespace num::linalg
constexpr idx rows() const noexcept
Definition matrix.hpp:87
constexpr idx cols() const noexcept
Definition matrix.hpp:88
idx cols() const noexcept
const Mat & base() const noexcept
idx rows() const noexcept
const Mat & base() const noexcept
Dense row-major matrix templated over scalar type T.
SymmetricMatrix< Matrix > make_symmetric(Matrix A, real tol=1e-12)
bool is_spd(const Matrix &A, real tol=1e-12)
SymmetricMatrix< Matrix > assume_symmetric(Matrix A)
bool is_symmetric(const Matrix &A, real tol=1e-12)
SPDMatrix< Matrix > make_spd(Matrix A, real tol=1e-12)
SPDMatrix< Matrix > assume_spd(Matrix A)
double real
Definition types.hpp:10
std::size_t idx
Definition types.hpp:11
constexpr real e
Definition math.hpp:44