floatguard 0.1.2

A library for checked floating-point arithmetic in Rust, safely elminating NaN and Infinity from floating-point computations.
Documentation
use super::{GuardedF64, UnguardedF64};
use crate::unary_operation;
use std::ops::Neg;

unary_operation!(
    impl Neg for ...(GuardedF64, UnguardedF64) {
        r"
            Negates the `GuardedF64` or `UnguardedF64` value.
    
            # Returns
    
            Returns a new `Self` instance with the negated value. Unlike other operations, this does not
            default to creating an `UnguardedF64` for `GuardedF64`, as `-x` is always valid for finite
            and non-NaN values.
    
            # Example
    
            ```rust
            use floatguard::{GuardedF64, FloatError, UnguardedF64};
    
            let value = GuardedF64::new(2.0).unwrap();
            assert_eq!(-value, -2.0);
    
            let value = UnguardedF64::new(2.0);
            assert_eq!(f64::try_from(-value), Ok(-2.0));
    
            let invalid_value = UnguardedF64::new(f64::NAN);
            assert_eq!((-invalid_value).check(), Err(FloatError::NaN));
    
            let infinity_value = UnguardedF64::new(f64::INFINITY);
            assert_eq!((-infinity_value).check(), Err(FloatError::Infinity));
            ```
        "
        fn neg(base: f64) -> Self::Output {
            Self(base.neg())
        }
    }
);

#[cfg(test)]
mod tests {
    use crate::{
        FloatError, GuardedF64, UnguardedF64,
        f64::tests::{invalid_f64, valid_f64},
    };
    use proptest::prelude::*;

    proptest! {
        #[test]
        fn test_negation(a in valid_f64()) {
            let checked_a = GuardedF64::new(a).unwrap();
            let expected = GuardedF64::new(-a).unwrap();

            prop_assert_eq!(-checked_a, expected);
            prop_assert_eq!(-(&checked_a), expected);
            prop_assert_eq!(-checked_a, -a);
            prop_assert_eq!(-(&checked_a), -a);

            let unchecked_a = UnguardedF64::new(a);

            prop_assert_eq!((-unchecked_a).check(), Ok(expected));
            prop_assert_eq!((-(&unchecked_a)).check(), Ok(expected));
        }

        #[test]
        fn test_negation_invalid(a in invalid_f64()) {
            let checked_a = UnguardedF64::new(a);
            let float_error = if a.is_nan() {
                FloatError::NaN
            } else if a.is_infinite() {
                FloatError::Infinity
            } else {
                unreachable!()
            };

            prop_assert_eq!((-checked_a).check(), Err(float_error));
            prop_assert_eq!((-(&checked_a)).check(), Err(float_error));
        }
    }
}