crypto_bigint/int/
bit_and.rs

1//! [`Int`] bitwise AND operations.
2
3use core::ops::{BitAnd, BitAndAssign};
4
5use crate::{ConstCtOption, Int, Limb, Uint, Wrapping};
6
7impl<const LIMBS: usize> Int<LIMBS> {
8    /// Computes bitwise `a & b`.
9    #[inline(always)]
10    pub const fn bitand(&self, rhs: &Self) -> Self {
11        Self(Uint::bitand(&self.0, &rhs.0))
12    }
13
14    /// Perform bitwise `AND` between `self` and the given [`Limb`], performing the `AND` operation
15    /// on every limb of `self`.
16    pub const fn bitand_limb(&self, rhs: Limb) -> Self {
17        Self(Uint::bitand_limb(&self.0, rhs))
18    }
19
20    /// Perform wrapping bitwise `AND`.
21    ///
22    /// There's no way wrapping could ever happen.
23    /// This function exists so that all operations are accounted for in the wrapping operations
24    pub const fn wrapping_and(&self, rhs: &Self) -> Self {
25        self.bitand(rhs)
26    }
27
28    /// Perform checked bitwise `AND`, returning a [`ConstCtOption`] which `is_some` always
29    pub const fn checked_and(&self, rhs: &Self) -> ConstCtOption<Self> {
30        ConstCtOption::some(self.bitand(rhs))
31    }
32}
33
34impl<const LIMBS: usize> BitAnd for Int<LIMBS> {
35    type Output = Self;
36
37    fn bitand(self, rhs: Self) -> Int<LIMBS> {
38        self.bitand(&rhs)
39    }
40}
41
42impl<const LIMBS: usize> BitAnd<&Int<LIMBS>> for Int<LIMBS> {
43    type Output = Int<LIMBS>;
44
45    #[allow(clippy::needless_borrow)]
46    fn bitand(self, rhs: &Int<LIMBS>) -> Int<LIMBS> {
47        (&self).bitand(rhs)
48    }
49}
50
51impl<const LIMBS: usize> BitAnd<Int<LIMBS>> for &Int<LIMBS> {
52    type Output = Int<LIMBS>;
53
54    fn bitand(self, rhs: Int<LIMBS>) -> Int<LIMBS> {
55        self.bitand(&rhs)
56    }
57}
58
59impl<const LIMBS: usize> BitAnd<&Int<LIMBS>> for &Int<LIMBS> {
60    type Output = Int<LIMBS>;
61
62    fn bitand(self, rhs: &Int<LIMBS>) -> Int<LIMBS> {
63        self.bitand(rhs)
64    }
65}
66
67impl<const LIMBS: usize> BitAndAssign for Int<LIMBS> {
68    #[allow(clippy::assign_op_pattern)]
69    fn bitand_assign(&mut self, other: Self) {
70        *self = *self & other;
71    }
72}
73
74impl<const LIMBS: usize> BitAndAssign<&Int<LIMBS>> for Int<LIMBS> {
75    #[allow(clippy::assign_op_pattern)]
76    fn bitand_assign(&mut self, other: &Self) {
77        *self = *self & other;
78    }
79}
80
81impl<const LIMBS: usize> BitAnd for Wrapping<Int<LIMBS>> {
82    type Output = Self;
83
84    fn bitand(self, rhs: Self) -> Wrapping<Int<LIMBS>> {
85        Wrapping(self.0.bitand(&rhs.0))
86    }
87}
88
89impl<const LIMBS: usize> BitAnd<&Wrapping<Int<LIMBS>>> for Wrapping<Int<LIMBS>> {
90    type Output = Wrapping<Int<LIMBS>>;
91
92    fn bitand(self, rhs: &Wrapping<Int<LIMBS>>) -> Wrapping<Int<LIMBS>> {
93        Wrapping(self.0.bitand(&rhs.0))
94    }
95}
96
97impl<const LIMBS: usize> BitAnd<Wrapping<Int<LIMBS>>> for &Wrapping<Int<LIMBS>> {
98    type Output = Wrapping<Int<LIMBS>>;
99
100    fn bitand(self, rhs: Wrapping<Int<LIMBS>>) -> Wrapping<Int<LIMBS>> {
101        Wrapping(self.0.bitand(&rhs.0))
102    }
103}
104
105impl<const LIMBS: usize> BitAnd<&Wrapping<Int<LIMBS>>> for &Wrapping<Int<LIMBS>> {
106    type Output = Wrapping<Int<LIMBS>>;
107
108    fn bitand(self, rhs: &Wrapping<Int<LIMBS>>) -> Wrapping<Int<LIMBS>> {
109        Wrapping(self.0.bitand(&rhs.0))
110    }
111}
112
113impl<const LIMBS: usize> BitAndAssign for Wrapping<Int<LIMBS>> {
114    #[allow(clippy::assign_op_pattern)]
115    fn bitand_assign(&mut self, other: Self) {
116        *self = *self & other;
117    }
118}
119
120impl<const LIMBS: usize> BitAndAssign<&Wrapping<Int<LIMBS>>> for Wrapping<Int<LIMBS>> {
121    #[allow(clippy::assign_op_pattern)]
122    fn bitand_assign(&mut self, other: &Self) {
123        *self = *self & other;
124    }
125}
126
127#[cfg(test)]
128mod tests {
129    use crate::I128;
130
131    #[test]
132    fn checked_and_ok() {
133        assert_eq!(I128::ZERO.checked_and(&I128::ONE).unwrap(), I128::ZERO);
134        assert_eq!(I128::ONE.checked_and(&I128::ONE).unwrap(), I128::ONE);
135        assert_eq!(I128::MAX.checked_and(&I128::ONE).unwrap(), I128::ONE);
136    }
137
138    #[test]
139    fn wrapping_and_ok() {
140        assert_eq!(I128::ZERO.wrapping_and(&I128::ONE), I128::ZERO);
141        assert_eq!(I128::ONE.wrapping_and(&I128::ONE), I128::ONE);
142        assert_eq!(I128::MAX.wrapping_and(&I128::ONE), I128::ONE);
143    }
144}