//! Extraction of the low 256 bits from a [`U384`].
use super::U384;
use crate::u256::U256;

impl U384 {
    /// Returns the low (least significant) 256-bit value, reconstructed
    /// from limbs `[0]` through `[3]`.
    ///
    /// # Examples
    ///
    /// ```
    /// use cnfy_uint::u256::U256;
    /// use cnfy_uint::u384::U384;
    ///
    /// let v = U384::from_be_limbs([0xAA, 0xBB, 1, 2, 3, 4]);
    /// assert_eq!(v.low_u256(), U256::from_be_limbs([1, 2, 3, 4]));
    /// ```
    #[inline]
    pub const fn low_u256(&self) -> U256 {
        U256([self.0[0], self.0[1], self.0[2], self.0[3]])
    }
}

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

    /// Low 256 bits of zero is zero.
    #[test]
    fn zero() {
        assert_eq!(U384::ZERO.low_u256(), U256::from_be_limbs([0, 0, 0, 0]));
    }

    /// Low 256 bits of ONE is ONE.
    #[test]
    fn one() {
        assert_eq!(U384::ONE.low_u256(), U256::from_be_limbs([0, 0, 0, 1]));
    }

    /// Upper limbs are ignored.
    #[test]
    fn ignores_upper() {
        let v = U384::from_be_limbs([0xFF, 0xEE, 1, 2, 3, 4]);
        assert_eq!(v.low_u256(), U256::from_be_limbs([1, 2, 3, 4]));
    }

    /// Round-trip from U256 through U384 back to U256.
    #[test]
    fn round_trip_from_u256() {
        let original = U256::from_be_limbs([0xA, 0xB, 0xC, 0xD]);
        let wide = U384::from(original);
        assert_eq!(wide.low_u256(), original);
    }

    /// MAX gives all-ones in low 256 bits.
    #[test]
    fn max() {
        assert_eq!(
            U384::MAX.low_u256(),
            U256::from_be_limbs([u64::MAX, u64::MAX, u64::MAX, u64::MAX]),
        );
    }
}
