1use crate::{Uint, utils::select_unpredictable_u32};
2use core::ops::{
3 BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Not, Shl, ShlAssign, Shr,
4 ShrAssign,
5};
6
7#[inline(always)]
17const fn shift_amount(rhs: usize) -> u32 {
18 select_unpredictable_u32(rhs > u32::MAX as usize, u32::MAX, rhs as u32)
19}
20
21impl<const BITS: usize, const LIMBS: usize> Uint<BITS, LIMBS> {
22 #[must_use]
26 #[inline]
27 pub const fn bit(&self, index: usize) -> bool {
28 if index >= BITS {
29 return false;
30 }
31 let (limbs, bits) = (index / 64, index % 64);
32 self.limbs[limbs] & (1 << bits) != 0
33 }
34
35 #[inline]
37 pub const fn set_bit(&mut self, index: usize, value: bool) {
38 if index >= BITS {
39 return;
40 }
41 let (limbs, bits) = (index / 64, index % 64);
42 if value {
43 self.limbs[limbs] |= 1 << bits;
44 } else {
45 self.limbs[limbs] &= !(1 << bits);
46 }
47 }
48
49 #[inline]
83 #[must_use]
84 #[track_caller]
85 pub const fn byte(&self, index: usize) -> u8 {
86 #[cfg(target_endian = "little")]
87 {
88 self.as_le_slice()[index]
89 }
90
91 #[cfg(target_endian = "big")]
92 #[allow(clippy::cast_possible_truncation)] {
94 assert!(index < Self::BYTES, "index out of bounds");
95 (self.limbs[index / 8] >> ((index % 8) * 8)) as u8
96 }
97 }
98
99 #[inline]
113 #[must_use]
114 pub const fn checked_byte(&self, index: usize) -> Option<u8> {
115 if index < Self::BYTES {
116 Some(self.byte(index))
117 } else {
118 None
119 }
120 }
121
122 #[inline]
126 #[must_use]
127 pub const fn reverse_bits(mut self) -> Self {
128 const_range_for!(i in 0..LIMBS / 2 => {
129 let j = LIMBS - 1 - i;
130 let limb = self.limbs[i];
131 self.limbs[i] = self.limbs[j].reverse_bits();
132 self.limbs[j] = limb.reverse_bits();
133 });
134 if LIMBS % 2 == 1 {
135 let i = LIMBS / 2;
136 self.limbs[i] = self.limbs[i].reverse_bits();
137 }
138 if !BITS.is_multiple_of(64) {
139 self = self.wrapping_shr(64 - BITS % 64);
140 }
141 self
142 }
143
144 #[inline]
146 #[must_use]
147 pub const fn not(mut self) -> Self {
148 if BITS == 0 {
149 return Self::ZERO;
150 }
151 const_range_for!(limb in mut self.limbs => {
152 *limb = !*limb;
153 });
154 self.masked()
155 }
156
157 #[inline]
161 pub(crate) const fn count_significant_words(&self) -> usize {
162 let mut i = LIMBS;
163 while i > 0 {
164 i -= 1;
165 if self.limbs[i] != 0 {
166 return i + 1;
167 }
168 }
169 0
170 }
171
172 #[inline]
175 #[must_use]
176 pub const fn leading_zeros(&self) -> usize {
177 let fixed = Self::MASK.leading_zeros() as usize;
178
179 as_primitives!(self; {
180 u64(x) => return x.leading_zeros() as usize - fixed,
181 u128(x) => return x.leading_zeros() as usize - fixed,
182 u256((lo, hi)) => return (select_unpredictable_u32(hi != 0,
183 hi.leading_zeros(),
184 lo.leading_zeros() + 128
185 )) as usize - fixed,
186 });
187
188 let s = self.count_significant_words();
189 if s == 0 {
190 return BITS;
191 }
192 let n = LIMBS - s;
193 let skipped = n * 64;
194 let top = self.limbs[s - 1].leading_zeros() as usize;
195 skipped + top - fixed
196 }
197
198 #[inline]
201 #[must_use]
202 pub const fn leading_ones(&self) -> usize {
203 let fixed = Self::MASK.leading_zeros() as usize;
204
205 as_primitives!(self; {
206 u64(x) => return (x | !Self::MASK).leading_ones() as usize - fixed,
207 u128(x) => {
208 let mask = (Self::MASK as u128) << 64 | u64::MAX as u128;
209 return (x | !mask).leading_ones() as usize - fixed;
210 },
211 u256((lo, hi)) => {
212 let hi_mask = (Self::MASK as u128) << 64 | u64::MAX as u128;
213 let hi = hi | !hi_mask;
214 let ones = if hi == u128::MAX {
215 hi.leading_ones() + lo.leading_ones()
216 } else {
217 hi.leading_ones()
218 };
219 return ones as usize - fixed;
220 },
221 });
222
223 Self::not(*self).leading_zeros()
224 }
225
226 #[inline]
229 #[must_use]
230 pub const fn trailing_zeros(&self) -> usize {
231 as_primitives!(self; {
232 u64(x) => {
233 let zeros = x.trailing_zeros() as usize;
234 return if zeros > BITS { BITS } else { zeros };
235 },
236 u128(x) => {
237 let zeros = x.trailing_zeros() as usize;
238 return if zeros > BITS { BITS } else { zeros };
239 },
240 u256((lo, hi)) => {
241 let zeros = if lo == 0 {
242 hi.trailing_zeros() + 128
243 } else {
244 lo.trailing_zeros()
245 } as usize;
246 return if zeros > BITS { BITS } else { zeros };
247 },
248 });
249
250 const_range_for!(i in 0..LIMBS => {
251 if self.limbs[i] != 0 {
252 return i * 64 + self.limbs[i].trailing_zeros() as usize;
253 }
254 });
255 BITS
256 }
257
258 #[inline]
261 #[must_use]
262 pub const fn trailing_ones(&self) -> usize {
263 as_primitives!(self; {
264 u64(x) => return x.trailing_ones() as usize,
265 u128(x) => return x.trailing_ones() as usize,
266 u256((lo, hi)) => return if lo == u128::MAX {
267 (hi.trailing_ones() + 128) as usize
268 } else {
269 lo.trailing_ones() as usize
270 },
271 });
272
273 const_range_for!(i in 0..LIMBS => {
274 if self.limbs[i] != u64::MAX {
275 return i * 64 + self.limbs[i].trailing_ones() as usize;
276 }
277 });
278 BITS
279 }
280
281 #[inline]
283 #[must_use]
284 pub const fn count_ones(&self) -> usize {
285 let mut ones = 0;
286 const_range_for!(limb in ref self.as_limbs() => {
287 ones += limb.count_ones() as usize;
288 });
289 ones
290 }
291
292 #[must_use]
294 #[inline]
295 pub const fn count_zeros(&self) -> usize {
296 BITS - self.count_ones()
297 }
298
299 #[must_use]
304 #[inline]
305 pub const fn bit_len(&self) -> usize {
306 BITS - self.leading_zeros()
307 }
308
309 #[must_use]
314 #[inline]
315 pub const fn byte_len(&self) -> usize {
316 self.bit_len().div_ceil(8)
317 }
318
319 #[inline]
331 #[must_use]
332 pub const fn most_significant_bits(&self) -> (u64, usize) {
333 let significant_words = self.count_significant_words();
334 if significant_words == 0 {
335 (0, 0)
336 } else if significant_words == 1 {
337 (self.limbs[0], 0)
338 } else {
339 let i = significant_words - 1;
340 let hi = self.limbs[i];
341 let lo = self.limbs[i - 1];
342 let leading_zeros = hi.leading_zeros();
343 let bits = if leading_zeros > 0 {
344 (hi << leading_zeros) | (lo >> (64 - leading_zeros))
345 } else {
346 hi
347 };
348 let exponent = i * 64 - leading_zeros as usize;
349 (bits, exponent)
350 }
351 }
352
353 #[inline(always)]
362 #[must_use]
363 pub const fn checked_shl(self, rhs: usize) -> Option<Self> {
364 match self.overflowing_shl(rhs) {
365 (value, false) => Some(value),
366 _ => None,
367 }
368 }
369
370 #[inline(always)]
381 #[must_use]
382 #[track_caller]
383 pub const fn strict_shl(self, rhs: usize) -> Self {
384 match self.overflowing_shl(rhs) {
385 (value, false) => value,
386 _ => panic!("attempt to shift left with overflow"),
387 }
388 }
389
390 #[inline(always)]
396 #[must_use]
397 pub const fn saturating_shl(self, rhs: usize) -> Self {
398 match self.overflowing_shl(rhs) {
399 (value, false) => value,
400 _ => Self::MAX,
401 }
402 }
403
404 #[inline]
413 #[must_use]
414 pub const fn overflowing_shl(self, rhs: usize) -> (Self, bool) {
415 let (limbs, bits) = (rhs / 64, rhs % 64);
416 if limbs >= LIMBS {
417 return (Self::ZERO, !self.const_is_zero());
418 }
419 let mut r = Self::ZERO;
420 let bits = bits as u32;
421
422 let mut carry = 0;
423 const_range_for!(i in 0..LIMBS - limbs => {
425 let x = self.limbs[i];
426 r.limbs[i + limbs] = (x << bits) | carry;
427 carry = x.unbounded_shr(64 - bits);
428 });
429 const_range_for!(i in (LIMBS - limbs)..LIMBS => {
431 carry |= self.limbs[i];
432 });
433 carry |= r.maskable_bits();
435 (r.masked(), carry != 0)
436 }
437
438 #[inline]
442 pub(crate) fn overflowing_shl_big(self, rhs: Self) -> (Self, bool) {
443 if BITS == 0 {
444 return (Self::ZERO, false);
445 }
446 let Ok(rhs) = usize::try_from(rhs) else {
451 return (Self::ZERO, !self.const_is_zero());
452 };
453 self.overflowing_shl(rhs)
454 }
455
456 #[inline(always)]
463 #[must_use]
464 pub const fn wrapping_shl(self, rhs: usize) -> Self {
465 as_primitives!(self; {
466 u64(x) => {
467 let mut r = Self::ZERO;
468 r.limbs[0] = x.unbounded_shl(shift_amount(rhs));
469 return r.masked();
470 },
471 u128(x) => {
472 let r = x.unbounded_shl(shift_amount(rhs));
473 let mut out = Self::ZERO;
474 out.limbs[0] = r as u64;
475 out.limbs[1] = (r >> 64) as u64;
476 return out.masked();
477 },
478 u256((lo, hi)) => {
479 let rhs = shift_amount(rhs);
480 let new_lo = lo.unbounded_shl(rhs);
482 let new_hi = hi.unbounded_shl(rhs) | lo.unbounded_shr(128u32.wrapping_sub(rhs));
483 let cross = lo.unbounded_shl(rhs.wrapping_sub(128));
485 let mask = 0u128.wrapping_sub((rhs < 128) as u128);
486 let lo = new_lo & mask;
487 let hi = (new_hi & mask) | (cross & !mask);
488 let mut r = Self::ZERO;
489 r.limbs[0] = lo as u64;
490 r.limbs[1] = (lo >> 64) as u64;
491 r.limbs[2] = hi as u64;
492 r.limbs[3] = (hi >> 64) as u64;
493 return r.masked();
494 },
495 });
496
497 self.overflowing_shl(rhs).0
498 }
499
500 #[inline(always)]
512 #[must_use]
513 pub const fn checked_shr(self, rhs: usize) -> Option<Self> {
514 match self.overflowing_shr(rhs) {
515 (value, false) => Some(value),
516 _ => None,
517 }
518 }
519
520 #[inline(always)]
531 #[must_use]
532 #[track_caller]
533 pub const fn strict_shr(self, rhs: usize) -> Self {
534 match self.overflowing_shr(rhs) {
535 (value, false) => value,
536 _ => panic!("attempt to shift right with overflow"),
537 }
538 }
539
540 #[inline]
553 #[must_use]
554 pub const fn overflowing_shr(self, rhs: usize) -> (Self, bool) {
555 let (limbs, bits) = (rhs / 64, rhs % 64);
556 if limbs >= LIMBS {
557 return (Self::ZERO, !self.const_is_zero());
558 }
559 let mut r = Self::ZERO;
560 let bits = bits as u32;
561
562 let mut carry = 0;
563 const_range_for!(i in 0..LIMBS - limbs => {
565 let x = self.limbs[LIMBS - 1 - i];
566 r.limbs[LIMBS - 1 - i - limbs] = (x >> bits) | carry;
567 carry = x.unbounded_shl(64 - bits);
568 });
569 const_range_for!(i in 0..limbs => {
571 carry |= self.limbs[i];
572 });
573 (r, carry != 0)
574 }
575
576 #[inline]
580 pub(crate) fn overflowing_shr_big(self, rhs: Self) -> (Self, bool) {
581 if BITS == 0 {
582 return (Self::ZERO, false);
583 }
584 let Ok(rhs) = usize::try_from(rhs) else {
589 return (Self::ZERO, !self.const_is_zero());
590 };
591 self.overflowing_shr(rhs)
592 }
593
594 #[inline(always)]
604 #[must_use]
605 pub const fn wrapping_shr(self, rhs: usize) -> Self {
606 as_primitives!(self; {
607 u64(x) => {
608 let mut r = Self::ZERO;
609 r.limbs[0] = x.unbounded_shr(shift_amount(rhs));
610 return r;
611 },
612 u128(x) => {
613 let r = x.unbounded_shr(shift_amount(rhs));
614 let mut out = Self::ZERO;
615 out.limbs[0] = r as u64;
616 out.limbs[1] = (r >> 64) as u64;
617 return out;
618 },
619 u256((lo, hi)) => {
620 let rhs = shift_amount(rhs);
621 let new_hi = hi.unbounded_shr(rhs);
623 let new_lo = lo.unbounded_shr(rhs) | hi.unbounded_shl(128u32.wrapping_sub(rhs));
624 let cross = hi.unbounded_shr(rhs.wrapping_sub(128));
626 let mask = 0u128.wrapping_sub((rhs < 128) as u128);
627 let hi = new_hi & mask;
628 let lo = (new_lo & mask) | (cross & !mask);
629 let mut r = Self::ZERO;
630 r.limbs[0] = lo as u64;
631 r.limbs[1] = (lo >> 64) as u64;
632 r.limbs[2] = hi as u64;
633 r.limbs[3] = (hi >> 64) as u64;
634 return r;
635 },
636 });
637
638 self.overflowing_shr(rhs).0
639 }
640
641 #[inline]
643 #[must_use]
644 pub const fn arithmetic_shr(self, rhs: usize) -> Self {
645 if BITS == 0 {
646 return Self::ZERO;
647 }
648 let sign = self.bit(BITS - 1);
649 let mut r = self.wrapping_shr(rhs);
650 if sign {
651 r = r.bitor(Self::MAX.wrapping_shl(BITS.saturating_sub(rhs)));
653 }
654 r
655 }
656
657 #[inline]
660 #[must_use]
661 pub const fn rotate_left(self, rhs: usize) -> Self {
662 if BITS == 0 {
663 return Self::ZERO;
664 }
665 let rhs = rhs % BITS;
666 self.wrapping_shl(rhs).bitor(self.wrapping_shr(BITS - rhs))
668 }
669
670 #[inline(always)]
673 #[must_use]
674 pub const fn rotate_right(self, rhs: usize) -> Self {
675 if BITS == 0 {
676 return Self::ZERO;
677 }
678 let rhs = rhs % BITS;
679 self.rotate_left(BITS - rhs)
680 }
681}
682
683impl<const BITS: usize, const LIMBS: usize> Not for Uint<BITS, LIMBS> {
684 type Output = Self;
685
686 #[inline]
687 fn not(self) -> Self::Output {
688 self.not()
689 }
690}
691
692impl<const BITS: usize, const LIMBS: usize> Not for &Uint<BITS, LIMBS> {
693 type Output = Uint<BITS, LIMBS>;
694
695 #[inline]
696 fn not(self) -> Self::Output {
697 (*self).not()
698 }
699}
700
701macro_rules! impl_bit_op {
702 ($op:tt, $assign_op:tt, $trait:ident, $fn:ident, $trait_assign:ident, $fn_assign:ident) => {
703 impl<const BITS: usize, const LIMBS: usize> $trait_assign<Uint<BITS, LIMBS>>
704 for Uint<BITS, LIMBS>
705 {
706 #[inline(always)]
707 fn $fn_assign(&mut self, rhs: Uint<BITS, LIMBS>) {
708 self.$fn_assign(&rhs);
709 }
710 }
711
712 impl<const BITS: usize, const LIMBS: usize> $trait_assign<&Uint<BITS, LIMBS>>
713 for Uint<BITS, LIMBS>
714 {
715 #[inline]
716 fn $fn_assign(&mut self, rhs: &Uint<BITS, LIMBS>) {
717 for i in 0..LIMBS {
718 u64::$fn_assign(&mut self.limbs[i], rhs.limbs[i]);
719 }
720 }
721 }
722
723 impl<const BITS: usize, const LIMBS: usize> $trait<Uint<BITS, LIMBS>>
724 for Uint<BITS, LIMBS>
725 {
726 type Output = Uint<BITS, LIMBS>;
727
728 #[inline(always)]
729 fn $fn(mut self, rhs: Uint<BITS, LIMBS>) -> Self::Output {
730 self.$fn_assign(rhs);
731 self
732 }
733 }
734
735 impl<const BITS: usize, const LIMBS: usize> $trait<&Uint<BITS, LIMBS>>
736 for Uint<BITS, LIMBS>
737 {
738 type Output = Uint<BITS, LIMBS>;
739
740 #[inline(always)]
741 fn $fn(mut self, rhs: &Uint<BITS, LIMBS>) -> Self::Output {
742 self.$fn_assign(rhs);
743 self
744 }
745 }
746
747 impl<const BITS: usize, const LIMBS: usize> $trait<Uint<BITS, LIMBS>>
748 for &Uint<BITS, LIMBS>
749 {
750 type Output = Uint<BITS, LIMBS>;
751
752 #[inline(always)]
753 fn $fn(self, mut rhs: Uint<BITS, LIMBS>) -> Self::Output {
754 rhs.$fn_assign(self);
755 rhs
756 }
757 }
758
759 impl<const BITS: usize, const LIMBS: usize> $trait<&Uint<BITS, LIMBS>>
760 for &Uint<BITS, LIMBS>
761 {
762 type Output = Uint<BITS, LIMBS>;
763
764 #[inline(always)]
765 fn $fn(self, rhs: &Uint<BITS, LIMBS>) -> Self::Output {
766 <Uint<BITS, LIMBS>>::$fn(*self, *rhs)
767 }
768 }
769
770 impl<const BITS: usize, const LIMBS: usize> Uint<BITS, LIMBS> {
771 #[doc = concat!("Returns the bitwise `", stringify!($op), "` of the two numbers.")]
772 #[inline(always)]
773 #[must_use]
774 pub const fn $fn(mut self, rhs: Uint<BITS, LIMBS>) -> Uint<BITS, LIMBS> {
775 const_range_for!(i in 0..LIMBS => {
776 self.limbs[i] $assign_op rhs.limbs[i];
777 });
778 self
779 }
780 }
781 };
782}
783
784impl_bit_op!(|, |=, BitOr, bitor, BitOrAssign, bitor_assign);
785impl_bit_op!(&, &=, BitAnd, bitand, BitAndAssign, bitand_assign);
786impl_bit_op!(^, ^=, BitXor, bitxor, BitXorAssign, bitxor_assign);
787
788impl<const BITS: usize, const LIMBS: usize> Shl<Self> for Uint<BITS, LIMBS> {
789 type Output = Self;
790
791 #[inline(always)]
792 fn shl(self, rhs: Self) -> Self::Output {
793 self.overflowing_shl_big(rhs).0
794 }
795}
796
797impl<const BITS: usize, const LIMBS: usize> Shl<&Self> for Uint<BITS, LIMBS> {
798 type Output = Self;
799
800 #[inline(always)]
801 fn shl(self, rhs: &Self) -> Self::Output {
802 self << *rhs
803 }
804}
805
806impl<const BITS: usize, const LIMBS: usize> Shr<Self> for Uint<BITS, LIMBS> {
807 type Output = Self;
808
809 #[inline(always)]
810 fn shr(self, rhs: Self) -> Self::Output {
811 self.overflowing_shr_big(rhs).0
812 }
813}
814
815impl<const BITS: usize, const LIMBS: usize> Shr<&Self> for Uint<BITS, LIMBS> {
816 type Output = Self;
817
818 #[inline(always)]
819 fn shr(self, rhs: &Self) -> Self::Output {
820 self >> *rhs
821 }
822}
823
824impl<const BITS: usize, const LIMBS: usize> ShlAssign<Self> for Uint<BITS, LIMBS> {
825 #[inline(always)]
826 fn shl_assign(&mut self, rhs: Self) {
827 *self = *self << rhs;
828 }
829}
830
831impl<const BITS: usize, const LIMBS: usize> ShlAssign<&Self> for Uint<BITS, LIMBS> {
832 #[inline(always)]
833 fn shl_assign(&mut self, rhs: &Self) {
834 *self = *self << rhs;
835 }
836}
837
838impl<const BITS: usize, const LIMBS: usize> ShrAssign<Self> for Uint<BITS, LIMBS> {
839 #[inline(always)]
840 fn shr_assign(&mut self, rhs: Self) {
841 *self = *self >> rhs;
842 }
843}
844
845impl<const BITS: usize, const LIMBS: usize> ShrAssign<&Self> for Uint<BITS, LIMBS> {
846 #[inline(always)]
847 fn shr_assign(&mut self, rhs: &Self) {
848 *self = *self >> rhs;
849 }
850}
851
852macro_rules! impl_shift {
853 (@main $u:ty) => {
854 impl<const BITS: usize, const LIMBS: usize> Shl<$u> for Uint<BITS, LIMBS> {
855 type Output = Self;
856
857 #[inline(always)]
858 #[allow(clippy::cast_possible_truncation)]
859 fn shl(self, rhs: $u) -> Self::Output {
860 self.wrapping_shl(rhs as usize)
861 }
862 }
863
864 impl<const BITS: usize, const LIMBS: usize> Shr<$u> for Uint<BITS, LIMBS> {
865 type Output = Self;
866
867 #[inline(always)]
868 #[allow(clippy::cast_possible_truncation)]
869 fn shr(self, rhs: $u) -> Self::Output {
870 self.wrapping_shr(rhs as usize)
871 }
872 }
873 };
874
875 (@ref $u:ty) => {
876 impl<const BITS: usize, const LIMBS: usize> Shl<&$u> for Uint<BITS, LIMBS> {
877 type Output = Self;
878
879 #[inline(always)]
880 fn shl(self, rhs: &$u) -> Self::Output {
881 <Self>::shl(self, *rhs)
882 }
883 }
884
885 impl<const BITS: usize, const LIMBS: usize> Shr<&$u> for Uint<BITS, LIMBS> {
886 type Output = Self;
887
888 #[inline(always)]
889 fn shr(self, rhs: &$u) -> Self::Output {
890 <Self>::shr(self, *rhs)
891 }
892 }
893 };
894
895 (@assign $u:ty) => {
896 impl<const BITS: usize, const LIMBS: usize> ShlAssign<$u> for Uint<BITS, LIMBS> {
897 #[inline(always)]
898 fn shl_assign(&mut self, rhs: $u) {
899 *self = *self << rhs;
900 }
901 }
902
903 impl<const BITS: usize, const LIMBS: usize> ShrAssign<$u> for Uint<BITS, LIMBS> {
904 #[inline(always)]
905 fn shr_assign(&mut self, rhs: $u) {
906 *self = *self >> rhs;
907 }
908 }
909 };
910
911 ($u:ty) => {
912 impl_shift!(@main $u);
913 impl_shift!(@ref $u);
914 impl_shift!(@assign $u);
915 impl_shift!(@assign &$u);
916 };
917
918 ($u:ty, $($tail:ty),*) => {
919 impl_shift!($u);
920 impl_shift!($($tail),*);
921 };
922}
923
924impl_shift!(usize, u8, u16, u32, isize, i8, i16, i32);
925
926#[cfg(target_pointer_width = "64")]
928impl_shift!(u64, i64);
929
930#[cfg(test)]
931mod tests {
932 use super::*;
933 use crate::{
934 aliases::{U128, U256},
935 const_for, nlimbs,
936 };
937 use core::cmp::min;
938 use proptest::proptest;
939
940 fn reference_leading_zeros<const BITS: usize, const LIMBS: usize>(
941 value: Uint<BITS, LIMBS>,
942 ) -> usize {
943 let mut zeros = 0;
944 while zeros < BITS && !value.bit(BITS - zeros - 1) {
945 zeros += 1;
946 }
947 zeros
948 }
949
950 fn reference_leading_ones<const BITS: usize, const LIMBS: usize>(
951 value: Uint<BITS, LIMBS>,
952 ) -> usize {
953 let mut ones = 0;
954 while ones < BITS && value.bit(BITS - ones - 1) {
955 ones += 1;
956 }
957 ones
958 }
959
960 fn reference_trailing_zeros<const BITS: usize, const LIMBS: usize>(
961 value: Uint<BITS, LIMBS>,
962 ) -> usize {
963 let mut zeros = 0;
964 while zeros < BITS && !value.bit(zeros) {
965 zeros += 1;
966 }
967 zeros
968 }
969
970 fn reference_trailing_ones<const BITS: usize, const LIMBS: usize>(
971 value: Uint<BITS, LIMBS>,
972 ) -> usize {
973 let mut ones = 0;
974 while ones < BITS && value.bit(ones) {
975 ones += 1;
976 }
977 ones
978 }
979
980 #[test]
981 fn test_leading_zeros() {
982 assert_eq!(Uint::<0, 0>::ZERO.leading_zeros(), 0);
983 const_for!(BITS in NON_ZERO {
984 const LIMBS: usize = nlimbs(BITS);
985 type U = Uint::<BITS, LIMBS>;
986 assert_eq!(U::ZERO.leading_zeros(), BITS);
987 assert_eq!(U::MAX.leading_zeros(), 0);
988 assert_eq!(U::ONE.leading_zeros(), BITS - 1);
989 proptest!(|(value: U)| {
990 assert_eq!(value.leading_zeros(), reference_leading_zeros(value));
991 });
992 });
993
994 assert_eq!(
995 U256::from_limbs([1, 0, 0, 0]).leading_zeros(),
996 reference_leading_zeros(U256::from_limbs([1, 0, 0, 0]))
997 );
998 assert_eq!(
999 U256::from_limbs([0, 0, 1, 0]).leading_zeros(),
1000 reference_leading_zeros(U256::from_limbs([0, 0, 1, 0]))
1001 );
1002 }
1003
1004 #[test]
1005 fn test_leading_ones() {
1006 assert_eq!(Uint::<0, 0>::ZERO.leading_ones(), 0);
1007 const_for!(BITS in NON_ZERO {
1008 const LIMBS: usize = nlimbs(BITS);
1009 type U = Uint::<BITS, LIMBS>;
1010 assert_eq!(U::ZERO.leading_ones(), 0);
1011 assert_eq!(U::MAX.leading_ones(), BITS);
1012 assert_eq!((U::MAX << 1_usize).leading_ones(), BITS - 1);
1013 proptest!(|(value: U)| {
1014 assert_eq!(value.leading_ones(), reference_leading_ones(value));
1015 });
1016 });
1017
1018 assert_eq!(
1019 U256::from_limbs([u64::MAX, u64::MAX, u64::MAX, u64::MAX - 1]).leading_ones(),
1020 reference_leading_ones(U256::from_limbs([
1021 u64::MAX,
1022 u64::MAX,
1023 u64::MAX,
1024 u64::MAX - 1,
1025 ]))
1026 );
1027 assert_eq!(
1028 U256::from_limbs([0, 0, u64::MAX, u64::MAX]).leading_ones(),
1029 reference_leading_ones(U256::from_limbs([0, 0, u64::MAX, u64::MAX]))
1030 );
1031 }
1032
1033 #[test]
1034 fn test_trailing_zeros() {
1035 assert_eq!(Uint::<0, 0>::ZERO.trailing_zeros(), 0);
1036 const_for!(BITS in NON_ZERO {
1037 const LIMBS: usize = nlimbs(BITS);
1038 type U = Uint::<BITS, LIMBS>;
1039 assert_eq!(U::ZERO.trailing_zeros(), BITS);
1040 assert_eq!(U::MAX.trailing_zeros(), 0);
1041 assert_eq!((U::MAX << 1_usize).trailing_zeros(), 1);
1042 proptest!(|(value: U)| {
1043 assert_eq!(value.trailing_zeros(), reference_trailing_zeros(value));
1044 });
1045 });
1046
1047 assert_eq!(
1048 U256::from_limbs([0, 0, 1, 0]).trailing_zeros(),
1049 reference_trailing_zeros(U256::from_limbs([0, 0, 1, 0]))
1050 );
1051 }
1052
1053 #[test]
1054 fn test_trailing_ones() {
1055 assert_eq!(Uint::<0, 0>::ZERO.trailing_ones(), 0);
1056 const_for!(BITS in NON_ZERO {
1057 const LIMBS: usize = nlimbs(BITS);
1058 type U = Uint::<BITS, LIMBS>;
1059 assert_eq!(U::ZERO.trailing_ones(), 0);
1060 assert_eq!(U::MAX.trailing_ones(), BITS);
1061 assert_eq!((U::MAX << 1_usize).trailing_ones(), 0);
1062 proptest!(|(value: U)| {
1063 assert_eq!(value.trailing_ones(), reference_trailing_ones(value));
1064 });
1065 });
1066
1067 assert_eq!(
1068 U256::from_limbs([u64::MAX, u64::MAX, 0, 0]).trailing_ones(),
1069 reference_trailing_ones(U256::from_limbs([u64::MAX, u64::MAX, 0, 0]))
1070 );
1071 }
1072
1073 #[test]
1074 fn test_most_significant_bits() {
1075 const_for!(BITS in NON_ZERO {
1076 const LIMBS: usize = nlimbs(BITS);
1077 type U = Uint::<BITS, LIMBS>;
1078 proptest!(|(value: u64)| {
1079 let value = if U::LIMBS <= 1 { value & U::MASK } else { value };
1080 assert_eq!(U::from(value).most_significant_bits(), (value, 0));
1081 });
1082 });
1083 proptest!(|(mut limbs: [u64; 2])| {
1084 if limbs[1] == 0 {
1085 limbs[1] = 1;
1086 }
1087 let (bits, exponent) = U128::from_limbs(limbs).most_significant_bits();
1088 assert!(bits >= 1_u64 << 63);
1089 assert_eq!(exponent, 64 - limbs[1].leading_zeros() as usize);
1090 });
1091 }
1092
1093 #[test]
1094 fn test_checked_shl() {
1095 assert_eq!(
1096 Uint::<65, 2>::from_limbs([0x0010_0000_0000_0000, 0]).checked_shl(1),
1097 Some(Uint::<65, 2>::from_limbs([0x0020_0000_0000_0000, 0]))
1098 );
1099 assert_eq!(
1100 Uint::<127, 2>::from_limbs([0x0010_0000_0000_0000, 0]).checked_shl(64),
1101 Some(Uint::<127, 2>::from_limbs([0, 0x0010_0000_0000_0000]))
1102 );
1103 }
1104
1105 #[test]
1106 #[allow(
1107 clippy::cast_lossless,
1108 clippy::cast_possible_truncation,
1109 clippy::cast_possible_wrap
1110 )]
1111 fn test_small() {
1112 const_for!(BITS in [1, 2, 8, 16, 32, 63, 64] {
1113 type U = Uint::<BITS, 1>;
1114 proptest!(|(a: U, b: U)| {
1115 assert_eq!(a | b, U::from_limbs([a.limbs[0] | b.limbs[0]]));
1116 assert_eq!(a & b, U::from_limbs([a.limbs[0] & b.limbs[0]]));
1117 assert_eq!(a ^ b, U::from_limbs([a.limbs[0] ^ b.limbs[0]]));
1118 });
1119 proptest!(|(a: U, s in 0..BITS)| {
1120 assert_eq!(a << s, U::from_limbs([a.limbs[0] << s & U::MASK]));
1121 assert_eq!(a >> s, U::from_limbs([a.limbs[0] >> s]));
1122 });
1123 });
1124 proptest!(|(a: Uint::<32, 1>, s in 0_usize..=34)| {
1125 assert_eq!(a.reverse_bits(), Uint::from((a.limbs[0] as u32).reverse_bits() as u64));
1126 assert_eq!(a.rotate_left(s), Uint::from((a.limbs[0] as u32).rotate_left(s as u32) as u64));
1127 assert_eq!(a.rotate_right(s), Uint::from((a.limbs[0] as u32).rotate_right(s as u32) as u64));
1128 if s < 32 {
1129 let arr_shifted = (((a.limbs[0] as i32) >> s) as u32) as u64;
1130 assert_eq!(a.arithmetic_shr(s), Uint::from_limbs([arr_shifted]));
1131 }
1132 });
1133 proptest!(|(a: Uint::<64, 1>, s in 0_usize..=66)| {
1134 assert_eq!(a.reverse_bits(), Uint::from(a.limbs[0].reverse_bits()));
1135 assert_eq!(a.rotate_left(s), Uint::from(a.limbs[0].rotate_left(s as u32)));
1136 assert_eq!(a.rotate_right(s), Uint::from(a.limbs[0].rotate_right(s as u32)));
1137 if s < 64 {
1138 let arr_shifted = ((a.limbs[0] as i64) >> s) as u64;
1139 assert_eq!(a.arithmetic_shr(s), Uint::from_limbs([arr_shifted]));
1140 }
1141 });
1142 }
1143
1144 #[test]
1145 #[allow(clippy::absurd_extreme_comparisons)] fn test_const_reverse_and_most_significant_bits() {
1147 const_for!(BITS in SIZES {
1148 const LIMBS: usize = nlimbs(BITS);
1149 type U = Uint<BITS, LIMBS>;
1150 const {
1151 assert!(U::MAX.reverse_bits().const_eq(&U::MAX));
1152 let reversed_one = U::ONE.reverse_bits();
1153 let expected = if BITS == 0 { U::ZERO } else { U::ONE.wrapping_shl(BITS - 1) };
1154 assert!(reversed_one.const_eq(&expected));
1155
1156 let (bits, exponent) = U::MAX.most_significant_bits();
1157 if BITS <= 64 {
1158 assert!(bits == U::MASK);
1159 assert!(exponent == 0);
1160 } else {
1161 assert!(bits == u64::MAX);
1162 assert!(exponent == BITS - 64);
1163 }
1164 }
1165 });
1166 }
1167
1168 #[test]
1169 fn test_shift_reverse() {
1170 const_for!(BITS in SIZES {
1171 const LIMBS: usize = nlimbs(BITS);
1172 type U = Uint::<BITS, LIMBS>;
1173 proptest!(|(value: U, shift in 0..=BITS + 2)| {
1174 let left = (value << shift).reverse_bits();
1175 let right = value.reverse_bits() >> shift;
1176 assert_eq!(left, right);
1177 });
1178 });
1179 }
1180
1181 #[test]
1182 fn test_shift_very_big_rhs() {
1183 type U = Uint<128, 2>;
1184
1185 for rhs in [
1186 U::from(u64::MAX),
1187 U::from(u128::MAX),
1188 U::from_limbs([0, 1]),
1189 U::from_limbs([1, 1]),
1190 U::from_limbs([1, u64::MAX]),
1191 ] {
1192 assert_eq!(U::ONE << rhs, U::ZERO, "{rhs}");
1193 assert_eq!(U::ONE >> rhs, U::ZERO, "{rhs}");
1194 }
1195 }
1196
1197 #[test]
1198 fn test_rotate() {
1199 const_for!(BITS in SIZES {
1200 const LIMBS: usize = nlimbs(BITS);
1201 type U = Uint::<BITS, LIMBS>;
1202 proptest!(|(value: U, shift in 0..=BITS + 2)| {
1203 let rotated = value.rotate_left(shift).rotate_right(shift);
1204 assert_eq!(value, rotated);
1205 });
1206 });
1207 }
1208
1209 #[test]
1210 fn test_arithmetic_shr() {
1211 const_for!(BITS in SIZES {
1212 const LIMBS: usize = nlimbs(BITS);
1213 type U = Uint::<BITS, LIMBS>;
1214 proptest!(|(value: U, shift in 0..=BITS + 2)| {
1215 let shifted = value.arithmetic_shr(shift);
1216 assert_eq!(shifted.leading_ones(), match value.leading_ones() {
1217 0 => 0,
1218 n => min(BITS, n + shift)
1219 });
1220 });
1221 });
1222 }
1223
1224 #[test]
1225 fn test_overflowing_shr() {
1226 assert_eq!(
1229 Uint::<64, 1>::from_limbs([40u64]).overflowing_shr(1),
1230 (Uint::<64, 1>::from(20), false)
1231 );
1232
1233 assert_eq!(
1236 Uint::<64, 1>::from_limbs([41u64]).overflowing_shr(1),
1237 (Uint::<64, 1>::from(20), true)
1238 );
1239
1240 assert_eq!(
1243 Uint::<65, 2>::from_limbs([0x0010_0000_0000_0000, 0]).overflowing_shr(1),
1244 (Uint::<65, 2>::from_limbs([0x0008_0000_0000_0000, 0]), false)
1245 );
1246
1247 assert_eq!(
1251 Uint::<256, 4>::MAX.overflowing_shr(65),
1252 (
1253 Uint::<256, 4>::from_str_radix(
1254 "7fffffffffffffffffffffffffffffffffffffffffffffff",
1255 16
1256 )
1257 .unwrap(),
1258 true
1259 )
1260 );
1261 assert_eq!(
1264 Uint::<4096, 64>::from_str_radix("3ffffffffffffffffffffffffffffc00000000", 16,)
1265 .unwrap()
1266 .overflowing_shr(34),
1267 (
1268 Uint::<4096, 64>::from_str_radix("fffffffffffffffffffffffffffff", 16).unwrap(),
1269 false
1270 )
1271 );
1272 assert_eq!(
1275 Uint::<4096, 64>::from_str_radix(
1276 "fffffffffffffffffffffffffffff0000000000000000000000000",
1277 16,
1278 )
1279 .unwrap()
1280 .overflowing_shr(100),
1281 (
1282 Uint::<4096, 64>::from_str_radix("fffffffffffffffffffffffffffff", 16).unwrap(),
1283 false
1284 )
1285 );
1286 assert_eq!(
1289 Uint::<4096, 64>::from_str_radix(
1290 "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0bdbfe",
1291 16,
1292 )
1293 .unwrap()
1294 .overflowing_shr(1),
1295 (
1296 Uint::<4096, 64>::from_str_radix(
1297 "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffff85edff",
1298 16
1299 )
1300 .unwrap(),
1301 false
1302 )
1303 );
1304 assert_eq!(
1307 Uint::<4096, 64>::from_str_radix(
1308 "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
1309 16,
1310 )
1311 .unwrap()
1312 .overflowing_shr(1000),
1313 (
1314 Uint::<4096, 64>::from_str_radix(
1315 "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
1316 16
1317 )
1318 .unwrap(),
1319 false
1320 )
1321 );
1322 assert_eq!(
1325 Uint::<4096, 64>::MAX
1326 .overflowing_shr(34),
1327 (
1328 Uint::<4096, 64>::from_str_radix(
1329 "3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
1330 16
1331 )
1332 .unwrap(),
1333 true
1334 )
1335 );
1336 }
1337
1338 #[test]
1339 fn test_strict_shl_shr_ok() {
1340 use crate::aliases::U64;
1341 assert_eq!(U64::from(1u64).strict_shl(3), U64::from(8u64));
1342 assert_eq!(U64::from(8u64).strict_shr(3), U64::from(1u64));
1343 }
1344
1345 #[test]
1346 #[should_panic(expected = "attempt to shift left with overflow")]
1347 fn test_strict_shl_overflow() {
1348 let _ = crate::aliases::U64::MAX.strict_shl(1);
1349 }
1350
1351 #[test]
1352 #[should_panic(expected = "attempt to shift right with overflow")]
1353 fn test_strict_shr_overflow() {
1354 let _ = crate::aliases::U64::from(1u64).strict_shr(1);
1355 }
1356
1357 #[test]
1358 fn regression_overflowing_shl() {
1359 let num = Uint::<128, 2>::from_limbs([0, 1]);
1361 assert_eq!(num.overflowing_shl(64), (Uint::ZERO, true));
1362 assert!(num.checked_shl(64).is_none());
1363
1364 let num = Uint::<65, 2>::from_limbs([0, 1]);
1366 assert_eq!(num.overflowing_shl(1), (Uint::ZERO, true));
1367 assert_eq!(num.overflowing_shl(64), (Uint::ZERO, true));
1368 }
1369
1370 #[test]
1371 fn regression_overflowing_shr() {
1372 let num = Uint::<128, 2>::from(1u64);
1374 assert_eq!(num.overflowing_shr(64), (Uint::ZERO, true));
1375 assert!(num.checked_shr(64).is_none());
1376 }
1377
1378 #[cfg(target_pointer_width = "64")]
1381 #[test]
1382 fn regression_wrapping_shifts() {
1383 let huge = 1usize << 32;
1386 assert_eq!(Uint::<64, 1>::from(1u64).wrapping_shl(huge), Uint::ZERO);
1387 assert_eq!(Uint::<64, 1>::from(1u64).wrapping_shl(huge + 3), Uint::ZERO);
1388 assert_eq!(Uint::<64, 1>::MAX.wrapping_shr(huge), Uint::ZERO);
1389 assert_eq!(Uint::<128, 2>::MAX.wrapping_shl(huge), Uint::ZERO);
1390 assert_eq!(Uint::<256, 4>::MAX.wrapping_shr(huge), Uint::ZERO);
1391 assert_eq!(Uint::<256, 4>::MAX.wrapping_shl(huge + 130), Uint::ZERO);
1394 assert_eq!(Uint::<256, 4>::MAX.wrapping_shr(huge + 130), Uint::ZERO);
1395 assert_eq!(Uint::<192, 3>::from(1u64).wrapping_shl(huge), Uint::ZERO);
1397
1398 assert_eq!(Uint::<64, 1>::from(1u64) << huge, Uint::ZERO);
1400 assert_eq!(Uint::<64, 1>::MAX >> huge, Uint::ZERO);
1401
1402 assert_eq!(Uint::<64, 1>::from(5u64).arithmetic_shr(huge), Uint::ZERO);
1404 assert_eq!(Uint::<64, 1>::MAX.arithmetic_shr(huge), Uint::<64, 1>::MAX);
1405 }
1406
1407 #[test]
1408 fn regression_overflowing_big() {
1409 type U = Uint<256, 4>;
1418
1419 let big = U::from(1u64 << 32);
1421 assert_eq!(U::ONE.overflowing_shl_big(big), (U::ZERO, true));
1422 assert_eq!(U::ONE.overflowing_shr_big(big), (U::ZERO, true));
1423 assert_eq!(U::ONE << big, U::ZERO);
1425 assert_eq!(U::MAX >> big, U::ZERO);
1426
1427 assert_eq!(U::MAX.overflowing_shl_big(U::from(256)), (U::ZERO, true));
1429 assert_eq!(U::MAX.overflowing_shr_big(U::from(256)), (U::ZERO, true));
1430
1431 assert_eq!(U::ZERO.overflowing_shl_big(big), (U::ZERO, false));
1433 assert_eq!(U::ZERO.overflowing_shr_big(big), (U::ZERO, false));
1434
1435 let over_u64 = U::from_limbs([0, 0, 1, 0]); assert_eq!(U::MAX.overflowing_shl_big(over_u64), (U::ZERO, true));
1438 assert_eq!(U::MAX.overflowing_shr_big(over_u64), (U::ZERO, true));
1439 assert_eq!(U::ZERO.overflowing_shl_big(over_u64), (U::ZERO, false));
1441 assert_eq!(U::ZERO.overflowing_shr_big(over_u64), (U::ZERO, false));
1442
1443 assert_eq!(
1445 U::ONE.overflowing_shl_big(U::from(8)),
1446 (U::from(256), false)
1447 );
1448 assert_eq!(
1449 U::from(256).overflowing_shr_big(U::from(8)),
1450 (U::ONE, false)
1451 );
1452 }
1453}