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