numerics 0.1.0
Loading...
Searching...
No Matches
cholesky.cpp
Go to the documentation of this file.
2#include <cmath>
3#include <stdexcept>
4
5namespace num {
6
10
12 if (A.rows() != A.cols()) {
13 throw std::invalid_argument("cholesky: matrix must be square");
14 }
15
16 const idx n = A.rows();
17 Matrix L(n, n, 0.0);
18
19 for (idx i = 0; i < n; ++i) {
20 for (idx j = 0; j <= i; ++j) {
21 real sum = A(i, j);
22 for (idx k = 0; k < j; ++k) {
23 sum -= L(i, k) * L(j, k);
24 }
25
26 if (i == j) {
27 if (sum <= real(0)) {
28 return {std::move(L), false};
29 }
30 L(i, j) = std::sqrt(sum);
31 } else {
32 L(i, j) = sum / L(j, j);
33 }
34 }
35 }
36
37 return {std::move(L), true};
38}
39
40void cholesky_solve(const CholeskyResult& f, const Vector& b, Vector& x) {
41 if (!f.success) {
42 throw std::invalid_argument("cholesky_solve: factorization failed");
43 }
44 const idx n = f.L.rows();
45 if (f.L.cols() != n || b.size() != n || x.size() != n) {
46 throw std::invalid_argument("cholesky_solve: dimension mismatch");
47 }
48
49 Vector y(n, 0.0);
50 for (idx i = 0; i < n; ++i) {
51 real sum = b[i];
52 for (idx k = 0; k < i; ++k) {
53 sum -= f.L(i, k) * y[k];
54 }
55 y[i] = sum / f.L(i, i);
56 }
57
58 for (idx ii = n; ii > 0;) {
59 --ii;
60 real sum = y[ii];
61 for (idx k = ii + 1; k < n; ++k) {
62 sum -= f.L(k, ii) * x[k];
63 }
64 x[ii] = sum / f.L(ii, ii);
65 }
66}
67
68} // namespace num
Dense Cholesky factorization for SPD matrices.
constexpr idx rows() const noexcept
Definition matrix.hpp:87
constexpr idx cols() const noexcept
Definition matrix.hpp:88
constexpr idx size() const noexcept
Definition vector.hpp:83
const Mat & base() const noexcept
double real
Definition types.hpp:10
std::size_t idx
Definition types.hpp:11
CholeskyResult cholesky(const linalg::SPDMatrix< Matrix > &A)
Definition cholesky.cpp:7
void cholesky_solve(const CholeskyResult &f, const Vector &b, Vector &x)
Definition cholesky.cpp:40
Lower-triangular factorization .
Definition cholesky.hpp:13