Coverage Report

Created: 2026-05-16 07:38

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/num-bigint-0.4.4/src/lib.rs
Line
Count
Source
1
// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
2
// file at the top-level directory of this distribution and at
3
// http://rust-lang.org/COPYRIGHT.
4
//
5
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8
// option. This file may not be copied, modified, or distributed
9
// except according to those terms.
10
11
//! Big Integer Types for Rust
12
//!
13
//! * A [`BigUint`] is unsigned and represented as a vector of digits.
14
//! * A [`BigInt`] is signed and is a combination of [`BigUint`] and [`Sign`].
15
//!
16
//! Common numerical operations are overloaded, so we can treat them
17
//! the same way we treat other numbers.
18
//!
19
//! ## Example
20
//!
21
//! ```rust
22
//! # fn main() {
23
//! use num_bigint::BigUint;
24
//! use num_traits::{Zero, One};
25
//!
26
//! // Calculate large fibonacci numbers.
27
//! fn fib(n: usize) -> BigUint {
28
//!     let mut f0: BigUint = Zero::zero();
29
//!     let mut f1: BigUint = One::one();
30
//!     for _ in 0..n {
31
//!         let f2 = f0 + &f1;
32
//!         f0 = f1;
33
//!         f1 = f2;
34
//!     }
35
//!     f0
36
//! }
37
//!
38
//! // This is a very large number.
39
//! println!("fib(1000) = {}", fib(1000));
40
//! # }
41
//! ```
42
//!
43
//! It's easy to generate large random numbers:
44
//!
45
//! ```rust,ignore
46
//! use num_bigint::{ToBigInt, RandBigInt};
47
//!
48
//! let mut rng = rand::thread_rng();
49
//! let a = rng.gen_bigint(1000);
50
//!
51
//! let low = -10000.to_bigint().unwrap();
52
//! let high = 10000.to_bigint().unwrap();
53
//! let b = rng.gen_bigint_range(&low, &high);
54
//!
55
//! // Probably an even larger number.
56
//! println!("{}", a * b);
57
//! ```
58
//!
59
//! See the "Features" section for instructions for enabling random number generation.
60
//!
61
//! ## Features
62
//!
63
//! The `std` crate feature is enabled by default, and is mandatory before Rust
64
//! 1.36 and the stabilized `alloc` crate.  If you depend on `num-bigint` with
65
//! `default-features = false`, you must manually enable the `std` feature yourself
66
//! if your compiler is not new enough.
67
//!
68
//! ### Random Generation
69
//!
70
//! `num-bigint` supports the generation of random big integers when the `rand`
71
//! feature is enabled. To enable it include rand as
72
//!
73
//! ```toml
74
//! rand = "0.8"
75
//! num-bigint = { version = "0.4", features = ["rand"] }
76
//! ```
77
//!
78
//! Note that you must use the version of `rand` that `num-bigint` is compatible
79
//! with: `0.8`.
80
//!
81
//!
82
//! ## Compatibility
83
//!
84
//! The `num-bigint` crate is tested for rustc 1.31 and greater.
85
86
#![doc(html_root_url = "https://docs.rs/num-bigint/0.4")]
87
#![warn(rust_2018_idioms)]
88
#![no_std]
89
90
#[cfg(feature = "std")]
91
#[macro_use]
92
extern crate std;
93
94
#[cfg(feature = "std")]
95
mod std_alloc {
96
    pub(crate) use std::borrow::Cow;
97
    #[cfg(feature = "quickcheck")]
98
    pub(crate) use std::boxed::Box;
99
    pub(crate) use std::string::String;
100
    pub(crate) use std::vec::Vec;
101
}
102
103
#[cfg(not(feature = "std"))]
104
#[macro_use]
105
extern crate alloc;
106
107
#[cfg(not(feature = "std"))]
108
mod std_alloc {
109
    pub(crate) use alloc::borrow::Cow;
110
    #[cfg(feature = "quickcheck")]
111
    pub(crate) use alloc::boxed::Box;
112
    pub(crate) use alloc::string::String;
113
    pub(crate) use alloc::vec::Vec;
114
}
115
116
use core::fmt;
117
#[cfg(feature = "std")]
118
use std::error::Error;
119
120
#[macro_use]
121
mod macros;
122
123
mod bigint;
124
mod biguint;
125
126
#[cfg(feature = "rand")]
127
mod bigrand;
128
129
#[cfg(target_pointer_width = "32")]
130
type UsizePromotion = u32;
131
#[cfg(target_pointer_width = "64")]
132
type UsizePromotion = u64;
133
134
#[cfg(target_pointer_width = "32")]
135
type IsizePromotion = i32;
136
#[cfg(target_pointer_width = "64")]
137
type IsizePromotion = i64;
138
139
#[derive(Debug, Clone, PartialEq, Eq)]
140
pub struct ParseBigIntError {
141
    kind: BigIntErrorKind,
142
}
143
144
#[derive(Debug, Clone, PartialEq, Eq)]
145
enum BigIntErrorKind {
146
    Empty,
147
    InvalidDigit,
148
}
149
150
impl ParseBigIntError {
151
0
    fn __description(&self) -> &str {
152
        use crate::BigIntErrorKind::*;
153
0
        match self.kind {
154
0
            Empty => "cannot parse integer from empty string",
155
0
            InvalidDigit => "invalid digit found in string",
156
        }
157
0
    }
158
159
0
    fn empty() -> Self {
160
0
        ParseBigIntError {
161
0
            kind: BigIntErrorKind::Empty,
162
0
        }
163
0
    }
164
165
0
    fn invalid() -> Self {
166
0
        ParseBigIntError {
167
0
            kind: BigIntErrorKind::InvalidDigit,
168
0
        }
169
0
    }
170
}
171
172
impl fmt::Display for ParseBigIntError {
173
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
174
0
        self.__description().fmt(f)
175
0
    }
