crypto_bigint/uint/boxed/
bit_and.rs

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