Skip to content

Commit 4478a99

Browse files
Fix SymmetricEigen Routine (#1210)
* Add known-failing unit test case for SymmetricEigen * Fix eigenvector calculation for subdim=2 case in SymmetricEigen
1 parent 3014264 commit 4478a99

1 file changed

Lines changed: 45 additions & 5 deletions

File tree

src/linalg/symmetric_eigen.rs

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -205,10 +205,21 @@ where
205205
diag[start + 1].clone(),
206206
);
207207
let eigvals = m.eigenvalues().unwrap();
208-
let basis = Vector2::new(
209-
eigvals.x.clone() - diag[start + 1].clone(),
210-
off_diag[start].clone(),
211-
);
208+
209+
// Choose the basis least likely to experience cancellation
210+
let basis = if (eigvals.x.clone() - diag[start + 1].clone()).abs()
211+
> (eigvals.x.clone() - diag[start].clone()).abs()
212+
{
213+
Vector2::new(
214+
eigvals.x.clone() - diag[start + 1].clone(),
215+
off_diag[start].clone(),
216+
)
217+
} else {
218+
Vector2::new(
219+
off_diag[start].clone(),
220+
eigvals.x.clone() - diag[start].clone(),
221+
)
222+
};
212223

213224
diag[start] = eigvals[0].clone();
214225
diag[start + 1] = eigvals[1].clone();
@@ -348,7 +359,36 @@ where
348359

349360
#[cfg(test)]
350361
mod test {
351-
use crate::base::Matrix2;
362+
use crate::base::{Matrix2, Matrix4};
363+
364+
/// Exercises bug reported in issue #1109 of nalgebra (https://github.com/dimforge/nalgebra/issues/1109)
365+
#[test]
366+
fn symmetric_eigen_regression_issue_1109() {
367+
let m = Matrix4::new(
368+
-19884.07f64,
369+
-10.07188,
370+
11.277279,
371+
-188560.63,
372+
-10.07188,
373+
12.518197,
374+
1.3770627,
375+
-102.97504,
376+
11.277279,
377+
1.3770627,
378+
14.587362,
379+
113.26099,
380+
-188560.63,
381+
-102.97504,
382+
113.26099,
383+
-1788112.3,
384+
);
385+
let eig = m.symmetric_eigen();
386+
assert!(relative_eq!(
387+
m.lower_triangle(),
388+
eig.recompose().lower_triangle(),
389+
epsilon = 1.0e-5
390+
));
391+
}
352392

353393
fn expected_shift(m: Matrix2<f64>) -> f64 {
354394
let vals = m.eigenvalues().unwrap();

0 commit comments

Comments
 (0)