//! Significant limb count for [`U384`].
use super::U384;

impl U384 {
    /// Returns the number of significant (non-zero or trailing) 64-bit
    /// limbs needed to represent the value, from 1 to 6.
    ///
    /// Always returns at least 1, even for zero, since zero still
    /// occupies one limb in practice.
    ///
    /// # Examples
    ///
    /// ```
    /// use cnfy_uint::u384::U384;
    ///
    /// assert_eq!(U384::ZERO.sig_limbs(), 1);
    /// assert_eq!(U384::ONE.sig_limbs(), 1);
    /// assert_eq!(U384::MAX.sig_limbs(), 6);
    /// ```
    #[inline]
    pub const fn sig_limbs(&self) -> usize {
        let mut i = 5;
        loop {
            if self.0[i] != 0 {
                return i + 1;
            }
            if i == 0 {
                return 1;
            }
            i -= 1;
        }
    }
}

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

    /// Zero has 1 significant limb.
    #[test]
    fn zero() {
        assert_eq!(U384::ZERO.sig_limbs(), 1);
    }

    /// One has 1 significant limb.
    #[test]
    fn one() {
        assert_eq!(U384::ONE.sig_limbs(), 1);
    }

    /// MAX has 6 significant limbs.
    #[test]
    fn max() {
        assert_eq!(U384::MAX.sig_limbs(), 6);
    }

    /// Value in limb [4] only needs 2 limbs.
    #[test]
    fn two_limbs() {
        let v = U384::from_be_limbs([0, 0, 0, 0, 1, 0]);
        assert_eq!(v.sig_limbs(), 2);
    }

    /// Value in limb [0] needs 6 limbs.
    #[test]
    fn six_limbs() {
        let v = U384::from_be_limbs([1, 0, 0, 0, 0, 0]);
        assert_eq!(v.sig_limbs(), 6);
    }

    /// Value in limb [2] needs 4 limbs.
    #[test]
    fn four_limbs() {
        let v = U384::from_be_limbs([0, 0, 1, 0, 0, 0]);
        assert_eq!(v.sig_limbs(), 4);
    }
}
