|
1 | 1 | use crate::utils::is_sorted_descending; |
| 2 | +use approx::{AbsDiffEq, RelativeEq}; |
2 | 3 | use na::{DMatrix, Matrix6}; |
3 | 4 |
|
4 | 5 | #[cfg(feature = "proptest-support")] |
@@ -513,3 +514,47 @@ fn svd_regression_issue_1313() { |
513 | 514 | let m2 = svd.recompose().unwrap(); |
514 | 515 | assert_relative_eq!(&m, &m2, epsilon = 1e-5); |
515 | 516 | } |
| 517 | + |
| 518 | +#[test] |
| 519 | +// Accuracy bug reported in issue #1172 of nalgebra (https://github.com/dimforge/nalgebra/issues/1172) |
| 520 | +fn svd_regression_issue_1172() { |
| 521 | + use nalgebra::{Complex, Matrix4}; |
| 522 | + type M4C = Matrix4<Complex<f64>>; |
| 523 | + |
| 524 | + let m = M4C::new( |
| 525 | + Complex::new(0.4846888711394364, -0.0000000000000002529226450498658), |
| 526 | + Complex::new(0.4997655143494952, -0.00000000000000001731471891552503), |
| 527 | + Complex::new(0.00000000000000001527512211317369, 0.49976551434949495), |
| 528 | + Complex::new(0.00000000000000009643636194372324, -0.48468887113943676), |
| 529 | + Complex::new(0.4997655143494954, -0.00000000000000023999992468308935), |
| 530 | + Complex::new(0.5153111288605629, -0.0000000000000002516108359162637), |
| 531 | + Complex::new(-0.000000000000000005044961400919933, 0.5153111288605631), |
| 532 | + Complex::new(0.000000000000000042486770760464153, -0.49976551434949495), |
| 533 | + Complex::new(-0.000000000000000032383811520876863, -0.49976551434949484), |
| 534 | + Complex::new(0.000000000000000014710206963221994, -0.5153111288605633), |
| 535 | + Complex::new(0.5153111288605635, 0.00000000000000016459157448729957), |
| 536 | + Complex::new(-0.4997655143494946, -0.00000000000000028045339796436483), |
| 537 | + Complex::new(0.00000000000000007455816688442185, 0.4846888711394367), |
| 538 | + Complex::new(0.0000000000000000641248522548626, 0.49976551434949484), |
| 539 | + Complex::new(-0.49976551434949473, -0.00000000000000018487105599880945), |
| 540 | + Complex::new(0.48468887113943704, 0.00000000000000015953066497724206), |
| 541 | + ); |
| 542 | + let svd = m.svd(true, true); |
| 543 | + let sings = svd.singular_values; |
| 544 | + let u = svd.u.unwrap(); |
| 545 | + let v_t = svd.v_t.unwrap(); |
| 546 | + let sigma = M4C::from_diagonal(&sings.cast::<Complex<f64>>()); |
| 547 | + let m1 = u * sigma * v_t; |
| 548 | + |
| 549 | + // Should be accurate to machine precision |
| 550 | + assert_relative_eq!(m, m1, epsilon = 1e-12); |
| 551 | + |
| 552 | + // Singular values should be sorted and non-negative |
| 553 | + assert!(sings.iter().all(|&x| x >= 0.0)); |
| 554 | + |
| 555 | + // The largest singular value should be close to 2.0 |
| 556 | + assert!(sings[0].abs_diff_eq(&2.0, 1e-12)); |
| 557 | + |
| 558 | + // The smallest singular value should be small |
| 559 | + assert!(sings[3] < 1e-12); |
| 560 | +} |
0 commit comments