use matrixcompare::comparators::{ElementwiseComparator, ExactElementwiseComparator, ExactError};
use matrixcompare::{assert_matrix_eq, ElementsMismatch};
use matrixcompare::{compare_matrices, DimensionMismatch, MatrixComparisonFailure};
use matrixcompare_mock::{dense_matrix_strategy_i64, mock_matrix, MockDenseMatrix};
use quickcheck::{quickcheck, TestResult};
use proptest::prelude::*;
mod common;
use common::{reverse_result, MATRIX_DIM_RANGE};
quickcheck! {
fn property_elementwise_comparison_incompatible_matrices_yield_dimension_mismatch(
m: usize,
n: usize,
p: usize,
q: usize) -> TestResult {
if m == p && n == q {
return TestResult::discard()
}
let comp = ExactElementwiseComparator;
let ref x = MockDenseMatrix::from_row_major(m, n, vec![0; m * n]);
let ref y = MockDenseMatrix::from_row_major(p, q, vec![0; p * q]);
let expected = MatrixComparisonFailure::MismatchedDimensions(
DimensionMismatch { dim_left: (m, n), dim_right: (p, q) }
);
TestResult::from_bool(compare_matrices(x, y, &comp) == Err(expected))
}
}
quickcheck! {
fn property_elementwise_comparison_matrix_matches_self(m: usize, n: usize) -> bool {
let comp = ExactElementwiseComparator;
let ref x = MockDenseMatrix::from_row_major(m, n, vec![0; m * n]);
compare_matrices(x, x, &comp).is_ok()
}
}
#[test]
fn compare_matrices_reports_correct_mismatches() {
use matrixcompare::MatrixComparisonFailure::MismatchedElements;
use matrixcompare::MatrixElementComparisonFailure;
let comp = ExactElementwiseComparator;
let description =
<ExactElementwiseComparator as ElementwiseComparator<usize>>::description(&comp);
{
let ref x = MockDenseMatrix::from_row_major(1, 1, vec![1]);
let ref y = MockDenseMatrix::from_row_major(1, 1, vec![2]);
let expected = MismatchedElements(ElementsMismatch {
comparator_description: description.clone(),
mismatches: vec![MatrixElementComparisonFailure {
left: 1,
right: 2,
error: ExactError,
row: 0,
col: 0,
}],
});
assert_eq!(compare_matrices(x, y, &comp), Err(expected));
}
{
let ref x = MockDenseMatrix::from_row_major(2, 3, vec![0, 1, 2, 3, 4, 5]);
let ref y = MockDenseMatrix::from_row_major(2, 3, vec![1, 1, 2, 3, 4, 6]);
let mismatches = vec![
MatrixElementComparisonFailure {
left: 0,
right: 1,
error: ExactError,
row: 0,
col: 0,
},
MatrixElementComparisonFailure {
left: 5,
right: 6,
error: ExactError,
row: 1,
col: 2,
},
];
let expected = MismatchedElements(ElementsMismatch {
comparator_description: description.clone(),
mismatches: mismatches,
});
assert_eq!(compare_matrices(x, y, &comp), Err(expected));
}
{
let ref x = mock_matrix![ 0, 1;
2, 3;
4, 5 ];
let ref y = mock_matrix![ 1, 1;
2, 3;
4, 6 ];
let mismatches = vec![
MatrixElementComparisonFailure {
left: 0,
right: 1,
error: ExactError,
row: 0,
col: 0,
},
MatrixElementComparisonFailure {
left: 5,
right: 6,
error: ExactError,
row: 2,
col: 1,
},
];
let expected = MismatchedElements(ElementsMismatch {
comparator_description: description.clone(),
mismatches: mismatches,
});
assert_eq!(compare_matrices(x, y, &comp), Err(expected));
}
{
let ref x = MockDenseMatrix::from_row_major(2, 4, vec![0, 1, 2, 3, 4, 5, 6, 7]);
let ref y = MockDenseMatrix::from_row_major(2, 4, vec![0, 1, 3, 3, 4, 6, 6, 7]);
let mismatches = vec![
MatrixElementComparisonFailure {
left: 2,
right: 3,
error: ExactError,
row: 0,
col: 2,
},
MatrixElementComparisonFailure {
left: 5,
right: 6,
error: ExactError,
row: 1,
col: 1,
},
];
let expected = MismatchedElements(ElementsMismatch {
comparator_description: description.clone(),
mismatches: mismatches,
});
assert_eq!(compare_matrices(x, y, &comp), Err(expected));
}
}
#[test]
pub fn matrix_eq_absolute_compare_self_for_integer() {
let x = MockDenseMatrix::from_row_major(2, 3, vec![1, 2, 3, 4, 5, 6]);
assert_matrix_eq!(x, x, comp = abs, tol = 0);
}
#[test]
pub fn matrix_eq_absolute_compare_self_for_floating_point() {
let x = MockDenseMatrix::from_row_major(2, 3, vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0]);
assert_matrix_eq!(x, x, comp = abs, tol = 0.0);
}
#[test]
#[should_panic]
pub fn matrix_eq_absolute_mismatched_dimensions() {
let x = MockDenseMatrix::from_row_major(2, 3, vec![1, 2, 3, 4, 5, 6]);
let y = MockDenseMatrix::from_row_major(2, 3, vec![1, 2, 3, 4]);
assert_matrix_eq!(x, y, comp = abs, tol = 0);
}
#[test]
#[should_panic]
pub fn matrix_eq_absolute_mismatched_floating_point_elements() {
let x = MockDenseMatrix::from_row_major(2, 3, vec![1.00, 2.00, 3.00, 4.00, 5.00, 6.00]);
let y = MockDenseMatrix::from_row_major(2, 3, vec![1.00, 2.01, 3.00, 3.99, 5.00, 6.00]);
assert_matrix_eq!(x, y, comp = abs, tol = 1e-10);
}
#[test]
pub fn matrix_eq_exact_compare_self_for_integer() {
let x = MockDenseMatrix::from_row_major(2, 3, vec![1, 2, 3, 4, 5, 6]);
assert_matrix_eq!(x, x, comp = exact);
}
#[test]
pub fn matrix_eq_exact_compare_self_for_floating_point() {
let x = MockDenseMatrix::from_row_major(2, 3, vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0]);
assert_matrix_eq!(x, x, comp = exact);
}
#[test]
pub fn matrix_eq_ulp_compare_self() {
let x = MockDenseMatrix::from_row_major(2, 3, vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0]);
assert_matrix_eq!(x, x, comp = ulp, tol = 0);
}
#[test]
pub fn matrix_eq_default_compare_self_for_floating_point() {
let x = MockDenseMatrix::from_row_major(2, 3, vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0]);
assert_matrix_eq!(x, x);
}
#[test]
pub fn matrix_eq_default_compare_self_for_integer() {
let x = MockDenseMatrix::from_row_major(2, 3, vec![1, 2, 3, 4, 5, 6]);
assert_matrix_eq!(x, x);
}
#[test]
#[should_panic]
pub fn matrix_eq_ulp_different_signs() {
let x = MockDenseMatrix::from_row_major(2, 3, vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0]);
let y = MockDenseMatrix::from_row_major(2, 3, vec![1.0, 2.0, -3.0, 4.0, 5.0, 6.0]);
assert_matrix_eq!(x, y, comp = ulp, tol = 0);
}
#[test]
#[should_panic]
pub fn matrix_eq_ulp_nan() {
use std::f64;
let x = MockDenseMatrix::from_row_major(2, 3, vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0]);
let y = MockDenseMatrix::from_row_major(2, 3, vec![1.0, 2.0, f64::NAN, 4.0, 5.0, 6.0]);
assert_matrix_eq!(x, y, comp = ulp, tol = 0);
}
#[test]
pub fn matrix_eq_float_compare_self() {
let x = MockDenseMatrix::from_row_major(2, 3, vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0]);
assert_matrix_eq!(x, x, comp = float);
}
#[test]
pub fn matrix_eq_float_compare_self_with_eps() {
let x = MockDenseMatrix::from_row_major(2, 3, vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0]);
assert_matrix_eq!(x, x, comp = float, eps = 1e-6);
}
#[test]
pub fn matrix_eq_float_compare_self_with_ulp() {
let x = MockDenseMatrix::from_row_major(2, 3, vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0]);
assert_matrix_eq!(x, x, comp = float, ulp = 12);
}
#[test]
pub fn matrix_eq_float_compare_self_with_eps_and_ulp() {
let x = MockDenseMatrix::from_row_major(2, 3, vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0]);
assert_matrix_eq!(x, x, comp = float, eps = 1e-6, ulp = 12);
assert_matrix_eq!(x, x, comp = float, ulp = 12, eps = 1e-6);
}
#[test]
pub fn matrix_eq_pass_by_ref() {
let x = MockDenseMatrix::from_row_major(1, 1, vec![0.0f64]);
assert_matrix_eq!(&x, &x);
assert_matrix_eq!(&x, &x, comp = exact);
assert_matrix_eq!(&x, &x, comp = abs, tol = 0.0);
assert_matrix_eq!(&x, &x, comp = ulp, tol = 0);
assert_matrix_eq!(&x, &x, comp = float);
assert_matrix_eq!(&x, &x, comp = float, eps = 0.0, ulp = 0);
}
proptest! {
#[test]
fn dense_dense_comparison_is_symmetric_for_compatible_matrices_i64(
(dense1, dense2) in (MATRIX_DIM_RANGE, MATRIX_DIM_RANGE).prop_flat_map(|(r, c)| {
(dense_matrix_strategy_i64(r..=r, c..=c), dense_matrix_strategy_i64(r..=r, c..=c))
})
) {
let c = ExactElementwiseComparator;
let result1 = compare_matrices(&dense1, &dense2, &c);
let result2 = compare_matrices(&dense2, &dense1, &c);
prop_assert_eq!(result1.clone(), reverse_result(result2.clone()));
prop_assert_eq!(reverse_result(result1), result2);
}
#[test]
fn dense_dense_comparison_is_symmetric_for_all_matrices_i64(
dense1 in dense_matrix_strategy_i64(MATRIX_DIM_RANGE, MATRIX_DIM_RANGE),
dense2 in dense_matrix_strategy_i64(MATRIX_DIM_RANGE, MATRIX_DIM_RANGE)
) {
let c = ExactElementwiseComparator;
let result1 = compare_matrices(&dense1, &dense2, &c);
let result2 = compare_matrices(&dense2, &dense1, &c);
prop_assert_eq!(result1.clone(), reverse_result(result2.clone()));
prop_assert_eq!(reverse_result(result1), result2);
}
}