#![cfg(not(table_format = "q16_16"))]
use g_math::fixed_point::{FixedPoint, FixedVector, FixedMatrix};
use g_math::fixed_point::imperative::decompose::{
lu_decompose, qr_decompose, cholesky_decompose,
};
fn fp(s: &str) -> FixedPoint {
if s.starts_with('-') {
-FixedPoint::from_str(&s[1..])
} else {
FixedPoint::from_str(s)
}
}
fn tol() -> FixedPoint {
#[cfg(table_format = "q32_32")]
{ fp("0.0001") }
#[cfg(not(table_format = "q32_32"))]
{ fp("0.000000000001") }
}
fn assert_fp_eq(got: FixedPoint, expected: FixedPoint, name: &str) {
let diff = (got - expected).abs();
assert!(diff < tol(),
"mpmath validation failed for {}: got {}, expected {}, diff={}",
name, got, expected, diff);
}
fn assert_vec_eq(got: &FixedVector, expected: &[&str], name: &str) {
assert_eq!(got.len(), expected.len(), "{}: dimension mismatch", name);
for i in 0..got.len() {
assert_fp_eq(got[i], fp(expected[i]),
&format!("{}[{}]", name, i));
}
}
fn system1_a() -> FixedMatrix {
FixedMatrix::from_slice(3, 3, &[
fp("3"), fp("1"), fp("2"),
fp("1"), fp("4"), fp("1"),
fp("2"), fp("1"), fp("5"),
])
}
fn system1_b() -> FixedVector {
FixedVector::from_slice(&[fp("1"), fp("2"), fp("3")])
}
#[test]
fn test_mpmath_lu_solve_system1() {
let a = system1_a();
let b = system1_b();
let lu = lu_decompose(&a).unwrap();
let x = lu.solve(&b).unwrap();
assert_vec_eq(&x, &["-0.2", "0.4", "0.6"], "LU solve system1");
}
#[test]
fn test_mpmath_qr_solve_system1() {
let a = system1_a();
let b = system1_b();
let qr = qr_decompose(&a).unwrap();
let x = qr.solve(&b).unwrap();
assert_vec_eq(&x, &["-0.2", "0.4", "0.6"], "QR solve system1");
}
#[test]
fn test_mpmath_cholesky_solve_system1() {
let a = system1_a();
let b = system1_b();
let chol = cholesky_decompose(&a).unwrap();
let x = chol.solve(&b).unwrap();
assert_vec_eq(&x, &["-0.2", "0.4", "0.6"], "Cholesky solve system1");
}
#[test]
fn test_mpmath_det_system1() {
let a = system1_a();
let lu = lu_decompose(&a).unwrap();
assert_fp_eq(lu.determinant(), fp("40"), "det(system1)");
}
#[test]
fn test_mpmath_lu_solve_system2() {
let a = FixedMatrix::from_slice(2, 2, &[fp("2"), fp("1"), fp("5"), fp("3")]);
let b = FixedVector::from_slice(&[fp("4"), fp("7")]);
let lu = lu_decompose(&a).unwrap();
let x = lu.solve(&b).unwrap();
assert_vec_eq(&x, &["5", "-6"], "LU solve system2");
}
#[test]
fn test_mpmath_det_system2() {
let a = FixedMatrix::from_slice(2, 2, &[fp("2"), fp("1"), fp("5"), fp("3")]);
let lu = lu_decompose(&a).unwrap();
assert_fp_eq(lu.determinant(), fp("1"), "det(system2)");
}
#[test]
fn test_mpmath_inverse_system3() {
let a = FixedMatrix::from_slice(3, 3, &[
fp("1"), fp("2"), fp("3"),
fp("0"), fp("1"), fp("4"),
fp("5"), fp("6"), fp("0"),
]);
let lu = lu_decompose(&a).unwrap();
let inv = lu.inverse().unwrap();
assert_fp_eq(inv.get(0, 0), fp("-24"), "inv[0,0]");
assert_fp_eq(inv.get(0, 1), fp("18"), "inv[0,1]");
assert_fp_eq(inv.get(0, 2), fp("5"), "inv[0,2]");
assert_fp_eq(inv.get(1, 0), fp("20"), "inv[1,0]");
assert_fp_eq(inv.get(1, 1), fp("-15"), "inv[1,1]");
assert_fp_eq(inv.get(1, 2), fp("-4"), "inv[1,2]");
assert_fp_eq(inv.get(2, 0), fp("-5"), "inv[2,0]");
assert_fp_eq(inv.get(2, 1), fp("4"), "inv[2,1]");
assert_fp_eq(inv.get(2, 2), fp("1"), "inv[2,2]");
}
#[test]
fn test_mpmath_det_system3() {
let a = FixedMatrix::from_slice(3, 3, &[
fp("1"), fp("2"), fp("3"),
fp("0"), fp("1"), fp("4"),
fp("5"), fp("6"), fp("0"),
]);
let lu = lu_decompose(&a).unwrap();
assert_fp_eq(lu.determinant(), fp("1"), "det(system3)");
}
#[test]
fn test_mpmath_cholesky_factors() {
let a = FixedMatrix::from_slice(3, 3, &[
fp("4"), fp("12"), fp("-16"),
fp("12"), fp("37"), fp("-43"),
fp("-16"), fp("-43"), fp("98"),
]);
let chol = cholesky_decompose(&a).unwrap();
assert_fp_eq(chol.l.get(0, 0), fp("2"), "L[0,0]");
assert_fp_eq(chol.l.get(1, 0), fp("6"), "L[1,0]");
assert_fp_eq(chol.l.get(1, 1), fp("1"), "L[1,1]");
assert_fp_eq(chol.l.get(2, 0), fp("-8"), "L[2,0]");
assert_fp_eq(chol.l.get(2, 1), fp("5"), "L[2,1]");
assert_fp_eq(chol.l.get(2, 2), fp("3"), "L[2,2]");
assert_fp_eq(chol.l.get(0, 1), fp("0"), "L[0,1]");
assert_fp_eq(chol.l.get(0, 2), fp("0"), "L[0,2]");
assert_fp_eq(chol.l.get(1, 2), fp("0"), "L[1,2]");
}
#[test]
fn test_mpmath_cholesky_solve() {
let a = FixedMatrix::from_slice(2, 2, &[fp("4"), fp("2"), fp("2"), fp("3")]);
let b = FixedVector::from_slice(&[fp("1"), fp("2")]);
let chol = cholesky_decompose(&a).unwrap();
let x = chol.solve(&b).unwrap();
assert_vec_eq(&x, &["-0.125", "0.75"], "Cholesky solve");
}
#[test]
fn test_mpmath_det_2x2() {
let a = FixedMatrix::from_slice(2, 2, &[fp("1"), fp("2"), fp("3"), fp("4")]);
let lu = lu_decompose(&a).unwrap();
assert_fp_eq(lu.determinant(), fp("-2"), "det([[1,2],[3,4]])");
}
#[test]
fn test_mpmath_wilson_matrix_solve() {
let a = FixedMatrix::from_slice(4, 4, &[
fp("10"), fp("7"), fp("8"), fp("7"),
fp("7"), fp("5"), fp("6"), fp("5"),
fp("8"), fp("6"), fp("10"), fp("9"),
fp("7"), fp("5"), fp("9"), fp("10"),
]);
let b = FixedVector::from_slice(&[fp("32"), fp("23"), fp("33"), fp("31")]);
let lu = lu_decompose(&a).unwrap();
let x = lu.solve(&b).unwrap();
assert_vec_eq(&x, &["1", "1", "1", "1"], "Wilson LU solve");
}
#[test]
fn test_mpmath_wilson_matrix_det() {
let a = FixedMatrix::from_slice(4, 4, &[
fp("10"), fp("7"), fp("8"), fp("7"),
fp("7"), fp("5"), fp("6"), fp("5"),
fp("8"), fp("6"), fp("10"), fp("9"),
fp("7"), fp("5"), fp("9"), fp("10"),
]);
let lu = lu_decompose(&a).unwrap();
assert_fp_eq(lu.determinant(), fp("1"), "Wilson det");
}
#[test]
fn test_mpmath_wilson_qr_solve() {
let a = FixedMatrix::from_slice(4, 4, &[
fp("10"), fp("7"), fp("8"), fp("7"),
fp("7"), fp("5"), fp("6"), fp("5"),
fp("8"), fp("6"), fp("10"), fp("9"),
fp("7"), fp("5"), fp("9"), fp("10"),
]);
let b = FixedVector::from_slice(&[fp("32"), fp("23"), fp("33"), fp("31")]);
let qr = qr_decompose(&a).unwrap();
let x = qr.solve(&b).unwrap();
assert_vec_eq(&x, &["1", "1", "1", "1"], "Wilson QR solve");
}
#[test]
fn test_mpmath_wilson_cholesky_solve() {
let a = FixedMatrix::from_slice(4, 4, &[
fp("10"), fp("7"), fp("8"), fp("7"),
fp("7"), fp("5"), fp("6"), fp("5"),
fp("8"), fp("6"), fp("10"), fp("9"),
fp("7"), fp("5"), fp("9"), fp("10"),
]);
let b = FixedVector::from_slice(&[fp("32"), fp("23"), fp("33"), fp("31")]);
let chol = cholesky_decompose(&a).unwrap();
let x = chol.solve(&b).unwrap();
assert_vec_eq(&x, &["1", "1", "1", "1"], "Wilson Cholesky solve");
}