//! Leading zero bit count for [`U384`].
use super::U384;

impl U384 {
    /// Returns the number of leading zero bits in the 384-bit value.
    ///
    /// Returns 384 for the zero value and 0 when the most significant bit
    /// is set.
    ///
    /// # Examples
    ///
    /// ```
    /// use cnfy_uint::u384::U384;
    ///
    /// assert_eq!(U384::ZERO.leading_zeros(), 384);
    /// assert_eq!(U384::ONE.leading_zeros(), 383);
    /// assert_eq!(U384::MAX.leading_zeros(), 0);
    /// ```
    #[inline]
    pub const fn leading_zeros(&self) -> u32 {
        let mut i = 5;
        loop {
            if self.0[i] != 0 {
                return ((5 - i) as u32) * 64 + self.0[i].leading_zeros();
            }
            if i == 0 {
                return 384;
            }
            i -= 1;
        }
    }
}

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

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

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

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

    /// Value in limb [0] only.
    #[test]
    fn msb_limb() {
        let v = U384::from_be_limbs([1, 0, 0, 0, 0, 0]);
        assert_eq!(v.leading_zeros(), 63);
    }

    /// Value in limb [3] only.
    #[test]
    fn middle_limb() {
        let v = U384::from_be_limbs([0, 0, 0, 1, 0, 0]);
        assert_eq!(v.leading_zeros(), 3 * 64 + 63);
    }

    /// High bit set has zero leading zeros.
    #[test]
    fn high_bit() {
        let v = U384::from_be_limbs([1 << 63, 0, 0, 0, 0, 0]);
        assert_eq!(v.leading_zeros(), 0);
    }
}
