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}