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.
1011//! 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::One;
25//!
26//! // Calculate large fibonacci numbers.
27//! fn fib(n: usize) -> BigUint {
28//! let mut f0 = BigUint::ZERO;
29//! let mut f1 = BigUint::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, which enables [`std::error::Error`]
64//! implementations and some internal use of floating point approximations. This can be disabled by
65//! depending on `num-bigint` with `default-features = false`. Either way, the `alloc` crate is
66//! always required for heap allocation of the `BigInt`/`BigUint` digits.
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//! ### Arbitrary Big Integers
82//!
83//! `num-bigint` supports `arbitrary` and `quickcheck` features to implement
84//! [`arbitrary::Arbitrary`] and [`quickcheck::Arbitrary`], respectively, for both `BigInt` and
85//! `BigUint`. These are useful for fuzzing and other forms of randomized testing.
86//!
87//! ### Serialization
88//!
89//! The `serde` feature adds implementations of [`Serialize`][serde::Serialize] and
90//! [`Deserialize`][serde::Deserialize] for both `BigInt` and `BigUint`. Their serialized data is
91//! generated portably, regardless of platform differences like the internal digit size.
92//!
93//!
94//! ## Compatibility
95//!
96//! The `num-bigint` crate is tested for rustc 1.60 and greater.
9798#![cfg_attr(docsrs, feature(doc_cfg))]
99#![doc(html_root_url = "https://docs.rs/num-bigint/0.4")]
100#![warn(rust_2018_idioms)]
101#![no_std]
102103#[macro_use]
104extern crate alloc;
105106#[cfg(feature = "std")]
107extern crate std;
108109use core::fmt;
110111#[macro_use]
112mod macros;
113114mod bigint;
115mod bigrand;
116mod biguint;
117118#[cfg(target_pointer_width = "32")]
119type UsizePromotion = u32;
120#[cfg(target_pointer_width = "64")]
121type UsizePromotion = u64;
122123#[cfg(target_pointer_width = "32")]
124type IsizePromotion = i32;
125#[cfg(target_pointer_width = "64")]
126type IsizePromotion = i64;
127128#[derive(#[automatically_derived]
impl ::core::fmt::Debug for ParseBigIntError {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field1_finish(f,
"ParseBigIntError", "kind", &&self.kind)
}
}Debug, #[automatically_derived]
impl ::core::clone::Clone for ParseBigIntError {
#[inline]
fn clone(&self) -> ParseBigIntError {
ParseBigIntError { kind: ::core::clone::Clone::clone(&self.kind) }
}
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for ParseBigIntError {
#[inline]
fn eq(&self, other: &ParseBigIntError) -> bool { self.kind == other.kind }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for ParseBigIntError {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) -> () {
let _: ::core::cmp::AssertParamIsEq<BigIntErrorKind>;
}
}Eq)]
129pub struct ParseBigIntError {
130 kind: BigIntErrorKind,
131}
132133#[derive(#[automatically_derived]
impl ::core::fmt::Debug for BigIntErrorKind {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f,
match self {
BigIntErrorKind::Empty => "Empty",
BigIntErrorKind::InvalidDigit => "InvalidDigit",
})
}
}Debug, #[automatically_derived]
impl ::core::clone::Clone for BigIntErrorKind {
#[inline]
fn clone(&self) -> BigIntErrorKind {
match self {
BigIntErrorKind::Empty => BigIntErrorKind::Empty,
BigIntErrorKind::InvalidDigit => BigIntErrorKind::InvalidDigit,
}
}
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for BigIntErrorKind {
#[inline]
fn eq(&self, other: &BigIntErrorKind) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for BigIntErrorKind {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) -> () {}
}Eq)]
134enum BigIntErrorKind {
135 Empty,
136 InvalidDigit,
137}
138139impl ParseBigIntError {
140fn __description(&self) -> &str {
141use crate::BigIntErrorKind::*;
142match self.kind {
143Empty => "cannot parse integer from empty string",
144InvalidDigit => "invalid digit found in string",
145 }
146 }
147148fn empty() -> Self {
149ParseBigIntError {
150 kind: BigIntErrorKind::Empty,
151 }
152 }
153154fn invalid() -> Self {
155ParseBigIntError {
156 kind: BigIntErrorKind::InvalidDigit,
157 }
158 }
159}
160161impl fmt::Displayfor ParseBigIntError {
162fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
163self.__description().fmt(f)
164 }
165}
166167#[cfg(feature = "std")]
168#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
169impl std::error::Errorfor ParseBigIntError {
170fn description(&self) -> &str {
171self.__description()
172 }
173}
174175/// The error type returned when a checked conversion regarding big integer fails.
176#[derive(#[automatically_derived]
impl<T: ::core::fmt::Debug> ::core::fmt::Debug for TryFromBigIntError<T> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field1_finish(f,
"TryFromBigIntError", "original", &&self.original)
}
}Debug, #[automatically_derived]
impl<T: ::core::marker::Copy> ::core::marker::Copy for TryFromBigIntError<T> {
}Copy, #[automatically_derived]
impl<T: ::core::clone::Clone> ::core::clone::Clone for TryFromBigIntError<T> {
#[inline]
fn clone(&self) -> TryFromBigIntError<T> {
TryFromBigIntError {
original: ::core::clone::Clone::clone(&self.original),
}
}
}Clone, #[automatically_derived]
impl<T: ::core::cmp::PartialEq> ::core::cmp::PartialEq for
TryFromBigIntError<T> {
#[inline]
fn eq(&self, other: &TryFromBigIntError<T>) -> bool {
self.original == other.original
}
}PartialEq, #[automatically_derived]
impl<T: ::core::cmp::Eq> ::core::cmp::Eq for TryFromBigIntError<T> {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) -> () {
let _: ::core::cmp::AssertParamIsEq<T>;
}
}Eq)]
177pub struct TryFromBigIntError<T> {
178 original: T,
179}
180181impl<T> TryFromBigIntError<T> {
182fn new(original: T) -> Self {
183TryFromBigIntError { original }
184 }
185186fn __description(&self) -> &str {
187"out of range conversion regarding big integer attempted"
188}
189190/// Extract the original value, if available. The value will be available
191 /// if the type before conversion was either [`BigInt`] or [`BigUint`].
192pub fn into_original(self) -> T {
193self.original
194 }
195}
196197#[cfg(feature = "std")]
198#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
199impl<T> std::error::Errorfor TryFromBigIntError<T>
200where
201T: fmt::Debug,
202{
203fn description(&self) -> &str {
204self.__description()
205 }
206}
207208impl<T> fmt::Displayfor TryFromBigIntError<T> {
209fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
210self.__description().fmt(f)
211 }
212}
213214pub use crate::biguint::BigUint;
215pub use crate::biguint::ToBigUint;
216pub use crate::biguint::U32Digits;
217pub use crate::biguint::U64Digits;
218219pub use crate::bigint::BigInt;
220pub use crate::bigint::Sign;
221pub use crate::bigint::ToBigInt;
222223#[cfg(feature = "rand")]
224#[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
225pub use crate::bigrand::{RandBigInt, RandomBits, UniformBigInt, UniformBigUint};
226227mod big_digit {
228// A [`BigDigit`] is a [`BigUint`]'s composing element.
229cfg_digit!(
230pub(crate) type BigDigit = u32;
231pub(crate) type BigDigit = u64;
232 );
233234// A [`DoubleBigDigit`] is the internal type used to do the computations. Its
235 // size is the double of the size of [`BigDigit`].
236cfg_digit!(
237pub(crate) type DoubleBigDigit = u64;
238pub(crate) type DoubleBigDigit = u128;
239 );
240241pub(crate) const BITS: u8 = BigDigit::BITSas u8;
242pub(crate) const HALF_BITS: u8 = BITS / 2;
243pub(crate) const HALF: BigDigit = (1 << HALF_BITS) - 1;
244245pub(crate) const MAX: BigDigit = BigDigit::MAX;
246const LO_MASK: DoubleBigDigit = MAXas DoubleBigDigit;
247248#[inline]
249fn get_hi(n: DoubleBigDigit) -> BigDigit {
250 (n >> BITS) as BigDigit251 }
252#[inline]
253fn get_lo(n: DoubleBigDigit) -> BigDigit {
254 (n & LO_MASK) as BigDigit255 }
256257/// Split one [`DoubleBigDigit`] into two [`BigDigit`]s.
258#[inline]
259pub(crate) fn from_doublebigdigit(n: DoubleBigDigit) -> (BigDigit, BigDigit) {
260 (get_hi(n), get_lo(n))
261 }
262263/// Join two [`BigDigit`]s into one [`DoubleBigDigit`].
264#[inline]
265pub(crate) fn to_doublebigdigit(hi: BigDigit, lo: BigDigit) -> DoubleBigDigit {
266DoubleBigDigit::from(lo) | (DoubleBigDigit::from(hi) << BITS)
267 }
268}