num_bigint_dig/
lib.rs

1// Copyright 2018 Stichting Organism
2//
3// Copyright 2018 Friedel Ziegelmayer
4//
5// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
6// file at the top-level directory of this distribution and at
7// http://rust-lang.org/COPYRIGHT.
8//
9// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
10// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
11// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
12// option. This file may not be copied, modified, or distributed
13// except according to those terms.
14
15//! A Big integer (signed version: `BigInt`, unsigned version: `BigUint`).
16//!
17//! A `BigUint` is represented as a vector of `BigDigit`s.
18//! A `BigInt` is a combination of `BigUint` and `Sign`.
19//!
20//! Common numerical operations are overloaded, so we can treat them
21//! the same way we treat other numbers.
22//!
23//! ## Example
24//!
25//! ```rust
26//! extern crate num_bigint_dig as num_bigint;
27//! extern crate num_traits;
28//!
29//! # fn main() {
30//! use num_bigint::BigUint;
31//! use num_traits::{Zero, One};
32//! use std::mem::replace;
33//!
34//! // Calculate large fibonacci numbers.
35//! fn fib(n: usize) -> BigUint {
36//!     let mut f0: BigUint = Zero::zero();
37//!     let mut f1: BigUint = One::one();
38//!     for _ in 0..n {
39//!         let f2 = f0 + &f1;
40//!         // This is a low cost way of swapping f0 with f1 and f1 with f2.
41//!         f0 = replace(&mut f1, f2);
42//!     }
43//!     f0
44//! }
45//!
46//! // This is a very large number.
47//! //println!("fib(1000) = {}", fib(1000));
48//! # }
49//! ```
50//!
51//! It's easy to generate large random numbers:
52//!
53#![cfg_attr(feature = "std", doc = " ```")]
54#![cfg_attr(not(feature = "std"), doc = " ```ignore")]
55//!
56//! # #[cfg(feature = "rand")]
57//! extern crate rand;
58//! extern crate num_bigint_dig as bigint;
59//!
60//! # #[cfg(feature = "rand")]
61//! # fn main() {
62//! use bigint::{ToBigInt, RandBigInt};
63//!
64//! let mut rng = rand::thread_rng();
65//! let a = rng.gen_bigint(1000);
66//!
67//! let low = -10000.to_bigint().unwrap();
68//! let high = 10000.to_bigint().unwrap();
69//! let b = rng.gen_bigint_range(&low, &high);
70//!
71//! // Probably an even larger number.
72//! //println!("{}", a * b);
73//! # }
74//!
75//! # #[cfg(not(feature = "rand"))]
76//! # fn main() {
77//! # }
78//! ```
79//!
80//! ## Compatibility
81//!
82//! The `num-bigint-dig` crate is tested for rustc 1.56 and greater.
83//!
84//! ## `no_std` compatibility
85//!
86//! This crate is compatible with `no_std` environments.
87//!
88//! Note however that it still requires the `alloc` crate, so the user should
89//! ensure that they set a `global_allocator`.
90//!
91//! To use in no_std environment, add the crate as such in your `Cargo.toml`
92//! file:
93//!
94//! ```toml
95//! [dependencies]
96//! num-bigint-dig = { version = "0.8", default-features=false }
97//! ```
98//!
99//! Every features should be compatible with no_std environment, so feel free to
100//! add features like `prime`, `i128`, etc...
101
102#![doc(html_root_url = "https://docs.rs/num-bigint/0.2")]
103#![no_std]
104
105extern crate alloc;
106
107#[cfg(feature = "std")]
108extern crate std;
109
110#[macro_use]
111extern crate smallvec;
112
113#[cfg(feature = "prime")]
114#[macro_use]
115extern crate lazy_static;
116
117extern crate num_integer as integer;
118
119use core::fmt;
120#[cfg(feature = "std")]
121use std::error::Error;
122
123#[macro_use]
124mod macros;
125
126mod bigint;
127mod biguint;
128
129#[cfg(feature = "prime")]
130pub mod prime;
131
132pub mod algorithms;
133pub mod traits;
134
135pub use crate::traits::*;
136
137#[cfg(feature = "rand")]
138mod bigrand;
139
140#[cfg(target_pointer_width = "32")]
141type UsizePromotion = u32;
142#[cfg(target_pointer_width = "64")]
143type UsizePromotion = u64;
144
145#[cfg(target_pointer_width = "32")]
146type IsizePromotion = i32;
147#[cfg(target_pointer_width = "64")]
148type IsizePromotion = i64;
149
150#[derive(Debug, Clone, PartialEq, Eq)]
151pub struct ParseBigIntError {
152    kind: BigIntErrorKind,
153}
154
155#[derive(Debug, Clone, PartialEq, Eq)]
156enum BigIntErrorKind {
157    Empty,
158    InvalidDigit,
159}
160
161impl ParseBigIntError {
162    fn __description(&self) -> &str {
163        use crate::BigIntErrorKind::*;
164        match self.kind {
165            Empty => "cannot parse integer from empty string",
166            InvalidDigit => "invalid digit found in string",
167        }
168    }
169
170    fn empty() -> Self {
171        ParseBigIntError {
172            kind: BigIntErrorKind::Empty,
173        }
174    }
175
176    fn invalid() -> Self {
177        ParseBigIntError {
178            kind: BigIntErrorKind::InvalidDigit,
179        }
180    }
181}
182
183impl fmt::Display for ParseBigIntError {
184    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
185        self.__description().fmt(f)
186    }
187}
188
189#[cfg(feature = "std")]
190impl Error for ParseBigIntError {
191    fn description(&self) -> &str {
192        self.__description()
193    }
194}
195
196pub use crate::biguint::BigUint;
197pub use crate::biguint::IntoBigUint;
198pub use crate::biguint::ToBigUint;
199
200pub use crate::bigint::negate_sign;
201pub use crate::bigint::BigInt;
202pub use crate::bigint::IntoBigInt;
203pub use crate::bigint::Sign;
204pub use crate::bigint::ToBigInt;
205
206#[cfg(feature = "rand")]
207pub use crate::bigrand::{RandBigInt, RandomBits, UniformBigInt, UniformBigUint};
208
209#[cfg(feature = "prime")]
210pub use bigrand::RandPrime;
211
212#[cfg(not(feature = "u64_digit"))]
213pub const VEC_SIZE: usize = 8;
214
215#[cfg(feature = "u64_digit")]
216pub const VEC_SIZE: usize = 4;
217
218mod big_digit {
219    /// A `BigDigit` is a `BigUint`'s composing element.
220    #[cfg(not(feature = "u64_digit"))]
221    pub type BigDigit = u32;
222    #[cfg(feature = "u64_digit")]
223    pub type BigDigit = u64;
224
225    /// A `DoubleBigDigit` is the internal type used to do the computations.  Its
226    /// size is the double of the size of `BigDigit`.
227    #[cfg(not(feature = "u64_digit"))]
228    pub type DoubleBigDigit = u64;
229    #[cfg(feature = "u64_digit")]
230    pub type DoubleBigDigit = u128;
231
232    /// A `SignedDoubleBigDigit` is the signed version of `DoubleBigDigit`.
233    #[cfg(not(feature = "u64_digit"))]
234    pub type SignedDoubleBigDigit = i64;
235    #[cfg(feature = "u64_digit")]
236    pub type SignedDoubleBigDigit = i128;
237
238    // `DoubleBigDigit` size dependent
239    #[cfg(not(feature = "u64_digit"))]
240    pub const BITS: usize = 32;
241    #[cfg(feature = "u64_digit")]
242    pub const BITS: usize = 64;
243
244    #[cfg(not(feature = "u64_digit"))]
245    const LO_MASK: DoubleBigDigit = (-1i32 as DoubleBigDigit) >> BITS;
246    #[cfg(feature = "u64_digit")]
247    const LO_MASK: DoubleBigDigit = (-1i64 as DoubleBigDigit) >> BITS;
248
249    #[inline]
250    fn get_hi(n: DoubleBigDigit) -> BigDigit {
251        (n >> BITS) as BigDigit
252    }
253    #[inline]
254    fn get_lo(n: DoubleBigDigit) -> BigDigit {
255        (n & LO_MASK) as BigDigit
256    }
257
258    /// Split one `DoubleBigDigit` into two `BigDigit`s.
259    #[inline]
260    pub fn from_doublebigdigit(n: DoubleBigDigit) -> (BigDigit, BigDigit) {
261        (get_hi(n), get_lo(n))
262    }
263
264    /// Join two `BigDigit`s into one `DoubleBigDigit`
265    #[inline]
266    pub fn to_doublebigdigit(hi: BigDigit, lo: BigDigit) -> DoubleBigDigit {
267        (DoubleBigDigit::from(lo)) | ((DoubleBigDigit::from(hi)) << BITS)
268    }
269}