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 { __description(&self) -> &str151 fn __description(&self) -> &str { 152 use crate::BigIntErrorKind::*; 153 match self.kind { 154 Empty => "cannot parse integer from empty string", 155 InvalidDigit => "invalid digit found in string", 156 } 157 } 158 empty() -> Self159 fn empty() -> Self { 160 ParseBigIntError { 161 kind: BigIntErrorKind::Empty, 162 } 163 } 164 invalid() -> Self165 fn invalid() -> Self { 166 ParseBigIntError { 167 kind: BigIntErrorKind::InvalidDigit, 168 } 169 } 170 } 171 172 impl fmt::Display for ParseBigIntError { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result173 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 174 self.__description().fmt(f) 175 } 176 } 177 178 #[cfg(feature = "std")] 179 impl Error for ParseBigIntError { description(&self) -> &str180 fn description(&self) -> &str { 181 self.__description() 182 } 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> { new(original: T) -> Self194 fn new(original: T) -> Self { 195 TryFromBigIntError { original } 196 } 197 __description(&self) -> &str198 fn __description(&self) -> &str { 199 "out of range conversion regarding big integer attempted" 200 } 201 202 /// Extract the original value, if available. The value will be available 203 /// if the type before conversion was either [`BigInt`] or [`BigUint`]. into_original(self) -> T204 pub fn into_original(self) -> T { 205 self.original 206 } 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 { description(&self) -> &str214 fn description(&self) -> &str { 215 self.__description() 216 } 217 } 218 219 #[cfg(has_try_from)] 220 impl<T> fmt::Display for TryFromBigIntError<T> { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result221 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 222 self.__description().fmt(f) 223 } 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] get_hi(n: DoubleBigDigit) -> BigDigit271 fn get_hi(n: DoubleBigDigit) -> BigDigit { 272 (n >> BITS) as BigDigit 273 } 274 #[inline] get_lo(n: DoubleBigDigit) -> BigDigit275 fn get_lo(n: DoubleBigDigit) -> BigDigit { 276 (n & LO_MASK) as BigDigit 277 } 278 279 /// Split one [`DoubleBigDigit`] into two [`BigDigit`]s. 280 #[inline] from_doublebigdigit(n: DoubleBigDigit) -> (BigDigit, BigDigit)281 pub(crate) fn from_doublebigdigit(n: DoubleBigDigit) -> (BigDigit, BigDigit) { 282 (get_hi(n), get_lo(n)) 283 } 284 285 /// Join two [`BigDigit`]s into one [`DoubleBigDigit`]. 286 #[inline] to_doublebigdigit(hi: BigDigit, lo: BigDigit) -> DoubleBigDigit287 pub(crate) fn to_doublebigdigit(hi: BigDigit, lo: BigDigit) -> DoubleBigDigit { 288 DoubleBigDigit::from(lo) | (DoubleBigDigit::from(hi) << BITS) 289 } 290 } 291