From f6730dac1fe2c911ba1022e0347fd520f77c2e18 Mon Sep 17 00:00:00 2001 From: Andreas Longva Date: Sun, 11 Aug 2019 18:26:12 +0200 Subject: [PATCH 1/4] Basic matrixcompare functionality --- Cargo.toml | 5 +++ examples/matrixcompare.rs | 79 ++++++++++++++++++++++++++++++++++++ src/base/matrix.rs | 24 +++++++++++ tests/core/matrixcompare.rs | 81 +++++++++++++++++++++++++++++++++++++ tests/core/mod.rs | 3 ++ 5 files changed, 192 insertions(+) create mode 100644 examples/matrixcompare.rs create mode 100644 tests/core/matrixcompare.rs diff --git a/Cargo.toml b/Cargo.toml index 4adf2ab1..fe347ed0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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" ] diff --git a/examples/matrixcompare.rs b/examples/matrixcompare.rs new file mode 100644 index 00000000..60c632d3 --- /dev/null +++ b/examples/matrixcompare.rs @@ -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::::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(); +} \ No newline at end of file diff --git a/src/base/matrix.rs b/src/base/matrix.rs index d30773a3..8107a1dc 100644 --- a/src/base/matrix.rs +++ b/src/base/matrix.rs @@ -159,6 +159,30 @@ impl Abomonation for Matrix> + matrixcompare_core::Matrix for Matrix { + fn rows(&self) -> usize { + self.nrows() + } + + fn cols(&self) -> usize { + self.ncols() + } + + fn access(&self) -> matrixcompare_core::Access { + matrixcompare_core::Access::Dense(self) + } +} + +#[cfg(feature = "compare")] +impl> + matrixcompare_core::DenseAccess for Matrix { + fn fetch_single(&self, row: usize, col: usize) -> N { + self.index((row, col)).clone() + } +} + impl Matrix { /// Creates a new matrix with the given data without statically checking that the matrix /// dimension matches the storage dimension. diff --git a/tests/core/matrixcompare.rs b/tests/core/matrixcompare.rs new file mode 100644 index 00000000..d4b6f142 --- /dev/null +++ b/tests/core/matrixcompare.rs @@ -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) -> 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) -> bool { + matrix.nrows() == as matrixcompare::Matrix>::rows(&matrix) + && + matrix.ncols() == as matrixcompare::Matrix>::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); +} \ No newline at end of file diff --git a/tests/core/mod.rs b/tests/core/mod.rs index ec1c4e3e..1b3c7861 100644 --- a/tests/core/mod.rs +++ b/tests/core/mod.rs @@ -10,5 +10,8 @@ mod matrix_slice; mod mint; mod serde; +#[cfg(feature = "compare")] +mod matrixcompare; + #[cfg(feature = "arbitrary")] pub mod helper; From 9196759bc2f0d04d2ba0ce76d9f8acede2f1c82d Mon Sep 17 00:00:00 2001 From: Andreas Longva Date: Mon, 29 Jun 2020 19:03:20 +0200 Subject: [PATCH 2/4] Improve matrixcompare example --- examples/matrixcompare.rs | 27 +++++++++++++++------------ src/base/matrix.rs | 10 ++++++---- tests/core/matrixcompare.rs | 8 ++++++-- 3 files changed, 27 insertions(+), 18 deletions(-) diff --git a/examples/matrixcompare.rs b/examples/matrixcompare.rs index 60c632d3..713be25f 100644 --- a/examples/matrixcompare.rs +++ b/examples/matrixcompare.rs @@ -1,60 +1,63 @@ extern crate nalgebra as na; -#[macro_use] -extern crate quickcheck; - -use na::{U3, U4, MatrixMN}; +use matrixcompare::comparators::{AbsoluteElementwiseComparator, ExactElementwiseComparator}; use matrixcompare::compare_matrices; -use matrixcompare::comparators::{ExactElementwiseComparator, AbsoluteElementwiseComparator}; +use na::{MatrixMN, U3, U4}; fn compare_integers_fail() { println!("Comparing two integer matrices."); + #[rustfmt::skip] let a = MatrixMN::<_, U3, U4>::from_row_slice(&[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -2, 11 ]); + #[rustfmt::skip] 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); + if let Err(err) = compare_matrices(a, b, &ExactElementwiseComparator) { + println!("{}", err); } } fn compare_different_size() { println!("Comparing matrices of different size."); + #[rustfmt::skip] let a = MatrixMN::<_, U3, U3>::from_row_slice(&[ 0, 1, 2, 4, 5, 6, 8, 9, 10, ]); + #[rustfmt::skip] 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); + if let Err(err) = compare_matrices(a, b, &ExactElementwiseComparator) { + println!("{}", err); } } fn compare_f64_abs_tol_fail() { println!("Comparing two f64 matrices."); + #[rustfmt::skip] let a = MatrixMN::::from_row_slice(&[ 0.0, 1.0, 2.0 + 1e-10, 4.0, 5.0, 6.0, 8.0, 9.0, 10.0, ]); + #[rustfmt::skip] let b = MatrixMN::<_, U3, U3>::from_row_slice(&[ 0.0, 1.0, 2.0, 4.0, 5.0, 6.0, @@ -62,8 +65,8 @@ fn compare_f64_abs_tol_fail() { ]); let cmp = AbsoluteElementwiseComparator { tol: 1e-12 }; - if let Some(msg) = compare_matrices(a, b, &cmp).panic_message() { - println!("{}", msg); + if let Err(err) = compare_matrices(a, b, &cmp) { + println!("{}", err); } } @@ -76,4 +79,4 @@ fn main() { compare_f64_abs_tol_fail(); println!("======================================================"); compare_different_size(); -} \ No newline at end of file +} diff --git a/src/base/matrix.rs b/src/base/matrix.rs index 8107a1dc..6e6aaba5 100644 --- a/src/base/matrix.rs +++ b/src/base/matrix.rs @@ -160,8 +160,9 @@ impl Abomonation for Matrix> - matrixcompare_core::Matrix for Matrix { +impl> matrixcompare_core::Matrix + for Matrix +{ fn rows(&self) -> usize { self.nrows() } @@ -176,8 +177,9 @@ impl> } #[cfg(feature = "compare")] -impl> - matrixcompare_core::DenseAccess for Matrix { +impl> matrixcompare_core::DenseAccess + for Matrix +{ fn fetch_single(&self, row: usize, col: usize) -> N { self.index((row, col)).clone() } diff --git a/tests/core/matrixcompare.rs b/tests/core/matrixcompare.rs index d4b6f142..df112173 100644 --- a/tests/core/matrixcompare.rs +++ b/tests/core/matrixcompare.rs @@ -4,7 +4,7 @@ //! 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 nalgebra::{DMatrix, MatrixMN, U4, U5}; use matrixcompare::{assert_matrix_eq, DenseAccess}; @@ -31,6 +31,7 @@ quickcheck! { #[test] fn assert_matrix_eq_dense_positive_comparison() { + #[rustfmt::skip] let a = MatrixMN::<_, U4, U5>::from_row_slice(&[ 1210, 1320, 1430, 1540, 1650, 2310, 2420, 2530, 2640, 2750, @@ -38,6 +39,7 @@ fn assert_matrix_eq_dense_positive_comparison() { 4510, 4620, 4730, 4840, 4950, ]); + #[rustfmt::skip] let b = MatrixMN::<_, U4, U5>::from_row_slice(&[ 1210, 1320, 1430, 1540, 1650, 2310, 2420, 2530, 2640, 2750, @@ -63,6 +65,7 @@ fn assert_matrix_eq_dense_positive_comparison() { #[test] #[should_panic] fn assert_matrix_eq_dense_negative_comparison() { + #[rustfmt::skip] let a = MatrixMN::<_, U4, U5>::from_row_slice(&[ 1210, 1320, 1430, 1540, 1650, 2310, 2420, 2530, 2640, 2750, @@ -70,6 +73,7 @@ fn assert_matrix_eq_dense_negative_comparison() { 4510, 4620, -4730, 4840, 4950, ]); + #[rustfmt::skip] let b = MatrixMN::<_, U4, U5>::from_row_slice(&[ 1210, 1320, 1430, 1540, 1650, 2310, 2420, 2530, 2640, 2750, @@ -78,4 +82,4 @@ fn assert_matrix_eq_dense_negative_comparison() { ]); assert_matrix_eq!(a, b); -} \ No newline at end of file +} From 217a2bf312e2661824ac50d3af5ea51cccb7e99d Mon Sep 17 00:00:00 2001 From: Andreas Longva Date: Mon, 29 Jun 2020 19:07:44 +0200 Subject: [PATCH 3/4] Add compare feature to tests run by Makefile --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 01707964..0af9f3f2 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ all: - cargo test --features "debug arbitrary serde-serialize abomonation-serialize" + cargo test --features "debug arbitrary serde-serialize abomonation-serialize compare" # cargo check --features "debug arbitrary serde-serialize" doc: @@ -9,4 +9,4 @@ bench: cargo bench test: - cargo test --features "debug arbitrary serde-serialize abomonation-serialize" + cargo test --features "debug arbitrary serde-serialize abomonation-serialize compare" From d13b3de4e441dcf71173e00c30cd23bcb73c5bb7 Mon Sep 17 00:00:00 2001 From: Andreas Longva Date: Fri, 17 Jul 2020 09:54:30 +0200 Subject: [PATCH 4/4] Use matrixcompare 0.1.3 for tests (fixes no-std test issues) --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index fe347ed0..36047af0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -64,7 +64,7 @@ rand_isaac = "0.2" #criterion = "0.2.10" # For matrix comparison macro -matrixcompare = "0.1" +matrixcompare = "0.1.3" [workspace] members = [ "nalgebra-lapack", "nalgebra-glm" ]