num_bigint/lib.rs
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::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#![cfg_attr(feature = "rand_0_10", doc = "```")]
46#![cfg_attr(not(feature = "rand_0_10"), doc = "```ignore")]
47//! # use ::rand_0_10 as rand;
48//! use rand::{SeedableRng, rngs::SmallRng};
49//! use num_bigint::{BigInt, BigRng010};
50//!
51//! // This seed is just for demonstration, but in most cases
52//! // you'll probably want a non-deterministic `rng`.
53//! let mut rng = SmallRng::seed_from_u64(42);
54//! let a = rng.random_bigint(1000);
55//!
56//! let low = BigInt::from(-10000);
57//! let high = BigInt::from(10000);
58//! let b = rng.random_bigint_range(&low, &high);
59//!
60//! // Probably an even larger number.
61//! println!("{}", a * b);
62#![doc = "```"]
63//!
64//! See the "Features" section for instructions for enabling random number generation.
65//!
66//! ## Features
67//!
68//! The `std` crate feature is enabled by default, which enables [`std::error::Error`]
69//! implementations and some internal use of floating point approximations. This can be disabled by
70//! depending on `num-bigint` with `default-features = false`. Either way, the `alloc` crate is
71//! always required for heap allocation of the [`BigInt`]/[`BigUint`] digits.
72//!
73//! ### Random Generation
74//!
75//! `num-bigint` supports the generation of random big integers when either of the `rand_0_9` or
76//! `rand_0_10` features are enabled. The [`BigRng09`] and [`BigRng010`] traits provide extension
77//! methods for any `rand_core` RNG of their respective version, while the structs [`RandomBits`],
78//! [`UniformBigInt`], and [`UniformBigUint`] fulfill further functionality for random
79//! distributions in `rand::distr`.
80//!
81//! For example, using `rand v0.10` in your `Cargo.toml` may look like this:
82//!
83//! ```toml
84//! rand = "0.10"
85//! num-bigint = { version = "0.5", features = ["rand_0_10"] }
86//! ```
87//!
88//! Note that you must use the same version of `rand` as the feature you enable in `num-bigint`.
89//! It's also fine for multiple versions to be enabled at once -- the random-distribution structs
90//! will be shared with trait implementations for each `rand` feature that is enabled, while the
91//! `BigRng` traits are distinct.
92//!
93//! You can instead use `rand_core_0_9` or `rand_core_0_10` for a more restricted subset, with
94//! *only* the `BigRng` traits.
95//!
96//! ### Arbitrary Big Integers
97//!
98//! `num-bigint` supports `arbitrary` and `quickcheck` features to implement
99//! [`arbitrary::Arbitrary`] and [`quickcheck::Arbitrary`], respectively, for both [`BigInt`] and
100//! [`BigUint`]. These are useful for fuzzing and other forms of randomized testing.
101//!
102//! ### Serialization
103//!
104//! The `serde` feature adds implementations of [`Serialize`][serde::Serialize] and
105//! [`Deserialize`][serde::Deserialize] for both [`BigInt`] and [`BigUint`]. Their serialized data is
106//! generated portably, regardless of platform differences like the internal digit size.
107//!
108//!
109//! ## Compatibility
110//!
111//! The `num-bigint` crate is tested for rustc 1.60 and greater.
112
113#![cfg_attr(docsrs, feature(doc_cfg))]
114#![warn(rust_2018_idioms)]
115#![no_std]
116
117#[macro_use]
118extern crate alloc;
119
120#[cfg(feature = "std")]
121extern crate std;
122
123use core::fmt;
124
125#[macro_use]
126mod macros;
127
128mod bigint;
129mod bigrand;
130mod biguint;
131
132#[cfg(target_pointer_width = "32")]
133type UsizePromotion = u32;
134#[cfg(target_pointer_width = "64")]
135type UsizePromotion = u64;
136
137#[cfg(target_pointer_width = "32")]
138type IsizePromotion = i32;
139#[cfg(target_pointer_width = "64")]
140type IsizePromotion = i64;
141
142#[derive(Debug, Clone, PartialEq, Eq)]
143pub struct ParseBigIntError {
144 kind: BigIntErrorKind,
145}
146
147#[derive(Debug, Clone, PartialEq, Eq)]
148enum BigIntErrorKind {
149 Empty,
150 InvalidDigit,
151}
152
153impl ParseBigIntError {
154 fn __description(&self) -> &str {
155 use crate::BigIntErrorKind::*;
156 match self.kind {
157 Empty => "cannot parse integer from empty string",
158 InvalidDigit => "invalid digit found in string",
159 }
160 }
161
162 fn empty() -> Self {
163 ParseBigIntError {
164 kind: BigIntErrorKind::Empty,
165 }
166 }
167
168 fn invalid() -> Self {
169 ParseBigIntError {
170 kind: BigIntErrorKind::InvalidDigit,
171 }
172 }
173}
174
175impl fmt::Display for ParseBigIntError {
176 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
177 self.__description().fmt(f)
178 }
179}
180
181#[cfg(feature = "std")]
182#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
183impl std::error::Error for ParseBigIntError {
184 fn description(&self) -> &str {
185 self.__description()
186 }
187}
188
189/// The error type returned when a checked conversion regarding big integer fails.
190#[derive(Debug, Copy, Clone, PartialEq, Eq)]
191pub struct TryFromBigIntError<T> {
192 original: T,
193}
194
195impl<T> TryFromBigIntError<T> {
196 fn new(original: T) -> Self {
197 TryFromBigIntError { original }
198 }
199
200 fn __description(&self) -> &str {
201 "out of range conversion regarding big integer attempted"
202 }
203
204 /// Extract the original value, if available. The value will be available
205 /// if the type before conversion was either [`BigInt`] or [`BigUint`].
206 pub fn into_original(self) -> T {
207 self.original
208 }
209}
210
211#[cfg(feature = "std")]
212#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
213impl<T> std::error::Error for TryFromBigIntError<T>
214where
215 T: fmt::Debug,
216{
217 fn description(&self) -> &str {
218 self.__description()
219 }
220}
221
222impl<T> fmt::Display for TryFromBigIntError<T> {
223 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
224 self.__description().fmt(f)
225 }
226}
227
228pub use crate::biguint::BigUint;
229pub use crate::biguint::ToBigUint;
230pub use crate::biguint::U32Digits;
231pub use crate::biguint::U64Digits;
232
233pub use crate::bigint::BigInt;
234pub use crate::bigint::Sign;
235pub use crate::bigint::ToBigInt;
236
237#[cfg(feature = "rand_core_0_10")]
238pub use crate::bigrand::BigRng010;
239
240#[cfg(feature = "rand_core_0_9")]
241pub use crate::bigrand::BigRng09;
242
243#[cfg(any(feature = "rand_0_10", feature = "rand_0_9"))]
244pub use crate::bigrand::{RandomBits, UniformBigInt, UniformBigUint};
245
246mod big_digit;