1use crate::big_digit::{self, BigDigit};
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::{ConstZero, Num, One, Pow, ToPrimitive, Unsigned, Zero};
15
16mod addition;
17mod division;
18mod multiplication;
19mod subtraction;
20
21mod arbitrary;
22mod bits;
23mod convert;
24mod iter;
25mod monty;
26mod power;
27mod serde;
28mod shift;
29
30pub(crate) use self::convert::to_str_radix_reversed;
31pub use self::iter::{U32Digits, U64Digits};
32
33pub struct BigUint {
35 data: Vec<BigDigit>,
36}
37
38impl Clone for BigUint {
41 #[inline]
42 fn clone(&self) -> Self {
43 BigUint {
44 data: self.data.clone(),
45 }
46 }
47
48 #[inline]
49 fn clone_from(&mut self, other: &Self) {
50 self.data.clone_from(&other.data);
51 }
52}
53
54impl hash::Hash for BigUint {
55 #[inline]
56 fn hash<H: hash::Hasher>(&self, state: &mut H) {
57 debug_assert!(self.data.last() != Some(&0));
58 self.data.hash(state);
59 }
60}
61
62impl PartialEq for BigUint {
63 #[inline]
64 fn eq(&self, other: &BigUint) -> bool {
65 debug_assert!(self.data.last() != Some(&0));
66 debug_assert!(other.data.last() != Some(&0));
67 self.data == other.data
68 }
69}
70impl Eq for BigUint {}
71
72impl PartialOrd for BigUint {
73 #[inline]
74 fn partial_cmp(&self, other: &BigUint) -> Option<Ordering> {
75 Some(self.cmp(other))
76 }
77}
78
79impl Ord for BigUint {
80 #[inline]
81 fn cmp(&self, other: &BigUint) -> Ordering {
82 cmp_slice(&self.data[..], &other.data[..])
83 }
84}
85
86#[inline]
87fn cmp_slice(a: &[BigDigit], b: &[BigDigit]) -> Ordering {
88 debug_assert!(a.last() != Some(&0));
89 debug_assert!(b.last() != Some(&0));
90
91 match Ord::cmp(&a.len(), &b.len()) {
92 Ordering::Equal => Iterator::cmp(a.iter().rev(), b.iter().rev()),
93 other => other,
94 }
95}
96
97impl Default for BigUint {
98 #[inline]
99 fn default() -> BigUint {
100 Self::ZERO
101 }
102}
103
104impl fmt::Debug for BigUint {
105 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
106 fmt::Display::fmt(self, f)
107 }
108}
109
110impl fmt::Display for BigUint {
111 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
112 f.pad_integral(true, "", &self.to_str_radix(10))
113 }
114}
115
116impl fmt::LowerHex for BigUint {
117 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
118 f.pad_integral(true, "0x", &self.to_str_radix(16))
119 }
120}
121
122impl fmt::UpperHex for BigUint {
123 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
124 let mut s = self.to_str_radix(16);
125 s.make_ascii_uppercase();
126 f.pad_integral(true, "0x", &s)
127 }
128}
129
130impl fmt::Binary for BigUint {
131 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
132 f.pad_integral(true, "0b", &self.to_str_radix(2))
133 }
134}
135
136impl fmt::Octal for BigUint {
137 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
138 f.pad_integral(true, "0o", &self.to_str_radix(8))
139 }
140}
141
142impl Zero for BigUint {
143 #[inline]
144 fn zero() -> BigUint {
145 Self::ZERO
146 }
147
148 #[inline]
149 fn set_zero(&mut self) {
150 self.data.clear();
151 }
152
153 #[inline]
154 fn is_zero(&self) -> bool {
155 self.data.is_empty()
156 }
157}
158
159impl ConstZero for BigUint {
160 const ZERO: Self = Self::ZERO; }
163
164impl One for BigUint {
165 #[inline]
166 fn one() -> BigUint {
167 BigUint { data: vec![1] }
168 }
169
170 #[inline]
171 fn set_one(&mut self) {
172 self.data.clear();
173 self.data.push(1);
174 }
175
176 #[inline]
177 fn is_one(&self) -> bool {
178 self.data[..] == [1]
179 }
180}
181
182impl Unsigned for BigUint {}
183
184impl Integer for BigUint {
185 #[inline]
186 fn div_rem(&self, other: &BigUint) -> (BigUint, BigUint) {
187 division::div_rem_ref(self, other)
188 }
189
190 #[inline]
191 fn div_floor(&self, other: &BigUint) -> BigUint {
192 let (d, _) = division::div_rem_ref(self, other);
193 d
194 }
195
196 #[inline]
197 fn mod_floor(&self, other: &BigUint) -> BigUint {
198 let (_, m) = division::div_rem_ref(self, other);
199 m
200 }
201
202 #[inline]
203 fn div_mod_floor(&self, other: &BigUint) -> (BigUint, BigUint) {
204 division::div_rem_ref(self, other)
205 }
206
207 #[inline]
208 fn div_ceil(&self, other: &BigUint) -> BigUint {
209 let (d, m) = division::div_rem_ref(self, other);
210 if m.is_zero() {
211 d
212 } else {
213 d + 1u32
214 }
215 }
216
217 #[inline]
221 fn gcd(&self, other: &Self) -> Self {
222 #[inline]
223 fn twos(x: &BigUint) -> u64 {
224 x.trailing_zeros().unwrap_or(0)
225 }
226
227 if self.is_zero() {
229 return other.clone();
230 }
231 if other.is_zero() {
232 return self.clone();
233 }
234 let mut m = self.clone();
235 let mut n = other.clone();
236
237 let shift = cmp::min(twos(&n), twos(&m));
239
240 n >>= twos(&n);
243
244 while !m.is_zero() {
245 m >>= twos(&m);
246 if n > m {
247 mem::swap(&mut n, &mut m)
248 }
249 m -= &n;
250 }
251
252 n << shift
253 }
254
255 #[inline]
257 fn lcm(&self, other: &BigUint) -> BigUint {
258 if self.is_zero() && other.is_zero() {
259 Self::ZERO
260 } else {
261 self / self.gcd(other) * other
262 }
263 }
264
265 #[inline]
268 fn gcd_lcm(&self, other: &Self) -> (Self, Self) {
269 let gcd = self.gcd(other);
270 let lcm = if gcd.is_zero() {
271 Self::ZERO
272 } else {
273 self / &gcd * other
274 };
275 (gcd, lcm)
276 }
277
278 #[inline]
280 fn divides(&self, other: &BigUint) -> bool {
281 self.is_multiple_of(other)
282 }
283
284 #[inline]
286 fn is_multiple_of(&self, other: &BigUint) -> bool {
287 if other.is_zero() {
288 return self.is_zero();
289 }
290 (self % other).is_zero()
291 }
292
293 #[inline]
295 fn is_even(&self) -> bool {
296 match self.data.first() {
298 Some(x) => x.is_even(),
299 None => true,
300 }
301 }
302
303 #[inline]
305 fn is_odd(&self) -> bool {
306 !self.is_even()
307 }
308
309 #[inline]
311 fn next_multiple_of(&self, other: &Self) -> Self {
312 let m = self.mod_floor(other);
313 if m.is_zero() {
314 self.clone()
315 } else {
316 self + (other - m)
317 }
318 }
319 #[inline]
321 fn prev_multiple_of(&self, other: &Self) -> Self {
322 self - self.mod_floor(other)
323 }
324
325 fn dec(&mut self) {
326 *self -= 1u32;
327 }
328
329 fn inc(&mut self) {
330 *self += 1u32;
331 }
332}
333
334#[inline]
335fn fixpoint<F>(mut x: BigUint, max_bits: u64, f: F) -> BigUint
336where
337 F: Fn(&BigUint) -> BigUint,
338{
339 let mut xn = f(&x);
340
341 while x < xn {
344 x = if xn.bits() > max_bits {
348 BigUint::one() << max_bits
349 } else {
350 xn
351 };
352 xn = f(&x);
353 }
354
355 while x > xn {
357 x = xn;
358 xn = f(&x);
359 }
360 x
361}
362
363impl Roots for BigUint {
364 fn nth_root(&self, n: u32) -> Self {
370 assert!(n > 0, "root degree n must be at least 1");
371
372 if self.is_zero() || self.is_one() {
373 return self.clone();
374 }
375
376 match n {
377 1 => return self.clone(),
379 2 => return self.sqrt(),
380 3 => return self.cbrt(),
381 _ => (),
382 }
383
384 let bits = self.bits();
386 let n64 = u64::from(n);
387 if bits <= n64 {
388 return BigUint::one();
389 }
390
391 if let Some(x) = self.to_u64() {
393 return x.nth_root(n).into();
394 }
395
396 let max_bits = bits / n64 + 1;
397
398 #[cfg(feature = "std")]
399 let guess = match self.to_f64() {
400 Some(f) if f.is_finite() => {
401 use num_traits::FromPrimitive;
402
403 BigUint::from_f64((f.ln() / f64::from(n)).exp()).unwrap()
405 }
406 _ => {
407 let extra_bits = bits - (f64::MAX_EXP as u64 - 1);
410 let root_scale = Integer::div_ceil(&extra_bits, &n64);
411 let scale = root_scale * n64;
412 if scale < bits && bits - scale > n64 {
413 (self >> scale).nth_root(n) << root_scale
414 } else {
415 BigUint::one() << max_bits
416 }
417 }
418 };
419
420 #[cfg(not(feature = "std"))]
421 let guess = BigUint::one() << max_bits;
422
423 let n_min_1 = n - 1;
424 fixpoint(guess, max_bits, move |s| {
425 let q = self / s.pow(n_min_1);
426 let t = n_min_1 * s + q;
427 t / n
428 })
429 }
430
431 fn sqrt(&self) -> Self {
434 if self.is_zero() || self.is_one() {
435 return self.clone();
436 }
437
438 if let Some(x) = self.to_u64() {
440 return x.sqrt().into();
441 }
442
443 let bits = self.bits();
444 let max_bits = bits / 2 + 1;
445
446 #[cfg(feature = "std")]
447 let guess = match self.to_f64() {
448 Some(f) if f.is_finite() => {
449 use num_traits::FromPrimitive;
450
451 BigUint::from_f64(f.sqrt()).unwrap()
453 }
454 _ => {
455 let extra_bits = bits - (f64::MAX_EXP as u64 - 1);
458 let root_scale = (extra_bits + 1) / 2;
459 let scale = root_scale * 2;
460 (self >> scale).sqrt() << root_scale
461 }
462 };
463
464 #[cfg(not(feature = "std"))]
465 let guess = BigUint::one() << max_bits;
466
467 fixpoint(guess, max_bits, move |s| {
468 let q = self / s;
469 let t = s + q;
470 t >> 1
471 })
472 }
473
474 fn cbrt(&self) -> Self {
475 if self.is_zero() || self.is_one() {
476 return self.clone();
477 }
478
479 if let Some(x) = self.to_u64() {
481 return x.cbrt().into();
482 }
483
484 let bits = self.bits();
485 let max_bits = bits / 3 + 1;
486
487 #[cfg(feature = "std")]
488 let guess = match self.to_f64() {
489 Some(f) if f.is_finite() => {
490 use num_traits::FromPrimitive;
491
492 BigUint::from_f64(f.cbrt()).unwrap()
494 }
495 _ => {
496 let extra_bits = bits - (f64::MAX_EXP as u64 - 1);
499 let root_scale = (extra_bits + 2) / 3;
500 let scale = root_scale * 3;
501 (self >> scale).cbrt() << root_scale
502 }
503 };
504
505 #[cfg(not(feature = "std"))]
506 let guess = BigUint::one() << max_bits;
507
508 fixpoint(guess, max_bits, move |s| {
509 let q = self / (s * s);
510 let t = (s << 1) + q;
511 t / 3u32
512 })
513 }
514}
515
516pub trait ToBigUint {
518 fn to_biguint(&self) -> Option<BigUint>;
520}
521
522#[inline]
526pub(crate) fn biguint_from_vec(digits: Vec<BigDigit>) -> BigUint {
527 BigUint { data: digits }.normalized()
528}
529
530impl BigUint {
531 pub const ZERO: Self = BigUint { data: Vec::new() };
533
534 #[inline]
538 pub fn new(digits: Vec<u32>) -> BigUint {
539 let mut big = Self::ZERO;
540
541 cfg_digit_expr!(
542 {
543 big.data = digits;
544 big.normalize();
545 },
546 big.assign_from_slice(&digits)
547 );
548
549 big
550 }
551
552 #[inline]
556 pub fn from_slice(slice: &[u32]) -> BigUint {
557 let mut big = Self::ZERO;
558 big.assign_from_slice(slice);
559 big
560 }
561
562 #[inline]
566 pub fn assign_from_slice(&mut self, slice: &[u32]) {
567 self.data.clear();
568
569 cfg_digit_expr!(
570 self.data.extend_from_slice(slice),
571 self.data.extend(slice.chunks(2).map(u32_chunk_to_u64))
572 );
573
574 self.normalize();
575 }
576
577 #[inline]
596 pub fn from_bytes_be(bytes: &[u8]) -> BigUint {
597 if bytes.is_empty() {
598 Self::ZERO
599 } else {
600 let mut v = bytes.to_vec();
601 v.reverse();
602 BigUint::from_bytes_le(&v)
603 }
604 }
605
606 #[inline]
610 pub fn from_bytes_le(bytes: &[u8]) -> BigUint {
611 if bytes.is_empty() {
612 Self::ZERO
613 } else {
614 convert::from_bitwise_digits_le(bytes, 8)
615 }
616 }
617
618 #[inline]
635 pub fn parse_bytes(buf: &[u8], radix: u32) -> Option<BigUint> {
636 let s = str::from_utf8(buf).ok()?;
637 BigUint::from_str_radix(s, radix).ok()
638 }
639
640 pub fn from_radix_be(buf: &[u8], radix: u32) -> Option<BigUint> {
657 convert::from_radix_be(buf, radix)
658 }
659
660 pub fn from_radix_le(buf: &[u8], radix: u32) -> Option<BigUint> {
677 convert::from_radix_le(buf, radix)
678 }
679
680 #[inline]
691 pub fn to_bytes_be(&self) -> Vec<u8> {
692 let mut v = self.to_bytes_le();
693 v.reverse();
694 v
695 }
696
697 #[inline]
708 pub fn to_bytes_le(&self) -> Vec<u8> {
709 if self.is_zero() {
710 vec![0]
711 } else {
712 convert::to_bitwise_digits_le(self, 8)
713 }
714 }
715
716 #[inline]
730 pub fn to_u32_digits(&self) -> Vec<u32> {
731 self.iter_u32_digits().collect()
732 }
733
734 #[inline]
749 pub fn to_u64_digits(&self) -> Vec<u64> {
750 self.iter_u64_digits().collect()
751 }
752
753 #[inline]
767 pub fn iter_u32_digits(&self) -> U32Digits<'_> {
768 U32Digits::new(self.data.as_slice())
769 }
770
771 #[inline]
786 pub fn iter_u64_digits(&self) -> U64Digits<'_> {
787 U64Digits::new(self.data.as_slice())
788 }
789
790 #[inline]
802 pub fn to_str_radix(&self, radix: u32) -> String {
803 let mut v = to_str_radix_reversed(self, radix);
804 v.reverse();
805 unsafe { String::from_utf8_unchecked(v) }
806 }
807
808 #[inline]
823 pub fn to_radix_be(&self, radix: u32) -> Vec<u8> {
824 let mut v = convert::to_radix_le(self, radix);
825 v.reverse();
826 v
827 }
828
829 #[inline]
844 pub fn to_radix_le(&self, radix: u32) -> Vec<u8> {
845 convert::to_radix_le(self, radix)
846 }
847
848 #[inline]
850 pub fn bits(&self) -> u64 {
851 if self.is_zero() {
852 return 0;
853 }
854 let zeros: u64 = self.data.last().unwrap().leading_zeros().into();
855 self.data.len() as u64 * u64::from(big_digit::BITS) - zeros
856 }
857
858 #[inline]
861 fn normalize(&mut self) {
862 if let Some(&0) = self.data.last() {
863 let len = self.data.iter().rposition(|&d| d != 0).map_or(0, |i| i + 1);
864 self.data.truncate(len);
865 }
866 if self.data.len() < self.data.capacity() / 4 {
867 self.data.shrink_to_fit();
868 }
869 }
870
871 #[inline]
873 fn normalized(mut self) -> BigUint {
874 self.normalize();
875 self
876 }
877
878 pub fn pow(&self, exponent: u32) -> Self {
880 Pow::pow(self, exponent)
881 }
882
883 pub fn modpow(&self, exponent: &Self, modulus: &Self) -> Self {
887 power::modpow(self, exponent, modulus)
888 }
889
890 pub fn modinv(&self, modulus: &Self) -> Option<Self> {
914 assert!(
919 !modulus.is_zero(),
920 "attempt to calculate with zero modulus!"
921 );
922 if modulus.is_one() {
923 return Some(Self::zero());
924 }
925
926 let mut r0; let mut r1 = self % modulus;
928 let mut t0; let mut t1; if r1.is_zero() {
933 return None;
934 } else if r1.is_one() {
935 return Some(r1);
936 } else {
937 let (q, r2) = modulus.div_rem(&r1);
938 if r2.is_zero() {
939 return None;
940 }
941 r0 = r1;
942 r1 = r2;
943 t0 = Self::one();
944 t1 = modulus - q;
945 }
946
947 while !r1.is_zero() {
948 let (q, r2) = r0.div_rem(&r1);
949 r0 = r1;
950 r1 = r2;
951
952 let qt1 = q * &t1 % modulus;
954 let t2 = if t0 < qt1 {
955 t0 + (modulus - qt1)
956 } else {
957 t0 - qt1
958 };
959 t0 = t1;
960 t1 = t2;
961 }
962
963 if r0.is_one() {
964 Some(t0)
965 } else {
966 None
967 }
968 }
969
970 pub fn sqrt(&self) -> Self {
973 Roots::sqrt(self)
974 }
975
976 pub fn cbrt(&self) -> Self {
979 Roots::cbrt(self)
980 }
981
982 pub fn nth_root(&self, n: u32) -> Self {
985 Roots::nth_root(self, n)
986 }
987
988 pub fn trailing_zeros(&self) -> Option<u64> {
991 let i = self.data.iter().position(|&digit| digit != 0)?;
992 let zeros: u64 = self.data[i].trailing_zeros().into();
993 Some(i as u64 * u64::from(big_digit::BITS) + zeros)
994 }
995
996 pub fn trailing_ones(&self) -> u64 {
998 if let Some(i) = self.data.iter().position(|&digit| !digit != 0) {
999 let ones: u64 = self.data[i].trailing_ones().into();
1000 i as u64 * u64::from(big_digit::BITS) + ones
1001 } else {
1002 self.data.len() as u64 * u64::from(big_digit::BITS)
1003 }
1004 }
1005
1006 pub fn count_ones(&self) -> u64 {
1008 self.data.iter().map(|&d| u64::from(d.count_ones())).sum()
1009 }
1010
1011 pub fn bit(&self, bit: u64) -> bool {
1013 let bits_per_digit = u64::from(big_digit::BITS);
1014 if let Some(digit_index) = (bit / bits_per_digit).to_usize() {
1015 if let Some(digit) = self.data.get(digit_index) {
1016 let bit_mask = (1 as BigDigit) << (bit % bits_per_digit);
1017 return (digit & bit_mask) != 0;
1018 }
1019 }
1020 false
1021 }
1022
1023 pub fn set_bit(&mut self, bit: u64, value: bool) {
1028 let bits_per_digit = u64::from(big_digit::BITS);
1031 let digit_index = (bit / bits_per_digit).to_usize().unwrap_or(usize::MAX);
1032 let bit_mask = (1 as BigDigit) << (bit % bits_per_digit);
1033 if value {
1034 if digit_index >= self.data.len() {
1035 let new_len = digit_index.saturating_add(1);
1036 self.data.resize(new_len, 0);
1037 }
1038 self.data[digit_index] |= bit_mask;
1039 } else if digit_index < self.data.len() {
1040 self.data[digit_index] &= !bit_mask;
1041 self.normalize();
1043 }
1044 }
1045}
1046
1047impl num_traits::FromBytes for BigUint {
1048 type Bytes = [u8];
1049
1050 fn from_be_bytes(bytes: &Self::Bytes) -> Self {
1051 Self::from_bytes_be(bytes)
1052 }
1053
1054 fn from_le_bytes(bytes: &Self::Bytes) -> Self {
1055 Self::from_bytes_le(bytes)
1056 }
1057}
1058
1059impl num_traits::ToBytes for BigUint {
1060 type Bytes = Vec<u8>;
1061
1062 fn to_be_bytes(&self) -> Self::Bytes {
1063 self.to_bytes_be()
1064 }
1065
1066 fn to_le_bytes(&self) -> Self::Bytes {
1067 self.to_bytes_le()
1068 }
1069}
1070
1071pub(crate) trait IntDigits {
1072 fn digits(&self) -> &[BigDigit];
1073 fn digits_mut(&mut self) -> &mut Vec<BigDigit>;
1074 fn normalize(&mut self);
1075 fn capacity(&self) -> usize;
1076 fn len(&self) -> usize;
1077}
1078
1079impl IntDigits for BigUint {
1080 #[inline]
1081 fn digits(&self) -> &[BigDigit] {
1082 &self.data
1083 }
1084 #[inline]
1085 fn digits_mut(&mut self) -> &mut Vec<BigDigit> {
1086 &mut self.data
1087 }
1088 #[inline]
1089 fn normalize(&mut self) {
1090 self.normalize();
1091 }
1092 #[inline]
1093 fn capacity(&self) -> usize {
1094 self.data.capacity()
1095 }
1096 #[inline]
1097 fn len(&self) -> usize {
1098 self.data.len()
1099 }
1100}
1101
1102#[inline]
1104fn u32_chunk_to_u64(chunk: &[u32]) -> u64 {
1105 let mut digit = chunk[0] as u64;
1107 if let Some(&hi) = chunk.get(1) {
1108 digit |= (hi as u64) << 32;
1109 }
1110 digit
1111}
1112
1113cfg_32_or_test!(
1114 #[inline]
1116 fn u32_to_u128(a: u32, b: u32, c: u32, d: u32) -> u128 {
1117 u128::from(d) | (u128::from(c) << 32) | (u128::from(b) << 64) | (u128::from(a) << 96)
1118 }
1119);
1120
1121cfg_32_or_test!(
1122 #[inline]
1124 fn u32_from_u128(n: u128) -> (u32, u32, u32, u32) {
1125 (
1126 (n >> 96) as u32,
1127 (n >> 64) as u32,
1128 (n >> 32) as u32,
1129 n as u32,
1130 )
1131 }
1132);
1133
1134cfg_digit!(
1135 #[test]
1136 fn test_from_slice() {
1137 fn check(slice: &[u32], data: &[BigDigit]) {
1138 assert_eq!(BigUint::from_slice(slice).data, data);
1139 }
1140 check(&[1], &[1]);
1141 check(&[0, 0, 0], &[]);
1142 check(&[1, 2, 0, 0], &[1, 2]);
1143 check(&[0, 0, 1, 2], &[0, 0, 1, 2]);
1144 check(&[0, 0, 1, 2, 0, 0], &[0, 0, 1, 2]);
1145 check(&[-1i32 as u32], &[-1i32 as BigDigit]);
1146 }
1147
1148 #[test]
1149 fn test_from_slice() {
1150 fn check(slice: &[u32], data: &[BigDigit]) {
1151 assert_eq!(
1152 BigUint::from_slice(slice).data,
1153 data,
1154 "from {:?}, to {:?}",
1155 slice,
1156 data
1157 );
1158 }
1159 check(&[1], &[1]);
1160 check(&[0, 0, 0], &[]);
1161 check(&[1, 2], &[8_589_934_593]);
1162 check(&[1, 2, 0, 0], &[8_589_934_593]);
1163 check(&[0, 0, 1, 2], &[0, 8_589_934_593]);
1164 check(&[0, 0, 1, 2, 0, 0], &[0, 8_589_934_593]);
1165 check(&[-1i32 as u32], &[(-1i32 as u32) as BigDigit]);
1166 }
1167);
1168
1169#[test]
1170fn test_u32_u128() {
1171 assert_eq!(u32_from_u128(0u128), (0, 0, 0, 0));
1172 assert_eq!(
1173 u32_from_u128(u128::MAX),
1174 (u32::MAX, u32::MAX, u32::MAX, u32::MAX)
1175 );
1176
1177 assert_eq!(u32_from_u128(u32::MAX as u128), (0, 0, 0, u32::MAX));
1178
1179 assert_eq!(u32_from_u128(u64::MAX as u128), (0, 0, u32::MAX, u32::MAX));
1180
1181 assert_eq!(
1182 u32_from_u128((u64::MAX as u128) + u32::MAX as u128),
1183 (0, 1, 0, u32::MAX - 1)
1184 );
1185
1186 assert_eq!(u32_from_u128(36_893_488_151_714_070_528), (0, 2, 1, 0));
1187}
1188
1189#[test]
1190fn test_u128_u32_roundtrip() {
1191 let values = vec![
1193 0u128,
1194 1u128,
1195 u64::MAX as u128 * 3,
1196 u32::MAX as u128,
1197 u64::MAX as u128,
1198 (u64::MAX as u128) + u32::MAX as u128,
1199 u128::MAX,
1200 ];
1201
1202 for val in &values {
1203 let (a, b, c, d) = u32_from_u128(*val);
1204 assert_eq!(u32_to_u128(a, b, c, d), *val);
1205 }
1206}