Skip to content

Commit 02c5cd5

Browse files
committed
[fix] pivot checks so that non singular matrices aren't incorrectly marked as singular
1 parent 1272f99 commit 02c5cd5

File tree

1 file changed

+30
-3
lines changed

1 file changed

+30
-3
lines changed

crates/lambda-rs/src/math/matrix.rs

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,8 @@ pub fn identity_matrix<
271271
/// # Returns
272272
///
273273
/// - Determinant of `data`.
274-
/// - `0.0` when elimination detects a near-zero pivot (singular matrix).
274+
/// - `0.0` when elimination detects an exact zero pivot after pivoting
275+
/// (singular matrix).
275276
fn determinant_gaussian_stack<const N: usize>(mut data: [[f32; N]; N]) -> f32 {
276277
let mut sign = 1.0_f32;
277278
for pivot in 0..N {
@@ -285,7 +286,7 @@ fn determinant_gaussian_stack<const N: usize>(mut data: [[f32; N]; N]) -> f32 {
285286
}
286287
}
287288

288-
if pivot_abs <= f32::EPSILON {
289+
if pivot_abs == 0.0 {
289290
return 0.0;
290291
}
291292

@@ -459,7 +460,7 @@ where
459460
}
460461
}
461462

462-
if pivot_abs <= f32::EPSILON {
463+
if pivot_abs == 0.0 {
463464
return Ok(0.0);
464465
}
465466

@@ -571,6 +572,32 @@ mod tests {
571572
assert_eq!(m2.determinant(), Ok(-306.0));
572573
}
573574

575+
#[test]
576+
fn determinant_preserves_small_non_zero_pivot_in_stack_path() {
577+
let m = [[1.0e-8, 0.0, 0.0], [0.0, 2.0, 0.0], [0.0, 0.0, 3.0]];
578+
crate::assert_approximately_equal!(
579+
m.determinant().expect("determinant should succeed"),
580+
6.0e-8,
581+
1.0e-12
582+
);
583+
}
584+
585+
#[test]
586+
fn determinant_preserves_small_non_zero_pivot_in_dynamic_path() {
587+
let m = [
588+
[1.0e-8, 0.0, 0.0, 0.0, 0.0],
589+
[0.0, 2.0, 0.0, 0.0, 0.0],
590+
[0.0, 0.0, 3.0, 0.0, 0.0],
591+
[0.0, 0.0, 0.0, 4.0, 0.0],
592+
[0.0, 0.0, 0.0, 0.0, 5.0],
593+
];
594+
crate::assert_approximately_equal!(
595+
m.determinant().expect("determinant should succeed"),
596+
1.2e-6,
597+
1.0e-10
598+
);
599+
}
600+
574601
#[test]
575602
fn non_square_matrix_determinant() {
576603
let m = [[3.0, 8.0], [4.0, 6.0], [0.0, 1.0]];

0 commit comments

Comments
 (0)