This pull request is not intended as a candidate for merge (yet).
I'm working on the matrix equality macro mentioned in #67. I added an example in the examples/
subfolder, which one can run with cargo run --example mismatched_f64_elements
. See also the small number of tests currently included as well. The example looks like this:
#[macro_use]
extern crate rulinalg;
fn main() {
// The purpose of this example is to demonstrate the type of errors generated
// by `assert_matrix_eq!` when the comparison fails (which the below call will).
let a = matrix![1.00, 2.00;
3.00, 4.00];
let b = matrix![1.01, 2.00;
3.40, 4.00];
assert_matrix_eq!(a, b, comp = abs, tol = 1e-8);
}
and it gives the following output:
Running `target/debug/examples/mismatched_f64_elements`
thread 'main' panicked at '
Matrices X and Y have 2 mismatched element pairs. The mismatched elements are listed below, in the format
(row, col): x = x[[row, col]], y = y[[row, col]].
(0, 0): x = 1, y = 1.01. Error: 0.010000000000000009
(1, 0): x = 3, y = 3.4. Error: 0.3999999999999999
Comparison criterion: absolute difference, defined by
|x - y| <= 0.00000001.
', examples/mismatched_f64_elements.rs:11
note: Run with `RUST_BACKTRACE=1` for a backtrace.
Now, I'd like to give people the chance to give some input on how the macro should work. Comparing floating numbers is seriously hard. See for example this famous article. A preliminary conclusion is that there is no one-size-fits-all solution for comparing floating point numbers. Hence, it's impossible for us to have a default assert_matrix_eq!(a, b)
macro that works in all cases. This is why I've opted for explicitly making the user choose which criterion to assert with (the comp = abs
and tol = 1e-8
parameters).
However, I think we can provide a very conservative default assert_matrix_eq!(a, b)
macro. I need to think a bit more on exactly how it's going to work, but I have the following in mind:
- The default invocation is very strict and conservative.
- The user simply writes
assert_matrix_eq!(a, b)
for his/her tests, and this might be fine if the numbers are very close to exactly equal.
- However, in the case when the numbers are near but not sufficiently near, the macro will fail.
- When the macro fails, the error message should explain the next steps the user should take (ideally by referring to a fleshed out part in the documentation on this) to ensure that he/she is using the correct comparison criteria.
The reasoning in step 4 again comes back to the fact that a one-size-fits-all comparison does not exist. I'm a bit inspired by how rustc
guides users around compilation failures, by giving error messages that are truly helpful. Hopefully we can do the same for our users (and for our contributors).
Currently, the macro only supports absolute difference as a comparison criterion, but I want to at least support ULP-based comparison too (probably basing the default criterion on something involving ULP). I also need to write a lot more tests, as I hope this could form the cornerstone of future test assertions in rulinalg as a whole, as well as flesh out the documentation much more. Also, there should perhaps be an analogous assert_vector_eq
macro?
Would really appreciate any opinions, questions, reservations or advice anyone might have!