//! Checked subtraction for [`U384`].
use super::U384;

impl U384 {
    /// Computes `self - other`, returning `None` if the subtraction would
    /// underflow (i.e., `self < other`).
    ///
    /// # Examples
    ///
    /// ```
    /// use cnfy_uint::u384::U384;
    ///
    /// let a = U384::from_be_limbs([0, 0, 0, 0, 0, 10]);
    /// let b = U384::from_be_limbs([0, 0, 0, 0, 0, 3]);
    /// assert_eq!(a.checked_sub(&b), Some(U384::from_be_limbs([0, 0, 0, 0, 0, 7])));
    ///
    /// assert_eq!(U384::ZERO.checked_sub(&U384::ONE), None);
    /// ```
    #[inline]
    pub const fn checked_sub(&self, other: &U384) -> Option<U384> {
        let (result, underflow) = self.overflowing_sub(other);
        if underflow {
            None
        } else {
            Some(result)
        }
    }
}

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

    /// Small subtraction succeeds.
    #[test]
    fn small() {
        let a = U384::from_be_limbs([0, 0, 0, 0, 0, 10]);
        let b = U384::from_be_limbs([0, 0, 0, 0, 0, 3]);
        assert_eq!(
            a.checked_sub(&b),
            Some(U384::from_be_limbs([0, 0, 0, 0, 0, 7])),
        );
    }

    /// 0 - 1 returns None.
    #[test]
    fn underflow() {
        assert_eq!(U384::ZERO.checked_sub(&U384::ONE), None);
    }

    /// Subtracting zero always succeeds.
    #[test]
    fn zero() {
        let a = U384::from_be_limbs([0x1234, 0x5678, 0x9ABC, 0xDEF0, 0x1111, 0x2222]);
        assert_eq!(a.checked_sub(&U384::ZERO), Some(a));
    }

    /// Self minus self returns zero.
    #[test]
    fn self_sub() {
        let a = U384::from_be_limbs([1, 2, 3, 4, 5, 6]);
        assert_eq!(a.checked_sub(&a), Some(U384::ZERO));
    }
}
