• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use super::{biguint_from_vec, BigUint, ToBigUint};
2 
3 use super::addition::add2;
4 use super::division::div_rem_digit;
5 use super::multiplication::mac_with_carry;
6 
7 use crate::big_digit::{self, BigDigit};
8 use crate::std_alloc::Vec;
9 use crate::ParseBigIntError;
10 #[cfg(has_try_from)]
11 use crate::TryFromBigIntError;
12 
13 use core::cmp::Ordering::{Equal, Greater, Less};
14 #[cfg(has_try_from)]
15 use core::convert::TryFrom;
16 use core::mem;
17 use core::str::FromStr;
18 use num_integer::{Integer, Roots};
19 use num_traits::float::FloatCore;
20 use num_traits::{FromPrimitive, Num, PrimInt, ToPrimitive, Zero};
21 
22 /// Find last set bit
23 /// fls(0) == 0, fls(u32::MAX) == 32
fls<T: PrimInt>(v: T) -> u824 fn fls<T: PrimInt>(v: T) -> u8 {
25     mem::size_of::<T>() as u8 * 8 - v.leading_zeros() as u8
26 }
27 
ilog2<T: PrimInt>(v: T) -> u828 fn ilog2<T: PrimInt>(v: T) -> u8 {
29     fls(v) - 1
30 }
31 
32 impl FromStr for BigUint {
33     type Err = ParseBigIntError;
34 
35     #[inline]
from_str(s: &str) -> Result<BigUint, ParseBigIntError>36     fn from_str(s: &str) -> Result<BigUint, ParseBigIntError> {
37         BigUint::from_str_radix(s, 10)
38     }
39 }
40 
41 // Convert from a power of two radix (bits == ilog2(radix)) where bits evenly divides
42 // BigDigit::BITS
from_bitwise_digits_le(v: &[u8], bits: u8) -> BigUint43 pub(super) fn from_bitwise_digits_le(v: &[u8], bits: u8) -> BigUint {
44     debug_assert!(!v.is_empty() && bits <= 8 && big_digit::BITS % bits == 0);
45     debug_assert!(v.iter().all(|&c| BigDigit::from(c) < (1 << bits)));
46 
47     let digits_per_big_digit = big_digit::BITS / bits;
48 
49     let data = v
50         .chunks(digits_per_big_digit.into())
51         .map(|chunk| {
52             chunk
53                 .iter()
54                 .rev()
55                 .fold(0, |acc, &c| (acc << bits) | BigDigit::from(c))
56         })
57         .collect();
58 
59     biguint_from_vec(data)
60 }
61 
62 // Convert from a power of two radix (bits == ilog2(radix)) where bits doesn't evenly divide
63 // BigDigit::BITS
from_inexact_bitwise_digits_le(v: &[u8], bits: u8) -> BigUint64 fn from_inexact_bitwise_digits_le(v: &[u8], bits: u8) -> BigUint {
65     debug_assert!(!v.is_empty() && bits <= 8 && big_digit::BITS % bits != 0);
66     debug_assert!(v.iter().all(|&c| BigDigit::from(c) < (1 << bits)));
67 
68     let total_bits = (v.len() as u64).saturating_mul(bits.into());
69     let big_digits = Integer::div_ceil(&total_bits, &big_digit::BITS.into())
70         .to_usize()
71         .unwrap_or(core::usize::MAX);
72     let mut data = Vec::with_capacity(big_digits);
73 
74     let mut d = 0;
75     let mut dbits = 0; // number of bits we currently have in d
76 
77     // walk v accumululating bits in d; whenever we accumulate big_digit::BITS in d, spit out a
78     // big_digit:
79     for &c in v {
80         d |= BigDigit::from(c) << dbits;
81         dbits += bits;
82 
83         if dbits >= big_digit::BITS {
84             data.push(d);
85             dbits -= big_digit::BITS;
86             // if dbits was > big_digit::BITS, we dropped some of the bits in c (they couldn't fit
87             // in d) - grab the bits we lost here:
88             d = BigDigit::from(c) >> (bits - dbits);
89         }
90     }
91 
92     if dbits > 0 {
93         debug_assert!(dbits < big_digit::BITS);
94         data.push(d as BigDigit);
95     }
96 
97     biguint_from_vec(data)
98 }
99 
100 // Read little-endian radix digits
from_radix_digits_be(v: &[u8], radix: u32) -> BigUint101 fn from_radix_digits_be(v: &[u8], radix: u32) -> BigUint {
102     debug_assert!(!v.is_empty() && !radix.is_power_of_two());
103     debug_assert!(v.iter().all(|&c| u32::from(c) < radix));
104 
105     #[cfg(feature = "std")]
106     let radix_log2 = f64::from(radix).log2();
107     #[cfg(not(feature = "std"))]
108     let radix_log2 = ilog2(radix.next_power_of_two()) as f64;
109 
110     // Estimate how big the result will be, so we can pre-allocate it.
111     let bits = radix_log2 * v.len() as f64;
112     let big_digits = (bits / big_digit::BITS as f64).ceil();
113     let mut data = Vec::with_capacity(big_digits.to_usize().unwrap_or(0));
114 
115     let (base, power) = get_radix_base(radix, big_digit::BITS);
116     let radix = radix as BigDigit;
117 
118     let r = v.len() % power;
119     let i = if r == 0 { power } else { r };
120     let (head, tail) = v.split_at(i);
121 
122     let first = head
123         .iter()
124         .fold(0, |acc, &d| acc * radix + BigDigit::from(d));
125     data.push(first);
126 
127     debug_assert!(tail.len() % power == 0);
128     for chunk in tail.chunks(power) {
129         if data.last() != Some(&0) {
130             data.push(0);
131         }
132 
133         let mut carry = 0;
134         for d in data.iter_mut() {
135             *d = mac_with_carry(0, *d, base, &mut carry);
136         }
137         debug_assert!(carry == 0);
138 
139         let n = chunk
140             .iter()
141             .fold(0, |acc, &d| acc * radix + BigDigit::from(d));
142         add2(&mut data, &[n]);
143     }
144 
145     biguint_from_vec(data)
146 }
147 
from_radix_be(buf: &[u8], radix: u32) -> Option<BigUint>148 pub(super) fn from_radix_be(buf: &[u8], radix: u32) -> Option<BigUint> {
149     assert!(
150         2 <= radix && radix <= 256,
151         "The radix must be within 2...256"
152     );
153 
154     if buf.is_empty() {
155         return Some(Zero::zero());
156     }
157 
158     if radix != 256 && buf.iter().any(|&b| b >= radix as u8) {
159         return None;
160     }
161 
162     let res = if radix.is_power_of_two() {
163         // Powers of two can use bitwise masks and shifting instead of multiplication
164         let bits = ilog2(radix);
165         let mut v = Vec::from(buf);
166         v.reverse();
167         if big_digit::BITS % bits == 0 {
168             from_bitwise_digits_le(&v, bits)
169         } else {
170             from_inexact_bitwise_digits_le(&v, bits)
171         }
172     } else {
173         from_radix_digits_be(buf, radix)
174     };
175 
176     Some(res)
177 }
178 
from_radix_le(buf: &[u8], radix: u32) -> Option<BigUint>179 pub(super) fn from_radix_le(buf: &[u8], radix: u32) -> Option<BigUint> {
180     assert!(
181         2 <= radix && radix <= 256,
182         "The radix must be within 2...256"
183     );
184 
185     if buf.is_empty() {
186         return Some(Zero::zero());
187     }
188 
189     if radix != 256 && buf.iter().any(|&b| b >= radix as u8) {
190         return None;
191     }
192 
193     let res = if radix.is_power_of_two() {
194         // Powers of two can use bitwise masks and shifting instead of multiplication
195         let bits = ilog2(radix);
196         if big_digit::BITS % bits == 0 {
197             from_bitwise_digits_le(buf, bits)
198         } else {
199             from_inexact_bitwise_digits_le(buf, bits)
200         }
201     } else {
202         let mut v = Vec::from(buf);
203         v.reverse();
204         from_radix_digits_be(&v, radix)
205     };
206 
207     Some(res)
208 }
209 
210 impl Num for BigUint {
211     type FromStrRadixErr = ParseBigIntError;
212 
213     /// Creates and initializes a `BigUint`.
from_str_radix(s: &str, radix: u32) -> Result<BigUint, ParseBigIntError>214     fn from_str_radix(s: &str, radix: u32) -> Result<BigUint, ParseBigIntError> {
215         assert!(2 <= radix && radix <= 36, "The radix must be within 2...36");
216         let mut s = s;
217         if s.starts_with('+') {
218             let tail = &s[1..];
219             if !tail.starts_with('+') {
220                 s = tail
221             }
222         }
223 
224         if s.is_empty() {
225             return Err(ParseBigIntError::empty());
226         }
227 
228         if s.starts_with('_') {
229             // Must lead with a real digit!
230             return Err(ParseBigIntError::invalid());
231         }
232 
233         // First normalize all characters to plain digit values
234         let mut v = Vec::with_capacity(s.len());
235         for b in s.bytes() {
236             let d = match b {
237                 b'0'..=b'9' => b - b'0',
238                 b'a'..=b'z' => b - b'a' + 10,
239                 b'A'..=b'Z' => b - b'A' + 10,
240                 b'_' => continue,
241                 _ => core::u8::MAX,
242             };
243             if d < radix as u8 {
244                 v.push(d);
245             } else {
246                 return Err(ParseBigIntError::invalid());
247             }
248         }
249 
250         let res = if radix.is_power_of_two() {
251             // Powers of two can use bitwise masks and shifting instead of multiplication
252             let bits = ilog2(radix);
253             v.reverse();
254             if big_digit::BITS % bits == 0 {
255                 from_bitwise_digits_le(&v, bits)
256             } else {
257                 from_inexact_bitwise_digits_le(&v, bits)
258             }
259         } else {
260             from_radix_digits_be(&v, radix)
261         };
262         Ok(res)
263     }
264 }
265 
high_bits_to_u64(v: &BigUint) -> u64266 fn high_bits_to_u64(v: &BigUint) -> u64 {
267     match v.data.len() {
268         0 => 0,
269         1 => {
270             // XXX Conversion is useless if already 64-bit.
271             #[allow(clippy::useless_conversion)]
272             let v0 = u64::from(v.data[0]);
273             v0
274         }
275         _ => {
276             let mut bits = v.bits();
277             let mut ret = 0u64;
278             let mut ret_bits = 0;
279 
280             for d in v.data.iter().rev() {
281                 let digit_bits = (bits - 1) % u64::from(big_digit::BITS) + 1;
282                 let bits_want = Ord::min(64 - ret_bits, digit_bits);
283 
284                 if bits_want != 64 {
285                     ret <<= bits_want;
286                 }
287                 // XXX Conversion is useless if already 64-bit.
288                 #[allow(clippy::useless_conversion)]
289                 let d0 = u64::from(*d) >> (digit_bits - bits_want);
290                 ret |= d0;
291                 ret_bits += bits_want;
292                 bits -= bits_want;
293 
294                 if ret_bits == 64 {
295                     break;
296                 }
297             }
298 
299             ret
300         }
301     }
302 }
303 
304 impl ToPrimitive for BigUint {
305     #[inline]
to_i64(&self) -> Option<i64>306     fn to_i64(&self) -> Option<i64> {
307         self.to_u64().as_ref().and_then(u64::to_i64)
308     }
309 
310     #[inline]
to_i128(&self) -> Option<i128>311     fn to_i128(&self) -> Option<i128> {
312         self.to_u128().as_ref().and_then(u128::to_i128)
313     }
314 
315     #[allow(clippy::useless_conversion)]
316     #[inline]
to_u64(&self) -> Option<u64>317     fn to_u64(&self) -> Option<u64> {
318         let mut ret: u64 = 0;
319         let mut bits = 0;
320 
321         for i in self.data.iter() {
322             if bits >= 64 {
323                 return None;
324             }
325 
326             // XXX Conversion is useless if already 64-bit.
327             ret += u64::from(*i) << bits;
328             bits += big_digit::BITS;
329         }
330 
331         Some(ret)
332     }
333 
334     #[inline]
to_u128(&self) -> Option<u128>335     fn to_u128(&self) -> Option<u128> {
336         let mut ret: u128 = 0;
337         let mut bits = 0;
338 
339         for i in self.data.iter() {
340             if bits >= 128 {
341                 return None;
342             }
343 
344             ret |= u128::from(*i) << bits;
345             bits += big_digit::BITS;
346         }
347 
348         Some(ret)
349     }
350 
351     #[inline]
to_f32(&self) -> Option<f32>352     fn to_f32(&self) -> Option<f32> {
353         let mantissa = high_bits_to_u64(self);
354         let exponent = self.bits() - u64::from(fls(mantissa));
355 
356         if exponent > core::f32::MAX_EXP as u64 {
357             Some(core::f32::INFINITY)
358         } else {
359             Some((mantissa as f32) * 2.0f32.powi(exponent as i32))
360         }
361     }
362 
363     #[inline]
to_f64(&self) -> Option<f64>364     fn to_f64(&self) -> Option<f64> {
365         let mantissa = high_bits_to_u64(self);
366         let exponent = self.bits() - u64::from(fls(mantissa));
367 
368         if exponent > core::f64::MAX_EXP as u64 {
369             Some(core::f64::INFINITY)
370         } else {
371             Some((mantissa as f64) * 2.0f64.powi(exponent as i32))
372         }
373     }
374 }
375 
376 macro_rules! impl_try_from_biguint {
377     ($T:ty, $to_ty:path) => {
378         #[cfg(has_try_from)]
379         impl TryFrom<&BigUint> for $T {
380             type Error = TryFromBigIntError<()>;
381 
382             #[inline]
383             fn try_from(value: &BigUint) -> Result<$T, TryFromBigIntError<()>> {
384                 $to_ty(value).ok_or(TryFromBigIntError::new(()))
385             }
386         }
387 
388         #[cfg(has_try_from)]
389         impl TryFrom<BigUint> for $T {
390             type Error = TryFromBigIntError<BigUint>;
391 
392             #[inline]
393             fn try_from(value: BigUint) -> Result<$T, TryFromBigIntError<BigUint>> {
394                 <$T>::try_from(&value).map_err(|_| TryFromBigIntError::new(value))
395             }
396         }
397     };
398 }
399 
400 impl_try_from_biguint!(u8, ToPrimitive::to_u8);
401 impl_try_from_biguint!(u16, ToPrimitive::to_u16);
402 impl_try_from_biguint!(u32, ToPrimitive::to_u32);
403 impl_try_from_biguint!(u64, ToPrimitive::to_u64);
404 impl_try_from_biguint!(usize, ToPrimitive::to_usize);
405 impl_try_from_biguint!(u128, ToPrimitive::to_u128);
406 
407 impl_try_from_biguint!(i8, ToPrimitive::to_i8);
408 impl_try_from_biguint!(i16, ToPrimitive::to_i16);
409 impl_try_from_biguint!(i32, ToPrimitive::to_i32);
410 impl_try_from_biguint!(i64, ToPrimitive::to_i64);
411 impl_try_from_biguint!(isize, ToPrimitive::to_isize);
412 impl_try_from_biguint!(i128, ToPrimitive::to_i128);
413 
414 impl FromPrimitive for BigUint {
415     #[inline]
from_i64(n: i64) -> Option<BigUint>416     fn from_i64(n: i64) -> Option<BigUint> {
417         if n >= 0 {
418             Some(BigUint::from(n as u64))
419         } else {
420             None
421         }
422     }
423 
424     #[inline]
from_i128(n: i128) -> Option<BigUint>425     fn from_i128(n: i128) -> Option<BigUint> {
426         if n >= 0 {
427             Some(BigUint::from(n as u128))
428         } else {
429             None
430         }
431     }
432 
433     #[inline]
from_u64(n: u64) -> Option<BigUint>434     fn from_u64(n: u64) -> Option<BigUint> {
435         Some(BigUint::from(n))
436     }
437 
438     #[inline]
from_u128(n: u128) -> Option<BigUint>439     fn from_u128(n: u128) -> Option<BigUint> {
440         Some(BigUint::from(n))
441     }
442 
443     #[inline]
from_f64(mut n: f64) -> Option<BigUint>444     fn from_f64(mut n: f64) -> Option<BigUint> {
445         // handle NAN, INFINITY, NEG_INFINITY
446         if !n.is_finite() {
447             return None;
448         }
449 
450         // match the rounding of casting from float to int
451         n = n.trunc();
452 
453         // handle 0.x, -0.x
454         if n.is_zero() {
455             return Some(BigUint::zero());
456         }
457 
458         let (mantissa, exponent, sign) = FloatCore::integer_decode(n);
459 
460         if sign == -1 {
461             return None;
462         }
463 
464         let mut ret = BigUint::from(mantissa);
465         match exponent.cmp(&0) {
466             Greater => ret <<= exponent as usize,
467             Equal => {}
468             Less => ret >>= (-exponent) as usize,
469         }
470         Some(ret)
471     }
472 }
473 
474 impl From<u64> for BigUint {
475     #[inline]
from(mut n: u64) -> Self476     fn from(mut n: u64) -> Self {
477         let mut ret: BigUint = Zero::zero();
478 
479         while n != 0 {
480             ret.data.push(n as BigDigit);
481             // don't overflow if BITS is 64:
482             n = (n >> 1) >> (big_digit::BITS - 1);
483         }
484 
485         ret
486     }
487 }
488 
489 impl From<u128> for BigUint {
490     #[inline]
from(mut n: u128) -> Self491     fn from(mut n: u128) -> Self {
492         let mut ret: BigUint = Zero::zero();
493 
494         while n != 0 {
495             ret.data.push(n as BigDigit);
496             n >>= big_digit::BITS;
497         }
498 
499         ret
500     }
501 }
502 
503 macro_rules! impl_biguint_from_uint {
504     ($T:ty) => {
505         impl From<$T> for BigUint {
506             #[inline]
507             fn from(n: $T) -> Self {
508                 BigUint::from(n as u64)
509             }
510         }
511     };
512 }
513 
514 impl_biguint_from_uint!(u8);
515 impl_biguint_from_uint!(u16);
516 impl_biguint_from_uint!(u32);
517 impl_biguint_from_uint!(usize);
518 
519 macro_rules! impl_biguint_try_from_int {
520     ($T:ty, $from_ty:path) => {
521         #[cfg(has_try_from)]
522         impl TryFrom<$T> for BigUint {
523             type Error = TryFromBigIntError<()>;
524 
525             #[inline]
526             fn try_from(value: $T) -> Result<BigUint, TryFromBigIntError<()>> {
527                 $from_ty(value).ok_or(TryFromBigIntError::new(()))
528             }
529         }
530     };
531 }
532 
533 impl_biguint_try_from_int!(i8, FromPrimitive::from_i8);
534 impl_biguint_try_from_int!(i16, FromPrimitive::from_i16);
535 impl_biguint_try_from_int!(i32, FromPrimitive::from_i32);
536 impl_biguint_try_from_int!(i64, FromPrimitive::from_i64);
537 impl_biguint_try_from_int!(isize, FromPrimitive::from_isize);
538 impl_biguint_try_from_int!(i128, FromPrimitive::from_i128);
539 
540 impl ToBigUint for BigUint {
541     #[inline]
to_biguint(&self) -> Option<BigUint>542     fn to_biguint(&self) -> Option<BigUint> {
543         Some(self.clone())
544     }
545 }
546 
547 macro_rules! impl_to_biguint {
548     ($T:ty, $from_ty:path) => {
549         impl ToBigUint for $T {
550             #[inline]
551             fn to_biguint(&self) -> Option<BigUint> {
552                 $from_ty(*self)
553             }
554         }
555     };
556 }
557 
558 impl_to_biguint!(isize, FromPrimitive::from_isize);
559 impl_to_biguint!(i8, FromPrimitive::from_i8);
560 impl_to_biguint!(i16, FromPrimitive::from_i16);
561 impl_to_biguint!(i32, FromPrimitive::from_i32);
562 impl_to_biguint!(i64, FromPrimitive::from_i64);
563 impl_to_biguint!(i128, FromPrimitive::from_i128);
564 
565 impl_to_biguint!(usize, FromPrimitive::from_usize);
566 impl_to_biguint!(u8, FromPrimitive::from_u8);
567 impl_to_biguint!(u16, FromPrimitive::from_u16);
568 impl_to_biguint!(u32, FromPrimitive::from_u32);
569 impl_to_biguint!(u64, FromPrimitive::from_u64);
570 impl_to_biguint!(u128, FromPrimitive::from_u128);
571 
572 impl_to_biguint!(f32, FromPrimitive::from_f32);
573 impl_to_biguint!(f64, FromPrimitive::from_f64);
574 
575 // Extract bitwise digits that evenly divide BigDigit
to_bitwise_digits_le(u: &BigUint, bits: u8) -> Vec<u8>576 pub(super) fn to_bitwise_digits_le(u: &BigUint, bits: u8) -> Vec<u8> {
577     debug_assert!(!u.is_zero() && bits <= 8 && big_digit::BITS % bits == 0);
578 
579     let last_i = u.data.len() - 1;
580     let mask: BigDigit = (1 << bits) - 1;
581     let digits_per_big_digit = big_digit::BITS / bits;
582     let digits = Integer::div_ceil(&u.bits(), &u64::from(bits))
583         .to_usize()
584         .unwrap_or(core::usize::MAX);
585     let mut res = Vec::with_capacity(digits);
586 
587     for mut r in u.data[..last_i].iter().cloned() {
588         for _ in 0..digits_per_big_digit {
589             res.push((r & mask) as u8);
590             r >>= bits;
591         }
592     }
593 
594     let mut r = u.data[last_i];
595     while r != 0 {
596         res.push((r & mask) as u8);
597         r >>= bits;
598     }
599 
600     res
601 }
602 
603 // Extract bitwise digits that don't evenly divide BigDigit
to_inexact_bitwise_digits_le(u: &BigUint, bits: u8) -> Vec<u8>604 fn to_inexact_bitwise_digits_le(u: &BigUint, bits: u8) -> Vec<u8> {
605     debug_assert!(!u.is_zero() && bits <= 8 && big_digit::BITS % bits != 0);
606 
607     let mask: BigDigit = (1 << bits) - 1;
608     let digits = Integer::div_ceil(&u.bits(), &u64::from(bits))
609         .to_usize()
610         .unwrap_or(core::usize::MAX);
611     let mut res = Vec::with_capacity(digits);
612 
613     let mut r = 0;
614     let mut rbits = 0;
615 
616     for c in &u.data {
617         r |= *c << rbits;
618         rbits += big_digit::BITS;
619 
620         while rbits >= bits {
621             res.push((r & mask) as u8);
622             r >>= bits;
623 
624             // r had more bits than it could fit - grab the bits we lost
625             if rbits > big_digit::BITS {
626                 r = *c >> (big_digit::BITS - (rbits - bits));
627             }
628 
629             rbits -= bits;
630         }
631     }
632 
633     if rbits != 0 {
634         res.push(r as u8);
635     }
636 
637     while let Some(&0) = res.last() {
638         res.pop();
639     }
640 
641     res
642 }
643 
644 // Extract little-endian radix digits
645 #[inline(always)] // forced inline to get const-prop for radix=10
to_radix_digits_le(u: &BigUint, radix: u32) -> Vec<u8>646 pub(super) fn to_radix_digits_le(u: &BigUint, radix: u32) -> Vec<u8> {
647     debug_assert!(!u.is_zero() && !radix.is_power_of_two());
648 
649     #[cfg(feature = "std")]
650     let radix_log2 = f64::from(radix).log2();
651     #[cfg(not(feature = "std"))]
652     let radix_log2 = ilog2(radix) as f64;
653 
654     // Estimate how big the result will be, so we can pre-allocate it.
655     let radix_digits = ((u.bits() as f64) / radix_log2).ceil();
656     let mut res = Vec::with_capacity(radix_digits.to_usize().unwrap_or(0));
657 
658     let mut digits = u.clone();
659 
660     let (base, power) = get_radix_base(radix, big_digit::HALF_BITS);
661     let radix = radix as BigDigit;
662 
663     // For very large numbers, the O(n²) loop of repeated `div_rem_digit` dominates the
664     // performance. We can mitigate this by dividing into chunks of a larger base first.
665     // The threshold for this was chosen by anecdotal performance measurements to
666     // approximate where this starts to make a noticeable difference.
667     if digits.data.len() >= 64 {
668         let mut big_base = BigUint::from(base * base);
669         let mut big_power = 2usize;
670 
671         // Choose a target base length near √n.
672         let target_len = digits.data.len().sqrt();
673         while big_base.data.len() < target_len {
674             big_base = &big_base * &big_base;
675             big_power *= 2;
676         }
677 
678         // This outer loop will run approximately √n times.
679         while digits > big_base {
680             // This is still the dominating factor, with n digits divided by √n digits.
681             let (q, mut big_r) = digits.div_rem(&big_base);
682             digits = q;
683 
684             // This inner loop now has O(√n²)=O(n) behavior altogether.
685             for _ in 0..big_power {
686                 let (q, mut r) = div_rem_digit(big_r, base);
687                 big_r = q;
688                 for _ in 0..power {
689                     res.push((r % radix) as u8);
690                     r /= radix;
691                 }
692             }
693         }
694     }
695 
696     while digits.data.len() > 1 {
697         let (q, mut r) = div_rem_digit(digits, base);
698         for _ in 0..power {
699             res.push((r % radix) as u8);
700             r /= radix;
701         }
702         digits = q;
703     }
704 
705     let mut r = digits.data[0];
706     while r != 0 {
707         res.push((r % radix) as u8);
708         r /= radix;
709     }
710 
711     res
712 }
713 
to_radix_le(u: &BigUint, radix: u32) -> Vec<u8>714 pub(super) fn to_radix_le(u: &BigUint, radix: u32) -> Vec<u8> {
715     if u.is_zero() {
716         vec![0]
717     } else if radix.is_power_of_two() {
718         // Powers of two can use bitwise masks and shifting instead of division
719         let bits = ilog2(radix);
720         if big_digit::BITS % bits == 0 {
721             to_bitwise_digits_le(u, bits)
722         } else {
723             to_inexact_bitwise_digits_le(u, bits)
724         }
725     } else if radix == 10 {
726         // 10 is so common that it's worth separating out for const-propagation.
727         // Optimizers can often turn constant division into a faster multiplication.
728         to_radix_digits_le(u, 10)
729     } else {
730         to_radix_digits_le(u, radix)
731     }
732 }
733 
to_str_radix_reversed(u: &BigUint, radix: u32) -> Vec<u8>734 pub(crate) fn to_str_radix_reversed(u: &BigUint, radix: u32) -> Vec<u8> {
735     assert!(2 <= radix && radix <= 36, "The radix must be within 2...36");
736 
737     if u.is_zero() {
738         return vec![b'0'];
739     }
740 
741     let mut res = to_radix_le(u, radix);
742 
743     // Now convert everything to ASCII digits.
744     for r in &mut res {
745         debug_assert!(u32::from(*r) < radix);
746         if *r < 10 {
747             *r += b'0';
748         } else {
749             *r += b'a' - 10;
750         }
751     }
752     res
753 }
754 
755 /// Returns the greatest power of the radix for the given bit size
756 #[inline]
get_radix_base(radix: u32, bits: u8) -> (BigDigit, usize)757 fn get_radix_base(radix: u32, bits: u8) -> (BigDigit, usize) {
758     mod gen {
759         include! { concat!(env!("OUT_DIR"), "/radix_bases.rs") }
760     }
761 
762     debug_assert!(
763         2 <= radix && radix <= 256,
764         "The radix must be within 2...256"
765     );
766     debug_assert!(!radix.is_power_of_two());
767     debug_assert!(bits <= big_digit::BITS);
768 
769     match bits {
770         16 => {
771             let (base, power) = gen::BASES_16[radix as usize];
772             (base as BigDigit, power)
773         }
774         32 => {
775             let (base, power) = gen::BASES_32[radix as usize];
776             (base as BigDigit, power)
777         }
778         64 => {
779             let (base, power) = gen::BASES_64[radix as usize];
780             (base as BigDigit, power)
781         }
782         _ => panic!("Invalid bigdigit size"),
783     }
784 }
785