Coverage Report

Created: 2025-07-04 06:57

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