//! Bit-level trailing zero count for [`U256`].

use super::U256;

impl U256 {
    /// Returns the number of trailing zero bits in the 256-bit value.
    ///
    /// Scans from the least significant limb (`w3`) upward. Returns 256
    /// for zero, 0 for any odd value, and the position of the lowest set
    /// bit in general.
    ///
    /// # Examples
    ///
    /// ```
    /// use cnfy_uint::u256::U256;
    ///
    /// assert_eq!(U256::ZERO.trailing_zeros(), 256);
    /// assert_eq!(U256::ONE.trailing_zeros(), 0);
    /// assert_eq!(U256::from_be_limbs([0, 0, 0, 8]).trailing_zeros(), 3);
    /// ```
    #[inline]
    pub const fn trailing_zeros(&self) -> u32 {
        if self.0[0] != 0 {
            self.0[0].trailing_zeros()
        } else if self.0[1] != 0 {
            64 + self.0[1].trailing_zeros()
        } else if self.0[2] != 0 {
            128 + self.0[2].trailing_zeros()
        } else if self.0[3] != 0 {
            192 + self.0[3].trailing_zeros()
        } else {
            256
        }
    }
}

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

    /// Zero has 256 trailing zeros.
    #[test]
    fn zero() {
        assert_eq!(U256::ZERO.trailing_zeros(), 256);
    }

    /// One has 0 trailing zeros.
    #[test]
    fn one() {
        assert_eq!(U256::ONE.trailing_zeros(), 0);
    }

    /// MAX has 0 trailing zeros (all bits set).
    #[test]
    fn max() {
        assert_eq!(U256::MAX.trailing_zeros(), 0);
    }

    /// Powers of two have trailing_zeros = exponent.
    #[test]
    fn powers_of_two() {
        assert_eq!(U256::from_be_limbs([0, 0, 0, 2]).trailing_zeros(), 1);
        assert_eq!(U256::from_be_limbs([0, 0, 0, 8]).trailing_zeros(), 3);
        assert_eq!(U256::from_be_limbs([0, 0, 0, 0x100]).trailing_zeros(), 8);
        assert_eq!(U256::from_be_limbs([0, 0, 1, 0]).trailing_zeros(), 64);
        assert_eq!(U256::from_be_limbs([0, 1, 0, 0]).trailing_zeros(), 128);
        assert_eq!(U256::from_be_limbs([1, 0, 0, 0]).trailing_zeros(), 192);
    }

    /// MSB-only value has 255 trailing zeros.
    #[test]
    fn msb_only() {
        assert_eq!(
            U256::from_be_limbs([0x8000000000000000, 0, 0, 0]).trailing_zeros(),
            255,
        );
    }

    /// Odd values always have 0 trailing zeros.
    #[test]
    fn odd_values() {
        assert_eq!(U256::from_be_limbs([0, 0, 0, 3]).trailing_zeros(), 0);
        assert_eq!(U256::from_be_limbs([0xFF, 0, 0, 1]).trailing_zeros(), 0);
    }

    /// Even values in higher limbs.
    #[test]
    fn higher_limb_trailing() {
        // Only w2 set, at bit 64
        assert_eq!(U256::from_be_limbs([0, 0, 1, 0]).trailing_zeros(), 64);
        // w2 = 0x10 → trailing = 64 + 4 = 68
        assert_eq!(U256::from_be_limbs([0, 0, 0x10, 0]).trailing_zeros(), 68);
    }
}
