SVD
Singular value decomposition factors any rows x cols matrix a as u * diag(sigma) * vᵗ, where u has orthonormal columns, sigma is a length-cols vector of non-negative
singular values sorted in descending order, and v is a cols x cols orthogonal matrix.
Unlike LU or Cholesky, a doesn’t need to be square — the SVD exists for any matrix.
rustebra computes it via svd_qr_iteration: it eigendecomposes aᵗ * a using a
fixed-iteration QR algorithm (100 iterations, rather than convergence-checked, so behavior
stays predictable in no_std contexts) to get v and sigma, then recovers u from
a * v scaled by sigma. svd is the general-purpose entry point, delegating to
svd_qr_iteration with an automatically-computed tolerance so callers don’t have to pick
one. Both are shown below, alongside the ergonomic
StaticMatrix/DynamicMatrix::svd() method used in
Matrix Operations.
#![allow(unused)]
fn main() {
use rustebra::algorithm::matrix::{svd, svd_qr_iteration};
use rustebra::storage::StaticStorage;
pub(crate) fn run() {
println!("\n== Singular Value Decomposition (SVD) ==");
// [[2, 0], [0, 1]].
let a = StaticStorage::new([2.0, 0.0, 0.0, 1.0]);
let mut scratch = [0.0; 5 * 2 * 2 + 2 + 2];
let mut u = [0.0; 4];
let mut sigma = [0.0; 2];
let mut v = [0.0; 4];
svd(&a, 2, 2, &mut u, &mut sigma, &mut v, &mut scratch).unwrap();
println!("sigma = {sigma:?}, u = {u:?}, v = {v:?}");
let mut sigma_explicit = [0.0; 2];
svd_qr_iteration(
&a,
2,
2,
&mut u,
&mut sigma_explicit,
&mut v,
&mut scratch,
1e-9,
)
.unwrap();
println!("sigma (explicit QR iteration) = {sigma_explicit:?}");
}
}
Gotchas
svd/svd_qr_iterationneed a caller-providedscratchbuffer sized5 * cols * cols + cols + rows— get the length wrong and you getErr(DimensionMismatch)back, not a panic.DynamicMatrix::svd()allocates this internally and doesn’t expose the parameter.- The QR iteration count inside
svd_qr_iterationis fixed (100), not convergence-checked — for matrices with closely clustered singular values, more iterations might be needed for full precision than this budget provides.