1use super::{FixedUInt, MachineWord};
2
3use crate::patch_num_traits::{OverflowingShl, OverflowingShr};
4
5use num_traits::Zero;
6
7impl<T: MachineWord, const N: usize> core::ops::Not for FixedUInt<T, N> {
8 type Output = Self;
9 fn not(self) -> <Self as core::ops::Not>::Output {
10 let mut ret = Self::zero();
11 for i in 0..N {
12 ret.array[i] = !self.array[i]
13 }
14 ret
15 }
16}
17
18impl<T: MachineWord, const N: usize> core::ops::BitAnd<&FixedUInt<T, N>> for &FixedUInt<T, N> {
19 type Output = FixedUInt<T, N>;
20 fn bitand(self, other: &FixedUInt<T, N>) -> Self::Output {
21 let mut ret = Self::Output::zero();
22 for i in 0..N {
23 ret.array[i] = self.array[i] & other.array[i]
24 }
25 ret
26 }
27}
28
29impl<T: MachineWord, const N: usize> core::ops::BitAnd for FixedUInt<T, N> {
30 type Output = Self;
31 fn bitand(self, other: Self) -> Self::Output {
32 (&self).bitand(&other)
33 }
34}
35
36impl<T: MachineWord, const N: usize> core::ops::BitAnd<&FixedUInt<T, N>> for FixedUInt<T, N> {
37 type Output = Self;
38 fn bitand(self, other: &FixedUInt<T, N>) -> Self::Output {
39 (&self).bitand(other)
40 }
41}
42
43impl<T: MachineWord, const N: usize> core::ops::BitAnd<FixedUInt<T, N>> for &FixedUInt<T, N> {
44 type Output = FixedUInt<T, N>;
45 fn bitand(self, other: FixedUInt<T, N>) -> Self::Output {
46 self.bitand(&other)
47 }
48}
49
50impl<T: MachineWord, const N: usize> core::ops::BitAndAssign for FixedUInt<T, N> {
51 fn bitand_assign(&mut self, other: Self) {
52 for i in 0..N {
53 self.array[i] &= other.array[i]
54 }
55 }
56}
57
58impl<T: MachineWord, const N: usize> core::ops::BitOr<&FixedUInt<T, N>> for &FixedUInt<T, N> {
59 type Output = FixedUInt<T, N>;
60 fn bitor(self, other: &FixedUInt<T, N>) -> Self::Output {
61 let mut ret = Self::Output::zero();
62 for i in 0..N {
63 ret.array[i] = self.array[i] | other.array[i]
64 }
65 ret
66 }
67}
68
69impl<T: MachineWord, const N: usize> core::ops::BitOr for FixedUInt<T, N> {
70 type Output = Self;
71 fn bitor(self, other: Self) -> Self::Output {
72 (&self).bitor(&other)
73 }
74}
75
76impl<T: MachineWord, const N: usize> core::ops::BitOr<&FixedUInt<T, N>> for FixedUInt<T, N> {
77 type Output = Self;
78 fn bitor(self, other: &FixedUInt<T, N>) -> Self::Output {
79 (&self).bitor(other)
80 }
81}
82
83impl<T: MachineWord, const N: usize> core::ops::BitOr<FixedUInt<T, N>> for &FixedUInt<T, N> {
84 type Output = FixedUInt<T, N>;
85 fn bitor(self, other: FixedUInt<T, N>) -> Self::Output {
86 self.bitor(&other)
87 }
88}
89
90impl<T: MachineWord, const N: usize> core::ops::BitOrAssign for FixedUInt<T, N> {
91 fn bitor_assign(&mut self, other: Self) {
92 for i in 0..N {
93 self.array[i] |= other.array[i]
94 }
95 }
96}
97
98impl<T: MachineWord, const N: usize> core::ops::BitXor<&FixedUInt<T, N>> for &FixedUInt<T, N> {
99 type Output = FixedUInt<T, N>;
100 fn bitxor(self, other: &FixedUInt<T, N>) -> Self::Output {
101 let mut ret = Self::Output::zero();
102 for i in 0..N {
103 ret.array[i] = self.array[i] ^ other.array[i]
104 }
105 ret
106 }
107}
108
109impl<T: MachineWord, const N: usize> core::ops::BitXor for FixedUInt<T, N> {
110 type Output = Self;
111 fn bitxor(self, other: Self) -> Self::Output {
112 (&self).bitxor(&other)
113 }
114}
115
116impl<T: MachineWord, const N: usize> core::ops::BitXor<&FixedUInt<T, N>> for FixedUInt<T, N> {
117 type Output = Self;
118 fn bitxor(self, other: &FixedUInt<T, N>) -> Self::Output {
119 (&self).bitxor(other)
120 }
121}
122
123impl<T: MachineWord, const N: usize> core::ops::BitXor<FixedUInt<T, N>> for &FixedUInt<T, N> {
124 type Output = FixedUInt<T, N>;
125 fn bitxor(self, other: FixedUInt<T, N>) -> Self::Output {
126 self.bitxor(&other)
127 }
128}
129
130impl<T: MachineWord, const N: usize> core::ops::BitXorAssign for FixedUInt<T, N> {
131 fn bitxor_assign(&mut self, other: Self) {
132 for i in 0..N {
133 self.array[i] ^= other.array[i]
134 }
135 }
136}
137
138impl<T: MachineWord, const N: usize> OverflowingShl for FixedUInt<T, N> {
139 fn overflowing_shl(self, bits: u32) -> (Self, bool) {
140 let bitsu = bits as usize;
141 let (shift, overflow) = if bitsu >= Self::BIT_SIZE {
142 (bitsu & (Self::BIT_SIZE - 1), true)
143 } else {
144 (bitsu, false)
145 };
146 let res = core::ops::Shl::<usize>::shl(self, shift);
147 (res, overflow)
148 }
149}
150
151impl<T: MachineWord, const N: usize> core::ops::Shl<u32> for FixedUInt<T, N> {
152 type Output = Self;
153 fn shl(self, bits: u32) -> <Self as core::ops::Shl<u32>>::Output {
154 core::ops::Shl::<usize>::shl(self, bits as usize)
155 }
156}
157
158impl<T: MachineWord, const N: usize> core::ops::Shl<usize> for FixedUInt<T, N> {
159 type Output = Self;
160 fn shl(self, bits: usize) -> <Self as core::ops::Shl<usize>>::Output {
161 let mut result = self;
163 Self::shl_impl(&mut result, bits);
164 result
165 }
166}
167
168impl<T: MachineWord, const N: usize> core::ops::Shl<&'_ usize> for FixedUInt<T, N> {
169 type Output = Self;
170 fn shl(self, bits: &usize) -> <Self as core::ops::Shl<usize>>::Output {
171 let mut result = self;
172 Self::shl_impl(&mut result, *bits);
173 result
174 }
175}
176
177impl<T: MachineWord, const N: usize> num_traits::WrappingShl for FixedUInt<T, N> {
178 fn wrapping_shl(&self, bits: u32) -> Self {
179 self.overflowing_shl(bits).0
180 }
181}
182
183impl<T: MachineWord, const N: usize> num_traits::CheckedShl for FixedUInt<T, N> {
184 fn checked_shl(&self, bits: u32) -> Option<Self> {
185 let res = self.overflowing_shl(bits);
186 if res.1 {
187 None
188 } else {
189 Some(res.0)
190 }
191 }
192}
193
194impl<T: MachineWord, const N: usize> core::ops::ShlAssign<usize> for FixedUInt<T, N> {
197 fn shl_assign(&mut self, bits: usize) {
198 Self::shl_impl(self, bits);
199 }
200}
201
202impl<T: MachineWord, const N: usize> core::ops::ShlAssign<&'_ usize> for FixedUInt<T, N> {
203 fn shl_assign(&mut self, bits: &usize) {
204 Self::shl_impl(self, *bits);
205 }
206}
207
208impl<T: MachineWord, const N: usize> OverflowingShr for FixedUInt<T, N> {
209 fn overflowing_shr(self, bits: u32) -> (Self, bool) {
210 let bitsu = bits as usize;
211 let (shift, overflow) = if bitsu >= Self::BIT_SIZE {
212 (bitsu & (Self::BIT_SIZE - 1), true)
213 } else {
214 (bitsu, false)
215 };
216 let res = core::ops::Shr::<usize>::shr(self, shift);
217 (res, overflow)
218 }
219}
220
221impl<T: MachineWord, const N: usize> core::ops::Shr<u32> for FixedUInt<T, N> {
222 type Output = Self;
223 fn shr(self, bits: u32) -> <Self as core::ops::Shr<u32>>::Output {
224 core::ops::Shr::<usize>::shr(self, bits as usize)
225 }
226}
227
228impl<T: MachineWord, const N: usize> core::ops::Shr<usize> for FixedUInt<T, N> {
229 type Output = Self;
230 fn shr(self, bits: usize) -> <Self as core::ops::Shr<usize>>::Output {
231 let mut result = self;
233 Self::shr_impl(&mut result, bits);
234 result
235 }
236}
237
238impl<T: MachineWord, const N: usize> core::ops::Shr<&'_ usize> for FixedUInt<T, N> {
239 type Output = Self;
240 fn shr(self, bits: &usize) -> <Self as core::ops::Shr<usize>>::Output {
241 let mut result = self;
242 Self::shr_impl(&mut result, *bits);
243 result
244 }
245}
246
247impl<T: MachineWord, const N: usize> num_traits::WrappingShr for FixedUInt<T, N> {
248 fn wrapping_shr(&self, bits: u32) -> Self {
249 self.overflowing_shr(bits).0
250 }
251}
252
253impl<T: MachineWord, const N: usize> num_traits::CheckedShr for FixedUInt<T, N> {
254 fn checked_shr(&self, bits: u32) -> Option<Self> {
255 let res = self.overflowing_shr(bits);
256 if res.1 {
257 None
258 } else {
259 Some(res.0)
260 }
261 }
262}
263
264impl<T: MachineWord, const N: usize> core::ops::ShrAssign<usize> for FixedUInt<T, N> {
267 fn shr_assign(&mut self, bits: usize) {
268 Self::shr_impl(self, bits);
269 }
270}
271
272impl<T: MachineWord, const N: usize> core::ops::ShrAssign<&'_ usize> for FixedUInt<T, N> {
273 fn shr_assign(&mut self, bits: &usize) {
274 Self::shr_impl(self, *bits);
275 }
276}
277
278impl<T: MachineWord, const N: usize> core::ops::Shl<&usize> for &FixedUInt<T, N> {
279 type Output = FixedUInt<T, N>;
280 fn shl(self, bits: &usize) -> Self::Output {
281 let mut result = *self;
282 Self::Output::shl_impl(&mut result, *bits);
283 result
284 }
285}
286
287impl<T: MachineWord, const N: usize> core::ops::Shl<&u32> for &FixedUInt<T, N> {
288 type Output = FixedUInt<T, N>;
289 fn shl(self, bits: &u32) -> Self::Output {
290 self.shl(&(*bits as usize))
291 }
292}
293
294impl<T: MachineWord, const N: usize> core::ops::Shr<&usize> for &FixedUInt<T, N> {
295 type Output = FixedUInt<T, N>;
296 fn shr(self, bits: &usize) -> Self::Output {
297 let mut result = *self;
298 Self::Output::shr_impl(&mut result, *bits);
299 result
300 }
301}
302
303impl<T: MachineWord, const N: usize> core::ops::Shr<&u32> for &FixedUInt<T, N> {
304 type Output = FixedUInt<T, N>;
305 fn shr(self, bits: &u32) -> Self::Output {
306 self.shr(&(*bits as usize))
307 }
308}
309
310impl<T: MachineWord, const N: usize> core::ops::Shl<usize> for &FixedUInt<T, N> {
312 type Output = FixedUInt<T, N>;
313 fn shl(self, bits: usize) -> Self::Output {
314 self.shl(&bits)
315 }
316}
317
318impl<T: MachineWord, const N: usize> core::ops::Shl<u32> for &FixedUInt<T, N> {
319 type Output = FixedUInt<T, N>;
320 fn shl(self, bits: u32) -> Self::Output {
321 self.shl(&(bits as usize))
322 }
323}
324
325impl<T: MachineWord, const N: usize> core::ops::Shl<&u32> for FixedUInt<T, N> {
326 type Output = Self;
327 fn shl(self, bits: &u32) -> Self::Output {
328 self.shl(*bits)
329 }
330}
331
332impl<T: MachineWord, const N: usize> core::ops::Shr<usize> for &FixedUInt<T, N> {
334 type Output = FixedUInt<T, N>;
335 fn shr(self, bits: usize) -> Self::Output {
336 self.shr(&bits)
337 }
338}
339
340impl<T: MachineWord, const N: usize> core::ops::Shr<u32> for &FixedUInt<T, N> {
341 type Output = FixedUInt<T, N>;
342 fn shr(self, bits: u32) -> Self::Output {
343 self.shr(&(bits as usize))
344 }
345}
346
347impl<T: MachineWord, const N: usize> core::ops::Shr<&u32> for FixedUInt<T, N> {
348 type Output = Self;
349 fn shr(self, bits: &u32) -> Self::Output {
350 self.shr(*bits)
351 }
352}
353
354#[cfg(test)]
355mod tests {
356 use super::*;
357
358 #[test]
359 fn test_bitand_combinations() {
360 let a = FixedUInt::<u8, 2>::from(12u8); let b = FixedUInt::<u8, 2>::from(10u8); let expected = FixedUInt::<u8, 2>::from(8u8); assert_eq!(a & b, expected);
366 assert_eq!(a & &b, expected);
368 assert_eq!(&a & b, expected);
370 assert_eq!(&a & &b, expected);
372 }
373
374 #[test]
375 fn test_bitor_combinations() {
376 let a = FixedUInt::<u8, 2>::from(12u8); let b = FixedUInt::<u8, 2>::from(10u8); let expected = FixedUInt::<u8, 2>::from(14u8); assert_eq!(a | b, expected);
382 assert_eq!(a | &b, expected);
384 assert_eq!(&a | b, expected);
386 assert_eq!(&a | &b, expected);
388 }
389
390 #[test]
391 fn test_bitxor_combinations() {
392 let a = FixedUInt::<u8, 2>::from(12u8); let b = FixedUInt::<u8, 2>::from(10u8); let expected = FixedUInt::<u8, 2>::from(6u8); assert_eq!(a ^ b, expected);
398 assert_eq!(a ^ &b, expected);
400 assert_eq!(&a ^ b, expected);
402 assert_eq!(&a ^ &b, expected);
404 }
405
406 #[test]
407 fn test_shl_combinations() {
408 let a = FixedUInt::<u8, 2>::from(2u8); let shift: usize = 2;
410 let expected = FixedUInt::<u8, 2>::from(8u8); assert_eq!(a << shift, expected);
414 assert_eq!(a << &shift, expected);
416 assert_eq!(&a << shift, expected);
418 assert_eq!(&a << &shift, expected);
420
421 let shift32: u32 = 2;
423 assert_eq!(a << shift32, expected);
424 assert_eq!(a << &shift32, expected);
425 assert_eq!(&a << shift32, expected);
426 assert_eq!(&a << &shift32, expected);
427 }
428
429 #[test]
430 fn test_shr_combinations() {
431 let a = FixedUInt::<u8, 2>::from(8u8); let shift: usize = 2;
433 let expected = FixedUInt::<u8, 2>::from(2u8); assert_eq!(a >> shift, expected);
437 assert_eq!(a >> &shift, expected);
439 assert_eq!(&a >> shift, expected);
441 assert_eq!(&a >> &shift, expected);
443
444 let shift32: u32 = 2;
446 assert_eq!(a >> shift32, expected);
447 assert_eq!(a >> &shift32, expected);
448 assert_eq!(&a >> shift32, expected);
449 assert_eq!(&a >> &shift32, expected);
450 }
451}