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

impl U512 {
    /// Returns the low (least significant) 256-bit value from LE
    /// limbs `[0..3]`.
    ///
    /// # Examples
    ///
    /// ```
    /// use cnfy_uint::u256::U256;
    /// use cnfy_uint::u512::U512;
    ///
    /// let v = U512::from_be_limbs([0xAA, 0xBB, 0xCC, 0xDD, 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 of zero is zero.
    #[test]
    fn zero() {
        assert_eq!(U512::ZERO.low_u256(), U256::ZERO);
    }

    /// Low of ONE is ONE.
    #[test]
    fn one() {
        assert_eq!(U512::ONE.low_u256(), U256::ONE);
    }

    /// Low ignores the upper four limbs.
    #[test]
    fn ignores_upper() {
        let v = U512::from_be_limbs([0xFF, 0xEE, 0xDD, 0xCC, 1, 2, 3, 4]);
        assert_eq!(v.low_u256(), U256::from_be_limbs([1, 2, 3, 4]));
    }

    /// Low of MAX has all bits set in lower 256 bits.
    #[test]
    fn max() {
        assert_eq!(U512::MAX.low_u256(), U256::MAX);
    }

    /// Round-trip: from_u256 then low_u256 recovers the original.
    #[test]
    fn round_trip_from_u256() {
        let original = U256::from_be_limbs([0x1234, 0x5678, 0x9ABC, 0xDEF0]);
        assert_eq!(U512::from(original).low_u256(), original);
    }
}
