assertables/assert_f32/
assert_f32_ge.rs

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