//! Parity check for [`U256`] values.
use super::U256;

impl U256 {
    /// Returns `true` if the least significant bit is set (the value is odd).
    ///
    /// Checks bit 0 of the least significant limb `w0` (index 0). This is used by
    /// secp256k1 point compression to determine the SEC1 prefix byte
    /// (`0x02` for even y, `0x03` for odd y).
    ///
    /// # Examples
    ///
    /// ```
    /// use cnfy_uint::u256::U256;
    ///
    /// assert!(!U256::ZERO.is_odd());
    /// assert!(U256::ONE.is_odd());
    /// assert!(U256::MAX.is_odd());
    /// ```
    #[inline]
    pub fn is_odd(&self) -> bool {
        self.0[0] & 1 == 1
    }
}

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

    /// Zero is even.
    #[test]
    fn zero_is_even() {
        assert!(!U256::ZERO.is_odd());
    }

    /// One is odd.
    #[test]
    fn one_is_odd() {
        assert!(U256::ONE.is_odd());
    }

    /// Two is even.
    #[test]
    fn two_is_even() {
        let two = U256::from_be_limbs([0, 0, 0, 2]);
        assert!(!two.is_odd());
    }

    /// MAX (all bits set) is odd.
    #[test]
    fn max_is_odd() {
        assert!(U256::MAX.is_odd());
    }

    /// A large even number with only the MSB limb set.
    #[test]
    fn large_even() {
        let v = U256::from_be_limbs([0x8000_0000_0000_0000, 0, 0, 0]);
        assert!(!v.is_odd());
    }

    /// A large odd number with MSB and LSB set.
    #[test]
    fn large_odd() {
        let v = U256::from_be_limbs([0x8000_0000_0000_0000, 0, 0, 1]);
        assert!(v.is_odd());
    }

    /// secp256k1 field prime P is odd (ends in 0x...FC2F).
    #[test]
    fn secp256k1_p_is_odd() {
        let p = U256::from_be_limbs([
            0xFFFFFFFF_FFFFFFFF,
            0xFFFFFFFF_FFFFFFFF,
            0xFFFFFFFF_FFFFFFFF,
            0xFFFFFFFE_FFFFFC2F,
        ]);
        assert!(p.is_odd());
    }
}
