assertables/assert_f32/
assert_f32_ne.rs

1//! Assert a floating point 32-bit number is not equal to another within f32::EPSILON.
2//!
3//! Pseudocode:<br>
4//! a ≠ b
5//!
6//! # Example
7//!
8//! ```rust
9//! use assertables::*;
10//!
11//! let a: f32 = 1.0 / 3.0;
12//! let b: f32 = 0.3333336;
13//! assert_f32_ne!(a, b);
14//! ```
15//!
16//! # Module macros
17//!
18//! * [`assert_f32_ne`](macro@crate::assert_f32_ne)
19//! * [`assert_f32_ne_as_result`](macro@crate::assert_f32_ne_as_result)
20//! * [`debug_assert_f32_ne`](macro@crate::debug_assert_f32_ne)
21
22//! Assert a floating point 32-bit number is not equal to another within f32::EPSILON.
23///
24/// Pseudocode:<br>
25/// a ≠ b
26///
27/// * If true, return Result `Ok(())`.
28///
29/// * Otherwise, return Result `Err(message)`.
30///
31/// This macro is useful for runtime checks, such as checking parameters,
32/// or sanitizing inputs, or handling different results in different ways.
33///
34/// # Module macros
35///
36/// * [`assert_f32_ne`](macro@crate::assert_f32_ne)
37/// * [`assert_f32_ne_as_result`](macro@crate::assert_f32_ne_as_result)
38/// * [`debug_assert_f32_ne`](macro@crate::debug_assert_f32_ne)
39///
40#[macro_export]
41macro_rules! assert_f32_ne_as_result {
42    ($a:expr, $b:expr $(,)?) => {
43        match (&$a, &$b) {
44            (a, b) => {
45                if !(a >= b && a - b < f32::EPSILON) && !(a <= b && b - a < f32::EPSILON) {
46                    Ok(())
47                } else {
48                    Err(format!(
49                        concat!(
50                            "assertion failed: `assert_f32_ne!(a, b)`\n",
51                            "https://docs.rs/assertables/",
52                            env!("CARGO_PKG_VERSION"),
53                            "/assertables/macro.assert_f32_ne.html\n",
54                            " a label: `{}`,\n",
55                            " a debug: `{:?}`,\n",
56                            " b label: `{}`,\n",
57                            " b debug: `{:?}`,\n",
58                            "    diff: `{}`,\n",
59                            "       ε: `{}`",
60                        ),
61                        stringify!($a),
62                        a,
63                        stringify!($b),
64                        b,
65                        a - b,
66                        f32::EPSILON,
67                    ))
68                }
69            }
70        }
71    };
72}
73
74#[cfg(test)]
75mod test_assert_f32_ne_as_result {
76    use crate::assert_f32::{EQ,EQ_LT,EQ_GT,LT,GT};
77    use std::sync::Once;
78
79    #[test]
80    fn lt() {
81        let a: f32 = EQ;
82        let b: f32 = GT;
83        for _ in 0..1 {
84            let actual = assert_f32_ne_as_result!(a, b);
85            assert_eq!(actual.unwrap(), ());
86        }
87    }
88
89    #[test]
90    fn lt_once() {
91        static A: Once = Once::new();
92        fn a() -> f32 {
93            if A.is_completed() {
94                panic!("A.is_completed()")
95            } else {
96                A.call_once(|| {})
97            }
98            EQ
99        }
100
101        static B: Once = Once::new();
102        fn b() -> f32 {
103            if B.is_completed() {
104                panic!("B.is_completed()")
105            } else {
106                B.call_once(|| {})
107            }
108            GT
109        }
110
111        assert_eq!(A.is_completed(), false);
112        assert_eq!(B.is_completed(), false);
113        let result = assert_f32_ne_as_result!(a(), b());
114        assert!(result.is_ok());
115        assert_eq!(A.is_completed(), true);
116        assert_eq!(B.is_completed(), true);
117    }
118
119    #[test]
120    fn gt() {
121        let a: f32 = EQ;
122        let b: f32 = LT;
123        for _ in 0..1 {
124            let actual = assert_f32_ne_as_result!(a, b);
125            assert_eq!(actual.unwrap(), ());
126        }
127    }
128
129    #[test]
130    fn gt_once() {
131        static A: Once = Once::new();
132        fn a() -> f32 {
133            if A.is_completed() {
134                panic!("A.is_completed()")
135            } else {
136                A.call_once(|| {})
137            }
138            EQ
139        }
140
141        static B: Once = Once::new();
142        fn b() -> f32 {
143            if B.is_completed() {
144                panic!("B.is_completed()")
145            } else {
146                B.call_once(|| {})
147            }
148            LT
149        }
150
151        assert_eq!(A.is_completed(), false);
152        assert_eq!(B.is_completed(), false);
153        let result = assert_f32_ne_as_result!(a(), b());
154        assert!(result.is_ok());
155        assert_eq!(A.is_completed(), true);
156        assert_eq!(B.is_completed(), true);
157    }
158
159    #[test]
160    fn eq() {
161        let a: f32 = EQ;
162        let b: f32 = EQ;
163        let actual = assert_f32_ne_as_result!(a, b);
164        let message = concat!(
165            "assertion failed: `assert_f32_ne!(a, b)`\n",
166            "https://docs.rs/assertables/",
167            env!("CARGO_PKG_VERSION"),
168            "/assertables/macro.assert_f32_ne.html\n",
169            " a label: `a`,\n",
170            " a debug: `0.33333334`,\n",
171            " b label: `b`,\n",
172            " b debug: `0.33333334`,\n",
173            "    diff: `0`,\n",
174            "       ε: `0.00000011920929`",
175        );
176        assert_eq!(actual.unwrap_err(), message);
177    }
178
179    #[test]
180    fn eq_lt() {
181        let a: f32 = EQ;
182        let b: f32 = EQ_GT;
183        let actual = assert_f32_ne_as_result!(a, b);
184        let message = concat!(
185            "assertion failed: `assert_f32_ne!(a, b)`\n",
186            "https://docs.rs/assertables/",
187            env!("CARGO_PKG_VERSION"),
188            "/assertables/macro.assert_f32_ne.html\n",
189            " a label: `a`,\n",
190            " a debug: `0.33333334`,\n",
191            " b label: `b`,\n",
192            " b debug: `0.3333334`,\n",
193            "    diff: `-0.000000059604645`,\n",
194            "       ε: `0.00000011920929`",
195        );
196        assert_eq!(actual.unwrap_err(), message);
197    }
198
199    #[test]
200    fn eq_gt() {
201        let a: f32 = EQ;
202        let b: f32 = EQ_LT;
203        let actual = assert_f32_ne_as_result!(a, b);
204        let message = concat!(
205            "assertion failed: `assert_f32_ne!(a, b)`\n",
206            "https://docs.rs/assertables/",
207            env!("CARGO_PKG_VERSION"),
208            "/assertables/macro.assert_f32_ne.html\n",
209            " a label: `a`,\n",
210            " a debug: `0.33333334`,\n",
211            " b label: `b`,\n",
212            " b debug: `0.3333333`,\n",
213            "    diff: `0.000000029802322`,\n",
214            "       ε: `0.00000011920929`",
215        );
216        assert_eq!(actual.unwrap_err(), message);
217    }
218}
219
220/// Assert a floating point 32-bit number is not equal to another within f32::EPSILON.
221///
222/// Pseudocode:<br>
223/// a ≠ b
224///
225/// * If true, return `()`.
226///
227/// * Otherwise, call [`panic!`] with a message and the values of the
228///   expressions with their debug representations.
229///
230/// # Examples
231///
232/// ```rust
233/// use assertables::*;
234/// # use std::panic;
235///
236/// # fn main() {
237/// let a: f32 = 1.0 / 3.0;
238/// let b: f32 = 0.3333336;
239/// assert_f32_ne!(a, b);
240///
241/// # let result = panic::catch_unwind(|| {
242/// // This will panic
243/// let a: f32 = 1.0 / 3.0;
244/// let b: f32 = 1.0 / 3.0;
245/// assert_f32_ne!(a, b);
246/// # });
247/// // assertion failed: `assert_f32_ne!(a, b)`
248/// // https://docs.rs/assertables/9.7.0/assertables/macro.assert_f32_ne.html
249/// //  a label: `a`,
250/// //  a debug: `0.33333334`,
251/// //  b label: `b`,
252/// //  b debug: `0.33333334`,`
253/// //     diff: `0`,
254/// //        ε: `0.00000011920929`
255/// # let actual = result.unwrap_err().downcast::<String>().unwrap().to_string();
256/// # let message = concat!(
257/// #     "assertion failed: `assert_f32_ne!(a, b)`\n",
258/// #     "https://docs.rs/assertables/", env!("CARGO_PKG_VERSION"), "/assertables/macro.assert_f32_ne.html\n",
259/// #     " a label: `a`,\n",
260/// #     " a debug: `0.33333334`,\n",
261/// #     " b label: `b`,\n",
262/// #     " b debug: `0.33333334`,\n",
263/// #     "    diff: `0`,\n",
264/// #     "       ε: `0.00000011920929`",
265/// # );
266/// # assert_eq!(actual, message);
267/// # }
268/// ```
269///
270/// # Module macros
271///
272/// * [`assert_f32_ne`](macro@crate::assert_f32_ne)
273/// * [`assert_f32_ne_as_result`](macro@crate::assert_f32_ne_as_result)
274/// * [`debug_assert_f32_ne`](macro@crate::debug_assert_f32_ne)
275///
276#[macro_export]
277macro_rules! assert_f32_ne {
278    ($a:expr, $b:expr $(,)?) => {
279        match $crate::assert_f32_ne_as_result!($a, $b) {
280            Ok(()) => (),
281            Err(err) => panic!("{}", err),
282        }
283    };
284    ($a:expr, $b:expr, $($message:tt)+) => {
285        match $crate::assert_f32_ne_as_result!($a, $b) {
286            Ok(()) => (),
287            Err(err) => panic!("{}\n{}", format_args!($($message)+), err),
288        }
289    };
290}
291
292#[cfg(test)]
293mod test_assert_f32_ne {
294    use crate::assert_f32::{EQ,GT};
295    use std::panic;
296
297    #[test]
298    fn ne() {
299        let a: f32 = EQ;
300        let b: f32 = GT;
301        for _ in 0..1 {
302            let actual = assert_f32_ne!(a, b);
303            assert_eq!(actual, ());
304        }
305    }
306
307}
308
309/// Assert a floating point 32-bit number is not equal to another within f32::EPSILON.
310///
311/// Pseudocode:<br>
312/// a ≠ b
313///
314///
315/// This macro provides the same statements as [`assert_f32_ne`](macro.assert_f32_ne.html),
316/// except this macro's statements are only enabled in non-optimized
317/// builds by default. An optimized build will not execute this macro's
318/// statements unless `-C debug-assertions` is passed to the compiler.
319///
320/// This macro is useful for checks that are too expensive to be present
321/// in a release build but may be helpful during development.
322///
323/// The result of expanding this macro is always type checked.
324///
325/// An unchecked assertion allows a program in an inconsistent state to
326/// keep running, which might have unexpected consequences but does not
327/// introduce unsafety as long as this only happens in safe code. The
328/// performance cost of assertions, however, is not measurable in general.
329/// Replacing `assert*!` with `debug_assert*!` is thus only encouraged
330/// after thorough profiling, and more importantly, only in safe code!
331///
332/// This macro is intended to work in a similar way to
333/// [`::std::debug_assert`](https://doc.rust-lang.org/std/macro.debug_assert.html).
334///
335/// # Module macros
336///
337/// * [`assert_f32_ne`](macro@crate::assert_f32_ne)
338/// * [`assert_f32_ne`](macro@crate::assert_f32_ne)
339/// * [`debug_assert_f32_ne`](macro@crate::debug_assert_f32_ne)
340///
341#[macro_export]
342macro_rules! debug_assert_f32_ne {
343    ($($arg:tt)*) => {
344        if $crate::cfg!(debug_assertions) {
345            $crate::assert_f32_ne!($($arg)*);
346        }
347    };
348}