diff --git a/src/linalg/svd.rs b/src/linalg/svd.rs index 5fd3debc..dabcb491 100644 --- a/src/linalg/svd.rs +++ b/src/linalg/svd.rs @@ -643,6 +643,35 @@ where } } +impl, C: Dim> SVD +where + DefaultAllocator: Allocator, C> + + Allocator> + + Allocator>, +{ + /// converts SVD results to a polar form + + pub fn to_polar(&self) -> Result<(OMatrix, OMatrix), &'static str> + where DefaultAllocator: Allocator //result + + Allocator, R> // adjoint + + Allocator> // mapped vals + + Allocator // square matrix & result + + Allocator, DimMinimum> // ? + , + { + match (&self.u, &self.v_t) { + (Some(u), Some(v_t)) => Ok(( + u * OMatrix::from_diagonal(&self.singular_values.map(|e| T::from_real(e))) + * u.adjoint(), + u * v_t, + )), + (None, None) => Err("SVD solve: U and V^t have not been computed."), + (None, _) => Err("SVD solve: U has not been computed."), + (_, None) => Err("SVD solve: V^t has not been computed."), + } + } +} + impl, C: Dim> SVD where DimMinimum: DimSub, // for Bidiagonal. diff --git a/tests/linalg/svd.rs b/tests/linalg/svd.rs index d76d1759..65a92ddb 100644 --- a/tests/linalg/svd.rs +++ b/tests/linalg/svd.rs @@ -441,3 +441,14 @@ fn svd_sorted() { epsilon = 1.0e-5 ); } + +#[test] +fn svd_polar_decomposition() { + + let m = DMatrix::::new_random(4, 4); + let svd = m.clone().svd(true, true); + let (p,u) = svd.to_polar().unwrap(); + + assert_relative_eq!(m, p*u, epsilon = 1.0e-5); + +}