nalgebra-lapack: run tests with proptest instead of quickcheck.
This commit is contained in:
parent
6cfd2bca14
commit
74f4b0ba4d
|
@ -18,9 +18,11 @@ maintenance = { status = "actively-developed" }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
serde-serialize = [ "serde", "serde_derive" ]
|
serde-serialize = [ "serde", "serde_derive" ]
|
||||||
|
proptest-support = [ "nalgebra/proptest-support" ]
|
||||||
|
arbitrary = [ "nalgebra/arbitrary" ]
|
||||||
|
|
||||||
# For BLAS/LAPACK
|
# For BLAS/LAPACK
|
||||||
default = ["openblas"]
|
default = ["netlib"]
|
||||||
openblas = ["lapack-src/openblas"]
|
openblas = ["lapack-src/openblas"]
|
||||||
netlib = ["lapack-src/netlib"]
|
netlib = ["lapack-src/netlib"]
|
||||||
accelerate = ["lapack-src/accelerate"]
|
accelerate = ["lapack-src/accelerate"]
|
||||||
|
@ -39,6 +41,7 @@ lapack-src = { version = "0.6", default-features = false }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
nalgebra = { version = "0.24", features = [ "arbitrary" ], path = ".." }
|
nalgebra = { version = "0.24", features = [ "arbitrary" ], path = ".." }
|
||||||
|
proptest = { version = "1", default-features = false, features = ["std"] }
|
||||||
quickcheck = "1"
|
quickcheck = "1"
|
||||||
approx = "0.4"
|
approx = "0.4"
|
||||||
rand = "0.8"
|
rand = "0.8"
|
||||||
|
|
|
@ -1,8 +1,14 @@
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate approx;
|
extern crate approx;
|
||||||
|
#[cfg(not(feature = "proptest-support"))]
|
||||||
|
compile_error!("Tests must be run with `proptest-support`");
|
||||||
|
|
||||||
extern crate nalgebra as na;
|
extern crate nalgebra as na;
|
||||||
extern crate nalgebra_lapack as nl;
|
extern crate nalgebra_lapack as nl;
|
||||||
#[macro_use]
|
|
||||||
extern crate quickcheck;
|
extern crate lapack;
|
||||||
|
extern crate lapack_src;
|
||||||
|
|
||||||
mod linalg;
|
mod linalg;
|
||||||
|
#[path = "../../tests/proptest/mod.rs"]
|
||||||
|
mod proptest;
|
||||||
|
|
|
@ -1,101 +1,90 @@
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
|
|
||||||
use na::{DMatrix, DVector, Matrix3, Matrix4, Matrix4x3, Vector4};
|
use na::{DMatrix, DVector, Matrix4x3, Vector4};
|
||||||
use nl::Cholesky;
|
use nl::Cholesky;
|
||||||
|
|
||||||
quickcheck! {
|
use crate::proptest::*;
|
||||||
fn cholesky(m: DMatrix<f64>) -> bool {
|
use proptest::{prop_assert, proptest};
|
||||||
if m.len() != 0 {
|
|
||||||
let m = &m * m.transpose();
|
|
||||||
if let Some(chol) = Cholesky::new(m.clone()) {
|
|
||||||
let l = chol.unpack();
|
|
||||||
let reconstructed_m = &l * l.transpose();
|
|
||||||
|
|
||||||
return relative_eq!(reconstructed_m, m, epsilon = 1.0e-7)
|
proptest! {
|
||||||
}
|
#[test]
|
||||||
|
fn cholesky(m in dmatrix()) {
|
||||||
|
let m = &m * m.transpose();
|
||||||
|
if let Some(chol) = Cholesky::new(m.clone()) {
|
||||||
|
let l = chol.unpack();
|
||||||
|
let reconstructed_m = &l * l.transpose();
|
||||||
|
|
||||||
|
prop_assert!(relative_eq!(reconstructed_m, m, epsilon = 1.0e-7));
|
||||||
}
|
}
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cholesky_static(m: Matrix3<f64>) -> bool {
|
#[test]
|
||||||
|
fn cholesky_static(m in matrix3()) {
|
||||||
let m = &m * m.transpose();
|
let m = &m * m.transpose();
|
||||||
if let Some(chol) = Cholesky::new(m) {
|
if let Some(chol) = Cholesky::new(m) {
|
||||||
let l = chol.unpack();
|
let l = chol.unpack();
|
||||||
let reconstructed_m = &l * l.transpose();
|
let reconstructed_m = &l * l.transpose();
|
||||||
|
|
||||||
relative_eq!(reconstructed_m, m, epsilon = 1.0e-7)
|
prop_assert!(relative_eq!(reconstructed_m, m, epsilon = 1.0e-7))
|
||||||
}
|
|
||||||
else {
|
|
||||||
false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cholesky_solve(n: usize, nb: usize) -> bool {
|
#[test]
|
||||||
if n != 0 {
|
fn cholesky_solve(n in PROPTEST_MATRIX_DIM, nb in PROPTEST_MATRIX_DIM) {
|
||||||
let n = cmp::min(n, 15); // To avoid slowing down the test too much.
|
let n = cmp::min(n, 15); // To avoid slowing down the test too much.
|
||||||
let nb = cmp::min(nb, 15); // To avoid slowing down the test too much.
|
let nb = cmp::min(nb, 15); // To avoid slowing down the test too much.
|
||||||
let m = DMatrix::<f64>::new_random(n, n);
|
let m = DMatrix::<f64>::new_random(n, n);
|
||||||
let m = &m * m.transpose();
|
let m = &m * m.transpose();
|
||||||
|
|
||||||
if let Some(chol) = Cholesky::new(m.clone()) {
|
if let Some(chol) = Cholesky::new(m.clone()) {
|
||||||
let b1 = DVector::new_random(n);
|
let b1 = DVector::new_random(n);
|
||||||
let b2 = DMatrix::new_random(n, nb);
|
let b2 = DMatrix::new_random(n, nb);
|
||||||
|
|
||||||
let sol1 = chol.solve(&b1).unwrap();
|
let sol1 = chol.solve(&b1).unwrap();
|
||||||
let sol2 = chol.solve(&b2).unwrap();
|
let sol2 = chol.solve(&b2).unwrap();
|
||||||
|
|
||||||
return relative_eq!(&m * sol1, b1, epsilon = 1.0e-6) &&
|
prop_assert!(relative_eq!(&m * sol1, b1, epsilon = 1.0e-6));
|
||||||
relative_eq!(&m * sol2, b2, epsilon = 1.0e-6)
|
prop_assert!(relative_eq!(&m * sol2, b2, epsilon = 1.0e-6));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cholesky_solve_static(m: Matrix4<f64>) -> bool {
|
#[test]
|
||||||
|
fn cholesky_solve_static(m in matrix4()) {
|
||||||
let m = &m * m.transpose();
|
let m = &m * m.transpose();
|
||||||
match Cholesky::new(m) {
|
if let Some(chol) = Cholesky::new(m) {
|
||||||
Some(chol) => {
|
let b1 = Vector4::new_random();
|
||||||
let b1 = Vector4::new_random();
|
let b2 = Matrix4x3::new_random();
|
||||||
let b2 = Matrix4x3::new_random();
|
|
||||||
|
|
||||||
let sol1 = chol.solve(&b1).unwrap();
|
let sol1 = chol.solve(&b1).unwrap();
|
||||||
let sol2 = chol.solve(&b2).unwrap();
|
let sol2 = chol.solve(&b2).unwrap();
|
||||||
|
|
||||||
relative_eq!(m * sol1, b1, epsilon = 1.0e-7) &&
|
prop_assert!(relative_eq!(m * sol1, b1, epsilon = 1.0e-7));
|
||||||
relative_eq!(m * sol2, b2, epsilon = 1.0e-7)
|
prop_assert!(relative_eq!(m * sol2, b2, epsilon = 1.0e-7));
|
||||||
},
|
|
||||||
None => true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cholesky_inverse(n: usize) -> bool {
|
#[test]
|
||||||
if n != 0 {
|
fn cholesky_inverse(n in PROPTEST_MATRIX_DIM) {
|
||||||
let n = cmp::min(n, 15); // To avoid slowing down the test too much.
|
let n = cmp::min(n, 15); // To avoid slowing down the test too much.
|
||||||
let m = DMatrix::<f64>::new_random(n, n);
|
let m = DMatrix::<f64>::new_random(n, n);
|
||||||
let m = &m * m.transpose();
|
let m = &m * m.transpose();
|
||||||
|
|
||||||
if let Some(m1) = Cholesky::new(m.clone()).unwrap().inverse() {
|
if let Some(m1) = Cholesky::new(m.clone()).unwrap().inverse() {
|
||||||
let id1 = &m * &m1;
|
let id1 = &m * &m1;
|
||||||
let id2 = &m1 * &m;
|
let id2 = &m1 * &m;
|
||||||
|
|
||||||
return id1.is_identity(1.0e-6) && id2.is_identity(1.0e-6);
|
prop_assert!(id1.is_identity(1.0e-6) && id2.is_identity(1.0e-6));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cholesky_inverse_static(m: Matrix4<f64>) -> bool {
|
#[test]
|
||||||
|
fn cholesky_inverse_static(m in matrix4()) {
|
||||||
let m = m * m.transpose();
|
let m = m * m.transpose();
|
||||||
match Cholesky::new(m.clone()).unwrap().inverse() {
|
if let Some(m1) = Cholesky::new(m.clone()).unwrap().inverse() {
|
||||||
Some(m1) => {
|
let id1 = &m * &m1;
|
||||||
let id1 = &m * &m1;
|
let id2 = &m1 * &m;
|
||||||
let id2 = &m1 * &m;
|
|
||||||
|
|
||||||
id1.is_identity(1.0e-5) && id2.is_identity(1.0e-5)
|
prop_assert!(id1.is_identity(1.0e-5) && id2.is_identity(1.0e-5))
|
||||||
},
|
|
||||||
None => true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,38 +1,32 @@
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
|
|
||||||
use nl::Hessenberg;
|
|
||||||
use na::{DMatrix, Matrix4};
|
use na::{DMatrix, Matrix4};
|
||||||
|
use nl::Hessenberg;
|
||||||
|
|
||||||
quickcheck!{
|
use crate::proptest::*;
|
||||||
fn hessenberg(n: usize) -> bool {
|
use proptest::{prop_assert, proptest};
|
||||||
if n != 0 {
|
|
||||||
let n = cmp::min(n, 25);
|
|
||||||
let m = DMatrix::<f64>::new_random(n, n);
|
|
||||||
|
|
||||||
match Hessenberg::new(m.clone()) {
|
proptest! {
|
||||||
Some(hess) => {
|
#[test]
|
||||||
let h = hess.h();
|
fn hessenberg(n in PROPTEST_MATRIX_DIM) {
|
||||||
let p = hess.p();
|
let n = cmp::min(n, 25);
|
||||||
|
let m = DMatrix::<f64>::new_random(n, n);
|
||||||
|
|
||||||
relative_eq!(m, &p * h * p.transpose(), epsilon = 1.0e-7)
|
if let Some(hess) = Hessenberg::new(m.clone()) {
|
||||||
},
|
let h = hess.h();
|
||||||
None => true
|
let p = hess.p();
|
||||||
}
|
|
||||||
}
|
prop_assert!(relative_eq!(m, &p * h * p.transpose(), epsilon = 1.0e-7))
|
||||||
else {
|
|
||||||
true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn hessenberg_static(m: Matrix4<f64>) -> bool {
|
#[test]
|
||||||
match Hessenberg::new(m) {
|
fn hessenberg_static(m in matrix4()) {
|
||||||
Some(hess) => {
|
if let Some(hess) = Hessenberg::new(m) {
|
||||||
let h = hess.h();
|
let h = hess.h();
|
||||||
let p = hess.p();
|
let p = hess.p();
|
||||||
|
|
||||||
relative_eq!(m, p * h * p.transpose(), epsilon = 1.0e-7)
|
prop_assert!(relative_eq!(m, p * h * p.transpose(), epsilon = 1.0e-7))
|
||||||
},
|
|
||||||
None => true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,28 +1,28 @@
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
|
|
||||||
use na::{DMatrix, DVector, Matrix3x4, Matrix4, Matrix4x3, Vector4};
|
use na::{DMatrix, DVector, Matrix4x3, Vector4};
|
||||||
use nl::LU;
|
use nl::LU;
|
||||||
|
|
||||||
quickcheck! {
|
use crate::proptest::*;
|
||||||
fn lup(m: DMatrix<f64>) -> bool {
|
use proptest::{prop_assert, proptest};
|
||||||
if m.len() != 0 {
|
|
||||||
let lup = LU::new(m.clone());
|
|
||||||
let l = lup.l();
|
|
||||||
let u = lup.u();
|
|
||||||
let mut computed1 = &l * &u;
|
|
||||||
lup.permute(&mut computed1);
|
|
||||||
|
|
||||||
let computed2 = lup.p() * l * u;
|
proptest! {
|
||||||
|
#[test]
|
||||||
|
fn lup(m in dmatrix()) {
|
||||||
|
let lup = LU::new(m.clone());
|
||||||
|
let l = lup.l();
|
||||||
|
let u = lup.u();
|
||||||
|
let mut computed1 = &l * &u;
|
||||||
|
lup.permute(&mut computed1);
|
||||||
|
|
||||||
relative_eq!(computed1, m, epsilon = 1.0e-7) &&
|
let computed2 = lup.p() * l * u;
|
||||||
relative_eq!(computed2, m, epsilon = 1.0e-7)
|
|
||||||
}
|
prop_assert!(relative_eq!(computed1, m, epsilon = 1.0e-7));
|
||||||
else {
|
prop_assert!(relative_eq!(computed2, m, epsilon = 1.0e-7));
|
||||||
true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lu_static(m: Matrix3x4<f64>) -> bool {
|
#[test]
|
||||||
|
fn lu_static(m in matrix3x5()) {
|
||||||
let lup = LU::new(m);
|
let lup = LU::new(m);
|
||||||
let l = lup.l();
|
let l = lup.l();
|
||||||
let u = lup.u();
|
let u = lup.u();
|
||||||
|
@ -31,37 +31,34 @@ quickcheck! {
|
||||||
|
|
||||||
let computed2 = lup.p() * l * u;
|
let computed2 = lup.p() * l * u;
|
||||||
|
|
||||||
relative_eq!(computed1, m, epsilon = 1.0e-7) &&
|
prop_assert!(relative_eq!(computed1, m, epsilon = 1.0e-7));
|
||||||
relative_eq!(computed2, m, epsilon = 1.0e-7)
|
prop_assert!(relative_eq!(computed2, m, epsilon = 1.0e-7));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lu_solve(n: usize, nb: usize) -> bool {
|
#[test]
|
||||||
if n != 0 {
|
fn lu_solve(n in PROPTEST_MATRIX_DIM, nb in PROPTEST_MATRIX_DIM) {
|
||||||
let n = cmp::min(n, 25); // To avoid slowing down the test too much.
|
let n = cmp::min(n, 25); // To avoid slowing down the test too much.
|
||||||
let nb = cmp::min(nb, 25); // To avoid slowing down the test too much.
|
let nb = cmp::min(nb, 25); // To avoid slowing down the test too much.
|
||||||
let m = DMatrix::<f64>::new_random(n, n);
|
let m = DMatrix::<f64>::new_random(n, n);
|
||||||
|
|
||||||
let lup = LU::new(m.clone());
|
let lup = LU::new(m.clone());
|
||||||
let b1 = DVector::new_random(n);
|
let b1 = DVector::new_random(n);
|
||||||
let b2 = DMatrix::new_random(n, nb);
|
let b2 = DMatrix::new_random(n, nb);
|
||||||
|
|
||||||
let sol1 = lup.solve(&b1).unwrap();
|
let sol1 = lup.solve(&b1).unwrap();
|
||||||
let sol2 = lup.solve(&b2).unwrap();
|
let sol2 = lup.solve(&b2).unwrap();
|
||||||
|
|
||||||
let tr_sol1 = lup.solve_transpose(&b1).unwrap();
|
let tr_sol1 = lup.solve_transpose(&b1).unwrap();
|
||||||
let tr_sol2 = lup.solve_transpose(&b2).unwrap();
|
let tr_sol2 = lup.solve_transpose(&b2).unwrap();
|
||||||
|
|
||||||
relative_eq!(&m * sol1, b1, epsilon = 1.0e-7) &&
|
prop_assert!(relative_eq!(&m * sol1, b1, epsilon = 1.0e-7));
|
||||||
relative_eq!(&m * sol2, b2, epsilon = 1.0e-7) &&
|
prop_assert!(relative_eq!(&m * sol2, b2, epsilon = 1.0e-7));
|
||||||
relative_eq!(m.transpose() * tr_sol1, b1, epsilon = 1.0e-7) &&
|
prop_assert!(relative_eq!(m.transpose() * tr_sol1, b1, epsilon = 1.0e-7));
|
||||||
relative_eq!(m.transpose() * tr_sol2, b2, epsilon = 1.0e-7)
|
prop_assert!(relative_eq!(m.transpose() * tr_sol2, b2, epsilon = 1.0e-7));
|
||||||
}
|
|
||||||
else {
|
|
||||||
true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lu_solve_static(m: Matrix4<f64>) -> bool {
|
#[test]
|
||||||
|
fn lu_solve_static(m in matrix4()) {
|
||||||
let lup = LU::new(m);
|
let lup = LU::new(m);
|
||||||
let b1 = Vector4::new_random();
|
let b1 = Vector4::new_random();
|
||||||
let b2 = Matrix4x3::new_random();
|
let b2 = Matrix4x3::new_random();
|
||||||
|
@ -71,37 +68,32 @@ quickcheck! {
|
||||||
let tr_sol1 = lup.solve_transpose(&b1).unwrap();
|
let tr_sol1 = lup.solve_transpose(&b1).unwrap();
|
||||||
let tr_sol2 = lup.solve_transpose(&b2).unwrap();
|
let tr_sol2 = lup.solve_transpose(&b2).unwrap();
|
||||||
|
|
||||||
relative_eq!(m * sol1, b1, epsilon = 1.0e-7) &&
|
prop_assert!(relative_eq!(m * sol1, b1, epsilon = 1.0e-7));
|
||||||
relative_eq!(m * sol2, b2, epsilon = 1.0e-7) &&
|
prop_assert!(relative_eq!(m * sol2, b2, epsilon = 1.0e-7));
|
||||||
relative_eq!(m.transpose() * tr_sol1, b1, epsilon = 1.0e-7) &&
|
prop_assert!(relative_eq!(m.transpose() * tr_sol1, b1, epsilon = 1.0e-7));
|
||||||
relative_eq!(m.transpose() * tr_sol2, b2, epsilon = 1.0e-7)
|
prop_assert!(relative_eq!(m.transpose() * tr_sol2, b2, epsilon = 1.0e-7));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lu_inverse(n: usize) -> bool {
|
#[test]
|
||||||
if n != 0 {
|
fn lu_inverse(n in PROPTEST_MATRIX_DIM) {
|
||||||
let n = cmp::min(n, 25); // To avoid slowing down the test too much.
|
let n = cmp::min(n, 25); // To avoid slowing down the test too much.
|
||||||
let m = DMatrix::<f64>::new_random(n, n);
|
let m = DMatrix::<f64>::new_random(n, n);
|
||||||
|
|
||||||
if let Some(m1) = LU::new(m.clone()).inverse() {
|
if let Some(m1) = LU::new(m.clone()).inverse() {
|
||||||
let id1 = &m * &m1;
|
let id1 = &m * &m1;
|
||||||
let id2 = &m1 * &m;
|
let id2 = &m1 * &m;
|
||||||
|
|
||||||
return id1.is_identity(1.0e-7) && id2.is_identity(1.0e-7);
|
prop_assert!(id1.is_identity(1.0e-7) && id2.is_identity(1.0e-7));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lu_inverse_static(m: Matrix4<f64>) -> bool {
|
#[test]
|
||||||
match LU::new(m.clone()).inverse() {
|
fn lu_inverse_static(m in matrix4()) {
|
||||||
Some(m1) => {
|
if let Some(m1) = LU::new(m.clone()).inverse() {
|
||||||
let id1 = &m * &m1;
|
let id1 = &m * &m1;
|
||||||
let id2 = &m1 * &m;
|
let id2 = &m1 * &m;
|
||||||
|
|
||||||
id1.is_identity(1.0e-5) && id2.is_identity(1.0e-5)
|
prop_assert!(id1.is_identity(1.0e-5) && id2.is_identity(1.0e-5))
|
||||||
},
|
|
||||||
None => true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +1,24 @@
|
||||||
use na::{DMatrix, Matrix4x3};
|
|
||||||
use nl::QR;
|
use nl::QR;
|
||||||
|
|
||||||
quickcheck! {
|
use crate::proptest::*;
|
||||||
fn qr(m: DMatrix<f64>) -> bool {
|
use proptest::{prop_assert, proptest};
|
||||||
|
|
||||||
|
proptest! {
|
||||||
|
#[test]
|
||||||
|
fn qr(m in dmatrix()) {
|
||||||
let qr = QR::new(m.clone());
|
let qr = QR::new(m.clone());
|
||||||
let q = qr.q();
|
let q = qr.q();
|
||||||
let r = qr.r();
|
let r = qr.r();
|
||||||
|
|
||||||
relative_eq!(m, q * r, epsilon = 1.0e-7)
|
prop_assert!(relative_eq!(m, q * r, epsilon = 1.0e-7))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn qr_static(m: Matrix4x3<f64>) -> bool {
|
#[test]
|
||||||
|
fn qr_static(m in matrix5x3()) {
|
||||||
let qr = QR::new(m);
|
let qr = QR::new(m);
|
||||||
let q = qr.q();
|
let q = qr.q();
|
||||||
let r = qr.r();
|
let r = qr.r();
|
||||||
|
|
||||||
relative_eq!(m, q * r, epsilon = 1.0e-7)
|
prop_assert!(relative_eq!(m, q * r, epsilon = 1.0e-7))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,46 +3,40 @@ use std::cmp;
|
||||||
use na::{DMatrix, Matrix4};
|
use na::{DMatrix, Matrix4};
|
||||||
use nl::Eigen;
|
use nl::Eigen;
|
||||||
|
|
||||||
quickcheck! {
|
use crate::proptest::*;
|
||||||
fn eigensystem(n: usize) -> bool {
|
use proptest::{prop_assert, proptest};
|
||||||
if n != 0 {
|
|
||||||
let n = cmp::min(n, 25);
|
|
||||||
let m = DMatrix::<f64>::new_random(n, n);
|
|
||||||
|
|
||||||
match Eigen::new(m.clone(), true, true) {
|
proptest! {
|
||||||
Some(eig) => {
|
#[test]
|
||||||
let eigvals = DMatrix::from_diagonal(&eig.eigenvalues);
|
fn eigensystem(n in PROPTEST_MATRIX_DIM) {
|
||||||
let transformed_eigvectors = &m * eig.eigenvectors.as_ref().unwrap();
|
let n = cmp::min(n, 25);
|
||||||
let scaled_eigvectors = eig.eigenvectors.as_ref().unwrap() * &eigvals;
|
let m = DMatrix::<f64>::new_random(n, n);
|
||||||
|
|
||||||
let transformed_left_eigvectors = m.transpose() * eig.left_eigenvectors.as_ref().unwrap();
|
if let Some(eig) = Eigen::new(m.clone(), true, true) {
|
||||||
let scaled_left_eigvectors = eig.left_eigenvectors.as_ref().unwrap() * &eigvals;
|
let eigvals = DMatrix::from_diagonal(&eig.eigenvalues);
|
||||||
|
let transformed_eigvectors = &m * eig.eigenvectors.as_ref().unwrap();
|
||||||
|
let scaled_eigvectors = eig.eigenvectors.as_ref().unwrap() * &eigvals;
|
||||||
|
|
||||||
relative_eq!(transformed_eigvectors, scaled_eigvectors, epsilon = 1.0e-7) &&
|
let transformed_left_eigvectors = m.transpose() * eig.left_eigenvectors.as_ref().unwrap();
|
||||||
relative_eq!(transformed_left_eigvectors, scaled_left_eigvectors, epsilon = 1.0e-7)
|
let scaled_left_eigvectors = eig.left_eigenvectors.as_ref().unwrap() * &eigvals;
|
||||||
},
|
|
||||||
None => true
|
prop_assert!(relative_eq!(transformed_eigvectors, scaled_eigvectors, epsilon = 1.0e-7));
|
||||||
}
|
prop_assert!(relative_eq!(transformed_left_eigvectors, scaled_left_eigvectors, epsilon = 1.0e-7));
|
||||||
}
|
|
||||||
else {
|
|
||||||
true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eigensystem_static(m: Matrix4<f64>) -> bool {
|
#[test]
|
||||||
match Eigen::new(m, true, true) {
|
fn eigensystem_static(m in matrix4()) {
|
||||||
Some(eig) => {
|
if let Some(eig) = Eigen::new(m, true, true) {
|
||||||
let eigvals = Matrix4::from_diagonal(&eig.eigenvalues);
|
let eigvals = Matrix4::from_diagonal(&eig.eigenvalues);
|
||||||
let transformed_eigvectors = m * eig.eigenvectors.unwrap();
|
let transformed_eigvectors = m * eig.eigenvectors.unwrap();
|
||||||
let scaled_eigvectors = eig.eigenvectors.unwrap() * eigvals;
|
let scaled_eigvectors = eig.eigenvectors.unwrap() * eigvals;
|
||||||
|
|
||||||
let transformed_left_eigvectors = m.transpose() * eig.left_eigenvectors.unwrap();
|
let transformed_left_eigvectors = m.transpose() * eig.left_eigenvectors.unwrap();
|
||||||
let scaled_left_eigvectors = eig.left_eigenvectors.unwrap() * eigvals;
|
let scaled_left_eigvectors = eig.left_eigenvectors.unwrap() * eigvals;
|
||||||
|
|
||||||
relative_eq!(transformed_eigvectors, scaled_eigvectors, epsilon = 1.0e-7) &&
|
prop_assert!(relative_eq!(transformed_eigvectors, scaled_eigvectors, epsilon = 1.0e-7));
|
||||||
relative_eq!(transformed_left_eigvectors, scaled_left_eigvectors, epsilon = 1.0e-7)
|
prop_assert!(relative_eq!(transformed_left_eigvectors, scaled_left_eigvectors, epsilon = 1.0e-7));
|
||||||
},
|
|
||||||
None => true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +1,24 @@
|
||||||
use na::{DMatrix, Matrix4};
|
use na::DMatrix;
|
||||||
use nl::Schur;
|
use nl::Schur;
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
|
|
||||||
quickcheck! {
|
use crate::proptest::*;
|
||||||
fn schur(n: usize) -> bool {
|
use proptest::{prop_assert, proptest};
|
||||||
|
|
||||||
|
proptest! {
|
||||||
|
#[test]
|
||||||
|
fn schur(n in PROPTEST_MATRIX_DIM) {
|
||||||
let n = cmp::max(1, cmp::min(n, 10));
|
let n = cmp::max(1, cmp::min(n, 10));
|
||||||
let m = DMatrix::<f64>::new_random(n, n);
|
let m = DMatrix::<f64>::new_random(n, n);
|
||||||
|
|
||||||
let (vecs, vals) = Schur::new(m.clone()).unpack();
|
let (vecs, vals) = Schur::new(m.clone()).unpack();
|
||||||
|
|
||||||
relative_eq!(&vecs * vals * vecs.transpose(), m, epsilon = 1.0e-7)
|
prop_assert!(relative_eq!(&vecs * vals * vecs.transpose(), m, epsilon = 1.0e-7))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn schur_static(m: Matrix4<f64>) -> bool {
|
#[test]
|
||||||
|
fn schur_static(m in matrix4()) {
|
||||||
let (vecs, vals) = Schur::new(m.clone()).unpack();
|
let (vecs, vals) = Schur::new(m.clone()).unpack();
|
||||||
|
prop_assert!(relative_eq!(vecs * vals * vecs.transpose(), m, epsilon = 1.0e-7))
|
||||||
relative_eq!(vecs * vals * vecs.transpose(), m, epsilon = 1.0e-7)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,57 +1,53 @@
|
||||||
use na::{DMatrix, Matrix3x4};
|
use na::{DMatrix, Matrix3x5};
|
||||||
use nl::SVD;
|
use nl::SVD;
|
||||||
|
|
||||||
quickcheck! {
|
use crate::proptest::*;
|
||||||
fn svd(m: DMatrix<f64>) -> bool {
|
use proptest::{prop_assert, proptest};
|
||||||
if m.nrows() != 0 && m.ncols() != 0 {
|
|
||||||
let svd = SVD::new(m.clone()).unwrap();
|
|
||||||
let sm = DMatrix::from_partial_diagonal(m.nrows(), m.ncols(), svd.singular_values.as_slice());
|
|
||||||
|
|
||||||
let reconstructed_m = &svd.u * sm * &svd.vt;
|
proptest! {
|
||||||
let reconstructed_m2 = svd.recompose();
|
#[test]
|
||||||
|
fn svd(m in dmatrix()) {
|
||||||
|
let svd = SVD::new(m.clone()).unwrap();
|
||||||
|
let sm = DMatrix::from_partial_diagonal(m.nrows(), m.ncols(), svd.singular_values.as_slice());
|
||||||
|
|
||||||
relative_eq!(reconstructed_m, m, epsilon = 1.0e-7) &&
|
let reconstructed_m = &svd.u * sm * &svd.vt;
|
||||||
relative_eq!(reconstructed_m2, reconstructed_m, epsilon = 1.0e-7)
|
let reconstructed_m2 = svd.recompose();
|
||||||
}
|
|
||||||
else {
|
prop_assert!(relative_eq!(reconstructed_m, m, epsilon = 1.0e-7));
|
||||||
true
|
prop_assert!(relative_eq!(reconstructed_m2, reconstructed_m, epsilon = 1.0e-7));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn svd_static(m: Matrix3x4<f64>) -> bool {
|
#[test]
|
||||||
|
fn svd_static(m in matrix3x5()) {
|
||||||
let svd = SVD::new(m).unwrap();
|
let svd = SVD::new(m).unwrap();
|
||||||
let sm = Matrix3x4::from_partial_diagonal(svd.singular_values.as_slice());
|
let sm = Matrix3x5::from_partial_diagonal(svd.singular_values.as_slice());
|
||||||
|
|
||||||
let reconstructed_m = &svd.u * &sm * &svd.vt;
|
let reconstructed_m = &svd.u * &sm * &svd.vt;
|
||||||
let reconstructed_m2 = svd.recompose();
|
let reconstructed_m2 = svd.recompose();
|
||||||
|
|
||||||
relative_eq!(reconstructed_m, m, epsilon = 1.0e-7) &&
|
prop_assert!(relative_eq!(reconstructed_m, m, epsilon = 1.0e-7));
|
||||||
relative_eq!(reconstructed_m2, m, epsilon = 1.0e-7)
|
prop_assert!(relative_eq!(reconstructed_m2, m, epsilon = 1.0e-7));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pseudo_inverse(m: DMatrix<f64>) -> bool {
|
#[test]
|
||||||
if m.nrows() == 0 || m.ncols() == 0 {
|
fn pseudo_inverse(m in dmatrix()) {
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
let svd = SVD::new(m.clone()).unwrap();
|
let svd = SVD::new(m.clone()).unwrap();
|
||||||
let im = svd.pseudo_inverse(1.0e-7);
|
let im = svd.pseudo_inverse(1.0e-7);
|
||||||
|
|
||||||
if m.nrows() <= m.ncols() {
|
if m.nrows() <= m.ncols() {
|
||||||
return (&m * &im).is_identity(1.0e-7)
|
prop_assert!((&m * &im).is_identity(1.0e-7));
|
||||||
}
|
}
|
||||||
|
|
||||||
if m.nrows() >= m.ncols() {
|
if m.nrows() >= m.ncols() {
|
||||||
return (im * m).is_identity(1.0e-7)
|
prop_assert!((im * m).is_identity(1.0e-7));
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pseudo_inverse_static(m: Matrix3x4<f64>) -> bool {
|
#[test]
|
||||||
|
fn pseudo_inverse_static(m in matrix3x5()) {
|
||||||
let svd = SVD::new(m).unwrap();
|
let svd = SVD::new(m).unwrap();
|
||||||
let im = svd.pseudo_inverse(1.0e-7);
|
let im = svd.pseudo_inverse(1.0e-7);
|
||||||
|
|
||||||
(m * im).is_identity(1.0e-7)
|
prop_assert!((m * im).is_identity(1.0e-7))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +1,25 @@
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
|
|
||||||
use na::{DMatrix, Matrix4};
|
use na::DMatrix;
|
||||||
use nl::SymmetricEigen;
|
use nl::SymmetricEigen;
|
||||||
|
|
||||||
quickcheck! {
|
use crate::proptest::*;
|
||||||
fn symmetric_eigen(n: usize) -> bool {
|
use proptest::{prop_assert, proptest};
|
||||||
|
|
||||||
|
proptest! {
|
||||||
|
#[test]
|
||||||
|
fn symmetric_eigen(n in PROPTEST_MATRIX_DIM) {
|
||||||
let n = cmp::max(1, cmp::min(n, 10));
|
let n = cmp::max(1, cmp::min(n, 10));
|
||||||
let m = DMatrix::<f64>::new_random(n, n);
|
let m = DMatrix::<f64>::new_random(n, n);
|
||||||
let eig = SymmetricEigen::new(m.clone());
|
let eig = SymmetricEigen::new(m.clone());
|
||||||
let recomp = eig.recompose();
|
let recomp = eig.recompose();
|
||||||
relative_eq!(m.lower_triangle(), recomp.lower_triangle(), epsilon = 1.0e-5)
|
prop_assert!(relative_eq!(m.lower_triangle(), recomp.lower_triangle(), epsilon = 1.0e-5))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn symmetric_eigen_static(m: Matrix4<f64>) -> bool {
|
#[test]
|
||||||
|
fn symmetric_eigen_static(m in matrix4()) {
|
||||||
let eig = SymmetricEigen::new(m);
|
let eig = SymmetricEigen::new(m);
|
||||||
let recomp = eig.recompose();
|
let recomp = eig.recompose();
|
||||||
relative_eq!(m.lower_triangle(), recomp.lower_triangle(), epsilon = 1.0e-5)
|
prop_assert!(relative_eq!(m.lower_triangle(), recomp.lower_triangle(), epsilon = 1.0e-5))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
//! Tests for proptest-related functionality.
|
//! Tests for proptest-related functionality.
|
||||||
|
|
||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
use nalgebra::allocator::Allocator;
|
use nalgebra::allocator::Allocator;
|
||||||
use nalgebra::base::dimension::*;
|
use nalgebra::base::dimension::*;
|
||||||
use nalgebra::proptest::{DimRange, MatrixStrategy};
|
use nalgebra::proptest::{DimRange, MatrixStrategy};
|
||||||
|
@ -118,12 +121,10 @@ where
|
||||||
|
|
||||||
macro_rules! define_strategies(
|
macro_rules! define_strategies(
|
||||||
($($strategy_: ident $strategy: ident<$nrows: ident, $ncols: ident>),*) => {$(
|
($($strategy_: ident $strategy: ident<$nrows: ident, $ncols: ident>),*) => {$(
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn $strategy() -> impl Strategy<Value = MatrixMN<f64, $nrows, $ncols>> {
|
pub fn $strategy() -> impl Strategy<Value = MatrixMN<f64, $nrows, $ncols>> {
|
||||||
matrix(PROPTEST_F64, $nrows, $ncols)
|
matrix(PROPTEST_F64, $nrows, $ncols)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn $strategy_<ScalarStrategy>(scalar_strategy: ScalarStrategy) -> impl Strategy<Value = MatrixMN<ScalarStrategy::Value, $nrows, $ncols>>
|
pub fn $strategy_<ScalarStrategy>(scalar_strategy: ScalarStrategy) -> impl Strategy<Value = MatrixMN<ScalarStrategy::Value, $nrows, $ncols>>
|
||||||
where
|
where
|
||||||
ScalarStrategy: Strategy + Clone + 'static,
|
ScalarStrategy: Strategy + Clone + 'static,
|
||||||
|
|
Loading…
Reference in New Issue