use super::approx_eq;
use nalgebra::DMatrix;
use proptest::prelude::*;
use rustebra::algorithm::matrix::{lu, mul_matrix};
use rustebra::storage::StaticStorage;
const N: usize = 4;
const TOL: f64 = 1e-8;
proptest! {
#[test]
fn lu_reconstruction_matches_nalgebra_lu(
entries in prop::collection::vec(-10.0..10.0f64, N * N),
) {
let mut a = [0.0_f64; N * N];
a.copy_from_slice(&entries);
let mut l = [0.0_f64; N * N];
let mut u = [0.0_f64; N * N];
lu(&StaticStorage::new(a), N, N, &mut l, &mut u)
.expect("N x N input with correctly-sized buffers never returns Err");
let a_na = DMatrix::from_row_slice(N, N, &entries);
let lu_na = a_na.clone().lu();
let l_na = lu_na.l();
let u_na = lu_na.u();
let mut lu_product = [0.0_f64; N * N];
mul_matrix(&StaticStorage::new(l), N, N, &StaticStorage::new(u), N, N, &mut lu_product)
.expect("N x N matrices always multiply into N x N product");
let lu_na_product = &l_na * &u_na;
for r in 0..N {
for c in 0..N {
let ours = lu_product[r * N + c];
let theirs = lu_na_product[(r, c)];
prop_assert!(
approx_eq(ours, theirs, TOL),
"L*U reconstruction[{},{}]: ours={} vs nalgebra={}",
r,
c,
ours,
theirs
);
}
}
for r in 0..N {
for c in 0..N {
let ours = l[r * N + c];
let theirs = l_na[(r, c)];
prop_assert!(
approx_eq(ours, theirs, TOL),
"L[{},{}]: ours={} vs nalgebra={}",
r,
c,
ours,
theirs
);
}
}
for r in 0..N {
for c in 0..N {
let ours = u[r * N + c];
let theirs = u_na[(r, c)];
prop_assert!(
approx_eq(ours, theirs, TOL),
"U[{},{}]: ours={} vs nalgebra={}",
r,
c,
ours,
theirs
);
}
}
}
}