mdarray_linalg/svd.rs
1//! Singular Value Decomposition (SVD)
2use mdarray::{DSlice, DTensor, Layout};
3use thiserror::Error;
4
5/// Error types related to singular value decomposition
6#[derive(Debug, Error)]
7pub enum SVDError {
8 #[error("Backend error code: {0}")]
9 BackendError(i32),
10
11 #[error("Inconsistent U and VT: must be both Some or both None")]
12 InconsistentUV,
13
14 #[error("Backend failed to converge: {superdiagonals} superdiagonals did not converge to zero")]
15 BackendDidNotConverge { superdiagonals: i32 },
16}
17
18/// Holds the results of a singular value decomposition, including
19/// singular values and the left and right singular vectors
20pub struct SVDDecomp<T> {
21 pub s: DTensor<T, 2>,
22 pub u: DTensor<T, 2>,
23 pub vt: DTensor<T, 2>,
24}
25
26/// Result type for singular value decomposition, returning either an
27/// `SVDDecomp` or an `SVDError`
28pub type SVDResult<T> = Result<SVDDecomp<T>, SVDError>;
29
30/// Singular value decomposition for matrix factorization and analysis
31pub trait SVD<T> {
32 /// Compute full SVD with new allocated matrices
33 fn svd<L: Layout>(&self, a: &mut DSlice<T, 2, L>) -> SVDResult<T>;
34
35 /// Compute only singular values with new allocated matrix
36 fn svd_s<L: Layout>(&self, a: &mut DSlice<T, 2, L>) -> Result<DTensor<T, 2>, SVDError>;
37
38 /// Compute full SVD, overwriting existing matrices
39 /// The matrix A is decomposed as A = U * S * V^T where:
40 /// - `s` contains the singular values (diagonal matrix S)
41 /// - `u` contains the left singular vectors (matrix U)
42 /// - `vt` contains the transposed right singular vectors (matrix V^T)
43 fn svd_overwrite<L: Layout, Ls: Layout, Lu: Layout, Lvt: Layout>(
44 &self,
45 a: &mut DSlice<T, 2, L>,
46 s: &mut DSlice<T, 2, Ls>,
47 u: &mut DSlice<T, 2, Lu>,
48 vt: &mut DSlice<T, 2, Lvt>,
49 ) -> Result<(), SVDError>;
50
51 /// Compute only singular values, overwriting existing matrix
52 /// Computes only the diagonal elements of the S matrix from the SVD decomposition.
53 fn svd_overwrite_s<L: Layout, Ls: Layout>(
54 &self,
55 a: &mut DSlice<T, 2, L>,
56 s: &mut DSlice<T, 2, Ls>,
57 ) -> Result<(), SVDError>;
58}