# Macro extendr_api::prelude::assert_matrix_eq

macro_rules! assert_matrix_eq { ($($args:tt)*) => { ... }; }

## Expand description

Compare matrices for exact or approximate equality.

The `assert_matrix_eq!`

simplifies the comparison of two matrices by
providing the following features:

- Verifies that the dimensions of the matrices match.
- Offers both exact and approximate comparison of individual elements.
- Multiple types of comparators available, depending on the needs of the user.
- Built-in error reporting makes it easy to determine which elements of the two matrices that do not compare equal.

## §Usage

Given two matrices `x`

and `y`

, the default invocation performs an exact elementwise
comparison of the two matrices.

```
// Performs elementwise exact comparison
assert_matrix_eq!(x, y);
```

An exact comparison is often not desirable. In particular, with floating point types,
rounding errors or other sources of inaccuracies tend to complicate the matter.
For this purpose, `assert_matrix_eq!`

provides several comparators.

```
// Available comparators:
assert_matrix_eq!(x, y, comp = exact);
assert_matrix_eq!(x, y, comp = float);
assert_matrix_eq!(x, y, comp = abs, tol = 1e-12);
assert_matrix_eq!(x, y, comp = ulp, tol = 8);
```

**Note**: The `comp`

argument *must* be specified after `x`

and `y`

, and cannot come
after comparator-specific options. This is a deliberate design decision,
with the rationale that assertions should look as uniform as possible for
the sake of readability.

#### §The `exact`

comparator

This comparator simply uses the default `==`

operator to compare each pair of elements.
The default comparator delegates the comparison to the `exact`

comparator.

#### §The `float`

comparator

The `float`

comparator is designed to be a conservative default for comparing floating-point numbers.
It is inspired by the `AlmostEqualUlpsAndAbs`

comparison function proposed in the excellent blog post
Comparing Floating Point Numbers, 2012 Edition
by Bruce Dawson.

If you expect the two matrices to be almost exactly the same, but you want to leave some room for (very small) rounding errors, then this comparator should be your default choice.

The comparison criterion can be summarized as follows:

- If
`assert_matrix_eq!(x, y, comp = abs, tol = max_eps)`

holds for`max_eps`

close to the machine epsilon for the floating point type, then the comparison is successful. - Otherwise, returns the result of
`assert_matrix_eq!(x, y, comp = ulp, tol = max_ulp)`

, where`max_ulp`

is a small positive integer constant.

The `max_eps`

and `max_ulp`

parameters can be tweaked to your preference with the syntax:

`assert_matrix_eq!(x, y, comp = float, eps = max_eps, ulp = max_ulp);`

These additional parameters can be specified in any order after the choice of comparator, and do not both need to be present.

#### §The `abs`

comparator

Compares the absolute difference between individual elements against the specified tolerance. Specifically, for every pair of elements x and y picked from the same row and column in X and Y respectively, the criterion is defined by

```
| x - y | <= tol.
```

In addition to floating point numbers, the comparator can also be used for integral numbers,
both signed and unsigned. In order to avoid unsigned underflow, the difference is always
computed by subtracting the smaller number from the larger number.
Note that the type of `tol`

is required to be the same as that of the scalar field.

#### §The `ulp`

comparator

Elementwise comparison of floating point numbers based on their ULP difference. Once again, this is inspired by the proposals in the aforementioned blog post by Bruce Dawson, but it handles some cases explicitly as to provide better error reporting.

Note that the ULP difference of two floating point numbers is not defined in the following cases:

- The two numbers have different signs. The only exception here is +0 and -0, which are considered an exact match.
- One of the numbers is NaN.

ULP-based comparison is typically used when two numbers are expected to be very, very close to each other. However, it is typically not very useful very close to zero, which is discussed in the linked blog post above. The error in many mathematical functions can often be bounded by a certain number of ULP, and so this comparator is particularly useful if this number is known.

Note that the scalar type of the matrix must implement the Ulp trait in order
to be used with this comparator. By default, `f32`

and `f64`

implementations are provided.

## §Error reporting

One of the main motivations for the `assert_matrix_eq!`

macro is the ability to give
useful error messages which help pinpoint the problems. For example, consider the example

```
fn main() {
let a = mock_matrix![1.00, 2.00;
3.00, 4.00];
let b = mock_matrix![1.01, 2.00;
3.40, 4.00];
assert_matrix_eq!(a, b, comp = abs, tol = 1e-8);
}
```

which yields the output

```
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. Absolute error: 0.010000000000000009.
(1, 0): x = 3, y = 3.4. Absolute error: 0.3999999999999999.
Comparison criterion: absolute difference, |x - y| <= 0.00000001.
```

## §Trait bounds on elements

Each comparator has specific requirements on which traits the elements need to implement. To discover which traits are required for each comparator, we refer the reader to implementors of ElementwiseComparator, which provides the underlying comparison for the various macro invocations.

## §Examples

```
let ref a = mock_matrix![1, 2;
3, 4i64];
let ref b = mock_matrix![1, 3;
3, 4i64];
let ref x = mock_matrix![1.000, 2.000,
3.000, 4.000f64];
let ref y = mock_matrix![0.999, 2.001,
2.998, 4.000f64];
// comp = abs is also applicable to integers
assert_matrix_eq!(a, b, comp = abs, tol = 1);
assert_matrix_eq!(x, y, comp = abs, tol = 0.01);
```