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}