1use super::{HeaplessBigInt, zero};
17use crate::MachineWord;
18use const_num_traits::Personality;
19use core::marker::PhantomData;
20use core::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Not};
21
22macro_rules! forward_bitwise_receivers {
25 ($imp:ident, $method:ident) => {
26 impl<T: MachineWord, const CAP: usize, P: Personality> $imp for HeaplessBigInt<T, CAP, P> {
27 type Output = Self;
28 fn $method(self, other: Self) -> Self {
29 (&self).$method(&other)
30 }
31 }
32 impl<T: MachineWord, const CAP: usize, P: Personality> $imp<&HeaplessBigInt<T, CAP, P>>
33 for HeaplessBigInt<T, CAP, P>
34 {
35 type Output = Self;
36 fn $method(self, other: &Self) -> Self {
37 (&self).$method(other)
38 }
39 }
40 impl<T: MachineWord, const CAP: usize, P: Personality> $imp<HeaplessBigInt<T, CAP, P>>
41 for &HeaplessBigInt<T, CAP, P>
42 {
43 type Output = HeaplessBigInt<T, CAP, P>;
44 fn $method(self, other: HeaplessBigInt<T, CAP, P>) -> HeaplessBigInt<T, CAP, P> {
45 self.$method(&other)
46 }
47 }
48 };
49}
50
51impl<T: MachineWord, const CAP: usize, P: Personality> BitAnd<&HeaplessBigInt<T, CAP, P>>
53 for &HeaplessBigInt<T, CAP, P>
54{
55 type Output = HeaplessBigInt<T, CAP, P>;
56 fn bitand(self, other: &HeaplessBigInt<T, CAP, P>) -> Self::Output {
57 let out_len = core::cmp::max(self.len, other.len);
61 let n = out_len as usize;
62 let mut limbs = [zero::<T>(); CAP];
63 for ((&ai, &bi), oi) in self.limbs[..n]
64 .iter()
65 .zip(&other.limbs[..n])
66 .zip(&mut limbs[..n])
67 {
68 *oi = ai & bi;
69 }
70 HeaplessBigInt {
71 limbs,
72 len: out_len,
73 _p: PhantomData,
74 }
75 }
76}
77
78forward_bitwise_receivers!(BitAnd, bitand);
79
80impl<T: MachineWord, const CAP: usize, P: Personality> BitOr<&HeaplessBigInt<T, CAP, P>>
82 for &HeaplessBigInt<T, CAP, P>
83{
84 type Output = HeaplessBigInt<T, CAP, P>;
85 fn bitor(self, other: &HeaplessBigInt<T, CAP, P>) -> Self::Output {
86 let out_len = core::cmp::max(self.len, other.len);
87 let n = out_len as usize;
88 let mut limbs = [zero::<T>(); CAP];
89 for ((&ai, &bi), oi) in self.limbs[..n]
90 .iter()
91 .zip(&other.limbs[..n])
92 .zip(&mut limbs[..n])
93 {
94 *oi = ai | bi;
95 }
96 HeaplessBigInt {
97 limbs,
98 len: out_len,
99 _p: PhantomData,
100 }
101 }
102}
103
104forward_bitwise_receivers!(BitOr, bitor);
105
106impl<T: MachineWord, const CAP: usize, P: Personality> BitXor<&HeaplessBigInt<T, CAP, P>>
108 for &HeaplessBigInt<T, CAP, P>
109{
110 type Output = HeaplessBigInt<T, CAP, P>;
111 fn bitxor(self, other: &HeaplessBigInt<T, CAP, P>) -> Self::Output {
112 let out_len = core::cmp::max(self.len, other.len);
113 let n = out_len as usize;
114 let mut limbs = [zero::<T>(); CAP];
115 for ((&ai, &bi), oi) in self.limbs[..n]
116 .iter()
117 .zip(&other.limbs[..n])
118 .zip(&mut limbs[..n])
119 {
120 *oi = ai ^ bi;
121 }
122 HeaplessBigInt {
123 limbs,
124 len: out_len,
125 _p: PhantomData,
126 }
127 }
128}
129
130forward_bitwise_receivers!(BitXor, bitxor);
131
132impl<T: MachineWord, const CAP: usize, P: Personality> Not for HeaplessBigInt<T, CAP, P> {
137 type Output = Self;
138 fn not(self) -> Self {
139 let n = self.len as usize;
140 let mut limbs = [zero::<T>(); CAP];
141 for (o, &s) in limbs[..n].iter_mut().zip(&self.limbs[..n]) {
142 *o = !s;
143 }
144 HeaplessBigInt {
145 limbs,
146 len: self.len,
147 _p: PhantomData,
148 }
149 }
150}
151
152impl<T: MachineWord, const CAP: usize, P: Personality> Not for &HeaplessBigInt<T, CAP, P> {
153 type Output = HeaplessBigInt<T, CAP, P>;
154 fn not(self) -> Self::Output {
155 !*self
156 }
157}
158
159impl<T: MachineWord, const CAP: usize, P: Personality> BitAndAssign for HeaplessBigInt<T, CAP, P> {
162 fn bitand_assign(&mut self, other: Self) {
163 self.bitand_assign(&other);
164 }
165}
166
167impl<T: MachineWord, const CAP: usize, P: Personality> BitAndAssign<&HeaplessBigInt<T, CAP, P>>
168 for HeaplessBigInt<T, CAP, P>
169{
170 fn bitand_assign(&mut self, other: &Self) {
171 let min_len = core::cmp::min(self.len, other.len) as usize;
177 let self_len = self.len as usize;
178 let max_len = core::cmp::max(self.len, other.len);
179 for (si, &oi) in self.limbs[..min_len]
180 .iter_mut()
181 .zip(&other.limbs[..min_len])
182 {
183 *si &= oi;
184 }
185 for si in &mut self.limbs[min_len..self_len] {
186 *si = zero::<T>();
187 }
188 self.len = max_len;
189 }
190}
191
192impl<T: MachineWord, const CAP: usize, P: Personality> BitOrAssign for HeaplessBigInt<T, CAP, P> {
193 fn bitor_assign(&mut self, other: Self) {
194 self.bitor_assign(&other);
195 }
196}
197
198impl<T: MachineWord, const CAP: usize, P: Personality> BitOrAssign<&HeaplessBigInt<T, CAP, P>>
199 for HeaplessBigInt<T, CAP, P>
200{
201 fn bitor_assign(&mut self, other: &Self) {
202 let self_len = self.len as usize;
206 let max_len = core::cmp::max(self_len, other.len as usize);
207 for (si, &oi) in self.limbs[..self_len]
208 .iter_mut()
209 .zip(&other.limbs[..self_len])
210 {
211 *si |= oi;
212 }
213 for (si, &oi) in self.limbs[self_len..max_len]
214 .iter_mut()
215 .zip(&other.limbs[self_len..max_len])
216 {
217 *si = oi;
218 }
219 self.len = max_len as u16;
220 }
221}
222
223impl<T: MachineWord, const CAP: usize, P: Personality> BitXorAssign for HeaplessBigInt<T, CAP, P> {
224 fn bitxor_assign(&mut self, other: Self) {
225 self.bitxor_assign(&other);
226 }
227}
228
229impl<T: MachineWord, const CAP: usize, P: Personality> BitXorAssign<&HeaplessBigInt<T, CAP, P>>
230 for HeaplessBigInt<T, CAP, P>
231{
232 fn bitxor_assign(&mut self, other: &Self) {
233 let self_len = self.len as usize;
237 let max_len = core::cmp::max(self_len, other.len as usize);
238 for (si, &oi) in self.limbs[..self_len]
239 .iter_mut()
240 .zip(&other.limbs[..self_len])
241 {
242 *si ^= oi;
243 }
244 for (si, &oi) in self.limbs[self_len..max_len]
245 .iter_mut()
246 .zip(&other.limbs[self_len..max_len])
247 {
248 *si = oi;
249 }
250 self.len = max_len as u16;
251 }
252}