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