Basic matrixcompare functionality

This commit is contained in:
Andreas Longva 2019-08-11 18:26:12 +02:00
parent 6cd0007354
commit f6730dac1f
5 changed files with 192 additions and 0 deletions

View File

@ -30,6 +30,7 @@ sparse = [ ]
debug = [ "approx/num-complex", "rand/std" ]
alloc = [ ]
io = [ "pest", "pest_derive" ]
compare = [ "matrixcompare-core" ]
[dependencies]
typenum = "1.11"
@ -50,6 +51,7 @@ mint = { version = "0.5", optional = true }
quickcheck = { version = "0.9", optional = true }
pest = { version = "2.0", optional = true }
pest_derive = { version = "2.0", optional = true }
matrixcompare-core = { version = "0.1", optional = true }
[dev-dependencies]
serde_json = "1.0"
@ -61,6 +63,9 @@ rand_isaac = "0.2"
### https://github.com/rust-lang/cargo/issues/4866
#criterion = "0.2.10"
# For matrix comparison macro
matrixcompare = "0.1"
[workspace]
members = [ "nalgebra-lapack", "nalgebra-glm" ]

79
examples/matrixcompare.rs Normal file
View File

@ -0,0 +1,79 @@
extern crate nalgebra as na;
#[macro_use]
extern crate quickcheck;
use na::{U3, U4, MatrixMN};
use matrixcompare::compare_matrices;
use matrixcompare::comparators::{ExactElementwiseComparator, AbsoluteElementwiseComparator};
fn compare_integers_fail() {
println!("Comparing two integer matrices.");
let a = MatrixMN::<_, U3, U4>::from_row_slice(&[
0, 1, 2, 3,
4, 5, 6, 7,
8, 9, -2, 11
]);
let b = MatrixMN::<_, U3, U4>::from_row_slice(&[
0, 1, 2, 3,
4, 5, 6, 7,
8, 9, 10, 11
]);
if let Some(msg) = compare_matrices(a, b, &ExactElementwiseComparator).panic_message() {
println!("{}", msg);
}
}
fn compare_different_size() {
println!("Comparing matrices of different size.");
let a = MatrixMN::<_, U3, U3>::from_row_slice(&[
0, 1, 2,
4, 5, 6,
8, 9, 10,
]);
let b = MatrixMN::<_, U3, U4>::from_row_slice(&[
0, 1, 2, 3,
4, 5, 6, 7,
8, 9, 10, 11
]);
if let Some(msg) = compare_matrices(a, b, &ExactElementwiseComparator).panic_message() {
println!("{}", msg);
}
}
fn compare_f64_abs_tol_fail() {
println!("Comparing two f64 matrices.");
let a = MatrixMN::<f64, U3, U3>::from_row_slice(&[
0.0, 1.0, 2.0 + 1e-10,
4.0, 5.0, 6.0,
8.0, 9.0, 10.0,
]);
let b = MatrixMN::<_, U3, U3>::from_row_slice(&[
0.0, 1.0, 2.0,
4.0, 5.0, 6.0,
8.0, 9.0, 10.0
]);
let cmp = AbsoluteElementwiseComparator { tol: 1e-12 };
if let Some(msg) = compare_matrices(a, b, &cmp).panic_message() {
println!("{}", msg);
}
}
fn main() {
// This example mostly serves the purpose of demonstrating the kind of error messages
// that are given upon comparison failure.
// The more typical use case is using `assert_matrix_eq!` in tests.
compare_integers_fail();
println!("======================================================");
compare_f64_abs_tol_fail();
println!("======================================================");
compare_different_size();
}

View File

