From d87fd4f9aa33533e2acc986dcbfbfa4fd19e5c52 Mon Sep 17 00:00:00 2001 From: ferxades12 Date: Tue, 23 Jun 2026 23:46:07 +0200 Subject: [PATCH 1/3] fix: clone eigenvalues to avoid move error --- src/linalg/eigen.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/linalg/eigen.rs b/src/linalg/eigen.rs index 8fae6c348..10fd32204 100644 --- a/src/linalg/eigen.rs +++ b/src/linalg/eigen.rs @@ -82,20 +82,22 @@ where for j in 1..dim { for i in 0..j { - let diff = eigenvalues[(i, i)] - eigenvalues[(j, j)]; + let diff = eigenvalues[(i, i)].clone() - eigenvalues[(j, j)].clone(); if diff.is_zero() && !eigenvalues[(i, j)].is_zero() { return None; } - let z = -eigenvalues[(i, j)] / diff; + let z = -eigenvalues[(i, j)].clone() / diff; for k in j + 1..dim { - eigenvalues[(i, k)] -= z * eigenvalues[(j, k)]; + let rhs = z.clone() * eigenvalues[(j, k)].clone(); + eigenvalues[(i, k)] -= rhs; } for k in 0..dim { - eigenvectors[(k, j)] += z * eigenvectors[(k, i)]; + let rhs = z.clone() * eigenvectors[(k, i)].clone(); + eigenvectors[(k, j)] += rhs; } } } From 8a20f0c75cb308f2e3a57abc4746546e8f4b686f Mon Sep 17 00:00:00 2001 From: ferxades12 Date: Tue, 23 Jun 2026 23:47:07 +0200 Subject: [PATCH 2/3] fix: Delete debug println! --- src/linalg/eigen.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/linalg/eigen.rs b/src/linalg/eigen.rs index 10fd32204..429acedb2 100644 --- a/src/linalg/eigen.rs +++ b/src/linalg/eigen.rs @@ -71,8 +71,6 @@ where let dim = m.nrows(); let (mut eigenvectors, mut eigenvalues) = Schur::new(m, 0).unwrap().unpack(); - println!("Schur eigenvalues: {}", eigenvalues); - // Check that the eigenvalues are all Complex. for i in 0..dim - 1 { if !eigenvalues[(i + 1, i)].is_zero() { From 80071a1a2b39932649fd44e97a8b88cc097e4024 Mon Sep 17 00:00:00 2001 From: ferxades12 Date: Tue, 23 Jun 2026 23:48:20 +0200 Subject: [PATCH 3/3] fix: refactor Eigen::new() into new() and try_new() --- src/linalg/eigen.rs | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/src/linalg/eigen.rs b/src/linalg/eigen.rs index 429acedb2..900754997 100644 --- a/src/linalg/eigen.rs +++ b/src/linalg/eigen.rs @@ -1,6 +1,7 @@ #[cfg(feature = "serde-serialize-no-std")] use serde::{Deserialize, Serialize}; +use approx::AbsDiffEq; use num_complex::Complex; use simba::scalar::ComplexField; use std::cmp; @@ -16,8 +17,8 @@ use crate::base::{ use crate::constraint::{DimEq, ShapeConstraint}; use crate::geometry::{Reflection, UnitComplex}; -use crate::linalg::householder; use crate::linalg::Schur; +use crate::linalg::householder; /// Eigendecomposition of a real matrix with real eigenvalues (or complex eigen values for complex matrices). #[cfg_attr(feature = "serde-serialize-no-std", derive(Serialize, Deserialize))] @@ -59,17 +60,35 @@ where Allocator> + Allocator> + Allocator + Allocator, // XXX: for debug DefaultAllocator: Allocator, - OMatrix: Display, { - /// Computes the eigendecomposition of a diagonalizable matrix with Complex eigenvalues. - pub fn new(m: OMatrix) -> Option> { + /// Computes the eigendecomposition of a square matrix with distinct eigenvalues. + pub fn new(m: OMatrix) -> Self { + Self::try_new(m, T::RealField::default_epsilon(), 0).unwrap() + } + + /// Attempts to compute the eigendecomposition of a square matrix with distinct eigenvalues. + /// + /// Returns `None` if the Schur decomposition fails to converge, if any eigenvalues are + /// complex (only for real matrices), or if any eigenvalues are repeated. + /// + /// # Arguments + /// + /// * `eps` − tolerance used to determine when a value converged to 0. + /// * `max_niter` − maximum total number of iterations performed by the algorithm. If this + /// number of iteration is exceeded, `None` is returned. If `niter == 0`, then the algorithm + /// continues indefinitely until convergence. + pub fn try_new( + m: OMatrix, + eps: T::RealField, + max_niter: usize, + ) -> Option> { assert!( m.is_square(), "Unable to compute the eigendecomposition of a non-square matrix." ); let dim = m.nrows(); - let (mut eigenvectors, mut eigenvalues) = Schur::new(m, 0).unwrap().unpack(); + let (mut eigenvectors, mut eigenvalues) = Schur::try_new(m, eps, max_niter)?.unpack(); // Check that the eigenvalues are all Complex. for i in 0..dim - 1 {