176
}
177
178
#[cfg(feature = "std")]
179
impl Error for ParseBigIntError {
180
0
    fn description(&self) -> &str {
181
0
        self.__description()
182
0
    }
183
}
184
185
/// The error type returned when a checked conversion regarding big integer fails.
186
#[cfg(has_try_from)]
187
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
188
pub struct TryFromBigIntError<T> {
189
    original: T,
190
}
191
192
#[cfg(has_try_from)]
193
impl<T> TryFromBigIntError<T> {
194
0
    fn new(original: T) -> Self {
195
0
        TryFromBigIntError { original }
196
0
    }
197
198
0
    fn __description(&self) -> &str {
199
0
        "out of range conversion regarding big integer attempted"
200
0
    }
201
202
    /// Extract the original value, if available. The value will be available
203
    /// if the type before conversion was either [`BigInt`] or [`BigUint`].
204
0
    pub fn into_original(self) -> T {
205
0
        self.original
206
0
    }
207
}
208
209
#[cfg(all(feature = "std", has_try_from))]
210
impl<T> std::error::Error for TryFromBigIntError<T>
211
where
212
    T: fmt::Debug,
213
{
214
0
    fn description(&self) -> &str {
215
0
        self.__description()
216
0
    }
217
}
218
219
#[cfg(has_try_from)]
220
impl<T> fmt::Display for TryFromBigIntError<T> {
221
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
222
0
        self.__description().fmt(f)
223
0
    }
224
}
225
226
pub use crate::biguint::BigUint;
227
pub use crate::biguint::ToBigUint;
228
pub use crate::biguint::U32Digits;
229
pub use crate::biguint::U64Digits;
230
231
pub use crate::bigint::BigInt;
232
pub use crate::bigint::Sign;
233
pub use crate::bigint::ToBigInt;
234
235
#[cfg(feature = "rand")]
236
pub use crate::bigrand::{RandBigInt, RandomBits, UniformBigInt, UniformBigUint};
237
238
mod big_digit {
239
    /// A [`BigDigit`] is a [`BigUint`]'s composing element.
240
    #[cfg(not(u64_digit))]
241
    pub(crate) type BigDigit = u32;
242
    #[cfg(u64_digit)]
243
    pub(crate) type BigDigit = u64;
244
245
    /// A [`DoubleBigDigit`] is the internal type used to do the computations.  Its
246
    /// size is the double of the size of [`BigDigit`].
247
    #[cfg(not(u64_digit))]
248
    pub(crate) type DoubleBigDigit = u64;
249
    #[cfg(u64_digit)]
250
    pub(crate) type DoubleBigDigit = u128;
251
252
    /// A [`SignedDoubleBigDigit`] is the signed version of [`DoubleBigDigit`].
253
    #[cfg(not(u64_digit))]
254
    pub(crate) type SignedDoubleBigDigit = i64;
255
    #[cfg(u64_digit)]
256
    pub(crate) type SignedDoubleBigDigit = i128;
257
258
    // [`DoubleBigDigit`] size dependent
259
    #[cfg(not(u64_digit))]
260
    pub(crate) const BITS: u8 = 32;
261
    #[cfg(u64_digit)]
262
    pub(crate) const BITS: u8 = 64;
263
264
    pub(crate) const HALF_BITS: u8 = BITS / 2;
265
    pub(crate) const HALF: BigDigit = (1 << HALF_BITS) - 1;
266
267
    const LO_MASK: DoubleBigDigit = (1 << BITS) - 1;
268
    pub(crate) const MAX: BigDigit = LO_MASK as BigDigit;
269
270
    #[inline]
271
0
    fn get_hi(n: DoubleBigDigit) -> BigDigit {
272
0
        (n >> BITS) as BigDigit
273
0
    }
274
    #[inline]
275
0
    fn get_lo(n: DoubleBigDigit) -> BigDigit {
276
0
        (n & LO_MASK) as BigDigit
277
0
    }
278
279
    /// Split one [`DoubleBigDigit`] into two [`BigDigit`]s.
280
    #[inline]
281
0
    pub(crate) fn from_doublebigdigit(n: DoubleBigDigit) -> (BigDigit, BigDigit) {
282
0
        (get_hi(n), get_lo(n))
283
0
    }
284
285
    /// Join two [`BigDigit`]s into one [`DoubleBigDigit`].
286
    #[inline]
287
0
    pub(crate) fn to_doublebigdigit(hi: BigDigit, lo: BigDigit) -> DoubleBigDigit {
288
0
        DoubleBigDigit::from(lo) | (DoubleBigDigit::from(hi) << BITS)
289
0
    }
290
}