crypto_bigint/uint/
bit_and.rs1use super::Uint;
4use crate::{Limb, Wrapping};
5use core::ops::{BitAnd, BitAndAssign};
6use subtle::{Choice, CtOption};
7
8impl<const LIMBS: usize> Uint<LIMBS> {
9 #[inline(always)]
11 pub const fn bitand(&self, rhs: &Self) -> Self {
12 let mut limbs = [Limb::ZERO; LIMBS];
13 let mut i = 0;
14
15 while i < LIMBS {
16 limbs[i] = self.limbs[i].bitand(rhs.limbs[i]);
17 i += 1;
18 }
19
20 Self { limbs }
21 }
22
23 pub const fn bitand_limb(&self, rhs: Limb) -> Self {
26 let mut limbs = [Limb::ZERO; LIMBS];
27 let mut i = 0;
28
29 while i < LIMBS {
30 limbs[i] = self.limbs[i].bitand(rhs);
31 i += 1;
32 }
33
34 Self { limbs }
35 }
36
37 pub const fn wrapping_and(&self, rhs: &Self) -> Self {
42 self.bitand(rhs)
43 }
44
45 pub fn checked_and(&self, rhs: &Self) -> CtOption<Self> {
47 let result = self.bitand(rhs);
48 CtOption::new(result, Choice::from(1))
49 }
50}
51
52impl<const LIMBS: usize> BitAnd for Uint<LIMBS> {
53 type Output = Self;
54
55 fn bitand(self, rhs: Self) -> Uint<LIMBS> {
56 self.bitand(&rhs)
57 }
58}
59
60impl<const LIMBS: usize> BitAnd<&Uint<LIMBS>> for Uint<LIMBS> {
61 type Output = Uint<LIMBS>;
62
63 #[allow(clippy::needless_borrow)]
64 fn bitand(self, rhs: &Uint<LIMBS>) -> Uint<LIMBS> {
65 (&self).bitand(rhs)
66 }
67}
68
69impl<const LIMBS: usize> BitAnd<Uint<LIMBS>> for &Uint<LIMBS> {
70 type Output = Uint<LIMBS>;
71
72 fn bitand(self, rhs: Uint<LIMBS>) -> Uint<LIMBS> {
73 self.bitand(&rhs)
74 }
75}
76
77impl<const LIMBS: usize> BitAnd<&Uint<LIMBS>> for &Uint<LIMBS> {
78 type Output = Uint<LIMBS>;
79
80 fn bitand(self, rhs: &Uint<LIMBS>) -> Uint<LIMBS> {
81 self.bitand(rhs)
82 }
83}
84
85impl<const LIMBS: usize> BitAndAssign for Uint<LIMBS> {
86 #[allow(clippy::assign_op_pattern)]
87 fn bitand_assign(&mut self, other: Self) {
88 *self = *self & other;
89 }
90}
91
92impl<const LIMBS: usize> BitAndAssign<&Uint<LIMBS>> for Uint<LIMBS> {
93 #[allow(clippy::assign_op_pattern)]
94 fn bitand_assign(&mut self, other: &Self) {
95 *self = *self & other;
96 }
97}
98
99impl<const LIMBS: usize> BitAnd for Wrapping<Uint<LIMBS>> {
100 type Output = Self;
101
102 fn bitand(self, rhs: Self) -> Wrapping<Uint<LIMBS>> {
103 Wrapping(self.0.bitand(&rhs.0))
104 }
105}
106
107impl<const LIMBS: usize> BitAnd<&Wrapping<Uint<LIMBS>>> for Wrapping<Uint<LIMBS>> {
108 type Output = Wrapping<Uint<LIMBS>>;
109
110 fn bitand(self, rhs: &Wrapping<Uint<LIMBS>>) -> Wrapping<Uint<LIMBS>> {
111 Wrapping(self.0.bitand(&rhs.0))
112 }
113}
114
115impl<const LIMBS: usize> BitAnd<Wrapping<Uint<LIMBS>>> for &Wrapping<Uint<LIMBS>> {
116 type Output = Wrapping<Uint<LIMBS>>;
117
118 fn bitand(self, rhs: Wrapping<Uint<LIMBS>>) -> Wrapping<Uint<LIMBS>> {
119 Wrapping(self.0.bitand(&rhs.0))
120 }
121}
122
123impl<const LIMBS: usize> BitAnd<&Wrapping<Uint<LIMBS>>> for &Wrapping<Uint<LIMBS>> {
124 type Output = Wrapping<Uint<LIMBS>>;
125
126 fn bitand(self, rhs: &Wrapping<Uint<LIMBS>>) -> Wrapping<Uint<LIMBS>> {
127 Wrapping(self.0.bitand(&rhs.0))
128 }
129}
130
131impl<const LIMBS: usize> BitAndAssign for Wrapping<Uint<LIMBS>> {
132 #[allow(clippy::assign_op_pattern)]
133 fn bitand_assign(&mut self, other: Self) {
134 *self = *self & other;
135 }
136}
137
138impl<const LIMBS: usize> BitAndAssign<&Wrapping<Uint<LIMBS>>> for Wrapping<Uint<LIMBS>> {
139 #[allow(clippy::assign_op_pattern)]
140 fn bitand_assign(&mut self, other: &Self) {
141 *self = *self & other;
142 }
143}
144
145#[cfg(test)]
146mod tests {
147 use crate::U128;
148
149 #[test]
150 fn checked_and_ok() {
151 let result = U128::ZERO.checked_and(&U128::ONE);
152 assert_eq!(result.unwrap(), U128::ZERO);
153 }
154
155 #[test]
156 fn overlapping_and_ok() {
157 let result = U128::MAX.wrapping_and(&U128::ONE);
158 assert_eq!(result, U128::ONE);
159 }
160}