floatguard/f32/
ops_unary.rs

1use super::{GuardedF32, UnguardedF32};
2use crate::unary_operation;
3use std::ops::Neg;
4
5unary_operation!(
6    impl Neg for ...(GuardedF32, UnguardedF32) {
7        r"
8            Negates the `GuardedF32` or `UnguardedF32` value.
9
10            # Returns
11
12            Returns a new `Self` instance with the negated value. Unlike other operations, this does not
13            default to creating an `UnguardedF32` for `GuardedF32`, as `-x` is always valid for finite
14            and non-NaN values.
15
16            # Example
17
18            ```rust
19            use floatguard::{GuardedF32, FloatError, UnguardedF32};
20
21            let value = GuardedF32::new(2.0).unwrap();
22            assert_eq!(-value, -2.0);
23
24            let value = UnguardedF32::new(2.0);
25            assert_eq!(f32::try_from(-value), Ok(-2.0));
26
27            let invalid_value = UnguardedF32::new(f32::NAN);
28            assert_eq!((-invalid_value).check(), Err(FloatError::NaN));
29
30            let infinity_value = UnguardedF32::new(f32::INFINITY);
31            assert_eq!((-infinity_value).check(), Err(FloatError::Infinity));
32            ```
33        "
34        fn neg(base: f32) -> Self::Output {
35            Self(base.neg())
36        }
37    }
38);
39
40#[cfg(test)]
41mod tests {
42    use crate::{
43        FloatError, GuardedF32, UnguardedF32,
44        f32::tests::{invalid_f32, valid_f32},
45    };
46    use proptest::prelude::*;
47
48    proptest! {
49        #[test]
50        fn test_negation(a in valid_f32()) {
51            let checked_a = GuardedF32::new(a).unwrap();
52            let expected = GuardedF32::new(-a).unwrap();
53
54            prop_assert_eq!(-checked_a, expected);
55            prop_assert_eq!(-(&checked_a), expected);
56            prop_assert_eq!(-checked_a, -a);
57            prop_assert_eq!(-(&checked_a), -a);
58
59            let unchecked_a = UnguardedF32::new(a);
60
61            prop_assert_eq!((-unchecked_a).check(), Ok(expected));
62            prop_assert_eq!((-(&unchecked_a)).check(), Ok(expected));
63        }
64
65        #[test]
66        fn test_negation_invalid(a in invalid_f32()) {
67            let checked_a = UnguardedF32::new(a);
68            let float_error = if a.is_nan() {
69                FloatError::NaN
70            } else if a.is_infinite() {
71                FloatError::Infinity
72            } else {
73                unreachable!()
74            };
75
76            prop_assert_eq!((-checked_a).check(), Err(float_error));
77            prop_assert_eq!((-(&checked_a)).check(), Err(float_error));
78        }
79    }
80}