//! Two's complement negation wrapping at 2^512.
use super::U512;

impl U512 {
    /// Computes the two's complement negation `2^512 - self`, wrapping on
    /// overflow (i.e., negating zero returns zero).
    ///
    /// # Examples
    ///
    /// ```
    /// use cnfy_uint::u512::U512;
    ///
    /// let one = U512::ONE;
    /// assert_eq!(one.negate(), U512::MAX);
    /// ```
    #[inline]
    pub const fn negate(&self) -> U512 {
        U512::ZERO.overflowing_sub(self).0
    }
}

#[cfg(test)]
mod ai_tests {
    use super::*;

    /// Negating zero returns zero.
    #[test]
    fn neg_zero() {
        assert_eq!(U512::ZERO.negate(), U512::ZERO);
    }

    /// Negating one returns MAX.
    #[test]
    fn neg_one() {
        assert_eq!(U512::ONE.negate(), U512::MAX);
    }

    /// Double negation is identity.
    #[test]
    fn double_neg() {
        let a = U512::from_be_limbs([0x1234, 0x5678, 0x9ABC, 0xDEF0, 1, 2, 3, 4]);
        assert_eq!(a.negate().negate(), a);
    }

    /// x + (-x) wraps to zero.
    #[test]
    fn add_neg_is_zero() {
        let a = U512::from_be_limbs([0xAB, 0xCD, 0xEF, 0x42, 1, 2, 3, 4]);
        let (sum, _) = a.overflowing_add(&a.negate());
        assert_eq!(sum, U512::ZERO);
    }

    /// Negating MAX returns ONE.
    #[test]
    fn neg_max() {
        assert_eq!(U512::MAX.negate(), U512::ONE);
    }
}
