//! Bit-level leading zero count for [`U320`].
use super::U320;

impl U320 {
    /// Returns the number of leading zero bits in the 320-bit value.
    ///
    /// Scans from the most significant limb (index 4) downward. Returns 320
    /// for zero, 0 for any value with the MSB set, and `320 - bit_len()`
    /// in general.
    ///
    /// # Examples
    ///
    /// ```
    /// use cnfy_uint::u320::U320;
    ///
    /// assert_eq!(U320::ZERO.leading_zeros(), 320);
    /// assert_eq!(U320::ONE.leading_zeros(), 319);
    /// assert_eq!(U320::MAX.leading_zeros(), 0);
    /// ```
    #[inline]
    pub const fn leading_zeros(&self) -> u32 {
        if self.0[4] != 0 {
            self.0[4].leading_zeros()
        } else if self.0[3] != 0 {
            64 + self.0[3].leading_zeros()
        } else if self.0[2] != 0 {
            128 + self.0[2].leading_zeros()
        } else if self.0[1] != 0 {
            192 + self.0[1].leading_zeros()
        } else if self.0[0] != 0 {
            256 + self.0[0].leading_zeros()
        } else {
            320
        }
    }
}

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

    /// Zero has 320 leading zeros.
    #[test]
    fn zero() {
        assert_eq!(U320::ZERO.leading_zeros(), 320);
    }

    /// One has 319 leading zeros.
    #[test]
    fn one() {
        assert_eq!(U320::ONE.leading_zeros(), 319);
    }

    /// MAX has 0 leading zeros.
    #[test]
    fn max() {
        assert_eq!(U320::MAX.leading_zeros(), 0);
    }

    /// Powers of two have leading_zeros = 319 - exponent.
    #[test]
    fn powers_of_two() {
        assert_eq!(U320::from_be_limbs([0, 0, 0, 0, 1]).leading_zeros(), 319);
        assert_eq!(U320::from_be_limbs([0, 0, 0, 1, 0]).leading_zeros(), 255);
        assert_eq!(U320::from_be_limbs([0, 0, 1, 0, 0]).leading_zeros(), 191);
        assert_eq!(U320::from_be_limbs([0, 1, 0, 0, 0]).leading_zeros(), 127);
        assert_eq!(U320::from_be_limbs([1, 0, 0, 0, 0]).leading_zeros(), 63);
    }

    /// Full limb boundaries.
    #[test]
    fn limb_boundaries() {
        assert_eq!(U320::from_be_limbs([0, 0, 0, 0, u64::MAX]).leading_zeros(), 256);
        assert_eq!(U320::from_be_limbs([0, 0, 0, u64::MAX, 0]).leading_zeros(), 192);
        assert_eq!(U320::from_be_limbs([0, 0, u64::MAX, 0, 0]).leading_zeros(), 128);
        assert_eq!(U320::from_be_limbs([0, u64::MAX, 0, 0, 0]).leading_zeros(), 64);
        assert_eq!(U320::from_be_limbs([u64::MAX, 0, 0, 0, 0]).leading_zeros(), 0);
    }

    /// Value 0x80 in the LSB limb.
    #[test]
    fn byte_boundary() {
        assert_eq!(U320::from_be_limbs([0, 0, 0, 0, 0x80]).leading_zeros(), 312);
    }
}
