assert_eq_float/
eq.rs

1/// Asserts that two float expressions are (approximately) equal to each other.
2///
3/// On panic, this macro will print the values of the expressions with their
4/// debug representations.
5///
6/// Like [`assert_eq!`], this macro has a second form, where a custom
7/// panic message can be provided.
8///
9/// # Examples
10///
11/// ```rust
12/// use assert_eq_float::assert_eq_float;
13///
14/// let a = 3.0;
15/// let b = 1.0 + 2.0;
16///
17/// assert_eq_float!(a, b);
18///
19/// assert_eq_float!(a, b; "we are testing addition with {} and {}", a, b);
20///
21/// assert_eq_float!(a, b, 1e-7); // use a fixed error
22/// ```
23///
24/// Note that when setting a custom panic message, you should use a semicolon `;` instead of a comma `,`.
25#[macro_export]
26macro_rules! assert_eq_float {
27    (@standard $left:ident, $right:ident, $error:ident) => {
28        if $left != $right {
29            use $crate::num_traits::float::FloatCore;
30
31            let d_abs = ($left - $right).abs();
32
33            ::core::assert!(
34                d_abs < $error,
35                "assertion failed: `(left == right)`\n  left: `{:?}`,\n right: `{:?}`\n  diff: `{:?}`\n error: `{:?}`",
36                $left,
37                $right,
38                d_abs,
39                $error,
40            );
41        }
42    };
43    (@custom $left:ident, $right:ident, $error:ident; $($arg:tt)+) => {
44        if $left != $right {
45            use $crate::num_traits::float::FloatCore;
46
47            let d_abs = ($left - $right).abs();
48
49            ::core::assert!(
50                d_abs < $error,
51                $($arg)+
52            );
53        }
54    };
55    ($left:expr, $right:expr $(,)?) => {{
56        let left = $left;
57        let right = $right;
58        let error = $crate::get_error(left, right);
59
60        $crate::assert_eq_float!(@standard left, right, error);
61    }};
62    ($left:expr, $right:expr; $($arg:tt)+) => {{
63        let left = $left;
64        let right = $right;
65        let error = $crate::get_error(left, right);
66
67        $crate::assert_eq_float!(@custom left, right, error; $($arg)+);
68    }};
69    ($left:expr, $right:expr, $error:expr $(,)?) => {{
70        let left = $left;
71        let right = $right;
72        let error = $error;
73
74        $crate::assert_eq_float!(@standard left, right, error);
75    }};
76    ($left:expr, $right:expr, $error:expr; $($arg:tt)+) => {{
77        let left = $left;
78        let right = $right;
79        let error = $error;
80
81        $crate::assert_eq_float!(@custom left, right, error; $($arg)+);
82    }};
83}
84
85/// Asserts that two float expressions are (approximately) equal to each other.
86///
87/// Unlike [`assert_eq_float!`], `debug_assert_eq_float!` statements are only enabled in non
88/// optimized builds by default. An optimized build will not execute
89/// `debug_assert_eq_float!` statements unless `-C debug-assertions` is passed to the
90/// compiler. This makes `debug_assert_eq_float!` useful for checks that are too
91/// expensive to be present in a release build but may be helpful during
92/// development. The result of expanding `debug_assert_eq_float!` is always type checked.
93#[macro_export]
94macro_rules! debug_assert_eq_float {
95    ($left:expr, $right:expr $(,)?) => {
96        #[cfg(debug_assertions)]
97        $crate::assert_eq_float!($left, $right);
98    };
99    ($left:expr, $right:expr; $($arg:tt)+) => {
100        #[cfg(debug_assertions)]
101        $crate::assert_eq_float!($left, $right; $($arg)+);
102    };
103    ($left:expr, $right:expr, $error:expr $(,)?) => {
104        #[cfg(debug_assertions)]
105        $crate::assert_eq_float!($left, $right, $error);
106    };
107    ($left:expr, $right:expr, $error:expr; $($arg:tt)+) => {
108        #[cfg(debug_assertions)]
109        $crate::assert_eq_float!($left, $right, $error; $($arg)+);
110    };
111}