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

impl U384 {
    /// Computes `self + other`, returning `None` if the addition would
    /// overflow `2^384 - 1`.
    ///
    /// # 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, 20]);
    /// assert_eq!(a.checked_add(&b), Some(U384::from_be_limbs([0, 0, 0, 0, 0, 30])));
    ///
    /// assert_eq!(U384::MAX.checked_add(&U384::ONE), None);
    /// ```
    #[inline]
    pub const fn checked_add(&self, other: &U384) -> Option<U384> {
        let (result, overflow) = self.overflowing_add(other);
        if overflow {
            None
        } else {
            Some(result)
        }
    }
}

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

    /// Small addition succeeds.
    #[test]
    fn small() {
        let a = U384::from_be_limbs([0, 0, 0, 0, 0, 100]);
        let b = U384::from_be_limbs([0, 0, 0, 0, 0, 200]);
        assert_eq!(
            a.checked_add(&b),
            Some(U384::from_be_limbs([0, 0, 0, 0, 0, 300])),
        );
    }

    /// MAX + 1 returns None.
    #[test]
    fn overflow() {
        assert_eq!(U384::MAX.checked_add(&U384::ONE), None);
    }

    /// Adding zero always succeeds.
    #[test]
    fn zero() {
        assert_eq!(U384::MAX.checked_add(&U384::ZERO), Some(U384::MAX));
    }

    /// MAX + MAX returns None.
    #[test]
    fn double_max() {
        assert_eq!(U384::MAX.checked_add(&U384::MAX), None);
    }
}
