//! Constant-time equality comparison usable in `const fn` contexts.
use super::U512;

impl U512 {
    /// Returns `true` if `self` and `other` represent the same 512-bit value.
    ///
    /// This is a `const fn` alternative to the derived `PartialEq` (which
    /// cannot be called in const contexts). Internally it XORs each limb
    /// pair and ORs the results, producing a single zero/non-zero check
    /// -- branchless with one final comparison instead of eight short-circuit
    /// `&&` branches.
    ///
    /// # Examples
    ///
    /// ```
    /// use cnfy_uint::u512::U512;
    ///
    /// let a = U512::from_be_limbs([1, 2, 3, 4, 5, 6, 7, 8]);
    /// let b = U512::from_be_limbs([1, 2, 3, 4, 5, 6, 7, 8]);
    /// assert!(a.const_eq(&b));
    /// ```
    #[inline]
    pub const fn const_eq(&self, other: &U512) -> bool {
        (self.0[0] ^ other.0[0])
            | (self.0[1] ^ other.0[1])
            | (self.0[2] ^ other.0[2])
            | (self.0[3] ^ other.0[3])
            | (self.0[4] ^ other.0[4])
            | (self.0[5] ^ other.0[5])
            | (self.0[6] ^ other.0[6])
            | (self.0[7] ^ other.0[7])
            == 0
    }
}

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

    /// Equal values return true.
    #[test]
    fn equal_values() {
        let a = U512::from_be_limbs([0x1234, 0x5678, 0x9ABC, 0xDEF0, 1, 2, 3, 4]);
        assert!(a.const_eq(&a));
    }

    /// Different values return false.
    #[test]
    fn different_values() {
        let a = U512::from_be_limbs([1, 2, 3, 4, 5, 6, 7, 8]);
        let b = U512::from_be_limbs([1, 2, 3, 4, 5, 6, 7, 9]);
        assert!(!a.const_eq(&b));
    }

    /// Zero equals zero.
    #[test]
    fn zero_eq_zero() {
        assert!(U512::ZERO.const_eq(&U512::ZERO));
    }

    /// Zero and one are not equal.
    #[test]
    fn zero_ne_one() {
        assert!(!U512::ZERO.const_eq(&U512::ONE));
    }

    /// Difference in only the most significant limb is detected.
    #[test]
    fn msb_differs() {
        let a = U512::from_be_limbs([1, 0, 0, 0, 0, 0, 0, 0]);
        let b = U512::from_be_limbs([2, 0, 0, 0, 0, 0, 0, 0]);
        assert!(!a.const_eq(&b));
    }
}
