Coverage Report

Created: 2026-08-13 08:17

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/num-bigint-0.4.8/src/biguint/convert.rs
Line
Count
Source
1
// This uses stdlib features higher than the MSRV
2
#![allow(clippy::manual_range_contains)] // 1.35
3
4
use super::{biguint_from_vec, fls, ilog2, BigUint, ToBigUint};
5
6
use super::addition::add2;
7
use super::division::{div_rem_digit, FAST_DIV_WIDE};
8
use super::multiplication::mac_with_carry;
9
10
use crate::big_digit::{self, BigDigit, BigDigits};
11
use crate::ParseBigIntError;
12
use crate::TryFromBigIntError;
13
14
use alloc::vec::Vec;
15
use core::cmp::Ordering::{Equal, Greater, Less};
16
use core::convert::TryFrom;
17
use core::str::FromStr;
18
use num_integer::Integer;
19
use num_traits::float::FloatCore;
20
use num_traits::{FromPrimitive, Num, ToPrimitive, Zero};
21
22
impl FromStr for BigUint {
23
    type Err = ParseBigIntError;
24
25
    #[inline]
26
0
    fn from_str(s: &str) -> Result<BigUint, ParseBigIntError> {
27
0
        BigUint::from_str_radix(s, 10)
28
0
    }
29
}
30
31
// Convert from a power of two radix (bits == ilog2(radix)) where bits evenly divides
32
// BigDigit::BITS
33
0
pub(super) fn from_bitwise_digits_le(v: &[u8], bits: u8) -> BigUint {
34
0
    debug_assert!(!v.is_empty() && bits <= 8 && big_digit::BITS % bits == 0);
35
0
    debug_assert!(v.iter().all(|&c| BigDigit::from(c) < (1 << bits)));
36
37
0
    let digits_per_big_digit = big_digit::BITS / bits;
38
39
0
    let data = v
40
0
        .chunks(digits_per_big_digit.into())
41
0
        .map(|chunk| {
42
0
            chunk
43
0
                .iter()
44
0
                .rev()
45
0
                .fold(0, |acc, &c| (acc << bits) | BigDigit::from(c))
46
0
        })
47
0
        .collect();
48
49
0
    biguint_from_vec(data)
50
0
}
51
52
// Convert from a power of two radix (bits == ilog2(radix)) where bits doesn't evenly divide
53
// BigDigit::BITS
54
0
fn from_inexact_bitwise_digits_le(v: &[u8], bits: u8) -> BigUint {
55
0
    debug_assert!(!v.is_empty() && bits <= 8 && big_digit::BITS % bits != 0);
56
0
    debug_assert!(v.iter().all(|&c| BigDigit::from(c) < (1 << bits)));
57
58
0
    let total_bits = (v.len() as u64).saturating_mul(bits.into());
59
0
    let big_digits = Integer::div_ceil(&total_bits, &big_digit::BITS.into())
60
0
        .to_usize()
61
0
        .unwrap_or(usize::MAX);
62
0
    let mut data = Vec::with_capacity(big_digits);
63
64
0
    let mut d = 0;
65
0
    let mut dbits = 0; // number of bits we currently have in d
66
67
    // walk v accumululating bits in d; whenever we accumulate big_digit::BITS in d, spit out a
68
    // big_digit:
69
0
    for &c in v {
70
0
        d |= BigDigit::from(c) << dbits;
71
0
        dbits += bits;
72
73
0
        if dbits >= big_digit::BITS {
74
0
            data.push(d);
75
0
            dbits -= big_digit::BITS;
76
0
            // if dbits was > big_digit::BITS, we dropped some of the bits in c (they couldn't fit
77
0
            // in d) - grab the bits we lost here:
78
0
            d = BigDigit::from(c) >> (bits - dbits);
79
0
        }
80
    }
81
82
0
    if dbits > 0 {
83
0
        debug_assert!(dbits < big_digit::BITS);
84
0
        data.push(d as BigDigit);
85
0
    }
86
87
0
    biguint_from_vec(data)
88
0
}
89
90
// Read little-endian radix digits
91
0
fn from_radix_digits_be(v: &[u8], radix: u32) -> BigUint {
92
0
    debug_assert!(!v.is_empty() && !radix.is_power_of_two());
93
0
    debug_assert!(v.iter().all(|&c| u32::from(c) < radix));
94
95
    // Estimate how big the result will be, so we can pre-allocate it.
96
    #[cfg(feature = "std")]
97
0
    let big_digits = {
98
0
        let radix_log2 = f64::from(radix).log2();
99
0
        let bits = radix_log2 * v.len() as f64;
100
0
        (bits / big_digit::BITS as f64).ceil()
101
    };
102
    #[cfg(not(feature = "std"))]
103
    let big_digits = {
104
        let radix_log2 = ilog2(radix.next_power_of_two()) as usize;
105
        let bits = radix_log2 * v.len();
106
        (bits / big_digit::BITS as usize) + 1
107
    };
108
109
0
    let mut data = Vec::with_capacity(big_digits.to_usize().unwrap_or(0));
110
111
0
    let (base, power) = get_radix_base(radix);
112
0
    let radix = radix as BigDigit;
113
114
0
    let r = v.len() % power;
115
0
    let i = if r == 0 { power } else { r };
116
0
    let (head, tail) = v.split_at(i);
117
118
0
    let first = head
119
0
        .iter()
120
0
        .fold(0, |acc, &d| acc * radix + BigDigit::from(d));
121
0
    data.push(first);
122
123
0
    debug_assert!(tail.len() % power == 0);
124
0
    for chunk in tail.chunks(power) {
125
0
        if data.last() != Some(&0) {
126
0
            data.push(0);
127
0
        }
128
129
0
        let mut carry = 0;
130
0
        for d in data.iter_mut() {
131
0
            *d = mac_with_carry(0, *d, base, &mut carry);
132
0
        }
133
0
        debug_assert!(carry == 0);
134
135
0
        let n = chunk
136
0
            .iter()
137
0
            .fold(0, |acc, &d| acc * radix + BigDigit::from(d));
138
0
        add2(&mut data, &[n]);
139
    }
140
141
0
    biguint_from_vec(data)
142
0
}
143
144
0
pub(super) fn from_radix_be(buf: &[u8], radix: u32) -> Option<BigUint> {
145
0
    assert!(
146
0
        2 <= radix && radix <= 256,
147
0
        "The radix must be within 2...256"
148
    );
149
150
0
    if buf.is_empty() {
151
0
        return Some(BigUint::ZERO);
152
0
    }
153
154
0
    if radix != 256 && buf.iter().any(|&b| b >= radix as u8) {
155
0
        return None;
156
0
    }
157
158
0
    let res = if radix.is_power_of_two() {
159
        // Powers of two can use bitwise masks and shifting instead of multiplication
160
0
        let bits = ilog2(radix);
161
0
        let mut v = Vec::from(buf);
162
0
        v.reverse();
163
0
        if big_digit::BITS % bits == 0 {
164
0
            from_bitwise_digits_le(&v, bits)
165
        } else {
166
0
            from_inexact_bitwise_digits_le(&v, bits)
167
        }
168
    } else {
169
0
        from_radix_digits_be(buf, radix)
170
    };
171
172
0
    Some(res)
173
0
}
174
175
0
pub(super) fn from_radix_le(buf: &[u8], radix: u32) -> Option<BigUint> {
176
0
    assert!(
177
0
        2 <= radix && radix <= 256,
178
0
        "The radix must be within 2...256"
179
    );
180
181
0
    if buf.is_empty() {
182
0
        return Some(BigUint::ZERO);
183
0
    }
184
185
0
    if radix != 256 && buf.iter().any(|&b| b >= radix as u8) {
186
0
        return None;
187
0
    }
188
189
0
    let res = if radix.is_power_of_two() {
190
        // Powers of two can use bitwise masks and shifting instead of multiplication
191
0
        let bits = ilog2(radix);
192
0
        if big_digit::BITS % bits == 0 {
193
0
            from_bitwise_digits_le(buf, bits)
194
        } else {
195
0
            from_inexact_bitwise_digits_le(buf, bits)
196
        }
197
    } else {
198
0
        let mut v = Vec::from(buf);
199
0
        v.reverse();
200
0
        from_radix_digits_be(&v, radix)
201
    };
202
203
0
    Some(res)
204
0
}
205
206
impl Num for BigUint {
207
    type FromStrRadixErr = ParseBigIntError;
208
209
    /// Creates and initializes a [`BigUint`].
210
0
    fn from_str_radix(s: &str, radix: u32) -> Result<BigUint, ParseBigIntError> {
211
0
        assert!(2 <= radix && radix <= 36, "The radix must be within 2...36");
212
0
        let mut s = s;
213
0
        if let Some(tail) = s.strip_prefix('+') {
214
0
            if !tail.starts_with('+') {
215
0
                s = tail
216
0
            }
217
0
        }
218
219
0
        if s.is_empty() {
220
0
            return Err(ParseBigIntError::empty());
221
0
        }
222
223
0
        if s.starts_with('_') {
224
            // Must lead with a real digit!
225
0
            return Err(ParseBigIntError::invalid());
226
0
        }
227
228
        // First normalize all characters to plain digit values
229
0
        let mut v = Vec::with_capacity(s.len());
230
0
        for b in s.bytes() {
231
0
            let d = match b {
232
0
                b'0'..=b'9' => b - b'0',
233
0
                b'a'..=b'z' => b - b'a' + 10,
234
0
                b'A'..=b'Z' => b - b'A' + 10,
235
0
                b'_' => continue,
236
0
                _ => u8::MAX,
237
            };
238
0
            if d < radix as u8 {
239
0
                v.push(d);
240
0
            } else {
241
0
                return Err(ParseBigIntError::invalid());
242
            }
243
        }
244
245
0
        let res = if radix.is_power_of_two() {
246
            // Powers of two can use bitwise masks and shifting instead of multiplication
247
0
            let bits = ilog2(radix);
248
0
            v.reverse();
249
0
            if big_digit::BITS % bits == 0 {
250
0
                from_bitwise_digits_le(&v, bits)
251
            } else {
252
0
                from_inexact_bitwise_digits_le(&v, bits)
253
            }
254
        } else {
255
0
            from_radix_digits_be(&v, radix)
256
        };
257
0
        Ok(res)
258
0
    }
259
}
260
261
0
fn high_bits_to_u64(v: &BigUint) -> u64 {
262
0
    match v.data.len() {
263
0
        0 => 0,
264
        1 => {
265
            // XXX Conversion is useless if already 64-bit.
266
            #[allow(clippy::useless_conversion)]
267
0
            let v0 = u64::from(v.data[0]);
268
0
            v0
269
        }
270
        _ => {
271
0
            let mut bits = v.bits();
272
0
            let mut ret = 0u64;
273
0
            let mut ret_bits = 0;
274
275
0
            for d in v.data.iter().rev() {
276
0
                let digit_bits = (bits - 1) % u64::from(big_digit::BITS) + 1;
277
0
                let bits_want = Ord::min(64 - ret_bits, digit_bits);
278
279
0
                if bits_want != 0 {
280
0
                    if bits_want != 64 {
281
0
                        ret <<= bits_want;
282
0
                    }
283
                    // XXX Conversion is useless if already 64-bit.
284
                    #[allow(clippy::useless_conversion)]
285
0
                    let d0 = u64::from(*d) >> (digit_bits - bits_want);
286
0
                    ret |= d0;
287
0
                }
288
289
                // Implement round-to-odd: If any lower bits are 1, set LSB to 1
290
                // so that rounding again to floating point value using
291
                // nearest-ties-to-even is correct.
292
                //
293
                // See: https://en.wikipedia.org/wiki/Rounding#Rounding_to_prepare_for_shorter_precision
294
295
0
                if digit_bits - bits_want != 0 {
296
0
                    // XXX Conversion is useless if already 64-bit.
297
0
                    #[allow(clippy::useless_conversion)]
298
0
                    let masked = u64::from(*d) << (64 - (digit_bits - bits_want) as u32);
299
0
                    ret |= (masked != 0) as u64;
300
0
                }
301
302
0
                ret_bits += bits_want;
303
0
                bits -= bits_want;
304
            }
305
306
0
            ret
307
        }
308
    }
309
0
}
310
311
impl ToPrimitive for BigUint {
312
    #[inline]
313
0
    fn to_i64(&self) -> Option<i64> {
314
0
        self.to_u64().as_ref().and_then(u64::to_i64)
315
0
    }
316
317
    #[inline]
318
0
    fn to_i128(&self) -> Option<i128> {
319
0
        self.to_u128().as_ref().and_then(u128::to_i128)
320
0
    }
321
322
    #[allow(clippy::useless_conversion)]
323
    #[inline]
324
0
    fn to_u64(&self) -> Option<u64> {
325
0
        let mut ret: u64 = 0;
326
0
        let mut bits = 0;
327
328
0
        for i in self.data.iter() {
329
0
            if bits >= 64 {
330
0
                return None;
331
0
            }
332
333
            // XXX Conversion is useless if already 64-bit.
334
0
            ret += u64::from(*i) << bits;
335
0
            bits += big_digit::BITS;
336
        }
337
338
0
        Some(ret)
339
0
    }
340
341
    #[inline]
342
0
    fn to_u128(&self) -> Option<u128> {
343
0
        let mut ret: u128 = 0;
344
0
        let mut bits = 0;
345
346
0
        for i in self.data.iter() {
347
0
            if bits >= 128 {
348
0
                return None;
349
0
            }
350
351
0
            ret |= u128::from(*i) << bits;
352
0
            bits += big_digit::BITS;
353
        }
354
355
0
        Some(ret)
356
0
    }
357
358
    #[inline]
359
0
    fn to_f32(&self) -> Option<f32> {
360
0
        let mantissa = high_bits_to_u64(self);
361
0
        let exponent = self.bits() - u64::from(fls(mantissa));
362
363
0
        if exponent > f32::MAX_EXP as u64 {
364
0
            Some(f32::INFINITY)
365
        } else {
366
0
            Some((mantissa as f32) * 2.0f32.powi(exponent as i32))
367
        }
368
0
    }
369
370
    #[inline]
371
0
    fn to_f64(&self) -> Option<f64> {
372
0
        let mantissa = high_bits_to_u64(self);
373
0
        let exponent = self.bits() - u64::from(fls(mantissa));
374
375
0
        if exponent > f64::MAX_EXP as u64 {
376
0
            Some(f64::INFINITY)
377
        } else {
378
0
            Some((mantissa as f64) * 2.0f64.powi(exponent as i32))
379
        }
380
0
    }
381
}
382
383
macro_rules! impl_try_from_biguint {
384
    ($T:ty, $to_ty:path) => {
385
        impl TryFrom<&BigUint> for $T {
386
            type Error = TryFromBigIntError<()>;
387
388
            #[inline]
389
0
            fn try_from(value: &BigUint) -> Result<$T, TryFromBigIntError<()>> {
390
0
                $to_ty(value).ok_or(TryFromBigIntError::new(()))
391
0
            }
Unexecuted instantiation: <u8 as core::convert::TryFrom<&num_bigint::biguint::BigUint>>::try_from
Unexecuted instantiation: <u16 as core::convert::TryFrom<&num_bigint::biguint::BigUint>>::try_from
Unexecuted instantiation: <u32 as core::convert::TryFrom<&num_bigint::biguint::BigUint>>::try_from
Unexecuted instantiation: <u64 as core::convert::TryFrom<&num_bigint::biguint::BigUint>>::try_from
Unexecuted instantiation: <usize as core::convert::TryFrom<&num_bigint::biguint::BigUint>>::try_from
Unexecuted instantiation: <u128 as core::convert::TryFrom<&num_bigint::biguint::BigUint>>::try_from
Unexecuted instantiation: <i8 as core::convert::TryFrom<&num_bigint::biguint::BigUint>>::try_from
Unexecuted instantiation: <i16 as core::convert::TryFrom<&num_bigint::biguint::BigUint>>::try_from
Unexecuted instantiation: <i32 as core::convert::TryFrom<&num_bigint::biguint::BigUint>>::try_from
Unexecuted instantiation: <i64 as core::convert::TryFrom<&num_bigint::biguint::BigUint>>::try_from
Unexecuted instantiation: <isize as core::convert::TryFrom<&num_bigint::biguint::BigUint>>::try_from
Unexecuted instantiation: <i128 as core::convert::TryFrom<&num_bigint::biguint::BigUint>>::try_from
392
        }
393
394
        impl TryFrom<BigUint> for $T {
395
            type Error = TryFromBigIntError<BigUint>;
396
397
            #[inline]
398
0
            fn try_from(value: BigUint) -> Result<$T, TryFromBigIntError<BigUint>> {
399
0
                <$T>::try_from(&value).map_err(|_| TryFromBigIntError::new(value))
Unexecuted instantiation: <u8 as core::convert::TryFrom<num_bigint::biguint::BigUint>>::try_from::{closure#0}
Unexecuted instantiation: <u16 as core::convert::TryFrom<num_bigint::biguint::BigUint>>::try_from::{closure#0}
Unexecuted instantiation: <u32 as core::convert::TryFrom<num_bigint::biguint::BigUint>>::try_from::{closure#0}
Unexecuted instantiation: <u64 as core::convert::TryFrom<num_bigint::biguint::BigUint>>::try_from::{closure#0}
Unexecuted instantiation: <usize as core::convert::TryFrom<num_bigint::biguint::BigUint>>::try_from::{closure#0}
Unexecuted instantiation: <u128 as core::convert::TryFrom<num_bigint::biguint::BigUint>>::try_from::{closure#0}
Unexecuted instantiation: <i8 as core::convert::TryFrom<num_bigint::biguint::BigUint>>::try_from::{closure#0}
Unexecuted instantiation: <i16 as core::convert::TryFrom<num_bigint::biguint::BigUint>>::try_from::{closure#0}
Unexecuted instantiation: <i32 as core::convert::TryFrom<num_bigint::biguint::BigUint>>::try_from::{closure#0}
Unexecuted instantiation: <i64 as core::convert::TryFrom<num_bigint::biguint::BigUint>>::try_from::{closure#0}
Unexecuted instantiation: <isize as core::convert::TryFrom<num_bigint::biguint::BigUint>>::try_from::{closure#0}
Unexecuted instantiation: <i128 as core::convert::TryFrom<num_bigint::biguint::BigUint>>::try_from::{closure#0}
400
0
            }
Unexecuted instantiation: <u8 as core::convert::TryFrom<num_bigint::biguint::BigUint>>::try_from
Unexecuted instantiation: <u16 as core::convert::TryFrom<num_bigint::biguint::BigUint>>::try_from
Unexecuted instantiation: <u32 as core::convert::TryFrom<num_bigint::biguint::BigUint>>::try_from
Unexecuted instantiation: <u64 as core::convert::TryFrom<num_bigint::biguint::BigUint>>::try_from
Unexecuted instantiation: <usize as core::convert::TryFrom<num_bigint::biguint::BigUint>>::try_from
Unexecuted instantiation: <u128 as core::convert::TryFrom<num_bigint::biguint::BigUint>>::try_from
Unexecuted instantiation: <i8 as core::convert::TryFrom<num_bigint::biguint::BigUint>>::try_from
Unexecuted instantiation: <i16 as core::convert::TryFrom<num_bigint::biguint::BigUint>>::try_from
Unexecuted instantiation: <i32 as core::convert::TryFrom<num_bigint::biguint::BigUint>>::try_from
Unexecuted instantiation: <i64 as core::convert::TryFrom<num_bigint::biguint::BigUint>>::try_from
Unexecuted instantiation: <isize as core::convert::TryFrom<num_bigint::biguint::BigUint>>::try_from
Unexecuted instantiation: <i128 as core::convert::TryFrom<num_bigint::biguint::BigUint>>::try_from
401
        }
402
    };
403
}
404
405
impl_try_from_biguint!(u8, ToPrimitive::to_u8);
406
impl_try_from_biguint!(u16, ToPrimitive::to_u16);
407
impl_try_from_biguint!(u32, ToPrimitive::to_u32);
408
impl_try_from_biguint!(u64, ToPrimitive::to_u64);
409
impl_try_from_biguint!(usize, ToPrimitive::to_usize);
410
impl_try_from_biguint!(u128, ToPrimitive::to_u128);
411
412
impl_try_from_biguint!(i8, ToPrimitive::to_i8);
413
impl_try_from_biguint!(i16, ToPrimitive::to_i16);
414
impl_try_from_biguint!(i32, ToPrimitive::to_i32);
415
impl_try_from_biguint!(i64, ToPrimitive::to_i64);
416
impl_try_from_biguint!(isize, ToPrimitive::to_isize);
417
impl_try_from_biguint!(i128, ToPrimitive::to_i128);
418
419
impl FromPrimitive for BigUint {
420
    #[inline]
421
0
    fn from_i64(n: i64) -> Option<BigUint> {
422
0
        if n >= 0 {
423
0
            Some(BigUint::from(n as u64))
424
        } else {
425
0
            None
426
        }
427
0
    }
428
429
    #[inline]
430
0
    fn from_i128(n: i128) -> Option<BigUint> {
431
0
        if n >= 0 {
432
0
            Some(BigUint::from(n as u128))
433
        } else {
434
0
            None
435
        }
436
0
    }
437
438
    #[inline]
439
0
    fn from_u64(n: u64) -> Option<BigUint> {
440
0
        Some(BigUint::from(n))
441
0
    }
Unexecuted instantiation: <num_bigint::biguint::BigUint as num_traits::cast::FromPrimitive>::from_u64
Unexecuted instantiation: <num_bigint::biguint::BigUint as num_traits::cast::FromPrimitive>::from_u64
442
443
    #[inline]
444
0
    fn from_u128(n: u128) -> Option<BigUint> {
445
0
        Some(BigUint::from(n))
446
0
    }
447
448
    #[inline]
449
0
    fn from_f64(mut n: f64) -> Option<BigUint> {
450
        // handle NAN, INFINITY, NEG_INFINITY
451
0
        if !n.is_finite() {
452
0
            return None;
453
0
        }
454
455
        // match the rounding of casting from float to int
456
0
        n = n.trunc();
457
458
        // handle 0.x, -0.x
459
0
        if n.is_zero() {
460
0
            return Some(Self::ZERO);
461
0
        }
462
463
0
        let (mantissa, exponent, sign) = FloatCore::integer_decode(n);
464
465
0
        if sign == -1 {
466
0
            return None;
467
0
        }
468
469
0
        let mut ret = BigUint::from(mantissa);
470
0
        match exponent.cmp(&0) {
471
0
            Greater => ret <<= exponent as usize,
472
0
            Equal => {}
473
0
            Less => ret >>= (-exponent) as usize,
474
        }
475
0
        Some(ret)
476
0
    }
477
}
478
479
impl From<u8> for BigUint {
480
    #[inline]
481
0
    fn from(n: u8) -> Self {
482
0
        BigUint::from(u32::from(n))
483
0
    }
484
}
485
486
impl From<u16> for BigUint {
487
    #[inline]
488
0
    fn from(n: u16) -> Self {
489
0
        BigUint::from(u32::from(n))
490
0
    }
491
}
492
493
impl From<u32> for BigUint {
494
    #[inline]
495
0
    fn from(n: u32) -> Self {
496
0
        BigUint {
497
0
            data: BigDigits::from_digit(n as BigDigit),
498
0
        }
499
0
    }
500
}
501
502
impl From<u64> for BigUint {
503
    #[inline]
504
0
    fn from(n: u64) -> Self {
505
        cfg_digit_expr!(
506
            return if n > big_digit::MAX as u64 {
507
                BigUint::new(vec![n as BigDigit, (n >> big_digit::BITS) as BigDigit])
508
            } else {
509
                BigUint {
510
                    data: BigDigits::from_digit(n as BigDigit),
511
                }
512
            },
513
0
            return BigUint {
514
0
                data: BigDigits::from_digit(n),
515
0
            }
516
        );
517
0
    }
Unexecuted instantiation: <num_bigint::biguint::BigUint as core::convert::From<u64>>::from
Unexecuted instantiation: <num_bigint::biguint::BigUint as core::convert::From<u64>>::from
518
}
519
520
impl From<u128> for BigUint {
521
    #[inline]
522
0
    fn from(mut n: u128) -> Self {
523
0
        let mut ret: BigUint = Self::ZERO;
524
525
0
        while n != 0 {
526
0
            ret.data.push(n as BigDigit);
527
0
            n >>= big_digit::BITS;
528
0
        }
529
530
0
        ret
531
0
    }
Unexecuted instantiation: <num_bigint::biguint::BigUint as core::convert::From<u128>>::from
Unexecuted instantiation: <num_bigint::biguint::BigUint as core::convert::From<u128>>::from
532
}
533
534
impl From<usize> for BigUint {
535
    #[inline]
536
0
    fn from(n: usize) -> Self {
537
0
        BigUint::from(n as crate::UsizePromotion)
538
0
    }
539
}
540
541
macro_rules! impl_biguint_try_from_int {
542
    ($T:ty, $from_ty:path) => {
543
        impl TryFrom<$T> for BigUint {
544
            type Error = TryFromBigIntError<()>;
545
546
            #[inline]
547
0
            fn try_from(value: $T) -> Result<BigUint, TryFromBigIntError<()>> {
548
0
                $from_ty(value).ok_or(TryFromBigIntError::new(()))
549
0
            }
Unexecuted instantiation: <num_bigint::biguint::BigUint as core::convert::TryFrom<i32>>::try_from
Unexecuted instantiation: <num_bigint::biguint::BigUint as core::convert::TryFrom<i64>>::try_from
Unexecuted instantiation: <num_bigint::biguint::BigUint as core::convert::TryFrom<isize>>::try_from
Unexecuted instantiation: <num_bigint::biguint::BigUint as core::convert::TryFrom<i128>>::try_from
Unexecuted instantiation: <num_bigint::biguint::BigUint as core::convert::TryFrom<i8>>::try_from
Unexecuted instantiation: <num_bigint::biguint::BigUint as core::convert::TryFrom<i16>>::try_from
550
        }
551
    };
552
}
553
554
impl_biguint_try_from_int!(i8, FromPrimitive::from_i8);
555
impl_biguint_try_from_int!(i16, FromPrimitive::from_i16);
556
impl_biguint_try_from_int!(i32, FromPrimitive::from_i32);
557
impl_biguint_try_from_int!(i64, FromPrimitive::from_i64);
558
impl_biguint_try_from_int!(isize, FromPrimitive::from_isize);
559
impl_biguint_try_from_int!(i128, FromPrimitive::from_i128);
560
561
impl ToBigUint for BigUint {
562
    #[inline]
563
0
    fn to_biguint(&self) -> Option<BigUint> {
564
0
        Some(self.clone())
565
0
    }
566
}
567
568
macro_rules! impl_to_biguint {
569
    ($T:ty, $from_ty:path) => {
570
        impl ToBigUint for $T {
571
            #[inline]
572
0
            fn to_biguint(&self) -> Option<BigUint> {
573
0
                $from_ty(*self)
574
0
            }
Unexecuted instantiation: <isize as num_bigint::biguint::ToBigUint>::to_biguint
Unexecuted instantiation: <i8 as num_bigint::biguint::ToBigUint>::to_biguint
Unexecuted instantiation: <i16 as num_bigint::biguint::ToBigUint>::to_biguint
Unexecuted instantiation: <i32 as num_bigint::biguint::ToBigUint>::to_biguint
Unexecuted instantiation: <i64 as num_bigint::biguint::ToBigUint>::to_biguint
Unexecuted instantiation: <i128 as num_bigint::biguint::ToBigUint>::to_biguint
Unexecuted instantiation: <usize as num_bigint::biguint::ToBigUint>::to_biguint
Unexecuted instantiation: <u8 as num_bigint::biguint::ToBigUint>::to_biguint
Unexecuted instantiation: <u16 as num_bigint::biguint::ToBigUint>::to_biguint
Unexecuted instantiation: <u32 as num_bigint::biguint::ToBigUint>::to_biguint
Unexecuted instantiation: <u64 as num_bigint::biguint::ToBigUint>::to_biguint
Unexecuted instantiation: <u128 as num_bigint::biguint::ToBigUint>::to_biguint
Unexecuted instantiation: <f32 as num_bigint::biguint::ToBigUint>::to_biguint
Unexecuted instantiation: <f64 as num_bigint::biguint::ToBigUint>::to_biguint
575
        }
576
    };
577
}
578
579
impl_to_biguint!(isize, FromPrimitive::from_isize);
580
impl_to_biguint!(i8, FromPrimitive::from_i8);
581
impl_to_biguint!(i16, FromPrimitive::from_i16);
582
impl_to_biguint!(i32, FromPrimitive::from_i32);
583
impl_to_biguint!(i64, FromPrimitive::from_i64);
584
impl_to_biguint!(i128, FromPrimitive::from_i128);
585
586
impl_to_biguint!(usize, FromPrimitive::from_usize);
587
impl_to_biguint!(u8, FromPrimitive::from_u8);
588
impl_to_biguint!(u16, FromPrimitive::from_u16);
589
impl_to_biguint!(u32, FromPrimitive::from_u32);
590
impl_to_biguint!(u64, FromPrimitive::from_u64);
591
impl_to_biguint!(u128, FromPrimitive::from_u128);
592
593
impl_to_biguint!(f32, FromPrimitive::from_f32);
594
impl_to_biguint!(f64, FromPrimitive::from_f64);
595
596
impl From<bool> for BigUint {
597
0
    fn from(x: bool) -> Self {
598
0
        if x {
599
0
            Self::ONE
600
        } else {
601
0
            Self::ZERO
602
        }
603
0
    }
604
}
605
606
// Extract bitwise digits that evenly divide BigDigit
607
0
pub(super) fn to_bitwise_digits_le(u: &BigUint, bits: u8) -> Vec<u8> {
608
0
    debug_assert!(!u.is_zero() && bits <= 8 && big_digit::BITS % bits == 0);
609
610
0
    let last_i = u.data.len() - 1;
611
0
    let mask: BigDigit = (1 << bits) - 1;
612
0
    let digits_per_big_digit = big_digit::BITS / bits;
613
0
    let digits = Integer::div_ceil(&u.bits(), &u64::from(bits))
614
0
        .to_usize()
615
0
        .unwrap_or(usize::MAX);
616
0
    let mut res = Vec::with_capacity(digits);
617
618
0
    for mut r in u.data[..last_i].iter().cloned() {
619
0
        for _ in 0..digits_per_big_digit {
620
0
            res.push((r & mask) as u8);
621
0
            r >>= bits;
622
0
        }
623
    }
624
625
0
    let mut r = u.data[last_i];
626
0
    while r != 0 {
627
0
        res.push((r & mask) as u8);
628
0
        r >>= bits;
629
0
    }
630
631
0
    res
632
0
}
633
634
// Extract bitwise digits that don't evenly divide BigDigit
635
0
fn to_inexact_bitwise_digits_le(u: &BigUint, bits: u8) -> Vec<u8> {
636
0
    debug_assert!(!u.is_zero() && bits <= 8 && big_digit::BITS % bits != 0);
637
638
0
    let mask: BigDigit = (1 << bits) - 1;
639
0
    let digits = Integer::div_ceil(&u.bits(), &u64::from(bits))
640
0
        .to_usize()
641
0
        .unwrap_or(usize::MAX);
642
0
    let mut res = Vec::with_capacity(digits);
643
644
0
    let mut r = 0;
645
0
    let mut rbits = 0;
646
647
0
    for c in &*u.data {
648
0
        r |= *c << rbits;
649
0
        rbits += big_digit::BITS;
650
651
0
        while rbits >= bits {
652
0
            res.push((r & mask) as u8);
653
0
            r >>= bits;
654
655
            // r had more bits than it could fit - grab the bits we lost
656
0
            if rbits > big_digit::BITS {
657
0
                r = *c >> (big_digit::BITS - (rbits - bits));
658
0
            }
659
660
0
            rbits -= bits;
661
        }
662
    }
663
664
0
    if rbits != 0 {
665
0
        res.push(r as u8);
666
0
    }
667
668
0
    while let Some(&0) = res.last() {
669
0
        res.pop();
670
0
    }
671
672
0
    res
673
0
}
674
675
// Extract little-endian radix digits
676
#[inline(always)] // forced inline to get const-prop for radix=10
677
0
pub(super) fn to_radix_digits_le(u: &BigUint, radix: u32) -> Vec<u8> {
678
0
    debug_assert!(!u.is_zero() && !radix.is_power_of_two());
679
680
    #[cfg(feature = "std")]
681
0
    let radix_digits = {
682
0
        let radix_log2 = f64::from(radix).log2();
683
0
        ((u.bits() as f64) / radix_log2).ceil()
684
    };
685
    #[cfg(not(feature = "std"))]
686
    let radix_digits = {
687
        let radix_log2 = ilog2(radix) as usize;
688
        ((u.bits() as usize) / radix_log2) + 1
689
    };
690
691
    // Estimate how big the result will be, so we can pre-allocate it.
692
0
    let mut res = Vec::with_capacity(radix_digits.to_usize().unwrap_or(0));
693
694
0
    let digits = u.clone();
695
696
    // X86 DIV can quickly divide by a full digit, otherwise we choose a divisor
697
    // that's suitable for `div_half` to avoid slow `DoubleBigDigit` division.
698
0
    let (base, power) = if FAST_DIV_WIDE {
699
0
        get_radix_base(radix)
700
    } else {
701
0
        get_half_radix_base(radix)
702
    };
703
0
    let radix = radix as BigDigit;
704
705
    // For very large numbers, the O(n²) loop of repeated `div_rem_digit` dominates the
706
    // performance. We can mitigate this by dividing into chunks of a larger base first.
707
    // The threshold for this was chosen by anecdotal performance measurements to
708
    // approximate where this starts to make a noticeable difference.
709
0
    if digits.data.len() >= 32 {
710
0
        let mut big_bases = Vec::with_capacity(32);
711
0
        big_bases.push((BigUint::from(base), power));
712
713
        loop {
714
0
            let (big_base, power) = big_bases.last().unwrap();
715
0
            if big_base.data.len() > digits.data.len() / 2 + 1 {
716
0
                break;
717
0
            }
718
0
            let next_big_base = big_base * big_base;
719
0
            let next_power = *power * 2;
720
0
            big_bases.push((next_big_base, next_power));
721
        }
722
723
0
        to_radix_digits_le_divide_and_conquer(
724
0
            digits,
725
0
            base,
726
0
            power,
727
0
            &big_bases,
728
0
            big_bases.len() - 1,
729
0
            &mut res,
730
0
            radix,
731
        );
732
0
        while res.last() == Some(&0) {
733
0
            res.pop();
734
0
        }
735
0
        return res;
736
0
    }
737
738
0
    to_radix_digits_le_small(digits, base, power, &mut res, radix);
739
740
0
    res
741
0
}
742
743
// Extract little-endian radix digits for small numbers
744
#[inline(always)] // forced inline to get const-prop for radix=10
745
0
fn to_radix_digits_le_small(
746
0
    mut digits: BigUint,
747
0
    base: BigDigit,
748
0
    power: usize,
749
0
    res: &mut Vec<u8>,
750
0
    radix: BigDigit,
751
0
) {
752
0
    while digits.data.len() > 1 {
753
0
        let (q, mut r) = div_rem_digit(digits, base);
754
0
        for _ in 0..power {
755
0
            res.push((r % radix) as u8);
756
0
            r /= radix;
757
0
        }
758
0
        digits = q;
759
    }
760
761
0
    let mut r = digits.data[0];
762
0
    while r != 0 {
763
0
        res.push((r % radix) as u8);
764
0
        r /= radix;
765
0
    }
766
0
}
767
768
0
fn to_radix_digits_le_divide_and_conquer(
769
0
    number: BigUint,
770
0
    base: BigDigit,
771
0
    power: usize,
772
0
    big_bases: &[(BigUint, usize)],
773
0
    k: usize,
774
0
    res: &mut Vec<u8>,
775
0
    radix: BigDigit,
776
0
) {
777
0
    let &(ref big_base, result_len) = &big_bases[k];
778
0
    if number.data.len() < 8 {
779
0
        let prev_res_len = res.len();
780
0
        if !number.is_zero() {
781
0
            to_radix_digits_le_small(number, base, power, res, radix);
782
0
        }
783
0
        while res.len() < prev_res_len + result_len * 2 {
784
0
            res.push(0);
785
0
        }
786
0
        return;
787
0
    }
788
    // number always has two digits in the big base
789
0
    let (digit_1, digit_2) = number.div_rem(big_base);
790
0
    assert!(&digit_1 < big_base);
791
0
    assert!(&digit_2 < big_base);
792
0
    to_radix_digits_le_divide_and_conquer(digit_2, base, power, big_bases, k - 1, res, radix);
793
0
    to_radix_digits_le_divide_and_conquer(digit_1, base, power, big_bases, k - 1, res, radix);
794
0
}
795
796
0
pub(super) fn to_radix_le(u: &BigUint, radix: u32) -> Vec<u8> {
797
0
    if u.is_zero() {
798
0
        vec![0]
799
0
    } else if radix.is_power_of_two() {
800
        // Powers of two can use bitwise masks and shifting instead of division
801
0
        let bits = ilog2(radix);
802
0
        if big_digit::BITS % bits == 0 {
803
0
            to_bitwise_digits_le(u, bits)
804
        } else {
805
0
            to_inexact_bitwise_digits_le(u, bits)
806
        }
807
0
    } else if radix == 10 {
808
        // 10 is so common that it's worth separating out for const-propagation.
809
        // Optimizers can often turn constant division into a faster multiplication.
810
0
        to_radix_digits_le(u, 10)
811
    } else {
812
0
        to_radix_digits_le(u, radix)
813
    }
814
0
}
815
816
0
pub(crate) fn to_str_radix_reversed(u: &BigUint, radix: u32) -> Vec<u8> {
817
0
    assert!(2 <= radix && radix <= 36, "The radix must be within 2...36");
818
819
0
    if u.is_zero() {
820
0
        return vec![b'0'];
821
0
    }
822
823
0
    let mut res = to_radix_le(u, radix);
824
825
    // Now convert everything to ASCII digits.
826
0
    for r in &mut res {
827
0
        debug_assert!(u32::from(*r) < radix);
828
0
        if *r < 10 {
829
0
            *r += b'0';
830
0
        } else {
831
0
            *r += b'a' - 10;
832
0
        }
833
    }
834
0
    res
835
0
}
836
837
/// Returns the greatest power of the radix for the `BigDigit` bit size
838
#[inline]
839
0
fn get_radix_base(radix: u32) -> (BigDigit, usize) {
840
    static BASES: [(BigDigit, usize); 257] = generate_radix_bases(big_digit::MAX);
841
0
    debug_assert!(!radix.is_power_of_two());
842
0
    debug_assert!((3..256).contains(&radix));
843
0
    BASES[radix as usize]
844
0
}
845
846
/// Returns the greatest power of the radix for half the `BigDigit` bit size
847
#[inline]
848
0
fn get_half_radix_base(radix: u32) -> (BigDigit, usize) {
849
    static BASES: [(BigDigit, usize); 257] = generate_radix_bases(big_digit::HALF);
850
0
    debug_assert!(!radix.is_power_of_two());
851
0
    debug_assert!((3..256).contains(&radix));
852
0
    BASES[radix as usize]
853
0
}
854
855
/// Generate tables of the greatest power of each radix that is less that the given maximum. These
856
/// are returned from `get_radix_base` to batch the multiplication/division of radix conversions on
857
/// full [`BigUint`] values, operating on primitive integers as much as possible.
858
///
859
/// e.g. BASES_16[3] = (59049, 10) // 3¹⁰ fits in u16, but 3¹¹ is too big
860
///      BASES_32[3] = (3486784401, 20)
861
///      BASES_64[3] = (12157665459056928801, 40)
862
///
863
/// Powers of two are not included, just zeroed, as they're implemented with shifts.
864
0
const fn generate_radix_bases(max: BigDigit) -> [(BigDigit, usize); 257] {
865
0
    let mut bases = [(0, 0); 257];
866
867
0
    let mut radix: BigDigit = 3;
868
0
    while radix < 256 {
869
0
        if !radix.is_power_of_two() {
870
0
            let mut power = 1;
871
0
            let mut base = radix;
872
873
0
            while let Some(b) = base.checked_mul(radix) {
874
0
                if b > max {
875
0
                    break;
876
0
                }
877
0
                base = b;
878
0
                power += 1;
879
            }
880
0
            bases[radix as usize] = (base, power)
881
0
        }
882
0
        radix += 1;
883
    }
884
885
0
    bases
886
0
}
887
888
#[test]
889
fn test_radix_bases() {
890
    for radix in 3u32..256 {
891
        if !radix.is_power_of_two() {
892
            let (base, power) = get_radix_base(radix);
893
            let radix = BigDigit::from(radix);
894
            let power = u32::try_from(power).unwrap();
895
            assert_eq!(base, radix.pow(power));
896
            assert!(radix.checked_pow(power + 1).is_none());
897
        }
898
    }
899
}
900
901
#[test]
902
fn test_half_radix_bases() {
903
    for radix in 3u32..256 {
904
        if !radix.is_power_of_two() {
905
            let (base, power) = get_half_radix_base(radix);
906
            let radix = BigDigit::from(radix);
907
            let power = u32::try_from(power).unwrap();
908
            assert_eq!(base, radix.pow(power));
909
            assert!(radix.pow(power + 1) > big_digit::HALF);
910
        }
911
    }
912
}