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