1use super::{const_shl_impl, const_shr_impl, FixedUInt, MachineWord};
2
3use crate::const_numtraits::{
4 ConstCheckedShl, ConstCheckedShr, ConstOverflowingShl, ConstOverflowingShr,
5 ConstUnboundedShift, ConstWrappingShl, ConstWrappingShr, ConstZero,
6};
7use crate::machineword::ConstMachineWord;
8use crate::patch_num_traits::{OverflowingShl, OverflowingShr};
9
10c0nst::c0nst! {
11 impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> c0nst core::ops::Not for FixedUInt<T, N> {
12 type Output = Self;
13 fn not(self) -> Self::Output {
14 let mut ret = <Self as ConstZero>::zero();
15 let mut i = 0;
16 while i < N {
17 ret.array[i] = !self.array[i];
18 i += 1;
19 }
20 ret
21 }
22 }
23
24 impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> c0nst core::ops::BitAnd<&FixedUInt<T, N>> for &FixedUInt<T, N> {
25 type Output = FixedUInt<T, N>;
26 fn bitand(self, other: &FixedUInt<T, N>) -> Self::Output {
27 let mut ret = <FixedUInt<T, N> as ConstZero>::zero();
28 let mut i = 0;
29 while i < N {
30 ret.array[i] = self.array[i] & other.array[i];
31 i += 1;
32 }
33 ret
34 }
35 }
36
37 impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> c0nst core::ops::BitAnd for FixedUInt<T, N> {
38 type Output = Self;
39 fn bitand(self, other: Self) -> Self::Output {
40 (&self).bitand(&other)
41 }
42 }
43
44 impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> c0nst core::ops::BitAnd<&FixedUInt<T, N>> for FixedUInt<T, N> {
45 type Output = Self;
46 fn bitand(self, other: &FixedUInt<T, N>) -> Self::Output {
47 (&self).bitand(other)
48 }
49 }
50
51 impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> c0nst core::ops::BitAnd<FixedUInt<T, N>> for &FixedUInt<T, N> {
52 type Output = FixedUInt<T, N>;
53 fn bitand(self, other: FixedUInt<T, N>) -> Self::Output {
54 self.bitand(&other)
55 }
56 }
57
58 impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> c0nst core::ops::BitAndAssign for FixedUInt<T, N> {
59 fn bitand_assign(&mut self, other: Self) {
60 let mut i = 0;
61 while i < N {
62 self.array[i] &= other.array[i];
63 i += 1;
64 }
65 }
66 }
67
68 impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> c0nst core::ops::BitOr<&FixedUInt<T, N>> for &FixedUInt<T, N> {
69 type Output = FixedUInt<T, N>;
70 fn bitor(self, other: &FixedUInt<T, N>) -> Self::Output {
71 let mut ret = <FixedUInt<T, N> as ConstZero>::zero();
72 let mut i = 0;
73 while i < N {
74 ret.array[i] = self.array[i] | other.array[i];
75 i += 1;
76 }
77 ret
78 }
79 }
80
81 impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> c0nst core::ops::BitOr for FixedUInt<T, N> {
82 type Output = Self;
83 fn bitor(self, other: Self) -> Self::Output {
84 (&self).bitor(&other)
85 }
86 }
87
88 impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> c0nst core::ops::BitOr<&FixedUInt<T, N>> for FixedUInt<T, N> {
89 type Output = Self;
90 fn bitor(self, other: &FixedUInt<T, N>) -> Self::Output {
91 (&self).bitor(other)
92 }
93 }
94
95 impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> c0nst core::ops::BitOr<FixedUInt<T, N>> for &FixedUInt<T, N> {
96 type Output = FixedUInt<T, N>;
97 fn bitor(self, other: FixedUInt<T, N>) -> Self::Output {
98 self.bitor(&other)
99 }
100 }
101
102 impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> c0nst core::ops::BitOrAssign for FixedUInt<T, N> {
103 fn bitor_assign(&mut self, other: Self) {
104 let mut i = 0;
105 while i < N {
106 self.array[i] |= other.array[i];
107 i += 1;
108 }
109 }
110 }
111
112 impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> c0nst core::ops::BitXor<&FixedUInt<T, N>> for &FixedUInt<T, N> {
113 type Output = FixedUInt<T, N>;
114 fn bitxor(self, other: &FixedUInt<T, N>) -> Self::Output {
115 let mut ret = <FixedUInt<T, N> as ConstZero>::zero();
116 let mut i = 0;
117 while i < N {
118 ret.array[i] = self.array[i] ^ other.array[i];
119 i += 1;
120 }
121 ret
122 }
123 }
124
125 impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> c0nst core::ops::BitXor for FixedUInt<T, N> {
126 type Output = Self;
127 fn bitxor(self, other: Self) -> Self::Output {
128 (&self).bitxor(&other)
129 }
130 }
131
132 impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> c0nst core::ops::BitXor<&FixedUInt<T, N>> for FixedUInt<T, N> {
133 type Output = Self;
134 fn bitxor(self, other: &FixedUInt<T, N>) -> Self::Output {
135 (&self).bitxor(other)
136 }
137 }
138
139 impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> c0nst core::ops::BitXor<FixedUInt<T, N>> for &FixedUInt<T, N> {
140 type Output = FixedUInt<T, N>;
141 fn bitxor(self, other: FixedUInt<T, N>) -> Self::Output {
142 self.bitxor(&other)
143 }
144 }
145
146 impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> c0nst core::ops::BitXorAssign for FixedUInt<T, N> {
147 fn bitxor_assign(&mut self, other: Self) {
148 let mut i = 0;
149 while i < N {
150 self.array[i] ^= other.array[i];
151 i += 1;
152 }
153 }
154 }
155
156 impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> c0nst core::ops::Shl<usize> for FixedUInt<T, N> {
158 type Output = Self;
159 fn shl(self, bits: usize) -> Self::Output {
160 let mut result = self;
161 const_shl_impl(&mut result, bits);
162 result
163 }
164 }
165
166 impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> c0nst core::ops::Shr<usize> for FixedUInt<T, N> {
167 type Output = Self;
168 fn shr(self, bits: usize) -> Self::Output {
169 let mut result = self;
170 const_shr_impl(&mut result, bits);
171 result
172 }
173 }
174
175 impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> c0nst core::ops::Shl<u32> for FixedUInt<T, N> {
176 type Output = Self;
177 fn shl(self, bits: u32) -> Self::Output {
178 self.shl(bits as usize)
179 }
180 }
181
182 impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> c0nst core::ops::Shr<u32> for FixedUInt<T, N> {
183 type Output = Self;
184 fn shr(self, bits: u32) -> Self::Output {
185 self.shr(bits as usize)
186 }
187 }
188
189 impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> c0nst core::ops::Shl<&usize> for FixedUInt<T, N> {
190 type Output = Self;
191 fn shl(self, bits: &usize) -> Self::Output {
192 self.shl(*bits)
193 }
194 }
195
196 impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> c0nst core::ops::Shr<&usize> for FixedUInt<T, N> {
197 type Output = Self;
198 fn shr(self, bits: &usize) -> Self::Output {
199 self.shr(*bits)
200 }
201 }
202
203 impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> c0nst core::ops::Shl<&u32> for FixedUInt<T, N> {
204 type Output = Self;
205 fn shl(self, bits: &u32) -> Self::Output {
206 self.shl(*bits as usize)
207 }
208 }
209
210 impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> c0nst core::ops::Shr<&u32> for FixedUInt<T, N> {
211 type Output = Self;
212 fn shr(self, bits: &u32) -> Self::Output {
213 self.shr(*bits as usize)
214 }
215 }
216
217 impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> c0nst core::ops::Shl<usize> for &FixedUInt<T, N> {
219 type Output = FixedUInt<T, N>;
220 fn shl(self, bits: usize) -> Self::Output {
221 (*self).shl(bits)
222 }
223 }
224
225 impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> c0nst core::ops::Shr<usize> for &FixedUInt<T, N> {
226 type Output = FixedUInt<T, N>;
227 fn shr(self, bits: usize) -> Self::Output {
228 (*self).shr(bits)
229 }
230 }
231
232 impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> c0nst core::ops::Shl<u32> for &FixedUInt<T, N> {
233 type Output = FixedUInt<T, N>;
234 fn shl(self, bits: u32) -> Self::Output {
235 (*self).shl(bits as usize)
236 }
237 }
238
239 impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> c0nst core::ops::Shr<u32> for &FixedUInt<T, N> {
240 type Output = FixedUInt<T, N>;
241 fn shr(self, bits: u32) -> Self::Output {
242 (*self).shr(bits as usize)
243 }
244 }
245
246 impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> c0nst core::ops::Shl<&usize> for &FixedUInt<T, N> {
247 type Output = FixedUInt<T, N>;
248 fn shl(self, bits: &usize) -> Self::Output {
249 (*self).shl(*bits)
250 }
251 }
252
253 impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> c0nst core::ops::Shr<&usize> for &FixedUInt<T, N> {
254 type Output = FixedUInt<T, N>;
255 fn shr(self, bits: &usize) -> Self::Output {
256 (*self).shr(*bits)
257 }
258 }
259
260 impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> c0nst core::ops::Shl<&u32> for &FixedUInt<T, N> {
261 type Output = FixedUInt<T, N>;
262 fn shl(self, bits: &u32) -> Self::Output {
263 (*self).shl(*bits as usize)
264 }
265 }
266
267 impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> c0nst core::ops::Shr<&u32> for &FixedUInt<T, N> {
268 type Output = FixedUInt<T, N>;
269 fn shr(self, bits: &u32) -> Self::Output {
270 (*self).shr(*bits as usize)
271 }
272 }
273
274 impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> c0nst core::ops::ShlAssign<usize> for FixedUInt<T, N> {
276 fn shl_assign(&mut self, bits: usize) {
277 const_shl_impl(self, bits);
278 }
279 }
280
281 impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> c0nst core::ops::ShrAssign<usize> for FixedUInt<T, N> {
282 fn shr_assign(&mut self, bits: usize) {
283 const_shr_impl(self, bits);
284 }
285 }
286
287 impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> c0nst core::ops::ShlAssign<&usize> for FixedUInt<T, N> {
288 fn shl_assign(&mut self, bits: &usize) {
289 const_shl_impl(self, *bits);
290 }
291 }
292
293 impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> c0nst core::ops::ShrAssign<&usize> for FixedUInt<T, N> {
294 fn shr_assign(&mut self, bits: &usize) {
295 const_shr_impl(self, *bits);
296 }
297 }
298
299 c0nst fn normalize_shift_amount(bits: u32, bit_size: usize) -> (usize, bool) {
302 let bit_size_u32 = bit_size as u32;
303 if bit_size == 0 {
304 (0, true)
306 } else if bit_size_u32 == 0 {
307 (bits as usize, false)
310 } else if bits >= bit_size_u32 {
311 ((bits % bit_size_u32) as usize, true)
313 } else {
314 (bits as usize, false)
315 }
316 }
317
318 impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> c0nst ConstOverflowingShl for FixedUInt<T, N> {
319 fn overflowing_shl(&self, bits: u32) -> (Self, bool) {
320 let (shift, overflow) = normalize_shift_amount(bits, Self::BIT_SIZE);
321 let res = core::ops::Shl::<usize>::shl(*self, shift);
322 (res, overflow)
323 }
324 }
325
326 impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> c0nst ConstOverflowingShr for FixedUInt<T, N> {
327 fn overflowing_shr(&self, bits: u32) -> (Self, bool) {
328 let (shift, overflow) = normalize_shift_amount(bits, Self::BIT_SIZE);
329 let res = core::ops::Shr::<usize>::shr(*self, shift);
330 (res, overflow)
331 }
332 }
333
334 impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> c0nst ConstWrappingShl for FixedUInt<T, N> {
335 fn wrapping_shl(&self, bits: u32) -> Self {
336 ConstOverflowingShl::overflowing_shl(self, bits).0
337 }
338 }
339
340 impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> c0nst ConstWrappingShr for FixedUInt<T, N> {
341 fn wrapping_shr(&self, bits: u32) -> Self {
342 ConstOverflowingShr::overflowing_shr(self, bits).0
343 }
344 }
345
346 impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> c0nst ConstCheckedShl for FixedUInt<T, N> {
347 fn checked_shl(&self, bits: u32) -> Option<Self> {
348 let (res, overflow) = ConstOverflowingShl::overflowing_shl(self, bits);
349 if overflow { None } else { Some(res) }
350 }
351 }
352
353 impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> c0nst ConstCheckedShr for FixedUInt<T, N> {
354 fn checked_shr(&self, bits: u32) -> Option<Self> {
355 let (res, overflow) = ConstOverflowingShr::overflowing_shr(self, bits);
356 if overflow { None } else { Some(res) }
357 }
358 }
359
360 impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> c0nst ConstUnboundedShift for FixedUInt<T, N> {
361 fn unbounded_shl(self, rhs: u32) -> Self {
362 let (shift, overflow) = normalize_shift_amount(rhs, Self::BIT_SIZE);
363 if overflow {
364 Self::zero()
365 } else {
366 self << shift
367 }
368 }
369
370 fn unbounded_shr(self, rhs: u32) -> Self {
371 let (shift, overflow) = normalize_shift_amount(rhs, Self::BIT_SIZE);
372 if overflow {
373 Self::zero()
374 } else {
375 self >> shift
376 }
377 }
378 }
379}
380
381impl<T: MachineWord, const N: usize> OverflowingShl for FixedUInt<T, N> {
383 fn overflowing_shl(self, bits: u32) -> (Self, bool) {
384 ConstOverflowingShl::overflowing_shl(&self, bits)
385 }
386}
387
388impl<T: MachineWord, const N: usize> OverflowingShr for FixedUInt<T, N> {
389 fn overflowing_shr(self, bits: u32) -> (Self, bool) {
390 ConstOverflowingShr::overflowing_shr(&self, bits)
391 }
392}
393
394impl<T: MachineWord, const N: usize> num_traits::WrappingShl for FixedUInt<T, N> {
396 fn wrapping_shl(&self, bits: u32) -> Self {
397 ConstWrappingShl::wrapping_shl(self, bits)
398 }
399}
400
401impl<T: MachineWord, const N: usize> num_traits::WrappingShr for FixedUInt<T, N> {
402 fn wrapping_shr(&self, bits: u32) -> Self {
403 ConstWrappingShr::wrapping_shr(self, bits)
404 }
405}
406
407impl<T: MachineWord, const N: usize> num_traits::CheckedShl for FixedUInt<T, N> {
408 fn checked_shl(&self, bits: u32) -> Option<Self> {
409 ConstCheckedShl::checked_shl(self, bits)
410 }
411}
412
413impl<T: MachineWord, const N: usize> num_traits::CheckedShr for FixedUInt<T, N> {
414 fn checked_shr(&self, bits: u32) -> Option<Self> {
415 ConstCheckedShr::checked_shr(self, bits)
416 }
417}
418
419#[cfg(test)]
420mod tests {
421 use super::*;
422
423 #[test]
424 fn test_bitand_combinations() {
425 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);
431 assert_eq!(a & &b, expected);
433 assert_eq!(&a & b, expected);
435 assert_eq!(&a & &b, expected);
437 }
438
439 #[test]
440 fn test_bitor_combinations() {
441 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);
447 assert_eq!(a | &b, expected);
449 assert_eq!(&a | b, expected);
451 assert_eq!(&a | &b, expected);
453 }
454
455 #[test]
456 fn test_bitxor_combinations() {
457 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);
463 assert_eq!(a ^ &b, expected);
465 assert_eq!(&a ^ b, expected);
467 assert_eq!(&a ^ &b, expected);
469 }
470
471 #[test]
472 fn test_shl_combinations() {
473 let a = FixedUInt::<u8, 2>::from(2u8); let shift: usize = 2;
475 let expected = FixedUInt::<u8, 2>::from(8u8); assert_eq!(a << shift, expected);
479 assert_eq!(a << &shift, expected);
481 assert_eq!(&a << shift, expected);
483 assert_eq!(&a << &shift, expected);
485
486 let shift32: u32 = 2;
488 assert_eq!(a << shift32, expected);
489 assert_eq!(a << &shift32, expected);
490 assert_eq!(&a << shift32, expected);
491 assert_eq!(&a << &shift32, expected);
492 }
493
494 #[test]
495 fn test_shr_combinations() {
496 let a = FixedUInt::<u8, 2>::from(8u8); let shift: usize = 2;
498 let expected = FixedUInt::<u8, 2>::from(2u8); assert_eq!(a >> shift, expected);
502 assert_eq!(a >> &shift, expected);
504 assert_eq!(&a >> shift, expected);
506 assert_eq!(&a >> &shift, expected);
508
509 let shift32: u32 = 2;
511 assert_eq!(a >> shift32, expected);
512 assert_eq!(a >> &shift32, expected);
513 assert_eq!(&a >> shift32, expected);
514 assert_eq!(&a >> &shift32, expected);
515 }
516
517 #[test]
518 fn test_const_bitops() {
519 type TestInt = FixedUInt<u8, 2>;
520
521 let a = TestInt::from(0b11001100u8);
522 let b = TestInt::from(0b10101010u8);
523
524 let not_a = !a;
526 assert_eq!(not_a.array[0], 0b00110011);
527 assert_eq!(not_a.array[1], 0xFF);
528
529 assert_eq!(a & b, TestInt::from(0b10001000u8));
531
532 assert_eq!(a | b, TestInt::from(0b11101110u8));
534
535 assert_eq!(a ^ b, TestInt::from(0b01100110u8));
537
538 assert_eq!(TestInt::from(1u8) << 4usize, TestInt::from(16u8));
540
541 assert_eq!(TestInt::from(16u8) >> 2usize, TestInt::from(4u8));
543
544 #[cfg(feature = "nightly")]
545 {
546 const A: TestInt = FixedUInt {
547 array: [0b11001100, 0],
548 };
549 const B: TestInt = FixedUInt {
550 array: [0b10101010, 0],
551 };
552
553 const NOT_A: TestInt = !A;
554 const AND_AB: TestInt = A & B;
555 const OR_AB: TestInt = A | B;
556 const XOR_AB: TestInt = A ^ B;
557 const SHL_1: TestInt = FixedUInt { array: [1u8, 0] } << 4usize;
558 const SHR_16: TestInt = FixedUInt { array: [16u8, 0] } >> 2usize;
559
560 assert_eq!(NOT_A.array[0], 0b00110011);
561 assert_eq!(AND_AB.array[0], 0b10001000);
562 assert_eq!(OR_AB.array[0], 0b11101110);
563 assert_eq!(XOR_AB.array[0], 0b01100110);
564 assert_eq!(SHL_1.array[0], 16);
565 assert_eq!(SHR_16.array[0], 4);
566 }
567 }
568
569 #[test]
570 fn test_const_shift_traits() {
571 type TestInt = FixedUInt<u8, 2>; let a = TestInt::from(0x80u8); let (res, overflow) = ConstOverflowingShl::overflowing_shl(&a, 8);
576 assert_eq!(res.array, [0, 0x80]); assert!(!overflow);
578
579 let (res, overflow) = ConstOverflowingShl::overflowing_shl(&a, 16);
580 assert_eq!(res.array, [0x80, 0]); assert!(overflow);
582
583 let (res, overflow) = ConstOverflowingShl::overflowing_shl(&a, 9);
584 assert_eq!(res.array, [0, 0]); assert!(!overflow); let b = TestInt::from(0x0100u16); let (res, overflow) = ConstOverflowingShr::overflowing_shr(&b, 8);
590 assert_eq!(res.array, [1, 0]); assert!(!overflow);
592
593 let (res, overflow) = ConstOverflowingShr::overflowing_shr(&b, 16);
594 assert_eq!(res.array, [0, 1]); assert!(overflow);
596
597 let c = TestInt::from(1u8);
599 assert_eq!(ConstWrappingShl::wrapping_shl(&c, 4).array, [16, 0]);
600 assert_eq!(ConstWrappingShl::wrapping_shl(&c, 16).array, [1, 0]); assert_eq!(ConstWrappingShl::wrapping_shl(&c, 17).array, [2, 0]); let d = TestInt::from(0x8000u16);
605 assert_eq!(ConstWrappingShr::wrapping_shr(&d, 4).array, [0, 0x08]);
606 assert_eq!(ConstWrappingShr::wrapping_shr(&d, 16).array, [0, 0x80]); assert_eq!(ConstWrappingShr::wrapping_shr(&d, 17).array, [0, 0x40]); let e = TestInt::from(1u8);
611 assert_eq!(
612 ConstCheckedShl::checked_shl(&e, 4),
613 Some(TestInt::from(16u8))
614 );
615 assert_eq!(
616 ConstCheckedShl::checked_shl(&e, 15),
617 Some(TestInt::from(0x8000u16))
618 );
619 assert_eq!(ConstCheckedShl::checked_shl(&e, 16), None); let f = TestInt::from(0x8000u16);
623 assert_eq!(
624 ConstCheckedShr::checked_shr(&f, 15),
625 Some(TestInt::from(1u8))
626 );
627 assert_eq!(ConstCheckedShr::checked_shr(&f, 16), None); let g = TestInt::from(42u8);
631 assert_eq!(ConstOverflowingShl::overflowing_shl(&g, 0), (g, false));
632 assert_eq!(ConstOverflowingShr::overflowing_shr(&g, 0), (g, false));
633 assert_eq!(ConstWrappingShl::wrapping_shl(&g, 0), g);
634 assert_eq!(ConstWrappingShr::wrapping_shr(&g, 0), g);
635 assert_eq!(ConstCheckedShl::checked_shl(&g, 0), Some(g));
636 assert_eq!(ConstCheckedShr::checked_shr(&g, 0), Some(g));
637 }
638
639 #[test]
640 fn test_const_shift_traits_n0() {
641 type ZeroInt = FixedUInt<u8, 0>;
643 let z = ZeroInt { array: [] };
644
645 assert_eq!(ConstOverflowingShl::overflowing_shl(&z, 0), (z, true));
647 assert_eq!(ConstOverflowingShr::overflowing_shr(&z, 0), (z, true));
648 assert_eq!(ConstWrappingShl::wrapping_shl(&z, 0), z);
649 assert_eq!(ConstWrappingShr::wrapping_shr(&z, 0), z);
650 assert_eq!(ConstCheckedShl::checked_shl(&z, 0), None);
651 assert_eq!(ConstCheckedShr::checked_shr(&z, 0), None);
652 }
653
654 #[test]
655 fn test_num_traits_shift_wrappers() {
656 use num_traits::{CheckedShl, CheckedShr, WrappingShl, WrappingShr};
657
658 type TestInt = FixedUInt<u8, 2>;
659
660 let a = TestInt::from(1u8);
661
662 assert_eq!(WrappingShl::wrapping_shl(&a, 4), TestInt::from(16u8));
664 assert_eq!(WrappingShl::wrapping_shl(&a, 16), a); let b = TestInt::from(16u8);
668 assert_eq!(WrappingShr::wrapping_shr(&b, 4), TestInt::from(1u8));
669
670 assert_eq!(CheckedShl::checked_shl(&a, 4), Some(TestInt::from(16u8)));
672 assert_eq!(CheckedShl::checked_shl(&a, 16), None);
673
674 assert_eq!(CheckedShr::checked_shr(&b, 4), Some(TestInt::from(1u8)));
676 assert_eq!(CheckedShr::checked_shr(&b, 16), None);
677 }
678
679 #[test]
680 fn test_unbounded_shift() {
681 type U16 = FixedUInt<u8, 2>;
682
683 let one = U16::from(1u8);
684
685 assert_eq!(ConstUnboundedShift::unbounded_shl(one, 0), one);
687 assert_eq!(ConstUnboundedShift::unbounded_shl(one, 4), U16::from(16u8));
688 assert_eq!(
689 ConstUnboundedShift::unbounded_shl(one, 15),
690 U16::from(0x8000u16)
691 );
692
693 assert_eq!(
694 ConstUnboundedShift::unbounded_shr(U16::from(0x8000u16), 15),
695 one
696 );
697 assert_eq!(ConstUnboundedShift::unbounded_shr(U16::from(16u8), 4), one);
698
699 assert_eq!(ConstUnboundedShift::unbounded_shl(one, 16), U16::from(0u8));
701 assert_eq!(
702 ConstUnboundedShift::unbounded_shr(U16::from(0xFFFFu16), 16),
703 U16::from(0u8)
704 );
705
706 assert_eq!(
708 ConstUnboundedShift::unbounded_shl(U16::from(0xFFFFu16), 17),
709 U16::from(0u8)
710 );
711 assert_eq!(
712 ConstUnboundedShift::unbounded_shl(U16::from(0xFFFFu16), 100),
713 U16::from(0u8)
714 );
715 assert_eq!(
716 ConstUnboundedShift::unbounded_shr(U16::from(0xFFFFu16), 17),
717 U16::from(0u8)
718 );
719 assert_eq!(
720 ConstUnboundedShift::unbounded_shr(U16::from(0xFFFFu16), 100),
721 U16::from(0u8)
722 );
723
724 type U32 = FixedUInt<u8, 4>;
726 let one32 = U32::from(1u8);
727 assert_eq!(
728 ConstUnboundedShift::unbounded_shl(one32, 31),
729 U32::from(0x80000000u32)
730 );
731 assert_eq!(
732 ConstUnboundedShift::unbounded_shl(one32, 32),
733 U32::from(0u8)
734 );
735 assert_eq!(
736 ConstUnboundedShift::unbounded_shr(U32::from(0x80000000u32), 31),
737 one32
738 );
739 assert_eq!(
740 ConstUnboundedShift::unbounded_shr(U32::from(0x80000000u32), 32),
741 U32::from(0u8)
742 );
743 }
744
745 #[test]
746 fn test_unbounded_shift_polymorphic() {
747 fn test_unbounded<T>(val: T, shift: u32, expected_shl: T, expected_shr: T)
748 where
749 T: ConstUnboundedShift + Eq + core::fmt::Debug + Copy,
750 {
751 assert_eq!(ConstUnboundedShift::unbounded_shl(val, shift), expected_shl);
752 assert_eq!(ConstUnboundedShift::unbounded_shr(val, shift), expected_shr);
753 }
754
755 type U8x2 = FixedUInt<u8, 2>;
757 type U8x4 = FixedUInt<u8, 4>;
758 type U16x2 = FixedUInt<u16, 2>;
759
760 test_unbounded(U8x2::from(1u8), 4, U8x2::from(16u8), U8x2::from(0u8));
762 test_unbounded(U8x4::from(1u8), 4, U8x4::from(16u8), U8x4::from(0u8));
763 test_unbounded(U16x2::from(1u8), 4, U16x2::from(16u8), U16x2::from(0u8));
764
765 test_unbounded(1u8, 4, 16u8, 0u8);
767 test_unbounded(1u16, 4, 16u16, 0u16);
768 test_unbounded(1u32, 4, 16u32, 0u32);
769
770 test_unbounded(1u8, 8, 0u8, 0u8);
772 test_unbounded(U8x2::from(1u8), 16, U8x2::from(0u8), U8x2::from(0u8));
773 }
774}