Skip to main content

crypto_bigint/int/
cmp.rs

1//! [`Int`] comparisons.
2//!
3//! By default, these are all constant-time.
4
5use crate::{Choice, CtEq, Int, Uint};
6use core::cmp::Ordering;
7
8impl<const LIMBS: usize> Int<LIMBS> {
9    /// Swap `a` and `b` if `c` is truthy, otherwise, do nothing.
10    #[inline]
11    pub(crate) const fn conditional_swap(a: &mut Self, b: &mut Self, c: Choice) {
12        Uint::conditional_swap(&mut a.0, &mut b.0, c);
13    }
14
15    /// Returns the truthy value if `self`!=0 or the falsy value otherwise.
16    #[inline]
17    pub(crate) const fn is_nonzero(&self) -> Choice {
18        Uint::is_nonzero(&self.0)
19    }
20
21    /// Returns the truthy value if `self == rhs` or the falsy value otherwise.
22    #[inline]
23    pub(crate) const fn eq(lhs: &Self, rhs: &Self) -> Choice {
24        Uint::eq(&lhs.0, &rhs.0)
25    }
26
27    /// Returns the truthy value if `self < rhs` and the falsy value otherwise.
28    #[inline]
29    pub(crate) const fn lt(lhs: &Self, rhs: &Self) -> Choice {
30        Uint::lt(&lhs.invert_msb().0, &rhs.invert_msb().0)
31    }
32
33    /// Returns the truthy value if `self > rhs` and the falsy value otherwise.
34    #[inline]
35    pub(crate) const fn gt(lhs: &Self, rhs: &Self) -> Choice {
36        Uint::gt(&lhs.invert_msb().0, &rhs.invert_msb().0)
37    }
38
39    /// Returns the ordering between `self` and `rhs` as an i8.
40    /// Values correspond to the Ordering enum:
41    ///   -1 is Less
42    ///   0 is Equal
43    ///   1 is Greater
44    #[inline]
45    pub(crate) const fn cmp(lhs: &Self, rhs: &Self) -> Ordering {
46        Uint::cmp(&lhs.invert_msb().0, &rhs.invert_msb().0)
47    }
48
49    /// Returns the Ordering between `self` and `rhs` in variable time.
50    #[must_use]
51    pub const fn cmp_vartime(&self, rhs: &Self) -> Ordering {
52        self.invert_msb().0.cmp_vartime(&rhs.invert_msb().0)
53    }
54}
55
56impl<const LIMBS: usize> Eq for Int<LIMBS> {}
57
58impl<const LIMBS: usize> Ord for Int<LIMBS> {
59    fn cmp(&self, other: &Self) -> Ordering {
60        Self::cmp(self, other)
61    }
62}
63
64impl<const LIMBS: usize> PartialOrd for Int<LIMBS> {
65    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
66        Some(self.cmp(other))
67    }
68}
69
70impl<const LIMBS: usize> PartialEq for Int<LIMBS> {
71    fn eq(&self, other: &Self) -> bool {
72        self.ct_eq(other).into()
73    }
74}
75
76#[cfg(test)]
77mod tests {
78    use crate::I128;
79
80    #[test]
81    fn test_is_nonzero() {
82        assert_eq!(I128::MAX.is_nonzero().to_u8(), 1u8);
83        assert_eq!(I128::ONE.is_nonzero().to_u8(), 1u8);
84        assert_eq!(I128::ZERO.is_nonzero().to_u8(), 0u8);
85        assert_eq!(I128::MINUS_ONE.is_nonzero().to_u8(), 1u8);
86        assert_eq!(I128::MAX.is_nonzero().to_u8(), 1u8);
87    }
88
89    #[test]
90    fn test_eq() {
91        assert_eq!(I128::ZERO, I128::ONE.wrapping_add(&I128::MINUS_ONE));
92        assert_eq!(I128::ONE, I128::ZERO.wrapping_add(&I128::ONE));
93        assert_ne!(I128::ONE, I128::ZERO);
94    }
95
96    #[test]
97    #[allow(clippy::bool_assert_comparison)]
98    fn test_gt() {
99        // x > y
100        assert!(I128::MAX > I128::ONE);
101        assert!(I128::ONE > I128::ZERO);
102        assert!(I128::ZERO > I128::MINUS_ONE);
103        assert!(I128::MINUS_ONE > I128::MIN);
104        assert!(I128::MAX > I128::MIN);
105
106        // a !> a
107        assert_ne!(true, I128::MAX > I128::MAX);
108        assert_ne!(true, I128::ONE > I128::ONE);
109        assert_ne!(true, I128::ZERO > I128::ZERO);
110        assert_ne!(true, I128::MINUS_ONE > I128::MINUS_ONE);
111        assert_ne!(true, I128::MIN > I128::MIN);
112    }
113
114    #[test]
115    #[allow(clippy::bool_assert_comparison)]
116    fn test_lt() {
117        // x < y
118        assert!(I128::ONE < I128::MAX);
119        assert!(I128::ZERO < I128::ONE);
120        assert!(I128::MINUS_ONE < I128::ZERO);
121        assert!(I128::MIN < I128::MINUS_ONE);
122        assert!(I128::MIN < I128::MAX);
123
124        // a !< a
125        assert_ne!(true, I128::MAX < I128::MAX);
126        assert_ne!(true, I128::ONE < I128::ONE);
127        assert_ne!(true, I128::ZERO < I128::ZERO);
128        assert_ne!(true, I128::MINUS_ONE < I128::MINUS_ONE);
129        assert_ne!(true, I128::MIN < I128::MIN);
130    }
131}