@ -159,6 +159,30 @@ impl<N: Scalar, R: Dim, C: Dim, S: Abomonation> Abomonation for Matrix<N, R, C,
}
}
#[cfg(feature = "compare")]
impl<N: Scalar, R: Dim, C: Dim, S: Storage<N, R, C>>
matrixcompare_core::Matrix<N> for Matrix<N, R, C, S> {
fn rows(&self) -> usize {
self.nrows()
}
fn cols(&self) -> usize {
self.ncols()
}
fn access(&self) -> matrixcompare_core::Access<N> {
matrixcompare_core::Access::Dense(self)
}
}
#[cfg(feature = "compare")]
impl<N: Scalar, R: Dim, C: Dim, S: Storage<N, R, C>>
matrixcompare_core::DenseAccess<N> for Matrix<N, R, C, S> {
fn fetch_single(&self, row: usize, col: usize) -> N {
self.index((row, col)).clone()
}
}
impl<N: Scalar, R: Dim, C: Dim, S> Matrix<N, R, C, S> {
/// Creates a new matrix with the given data without statically checking that the matrix
/// dimension matches the storage dimension.

View File

@ -0,0 +1,81 @@
//! Tests for `matrixcompare` integration.
//!
//! The `matrixcompare` crate itself is responsible for testing the actual comparison.
//! The tests here only check that the necessary trait implementations are correctly implemented,
//! in addition to some sanity checks with example input.
use nalgebra::{U4, U5, MatrixMN, DMatrix};
use matrixcompare::{assert_matrix_eq, DenseAccess};
#[cfg(feature = "arbitrary")]
quickcheck! {
fn fetch_single_is_equivalent_to_index_f64(matrix: DMatrix<f64>) -> bool {
for i in 0 .. matrix.nrows() {
for j in 0 .. matrix.ncols() {
if matrix.fetch_single(i, j) != *matrix.index((i, j)) {
return false;
}
}
}
true
}
fn matrixcompare_shape_agrees_with_matrix(matrix: DMatrix<f64>) -> bool {
matrix.nrows() == <DMatrix<f64> as matrixcompare::Matrix<f64>>::rows(&matrix)
&&
matrix.ncols() == <DMatrix<f64> as matrixcompare::Matrix<f64>>::cols(&matrix)
}
}
#[test]
fn assert_matrix_eq_dense_positive_comparison() {
let a = MatrixMN::<_, U4, U5>::from_row_slice(&[
1210, 1320, 1430, 1540, 1650,
2310, 2420, 2530, 2640, 2750,
3410, 3520, 3630, 3740, 3850,
4510, 4620, 4730, 4840, 4950,
]);
let b = MatrixMN::<_, U4, U5>::from_row_slice(&[
1210, 1320, 1430, 1540, 1650,
2310, 2420, 2530, 2640, 2750,
3410, 3520, 3630, 3740, 3850,
4510, 4620, 4730, 4840, 4950,
]);
// Test matrices of static size
assert_matrix_eq!(a, b);
assert_matrix_eq!(&a, b);
assert_matrix_eq!(a, &b);
assert_matrix_eq!(&a, &b);
// Test matrices of dynamic size
let a_dyn = a.index((0..4, 0..5));
let b_dyn = b.index((0..4, 0..5));
assert_matrix_eq!(a_dyn, b_dyn);
assert_matrix_eq!(a_dyn, &b_dyn);
assert_matrix_eq!(&a_dyn, b_dyn);
assert_matrix_eq!(&a_dyn, &b_dyn);
}
#[test]
#[should_panic]
fn assert_matrix_eq_dense_negative_comparison() {
let a = MatrixMN::<_, U4, U5>::from_row_slice(&[
1210, 1320, 1430, 1540, 1650,
2310, 2420, 2530, 2640, 2750,
3410, 3520, 3630, 3740, 3850,
4510, 4620, -4730, 4840, 4950,
]);
let b = MatrixMN::<_, U4, U5>::from_row_slice(&[
1210, 1320, 1430, 1540, 1650,
2310, 2420, 2530, 2640, 2750,
3410, 3520, 3630, 3740, 3850,
4510, 4620, 4730, 4840, 4950,
]);
assert_matrix_eq!(a, b);
}

View File

@ -10,5 +10,8 @@ mod matrix_slice;
mod mint;
mod serde;
#[cfg(feature = "compare")]
mod matrixcompare;
#[cfg(feature = "arbitrary")]
pub mod helper;