1use crate::big_digit::{self, BigDigit, BigDigits};
2
3use alloc::string::String;
4use alloc::vec::Vec;
5use core::cmp;
6use core::cmp::Ordering;
7use core::default::Default;
8use core::fmt;
9use core::hash;
10use core::mem;
11use core::str;
12
13use num_integer::{Integer, Roots};
14use num_traits::bounds::LowerBounded;
15use num_traits::{ConstZero, Num, One, Pow, PrimInt, ToPrimitive, Unsigned, Zero};
16
17mod addition;
18mod division;
19mod multiplication;
20mod subtraction;
21
22mod arbitrary;
23mod bits;
24mod convert;
25mod iter;
26mod monty;
27mod power;
28mod serde;
29mod shift;
30
31pub(crate) use self::convert::to_str_radix_reversed;
32pub use self::iter::{U32Digits, U64Digits};
33
34fn fls<T: PrimInt>(v: T) -> u8 {
37 mem::size_of::<T>() as u8 * 8 - v.leading_zeros() as u8
38}
39
40fn ilog2<T: PrimInt>(v: T) -> u8 {
42 fls(v) - 1
43}
44
45pub struct BigUint {
47 data: BigDigits,
48}
49
50impl Clone for BigUint {
53 #[inline]
54 fn clone(&self) -> Self {
55 BigUint {
56 data: self.data.clone(),
57 }
58 }
59
60 #[inline]
61 fn clone_from(&mut self, other: &Self) {
62 self.data.clone_from(&other.data);
63 }
64}
65
66impl hash::Hash for BigUint {
67 #[inline]
68 fn hash<H: hash::Hasher>(&self, state: &mut H) {
69 debug_assert!(self.data.is_normal());
70 self.data.hash(state);
71 }
72}
73
74impl PartialEq for BigUint {
75 #[inline]
76 fn eq(&self, other: &BigUint) -> bool {
77 debug_assert!(self.data.is_normal());
78 debug_assert!(other.data.is_normal());
79 *self.data == *other.data
80 }
81}
82impl Eq for BigUint {}
83
84impl PartialOrd for BigUint {
85 #[inline]
86 fn partial_cmp(&self, other: &BigUint) -> Option<Ordering> {
87 Some(self.cmp(other))
88 }
89}
90
91impl Ord for BigUint {
92 #[inline]
93 fn cmp(&self, other: &BigUint) -> Ordering {
94 debug_assert!(self.data.is_normal());
95 debug_assert!(other.data.is_normal());
96 cmp_slice(&self.data, &other.data)
97 }
98}
99
100#[inline]
101fn cmp_slice(a: &[BigDigit], b: &[BigDigit]) -> Ordering {
102 match Ord::cmp(&a.len(), &b.len()) {
103 Ordering::Equal => Iterator::cmp(a.iter().rev(), b.iter().rev()),
104 other => other,
105 }
106}
107
108impl Default for BigUint {
109 #[inline]
110 fn default() -> BigUint {
111 Self::ZERO
112 }
113}
114
115impl fmt::Debug for BigUint {
116 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
117 fmt::Display::fmt(self, f)
118 }
119}
120
121impl fmt::Display for BigUint {
122 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
123 f.pad_integral(true, "", &self.to_str_radix(10))
124 }
125}
126
127impl fmt::LowerHex for BigUint {
128 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
129 f.pad_integral(true, "0x", &self.to_str_radix(16))
130 }
131}
132
133impl fmt::UpperHex for BigUint {
134 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
135 let mut s = self.to_str_radix(16);
136 s.make_ascii_uppercase();
137 f.pad_integral(true, "0x", &s)
138 }
139}
140
141impl fmt::Binary for BigUint {
142 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
143 f.pad_integral(true, "0b", &self.to_str_radix(2))
144 }
145}
146
147impl fmt::Octal for BigUint {
148 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
149 f.pad_integral(true, "0o", &self.to_str_radix(8))
150 }
151}
152
153impl Zero for BigUint {
154 #[inline]
155 fn zero() -> BigUint {
156 Self::ZERO
157 }
158
159 #[inline]
160 fn set_zero(&mut self) {
161 self.data.clear();
162 }
163
164 #[inline]
165 fn is_zero(&self) -> bool {
166 self.data.is_empty()
167 }
168}
169
170impl ConstZero for BigUint {
171 const ZERO: Self = Self::ZERO;
173}
174
175impl LowerBounded for BigUint {
176 fn min_value() -> Self {
177 Self::ZERO
178 }
179}
180
181impl One for BigUint {
182 #[inline]
183 fn one() -> BigUint {
184 Self::ONE
185 }
186
187 #[inline]
188 fn set_one(&mut self) {
189 self.data.clear();
190 self.data.push(1);
191 }
192
193 #[inline]
194 fn is_one(&self) -> bool {
195 *self.data == [1]
196 }
197}
198
199impl num_traits::ConstOne for BigUint {
200 const ONE: Self = Self::ONE;
202}
203
204impl Unsigned for BigUint {}
205
206impl Integer for BigUint {
207 #[inline]
208 fn div_rem(&self, other: &BigUint) -> (BigUint, BigUint) {
209 division::div_rem_ref(self, other)
210 }
211
212 #[inline]
213 fn div_floor(&self, other: &BigUint) -> BigUint {
214 let (d, _) = division::div_rem_ref(self, other);
215 d
216 }
217
218 #[inline]
219 fn mod_floor(&self, other: &BigUint) -> BigUint {
220 let (_, m) = division::div_rem_ref(self, other);
221 m
222 }
223
224 #[inline]
225 fn div_mod_floor(&self, other: &BigUint) -> (BigUint, BigUint) {
226 division::div_rem_ref(self, other)
227 }
228
229 #[inline]
230 fn div_ceil(&self, other: &BigUint) -> BigUint {
231 let (d, m) = division::div_rem_ref(self, other);
232 if m.is_zero() {
233 d
234 } else {
235 d + 1u32
236 }
237 }
238
239 #[inline]
241 fn gcd(&self, other: &Self) -> Self {
242 #[inline]
243 fn twos(x: &BigUint) -> u64 {
244 x.trailing_zeros().unwrap_or(0)
245 }
246
247 if self.is_zero() {
249 return other.clone();
250 }
251 if other.is_zero() {
252 return self.clone();
253 }
254 let mut m = self.clone();
255 let mut n = other.clone();
256
257 let shift = cmp::min(twos(&n), twos(&m));
259
260 n >>= twos(&n);
263
264 while !m.is_zero() {
265 m >>= twos(&m);
266 if n > m {
267 mem::swap(&mut n, &mut m)
268 }
269 m -= &n;
270 }
271
272 n << shift
273 }
274
275 #[inline]
277 fn lcm(&self, other: &BigUint) -> BigUint {
278 if self.is_zero() && other.is_zero() {
279 Self::ZERO
280 } else {
281 self / self.gcd(other) * other
282 }
283 }
284
285 #[inline]
288 fn gcd_lcm(&self, other: &Self) -> (Self, Self) {
289 let gcd = self.gcd(other);
290 let lcm = if gcd.is_zero() {
291 Self::ZERO
292 } else {
293 self / &gcd * other
294 };
295 (gcd, lcm)
296 }
297
298 #[inline]
300 fn divides(&self, other: &BigUint) -> bool {
301 self.is_multiple_of(other)
302 }
303
304 #[inline]
306 fn is_multiple_of(&self, other: &BigUint) -> bool {
307 if other.is_zero() {
308 return self.is_zero();
309 }
310 (self % other).is_zero()
311 }
312
313 #[inline]
315 fn is_even(&self) -> bool {
316 match self.data.first() {
318 Some(x) => x.is_even(),
319 None => true,
320 }
321 }
322
323 #[inline]
325 fn is_odd(&self) -> bool {
326 !self.is_even()
327 }
328
329 #[inline]
331 fn next_multiple_of(&self, other: &Self) -> Self {
332 let m = self.mod_floor(other);
333 if m.is_zero() {
334 self.clone()
335 } else {
336 self + (other - m)
337 }
338 }
339 #[inline]
341 fn prev_multiple_of(&self, other: &Self) -> Self {
342 self - self.mod_floor(other)
343 }
344
345 fn dec(&mut self) {
346 *self -= 1u32;
347 }
348
349 fn inc(&mut self) {
350 *self += 1u32;
351 }
352}
353
354#[inline]
355fn fixpoint<F>(mut x: BigUint, max_bits: u64, f: F) -> BigUint
356where
357 F: Fn(&BigUint) -> BigUint,
358{
359 let mut xn = f(&x);
360
361 while x < xn {
364 x = if xn.bits() > max_bits {
368 BigUint::ONE << max_bits
369 } else {
370 xn
371 };
372 xn = f(&x);
373 }
374
375 while x > xn {
377 x = xn;
378 xn = f(&x);
379 }
380 x
381}
382
383impl Roots for BigUint {
384 fn nth_root(&self, n: u32) -> Self {
390 assert!(n > 0, "root degree n must be at least 1");
391
392 if self.is_zero() || self.is_one() {
393 return self.clone();
394 }
395
396 match n {
397 1 => return self.clone(),
399 2 => return self.sqrt(),
400 3 => return self.cbrt(),
401 _ => (),
402 }
403
404 let bits = self.bits();
406 let n64 = u64::from(n);
407 if bits <= n64 {
408 return BigUint::ONE;
409 }
410
411 if let Some(x) = self.to_u64() {
413 return x.nth_root(n).into();
414 }
415
416 let max_bits = bits / n64 + 1;
417
418 #[cfg(feature = "std")]
419 let guess = match self.to_f64() {
420 Some(f) if f.is_finite() => {
421 use num_traits::FromPrimitive;
422
423 BigUint::from_f64((f.ln() / f64::from(n)).exp()).unwrap()
425 }
426 _ => {
427 let extra_bits = bits - (f64::MAX_EXP as u64 - 1);
430 let root_scale = Integer::div_ceil(&extra_bits, &n64);
431 let scale = root_scale * n64;
432 if scale < bits && bits - scale > n64 {
433 (self >> scale).nth_root(n) << root_scale
434 } else {
435 BigUint::ONE << max_bits
436 }
437 }
438 };
439
440 #[cfg(not(feature = "std"))]
441 let guess = BigUint::ONE << max_bits;
442
443 let n_min_1 = n - 1;
444 fixpoint(guess, max_bits, move |s| {
445 let q = self / s.pow(n_min_1);
446 let t = n_min_1 * s + q;
447 t / n
448 })
449 }
450
451 fn sqrt(&self) -> Self {
454 if self.is_zero() || self.is_one() {
455 return self.clone();
456 }
457
458 if let Some(x) = self.to_u64() {
460 return x.sqrt().into();
461 }
462
463 let bits = self.bits();
464 let max_bits = bits / 2 + 1;
465
466 #[cfg(feature = "std")]
467 let guess = match self.to_f64() {
468 Some(f) if f.is_finite() => {
469 use num_traits::FromPrimitive;
470
471 BigUint::from_f64(f.sqrt()).unwrap()
473 }
474 _ => {
475 let extra_bits = bits - (f64::MAX_EXP as u64 - 1);
478 let root_scale = (extra_bits + 1) / 2;
479 let scale = root_scale * 2;
480 (self >> scale).sqrt() << root_scale
481 }
482 };
483
484 #[cfg(not(feature = "std"))]
485 let guess = BigUint::ONE << max_bits;
486
487 fixpoint(guess, max_bits, move |s| {
488 let q = self / s;
489 let t = s + q;
490 t >> 1
491 })
492 }
493
494 fn cbrt(&self) -> Self {
495 if self.is_zero() || self.is_one() {
496 return self.clone();
497 }
498
499 if let Some(x) = self.to_u64() {
501 return x.cbrt().into();
502 }
503
504 let bits = self.bits();
505 let max_bits = bits / 3 + 1;
506
507 #[cfg(feature = "std")]
508 let guess = match self.to_f64() {
509 Some(f) if f.is_finite() => {
510 use num_traits::FromPrimitive;
511
512 BigUint::from_f64(f.cbrt()).unwrap()
514 }
515 _ => {
516 let extra_bits = bits - (f64::MAX_EXP as u64 - 1);
519 let root_scale = (extra_bits + 2) / 3;
520 let scale = root_scale * 3;
521 (self >> scale).cbrt() << root_scale
522 }
523 };
524
525 #[cfg(not(feature = "std"))]
526 let guess = BigUint::ONE << max_bits;
527
528 fixpoint(guess, max_bits, move |s| {
529 let q = self / (s * s);
530 let t = (s << 1) + q;
531 t / 3u32
532 })
533 }
534}
535
536pub trait ToBigUint {
538 fn to_biguint(&self) -> Option<BigUint>;
540}
541
542#[inline]
546pub(crate) fn biguint_from_vec(digits: Vec<BigDigit>) -> BigUint {
547 let mut n = BigUint {
548 data: BigDigits::from_vec(digits),
549 };
550 n.normalize();
551 n
552}
553
554impl BigUint {
555 pub const ZERO: Self = BigUint {
557 data: BigDigits::ZERO,
558 };
559
560 pub const ONE: Self = BigUint {
562 data: BigDigits::ONE,
563 };
564
565 #[inline]
569 pub fn new(digits: Vec<u32>) -> BigUint {
570 let mut big = Self::ZERO;
571
572 cfg_digit_expr!(
573 {
574 big.data = BigDigits::from_vec(digits);
575 big.normalize();
576 },
577 big.assign_from_slice(&digits)
578 );
579
580 big
581 }
582
583 #[inline]
587 pub const fn new_const(n: u32) -> Self {
588 BigUint {
589 data: BigDigits::from_digit(n as BigDigit),
590 }
591 }
592
593 #[inline]
597 pub fn from_slice(slice: &[u32]) -> BigUint {
598 let mut big = Self::ZERO;
599 big.assign_from_slice(slice);
600 big
601 }
602
603 #[inline]
607 pub fn assign_from_slice(&mut self, slice: &[u32]) {
608 self.data.clear();
609
610 cfg_digit_expr!(
611 self.data.extend_from_slice(slice),
612 self.data.extend(slice.chunks(2).map(u32_chunk_to_u64))
613 );
614
615 self.normalize();
616 }
617
618 #[inline]
637 pub fn from_bytes_be(bytes: &[u8]) -> BigUint {
638 if bytes.is_empty() {
639 Self::ZERO
640 } else {
641 let mut v = bytes.to_vec();
642 v.reverse();
643 BigUint::from_bytes_le(&v)
644 }
645 }
646
647 #[inline]
651 pub fn from_bytes_le(bytes: &[u8]) -> BigUint {
652 if bytes.is_empty() {
653 Self::ZERO
654 } else {
655 convert::from_bitwise_digits_le(bytes, 8)
656 }
657 }
658
659 #[inline]
676 pub fn parse_bytes(buf: &[u8], radix: u32) -> Option<BigUint> {
677 let s = str::from_utf8(buf).ok()?;
678 BigUint::from_str_radix(s, radix).ok()
679 }
680
681 pub fn from_radix_be(buf: &[u8], radix: u32) -> Option<BigUint> {
698 convert::from_radix_be(buf, radix)
699 }
700
701 pub fn from_radix_le(buf: &[u8], radix: u32) -> Option<BigUint> {
718 convert::from_radix_le(buf, radix)
719 }
720
721 #[inline]
732 pub fn to_bytes_be(&self) -> Vec<u8> {
733 let mut v = self.to_bytes_le();
734 v.reverse();
735 v
736 }
737
738 #[inline]
749 pub fn to_bytes_le(&self) -> Vec<u8> {
750 if self.is_zero() {
751 vec![0]
752 } else {
753 convert::to_bitwise_digits_le(self, 8)
754 }
755 }
756
757 #[inline]
771 pub fn to_u32_digits(&self) -> Vec<u32> {
772 self.iter_u32_digits().collect()
773 }
774
775 #[inline]
790 pub fn to_u64_digits(&self) -> Vec<u64> {
791 self.iter_u64_digits().collect()
792 }
793
794 #[inline]
808 pub fn iter_u32_digits(&self) -> U32Digits<'_> {
809 U32Digits::new(&self.data)
810 }
811
812 #[inline]
827 pub fn iter_u64_digits(&self) -> U64Digits<'_> {
828 U64Digits::new(&self.data)
829 }
830
831 #[inline]
843 pub fn to_str_radix(&self, radix: u32) -> String {
844 let mut v = to_str_radix_reversed(self, radix);
845 v.reverse();
846 unsafe { String::from_utf8_unchecked(v) }
847 }
848
849 #[inline]
864 pub fn to_radix_be(&self, radix: u32) -> Vec<u8> {
865 let mut v = convert::to_radix_le(self, radix);
866 v.reverse();
867 v
868 }
869
870 #[inline]
885 pub fn to_radix_le(&self, radix: u32) -> Vec<u8> {
886 convert::to_radix_le(self, radix)
887 }
888
889 #[inline]
891 pub fn bits(&self) -> u64 {
892 match self.data.last() {
893 Some(x) => {
894 let zeros: u64 = x.leading_zeros().into();
895 self.data.len() as u64 * u64::from(big_digit::BITS) - zeros
896 }
897 None => 0,
898 }
899 }
900
901 pub fn pow(&self, exponent: u32) -> Self {
903 Pow::pow(self, exponent)
904 }
905
906 pub fn modpow(&self, exponent: &Self, modulus: &Self) -> Self {
910 power::modpow(self, exponent, modulus)
911 }
912
913 pub fn modinv(&self, modulus: &Self) -> Option<Self> {
937 assert!(
942 !modulus.is_zero(),
943 "attempt to calculate with zero modulus!"
944 );
945 if modulus.is_one() {
946 return Some(Self::ZERO);
947 }
948
949 let mut r0; let mut r1 = self % modulus;
951 let mut t0; let mut t1; if r1.is_zero() {
956 return None;
957 } else if r1.is_one() {
958 return Some(r1);
959 } else {
960 let (q, r2) = modulus.div_rem(&r1);
961 if r2.is_zero() {
962 return None;
963 }
964 r0 = r1;
965 r1 = r2;
966 t0 = Self::ONE;
967 t1 = modulus - q;
968 }
969
970 while !r1.is_zero() {
971 let (q, r2) = r0.div_rem(&r1);
972 r0 = r1;
973 r1 = r2;
974
975 let qt1 = q * &t1 % modulus;
977 let t2 = if t0 < qt1 {
978 t0 + (modulus - qt1)
979 } else {
980 t0 - qt1
981 };
982 t0 = t1;
983 t1 = t2;
984 }
985
986 if r0.is_one() {
987 Some(t0)
988 } else {
989 None
990 }
991 }
992
993 pub fn sqrt(&self) -> Self {
996 Roots::sqrt(self)
997 }
998
999 pub fn cbrt(&self) -> Self {
1002 Roots::cbrt(self)
1003 }
1004
1005 pub fn nth_root(&self, n: u32) -> Self {
1008 Roots::nth_root(self, n)
1009 }
1010
1011 pub fn trailing_zeros(&self) -> Option<u64> {
1014 let data = &*self.data;
1015 let i = data.iter().position(|&digit| digit != 0)?;
1016 let zeros: u64 = data[i].trailing_zeros().into();
1017 Some(i as u64 * u64::from(big_digit::BITS) + zeros)
1018 }
1019
1020 pub fn trailing_ones(&self) -> u64 {
1022 let data = &*self.data;
1023 if let Some(i) = data.iter().position(|&digit| !digit != 0) {
1024 let ones: u64 = data[i].trailing_ones().into();
1025 i as u64 * u64::from(big_digit::BITS) + ones
1026 } else {
1027 data.len() as u64 * u64::from(big_digit::BITS)
1028 }
1029 }
1030
1031 pub fn count_ones(&self) -> u64 {
1033 self.data.iter().map(|&d| u64::from(d.count_ones())).sum()
1034 }
1035
1036 pub fn bit(&self, bit: u64) -> bool {
1038 let bits_per_digit = u64::from(big_digit::BITS);
1039 if let Some(digit_index) = (bit / bits_per_digit).to_usize() {
1040 if let Some(digit) = self.data.get(digit_index) {
1041 let bit_mask = (1 as BigDigit) << (bit % bits_per_digit);
1042 return (digit & bit_mask) != 0;
1043 }
1044 }
1045 false
1046 }
1047
1048 pub fn set_bit(&mut self, bit: u64, value: bool) {
1053 let bits_per_digit = u64::from(big_digit::BITS);
1056 let digit_index = (bit / bits_per_digit).to_usize().unwrap_or(usize::MAX);
1057 let bit_mask = (1 as BigDigit) << (bit % bits_per_digit);
1058 if value {
1059 if digit_index >= self.data.len() {
1060 let new_len = digit_index.saturating_add(1);
1061 self.data.resize(new_len, 0);
1062 }
1063 self.data[digit_index] |= bit_mask;
1064 } else if let Some(digit) = self.data.get_mut(digit_index) {
1065 *digit &= !bit_mask;
1066 if *digit == 0 && digit_index + 1 == self.data.len() {
1068 self.data.normalize();
1069 }
1070 }
1071 }
1072}
1073
1074impl num_traits::FromBytes for BigUint {
1075 type Bytes = [u8];
1076
1077 fn from_be_bytes(bytes: &Self::Bytes) -> Self {
1078 Self::from_bytes_be(bytes)
1079 }
1080
1081 fn from_le_bytes(bytes: &Self::Bytes) -> Self {
1082 Self::from_bytes_le(bytes)
1083 }
1084}
1085
1086impl num_traits::ToBytes for BigUint {
1087 type Bytes = Vec<u8>;
1088
1089 fn to_be_bytes(&self) -> Self::Bytes {
1090 self.to_bytes_be()
1091 }
1092
1093 fn to_le_bytes(&self) -> Self::Bytes {
1094 self.to_bytes_le()
1095 }
1096}
1097
1098pub(crate) trait IntDigits {
1099 fn digits(&self) -> &[BigDigit];
1100 fn digits_mut(&mut self) -> &mut BigDigits;
1101 fn normalize(&mut self);
1102 fn capacity(&self) -> usize;
1103 fn len(&self) -> usize;
1104}
1105
1106impl IntDigits for BigUint {
1107 #[inline]
1108 fn digits(&self) -> &[BigDigit] {
1109 &self.data
1110 }
1111 #[inline]
1112 fn digits_mut(&mut self) -> &mut BigDigits {
1113 &mut self.data
1114 }
1115 #[inline]
1116 fn normalize(&mut self) {
1117 self.data.normalize();
1118 }
1119 #[inline]
1120 fn capacity(&self) -> usize {
1121 self.data.capacity()
1122 }
1123 #[inline]
1124 fn len(&self) -> usize {
1125 self.data.len()
1126 }
1127}
1128
1129#[inline]
1131fn u32_chunk_to_u64(chunk: &[u32]) -> u64 {
1132 let mut digit = chunk[0] as u64;
1134 if let Some(&hi) = chunk.get(1) {
1135 digit |= (hi as u64) << 32;
1136 }
1137 digit
1138}
1139
1140cfg_32_or_test!(
1141 #[inline]
1143 fn u32_to_u128(a: u32, b: u32, c: u32, d: u32) -> u128 {
1144 u128::from(d) | (u128::from(c) << 32) | (u128::from(b) << 64) | (u128::from(a) << 96)
1145 }
1146);
1147
1148cfg_32_or_test!(
1149 #[inline]
1151 fn u32_from_u128(n: u128) -> (u32, u32, u32, u32) {
1152 (
1153 (n >> 96) as u32,
1154 (n >> 64) as u32,
1155 (n >> 32) as u32,
1156 n as u32,
1157 )
1158 }
1159);
1160
1161cfg_digit!(
1162 #[test]
1163 fn test_from_slice() {
1164 fn check(slice: &[u32], data: &[BigDigit]) {
1165 assert_eq!(*BigUint::from_slice(slice).data, *data);
1166 }
1167 check(&[1], &[1]);
1168 check(&[0, 0, 0], &[]);
1169 check(&[1, 2, 0, 0], &[1, 2]);
1170 check(&[0, 0, 1, 2], &[0, 0, 1, 2]);
1171 check(&[0, 0, 1, 2, 0, 0], &[0, 0, 1, 2]);
1172 check(&[-1i32 as u32], &[-1i32 as BigDigit]);
1173 }
1174
1175 #[test]
1176 fn test_from_slice() {
1177 fn check(slice: &[u32], data: &[BigDigit]) {
1178 assert_eq!(
1179 *BigUint::from_slice(slice).data,
1180 *data,
1181 "from {:?}, to {:?}",
1182 slice,
1183 data
1184 );
1185 }
1186 check(&[1], &[1]);
1187 check(&[0, 0, 0], &[]);
1188 check(&[1, 2], &[8_589_934_593]);
1189 check(&[1, 2, 0, 0], &[8_589_934_593]);
1190 check(&[0, 0, 1, 2], &[0, 8_589_934_593]);
1191 check(&[0, 0, 1, 2, 0, 0], &[0, 8_589_934_593]);
1192 check(&[-1i32 as u32], &[(-1i32 as u32) as BigDigit]);
1193 }
1194);
1195
1196#[test]
1197fn test_u32_u128() {
1198 assert_eq!(u32_from_u128(0u128), (0, 0, 0, 0));
1199 assert_eq!(
1200 u32_from_u128(u128::MAX),
1201 (u32::MAX, u32::MAX, u32::MAX, u32::MAX)
1202 );
1203
1204 assert_eq!(u32_from_u128(u32::MAX as u128), (0, 0, 0, u32::MAX));
1205
1206 assert_eq!(u32_from_u128(u64::MAX as u128), (0, 0, u32::MAX, u32::MAX));
1207
1208 assert_eq!(
1209 u32_from_u128((u64::MAX as u128) + u32::MAX as u128),
1210 (0, 1, 0, u32::MAX - 1)
1211 );
1212
1213 assert_eq!(u32_from_u128(36_893_488_151_714_070_528), (0, 2, 1, 0));
1214}
1215
1216#[test]
1217fn test_u128_u32_roundtrip() {
1218 let values = vec![
1220 0u128,
1221 1u128,
1222 u64::MAX as u128 * 3,
1223 u32::MAX as u128,
1224 u64::MAX as u128,
1225 (u64::MAX as u128) + u32::MAX as u128,
1226 u128::MAX,
1227 ];
1228
1229 for val in &values {
1230 let (a, b, c, d) = u32_from_u128(*val);
1231 assert_eq!(u32_to_u128(a, b, c, d), *val);
1232 }
1233}