akreon-linalg
Fixed-size linear algebra and numerical methods in C++26.
Loading...
Searching...
No Matches
svd.hpp
Go to the documentation of this file.
1/*
2 * Copyright © 2025-2026 Akreon LLC
3 * SPDX-License-Identifier: Apache-2.0
4 */
5
6#pragma once
7
9#include "eig_decomp.hpp"
10
11namespace linalg {
12
22template <MatrixContainer Mat>
23struct SVD {
24 // @brief aliasing complex and real types for eigen decomposition
27 using Complex = std::conditional_t<linalg::Complex<T>, T, std::complex<Real>>;
28
29 // @brief helpers for Rows & Cols
30 static constexpr std::size_t Rows = mat_rows_v<Mat>;
31 static constexpr std::size_t Cols = mat_cols_v<Mat>;
32
38 constexpr SVD(const Mat& A) : converged(false) { svd(A); }
39
44 bool converged;
45
46private:
52 constexpr void svd(const Mat& A) {
53 // Form the Hermitian Gram matrix M = A^* A.
55 if constexpr (linalg::Real<T>) M = transpose(A) * A;
56 else M = conjugate_transpose(A) * A;
57
58 // Its orthonormal eigenvectors provide the right singular basis V.
59 const auto result = EigenDecomposition(M);
60 converged = result.converged;
61 if (!converged) return;
62
63 const auto& V = result.V;
65 for (std::size_t i = 0; i < Cols; ++i) {
66 // Compute sigma_i = ||A*v_i|| with scaling, then u_i = A*v_i / sigma_i.
67 const auto column = as_complex_matrix(A) * get_col(V, i);
68 Real scale = 0;
69 for (const auto& value : column)
70 scale = std::max(scale, constexpr_abs(value));
71 if (scale == Real(0)) continue;
72 auto normalized = column;
73 for (std::size_t j = 0; j < Rows; ++j) normalized(j) /= scale;
75 for (std::size_t j = 0; j < Rows; ++j) U(j, i) = column(j) / S(i, i);
76 }
77
78 // Store the right factor V^* for reconstruction.
80
81 // Apply one descending permutation to sigma_i, u_i, and v_i.
82 sort_svd_desc();
83 }
84
88 constexpr void sort_svd_desc() {
89 // Determine the order from the diagonal of Sigma.
90 const auto P = argsort_desc(get_diag(S));
91
92 // Permute U columns and V^* rows together with their singular values.
96 for (std::size_t i = 0; i < Cols; ++i) {
97 const auto idx = P[i];
98 S_tmp(i, i) = S(idx, idx);
99
100 for (std::size_t r = 0; r < Rows; ++r) U_tmp(r, i) = U(r, idx);
101
102 for (std::size_t c = 0; c < Cols; ++c) VT_tmp(i, c) = VT(idx, c);
103 }
104
105 S = S_tmp;
106 U = U_tmp;
107 VT = VT_tmp;
108 }
109};
110
111} // namespace linalg
Field classified by scalar_traits as complex.
Field classified by scalar_traits as real.
constexpr auto get_diag(const Mat &A)
get the diagonal of a matrix A
typename scalar_traits_t< T >::real_type real_type_t
Associated real component type registered for T.
constexpr auto as_complex_matrix(const Mat &A)
express matrix as complex one
constexpr auto conjugate_transpose(const Mat &A)
conjugate transpose of a matrix
constexpr auto transpose(const Vec &x)
tranpose of a vector
constexpr T constexpr_abs(T x)
Compute real absolute value or complex magnitude.
constexpr std::size_t mat_rows_v
Registered compile-time row count after cv/ref normalization.
constexpr auto get_col(const Mat &A, std::size_t idx)
get the column of matrix A based on given index
constexpr auto argsort_desc(const Vec &x)
Return coordinate indices sorted by descending real value.
typename mat_traits< remove_cvref_t< Mat > >::value_type matrix_scalar_t
Registered matrix scalar type after cv/ref normalization.
Computes eigenvalues and eigenvectors satisfying A V = V diag(lambda).
forward declaration for L2 norm
Owning, fixed-size, row-major matrix container over a scalar field.
Definition matrix.hpp:44
Computes A = U Sigma V^* from the eigendecomposition of A^* A.
Definition svd.hpp:23
Matrix< Complex, Cols, Cols > VT
SVD member variables.
Definition svd.hpp:41
Matrix< Complex, Rows, Rows > U
left singular vectors
Definition svd.hpp:42
matrix_scalar_t< Mat > T
Definition svd.hpp:25
constexpr SVD(const Mat &A)
Compute singular triplets for A.
Definition svd.hpp:38
static constexpr std::size_t Rows
Definition svd.hpp:30
real_type_t< T > Real
Definition svd.hpp:26
Matrix< Real, Rows, Cols > S
singular values
Definition svd.hpp:43
static constexpr std::size_t Cols
Definition svd.hpp:31
bool converged
converged
Definition svd.hpp:44