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::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.65 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")]
114extern crate once_cell;
115
116extern crate num_integer as integer;
117
118use core::fmt;
119#[cfg(feature = "std")]
120use std::error::Error;
121
122#[macro_use]
123mod macros;
124
125mod bigint;
126mod biguint;
127
128#[cfg(feature = "prime")]
129pub mod prime;
130
131pub mod algorithms;
132pub mod traits;
133
134pub use crate::traits::*;
135
136#[cfg(feature = "rand")]
137mod bigrand;
138
139#[cfg(target_pointer_width = "32")]
140type UsizePromotion = u32;
141#[cfg(target_pointer_width = "64")]
142type UsizePromotion = u64;
143
144#[cfg(target_pointer_width = "32")]
145type IsizePromotion = i32;
146#[cfg(target_pointer_width = "64")]
147type IsizePromotion = i64;
148
149#[derive(Debug, Clone, PartialEq, Eq)]
150pub struct ParseBigIntError {
151    kind: BigIntErrorKind,
152}
153
154#[derive(Debug, Clone, PartialEq, Eq)]
155enum BigIntErrorKind {
156    Empty,
157    InvalidDigit,
158}
159
160impl ParseBigIntError {
161    fn __description(&self) -> &str {
162        use crate::BigIntErrorKind::*;
163        match self.kind {
164            Empty => "cannot parse integer from empty string",
165            InvalidDigit => "invalid digit found in string",
166        }
167    }
168
169    fn empty() -> Self {
170        ParseBigIntError {
171            kind: BigIntErrorKind::Empty,
172        }
173    }
174
175    fn invalid() -> Self {
176        ParseBigIntError {
177            kind: BigIntErrorKind::InvalidDigit,
178        }
179    }
180}
181
182impl fmt::Display for ParseBigIntError {
183    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
184        self.__description().fmt(f)
185    }
186}
187
188#[cfg(feature = "std")]
189impl Error for ParseBigIntError {
190    fn description(&self) -> &str {
191        self.__description()
192    }
193}
194
195pub use crate::biguint::BigUint;
196pub use crate::biguint::IntoBigUint;
197pub use crate::biguint::ToBigUint;
198
199pub use crate::bigint::negate_sign;
200pub use crate::bigint::BigInt;
201pub use crate::bigint::IntoBigInt;
202pub use crate::bigint::Sign;
203pub use crate::bigint::ToBigInt;
204
205#[cfg(feature = "rand")]
206pub use crate::bigrand::{RandBigInt, RandomBits, UniformBigInt, UniformBigUint};
207
208#[cfg(feature = "prime")]
209pub use bigrand::RandPrime;
210
211#[cfg(not(feature = "u64_digit"))]
212pub const VEC_SIZE: usize = 8;
213
214#[cfg(feature = "u64_digit")]
215pub const VEC_SIZE: usize = 4;
216
217mod big_digit {
218    /// A `BigDigit` is a `BigUint`'s composing element.
219    #[cfg(not(feature = "u64_digit"))]
220    pub type BigDigit = u32;
221    #[cfg(feature = "u64_digit")]
222    pub type BigDigit = u64;
223
224    /// A `DoubleBigDigit` is the internal type used to do the computations.  Its
225    /// size is the double of the size of `BigDigit`.
226    #[cfg(not(feature = "u64_digit"))]
227    pub type DoubleBigDigit = u64;
228    #[cfg(feature = "u64_digit")]
229    pub type DoubleBigDigit = u128;
230
231    /// A `SignedDoubleBigDigit` is the signed version of `DoubleBigDigit`.
232    #[cfg(not(feature = "u64_digit"))]
233    pub type SignedDoubleBigDigit = i64;
234    #[cfg(feature = "u64_digit")]
235    pub type SignedDoubleBigDigit = i128;
236
237    // `DoubleBigDigit` size dependent
238    #[cfg(not(feature = "u64_digit"))]
239    pub const BITS: usize = 32;
240    #[cfg(feature = "u64_digit")]
241    pub const BITS: usize = 64;
242
243    #[cfg(not(feature = "u64_digit"))]
244    const LO_MASK: DoubleBigDigit = (-1i32 as DoubleBigDigit) >> BITS;
245    #[cfg(feature = "u64_digit")]
246    const LO_MASK: DoubleBigDigit = (-1i64 as DoubleBigDigit) >> BITS;
247
248    #[inline]
249    fn get_hi(n: DoubleBigDigit) -> BigDigit {
250        (n >> BITS) as BigDigit
251    }
252    #[inline]
253    fn get_lo(n: DoubleBigDigit) -> BigDigit {
254        (n & LO_MASK) as BigDigit
255    }
256
257    /// Split one `DoubleBigDigit` into two `BigDigit`s.
258    #[inline]
259    pub 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]
265    pub fn to_doublebigdigit(hi: BigDigit, lo: BigDigit) -> DoubleBigDigit {
266        (DoubleBigDigit::from(lo)) | ((DoubleBigDigit::from(hi)) << BITS)
267    }
268}