• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 //! ```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.
97 
98 #![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]
102 
103 #[macro_use]
104 extern crate alloc;
105 
106 #[cfg(feature = "std")]
107 extern crate std;
108 
109 use core::fmt;
110 
111 #[macro_use]
112 mod macros;
113 
114 mod bigint;
115 mod bigrand;
116 mod biguint;
117 
118 #[cfg(target_pointer_width = "32")]
119 type UsizePromotion = u32;
120 #[cfg(target_pointer_width = "64")]
121 type UsizePromotion = u64;
122 
123 #[cfg(target_pointer_width = "32")]
124 type IsizePromotion = i32;
125 #[cfg(target_pointer_width = "64")]
126 type IsizePromotion = i64;
127 
128 #[derive(Debug, Clone, PartialEq, Eq)]
129 pub struct ParseBigIntError {
130     kind: BigIntErrorKind,
131 }
132 
133 #[derive(Debug, Clone, PartialEq, Eq)]
134 enum BigIntErrorKind {
135     Empty,
136     InvalidDigit,
137 }
138 
139 impl ParseBigIntError {
__description(&self) -> &str140     fn __description(&self) -> &str {
141         use crate::BigIntErrorKind::*;
142         match self.kind {
143             Empty => "cannot parse integer from empty string",
144             InvalidDigit => "invalid digit found in string",
145         }
146     }
147 
empty() -> Self148     fn empty() -> Self {
149         ParseBigIntError {
150             kind: BigIntErrorKind::Empty,
151         }
152     }
153 
invalid() -> Self154     fn invalid() -> Self {
155         ParseBigIntError {
156             kind: BigIntErrorKind::InvalidDigit,
157         }
158     }
159 }
160 
161 impl fmt::Display for ParseBigIntError {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result162     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
163         self.__description().fmt(f)
164     }
165 }
166 
167 #[cfg(feature = "std")]
168 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
169 impl std::error::Error for ParseBigIntError {
description(&self) -> &str170     fn description(&self) -> &str {
171         self.__description()
172     }
173 }
174 
175 /// The error type returned when a checked conversion regarding big integer fails.
176 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
177 pub struct TryFromBigIntError<T> {
178     original: T,
179 }
180 
181 impl<T> TryFromBigIntError<T> {
new(original: T) -> Self182     fn new(original: T) -> Self {
183         TryFromBigIntError { original }
184     }
185 
__description(&self) -> &str186     fn __description(&self) -> &str {
187         "out of range conversion regarding big integer attempted"
188     }
189 
190     /// Extract the original value, if available. The value will be available
191     /// if the type before conversion was either [`BigInt`] or [`BigUint`].
into_original(self) -> T192     pub fn into_original(self) -> T {
193         self.original
194     }
195 }
196 
197 #[cfg(feature = "std")]
198 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
199 impl<T> std::error::Error for TryFromBigIntError<T>
200 where
201     T: fmt::Debug,
202 {
description(&self) -> &str203     fn description(&self) -> &str {
204         self.__description()
205     }
206 }
207 
208 impl<T> fmt::Display for TryFromBigIntError<T> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result209     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
210         self.__description().fmt(f)
211     }
212 }
213 
214 pub use crate::biguint::BigUint;
215 pub use crate::biguint::ToBigUint;
216 pub use crate::biguint::U32Digits;
217 pub use crate::biguint::U64Digits;
218 
219 pub use crate::bigint::BigInt;
220 pub use crate::bigint::Sign;
221 pub use crate::bigint::ToBigInt;
222 
223 #[cfg(feature = "rand")]
224 #[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
225 pub use crate::bigrand::{RandBigInt, RandomBits, UniformBigInt, UniformBigUint};
226 
227 mod big_digit {
228     // A [`BigDigit`] is a [`BigUint`]'s composing element.
229     cfg_digit!(
230         pub(crate) type BigDigit = u32;
231         pub(crate) type BigDigit = u64;
232     );
233 
234     // A [`DoubleBigDigit`] is the internal type used to do the computations.  Its
235     // size is the double of the size of [`BigDigit`].
236     cfg_digit!(
237         pub(crate) type DoubleBigDigit = u64;
238         pub(crate) type DoubleBigDigit = u128;
239     );
240 
241     pub(crate) const BITS: u8 = BigDigit::BITS as u8;
242     pub(crate) const HALF_BITS: u8 = BITS / 2;
243     pub(crate) const HALF: BigDigit = (1 << HALF_BITS) - 1;
244 
245     pub(crate) const MAX: BigDigit = BigDigit::MAX;
246     const LO_MASK: DoubleBigDigit = MAX as DoubleBigDigit;
247 
248     #[inline]
get_hi(n: DoubleBigDigit) -> BigDigit249     fn get_hi(n: DoubleBigDigit) -> BigDigit {
250         (n >> BITS) as BigDigit
251     }
252     #[inline]
get_lo(n: DoubleBigDigit) -> BigDigit253     fn get_lo(n: DoubleBigDigit) -> BigDigit {
254         (n & LO_MASK) as BigDigit
255     }
256 
257     /// Split one [`DoubleBigDigit`] into two [`BigDigit`]s.
258     #[inline]
from_doublebigdigit(n: DoubleBigDigit) -> (BigDigit, BigDigit)259     pub(crate) fn from_doublebigdigit(n: DoubleBigDigit) -> (BigDigit, BigDigit) {
260         (get_hi(n), get_lo(n))
261     }
262 
263     /// Join two [`BigDigit`]s into one [`DoubleBigDigit`].
264     #[inline]
to_doublebigdigit(hi: BigDigit, lo: BigDigit) -> DoubleBigDigit265     pub(crate) fn to_doublebigdigit(hi: BigDigit, lo: BigDigit) -> DoubleBigDigit {
266         DoubleBigDigit::from(lo) | (DoubleBigDigit::from(hi) << BITS)
267     }
268 }
269