From 6ac6e7f75e17197ff9655b69d474fac05d8f61b3 Mon Sep 17 00:00:00 2001 From: metric-space Date: Wed, 22 Dec 2021 00:12:27 -0500 Subject: [PATCH] First compiling commit for take-2 of polar-decomposition: Code inspired by this thread: https://github.com/dimforge/nalgebra/pull/656 Main person behind this is LucasCampos --- src/linalg/svd.rs | 29 +++++++++++++++++++++++++++++ tests/linalg/svd.rs | 11 +++++++++++ 2 files changed, 40 insertions(+) diff --git a/src/linalg/svd.rs b/src/linalg/svd.rs index 5fd3debc8..dabcb491d 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 d76d17598..65a92ddb3 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); + +}