2018-09-13 12:06:04 +08:00
|
|
|
#![cfg(all(feature = "arbitrary", feature = "debug"))]
|
2018-01-17 22:47:28 +08:00
|
|
|
|
2017-08-03 01:37:44 +08:00
|
|
|
use na::debug::RandomSDP;
|
2018-10-21 04:26:44 +08:00
|
|
|
use na::dimension::U4;
|
|
|
|
use na::{DMatrix, DVector, Matrix4x3, Vector4};
|
|
|
|
use std::cmp;
|
2017-08-03 01:37:44 +08:00
|
|
|
|
|
|
|
quickcheck! {
|
|
|
|
fn cholesky(m: RandomSDP<f64>) -> bool {
|
|
|
|
let mut m = m.unwrap();
|
|
|
|
|
|
|
|
// Put garbage on the upper triangle to make sure it is not read by the decomposition.
|
|
|
|
m.fill_upper_triangle(23.0, 1);
|
|
|
|
|
2017-08-14 01:52:46 +08:00
|
|
|
let l = m.clone().cholesky().unwrap().unpack();
|
2017-08-03 01:37:44 +08:00
|
|
|
m.fill_upper_triangle_with_lower_triangle();
|
|
|
|
relative_eq!(m, &l * l.transpose(), epsilon = 1.0e-7)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn cholesky_static(m: RandomSDP<f64, U4>) -> bool {
|
|
|
|
let m = m.unwrap();
|
2017-08-14 01:52:46 +08:00
|
|
|
let chol = m.cholesky().unwrap();
|
2017-08-03 01:37:44 +08:00
|
|
|
let l = chol.unpack();
|
|
|
|
|
|
|
|
if !relative_eq!(m, &l * l.transpose(), epsilon = 1.0e-7) {
|
|
|
|
false
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn cholesky_solve(m: RandomSDP<f64>, nb: usize) -> bool {
|
|
|
|
let m = m.unwrap();
|
|
|
|
let n = m.nrows();
|
|
|
|
let nb = cmp::min(nb, 50); // To avoid slowing down the test too much.
|
|
|
|
|
2017-08-14 01:52:46 +08:00
|
|
|
let chol = m.clone().cholesky().unwrap();
|
2017-08-03 01:37:44 +08:00
|
|
|
let b1 = DVector::new_random(n);
|
|
|
|
let b2 = DMatrix::new_random(n, nb);
|
|
|
|
|
|
|
|
let sol1 = chol.solve(&b1);
|
|
|
|
let sol2 = chol.solve(&b2);
|
|
|
|
|
|
|
|
relative_eq!(&m * &sol1, b1, epsilon = 1.0e-7) &&
|
|
|
|
relative_eq!(&m * &sol2, b2, epsilon = 1.0e-7)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn cholesky_solve_static(m: RandomSDP<f64, U4>) -> bool {
|
|
|
|
let m = m.unwrap();
|
2017-08-14 01:52:46 +08:00
|
|
|
let chol = m.clone().cholesky().unwrap();
|
2017-08-03 01:37:44 +08:00
|
|
|
let b1 = Vector4::new_random();
|
|
|
|
let b2 = Matrix4x3::new_random();
|
|
|
|
|
|
|
|
let sol1 = chol.solve(&b1);
|
|
|
|
let sol2 = chol.solve(&b2);
|
|
|
|
|
|
|
|
relative_eq!(m * sol1, b1, epsilon = 1.0e-7) &&
|
|
|
|
relative_eq!(m * sol2, b2, epsilon = 1.0e-7)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn cholesky_inverse(m: RandomSDP<f64>) -> bool {
|
|
|
|
let m = m.unwrap();
|
|
|
|
|
2017-08-14 01:52:46 +08:00
|
|
|
let m1 = m.clone().cholesky().unwrap().inverse();
|
2017-08-03 01:37:44 +08:00
|
|
|
let id1 = &m * &m1;
|
|
|
|
let id2 = &m1 * &m;
|
|
|
|
|
|
|
|
id1.is_identity(1.0e-7) && id2.is_identity(1.0e-7)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn cholesky_inverse_static(m: RandomSDP<f64, U4>) -> bool {
|
|
|
|
let m = m.unwrap();
|
2017-08-14 01:52:46 +08:00
|
|
|
let m1 = m.clone().cholesky().unwrap().inverse();
|
2017-08-03 01:37:44 +08:00
|
|
|
let id1 = &m * &m1;
|
|
|
|
let id2 = &m1 * &m;
|
|
|
|
|
|
|
|
id1.is_identity(1.0e-7) && id2.is_identity(1.0e-7)
|
|
|
|
}
|
|
|
|
}
|