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

impl U512 {
    /// Returns the high (most significant) 256-bit value from LE
    /// limbs `[4..7]`.
    ///
    /// # Examples
    ///
    /// ```
    /// use cnfy_uint::u256::U256;
    /// use cnfy_uint::u512::U512;
    ///
    /// let v = U512::from_be_limbs([1, 2, 3, 4, 0xAA, 0xBB, 0xCC, 0xDD]);
    /// assert_eq!(v.high_u256(), U256::from_be_limbs([1, 2, 3, 4]));
    /// ```
    #[inline]
    pub const fn high_u256(&self) -> U256 {
        U256([self.0[4], self.0[5], self.0[6], self.0[7]])
    }
}

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

    /// High of zero is zero.
    #[test]
    fn zero() {
        assert_eq!(U512::ZERO.high_u256(), U256::ZERO);
    }

    /// High of ONE is zero (1 is in the low half).
    #[test]
    fn one() {
        assert_eq!(U512::ONE.high_u256(), U256::ZERO);
    }

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

    /// High of MAX has all bits set.
    #[test]
    fn max() {
        assert_eq!(U512::MAX.high_u256(), U256::MAX);
    }

    /// High and low together reconstruct the full value.
    #[test]
    fn high_low_complement() {
        let v = U512::from_be_limbs([0xA, 0xB, 0xC, 0xD, 0x1, 0x2, 0x3, 0x4]);
        assert_eq!(v.high_u256(), U256::from_be_limbs([0xA, 0xB, 0xC, 0xD]));
        assert_eq!(v.low_u256(), U256::from_be_limbs([0x1, 0x2, 0x3, 0x4]));
    }
}
