Skip to content
25 changes: 21 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ categories = [ "algorithms", "data-structures", "science" ]
license = "MIT OR Apache-2.0"
name = "num-bigint"
repository = "https://github.com/rust-num/num-bigint"
version = "0.4.6"
version = "0.5.0"
readme = "README.md"
exclude = ["/ci/*", "/.github/*"]
edition = "2021"
rust-version = "1.60"

[features]
default = ["std"]
default = ["std", "rand"]
std = ["num-integer/std", "num-traits/std"]
arbitrary = ["dep:arbitrary"]
quickcheck = ["dep:quickcheck"]
Expand Down Expand Up @@ -50,13 +50,18 @@ default-features = false
features = ["i128"]

[dependencies.num-traits]
version = "0.2.18"
version = "0.2.19"
default-features = false
features = ["i128"]

[dependencies.rand]
optional = true
version = "0.8"
version = "0.10"
default-features = false

[dependencies.rand_core]
optional = true
version = "0.10"
default-features = false

[dependencies.serde]
Expand All @@ -73,3 +78,15 @@ default-features = false
optional = true
version = "1"
default-features = false

[dev-dependencies]
rand = { version = "0.10", features = ["thread_rng"]}

[lints.clippy]
correctness = "deny"
perf = "deny"
complexity = "deny"
suspicious = "deny"
style = "warn"
pedantic = "warn"
nursery = "warn"
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Add this to your `Cargo.toml`:

```toml
[dependencies]
num-bigint = "0.4"
num-bigint = "0.5"
```

## Features
Expand All @@ -29,12 +29,12 @@ if your compiler is not new enough.
feature is enabled. To enable it include rand as

```toml
rand = "0.8"
num-bigint = { version = "0.4", features = ["rand"] }
rand = " =0.9.0-beta.3"
num-bigint = { version = "0.5", features = ["rand"] }
```

Note that you must use the version of `rand` that `num-bigint` is compatible
with: `0.8`.
with: ` =0.9.0-beta.3`.

## Releases

Expand Down
46 changes: 24 additions & 22 deletions benches/bigint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,24 @@ use rng::get_rng;

fn multiply_bench(b: &mut Bencher, xbits: u64, ybits: u64) {
let mut rng = get_rng();
let x = rng.gen_bigint(xbits);
let y = rng.gen_bigint(ybits);
let x = rng.random_bigint(xbits);
let y = rng.random_bigint(ybits);

b.iter(|| &x * &y);
}

fn divide_bench(b: &mut Bencher, xbits: u64, ybits: u64) {
let mut rng = get_rng();
let x = rng.gen_bigint(xbits);
let y = rng.gen_bigint(ybits);
let x = rng.random_bigint(xbits);
let y = rng.random_bigint(ybits);

b.iter(|| &x / &y);
}

fn remainder_bench(b: &mut Bencher, xbits: u64, ybits: u64) {
let mut rng = get_rng();
let x = rng.gen_bigint(xbits);
let y = rng.gen_bigint(ybits);
let x = rng.random_bigint(xbits);
let y = rng.random_bigint(ybits);

b.iter(|| &x % &y);
}
Expand Down Expand Up @@ -186,7 +186,7 @@ fn fib_to_string(b: &mut Bencher) {

fn to_str_radix_bench(b: &mut Bencher, radix: u32, bits: u64) {
let mut rng = get_rng();
let x = rng.gen_bigint(bits);
let x = rng.random_bigint(bits);
b.iter(|| x.to_str_radix(radix));
}

Expand Down Expand Up @@ -222,7 +222,7 @@ fn to_str_radix_36(b: &mut Bencher) {

fn from_str_radix_bench(b: &mut Bencher, radix: u32) {
let mut rng = get_rng();
let x = rng.gen_bigint(1009);
let x = rng.random_bigint(1009);
let s = x.to_str_radix(radix);
assert_eq!(x, BigInt::from_str_radix(&s, radix).unwrap());
b.iter(|| BigInt::from_str_radix(&s, radix));
Expand Down Expand Up @@ -256,7 +256,7 @@ fn from_str_radix_36(b: &mut Bencher) {
fn rand_bench(b: &mut Bencher, bits: u64) {
let mut rng = get_rng();

b.iter(|| rng.gen_bigint(bits));
b.iter(|| rng.random_bigint(bits));
}

#[bench]
Expand Down Expand Up @@ -308,7 +308,7 @@ fn shl(b: &mut Bencher) {
for i in 0..50 {
m <<= i;
}
})
});
}

#[bench]
Expand All @@ -320,14 +320,14 @@ fn shr(b: &mut Bencher) {
for i in 0..50 {
m >>= i;
}
})
});
}

#[bench]
fn hash(b: &mut Bencher) {
use std::collections::HashSet;
let mut rng = get_rng();
let v: Vec<BigInt> = (1000..2000).map(|bits| rng.gen_bigint(bits)).collect();
let v: Vec<BigInt> = (1000..2000).map(|bits| rng.random_bigint(bits)).collect();
b.iter(|| {
let h: HashSet<&BigInt> = v.iter().collect();
assert_eq!(h.len(), v.len());
Expand All @@ -342,7 +342,9 @@ fn pow_bench(b: &mut Bencher) {
for _i in 2..=upper {
i_big += 1u32;
for j in 2..=upper {
i_big.pow(j);
let x = i_big.pow(j);
// added black box to prevent the compiler from optimizing out the pow
std::hint::black_box(&x);
}
}
});
Expand Down Expand Up @@ -382,7 +384,7 @@ fn pow_bench_1e100000(b: &mut Bencher) {
}

/// This modulus is the prime from the 2048-bit MODP DH group:
/// https://tools.ietf.org/html/rfc3526#section-3
/// <https://tools.ietf.org/html/rfc3526#section-3>
const RFC3526_2048BIT_MODP_GROUP: &str = "\
FFFFFFFF_FFFFFFFF_C90FDAA2_2168C234_C4C6628B_80DC1CD1\
29024E08_8A67CC74_020BBEA6_3B139B22_514A0879_8E3404DD\
Expand All @@ -399,8 +401,8 @@ const RFC3526_2048BIT_MODP_GROUP: &str = "\
#[bench]
fn modpow(b: &mut Bencher) {
let mut rng = get_rng();
let base = rng.gen_biguint(2048);
let e = rng.gen_biguint(2048);
let base = rng.random_biguint(2048);
let e = rng.random_biguint(2048);
let m = BigUint::from_str_radix(RFC3526_2048BIT_MODP_GROUP, 16).unwrap();

b.iter(|| base.modpow(&e, &m));
Expand All @@ -409,8 +411,8 @@ fn modpow(b: &mut Bencher) {
#[bench]
fn modpow_even(b: &mut Bencher) {
let mut rng = get_rng();
let base = rng.gen_biguint(2048);
let e = rng.gen_biguint(2048);
let base = rng.random_biguint(2048);
let e = rng.random_biguint(2048);
// Make the modulus even, so monty (base-2^32) doesn't apply.
let m = BigUint::from_str_radix(RFC3526_2048BIT_MODP_GROUP, 16).unwrap() - 1u32;

Expand All @@ -420,31 +422,31 @@ fn modpow_even(b: &mut Bencher) {
#[bench]
fn to_u32_digits(b: &mut Bencher) {
let mut rng = get_rng();
let n = rng.gen_biguint(2048);
let n = rng.random_biguint(2048);

b.iter(|| n.to_u32_digits());
}

#[bench]
fn iter_u32_digits(b: &mut Bencher) {
let mut rng = get_rng();
let n = rng.gen_biguint(2048);
let n = rng.random_biguint(2048);

b.iter(|| n.iter_u32_digits().max());
}

#[bench]
fn to_u64_digits(b: &mut Bencher) {
let mut rng = get_rng();
let n = rng.gen_biguint(2048);
let n = rng.random_biguint(2048);

b.iter(|| n.to_u64_digits());
}

#[bench]
fn iter_u64_digits(b: &mut Bencher) {
let mut rng = get_rng();
let n = rng.gen_biguint(2048);
let n = rng.random_biguint(2048);

b.iter(|| n.iter_u64_digits().max());
}
4 changes: 2 additions & 2 deletions benches/gcd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ use rng::get_rng;

fn bench(b: &mut Bencher, bits: u64, gcd: fn(&BigUint, &BigUint) -> BigUint) {
let mut rng = get_rng();
let x = rng.gen_biguint(bits);
let y = rng.gen_biguint(bits);
let x = rng.random_biguint(bits);
let y = rng.random_biguint(bits);

assert_eq!(euclid(&x, &y), x.gcd(&y));

Expand Down
28 changes: 15 additions & 13 deletions benches/rng/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use rand::RngCore;
use rand_core::{Rng, TryRng};

pub(crate) fn get_rng() -> impl RngCore {
pub(crate) fn get_rng() -> impl Rng {
XorShiftStar {
a: 0x0123_4567_89AB_CDEF,
}
Expand All @@ -11,28 +11,30 @@ struct XorShiftStar {
a: u64,
}

impl RngCore for XorShiftStar {
fn next_u32(&mut self) -> u32 {
self.next_u64() as u32
impl TryRng for XorShiftStar {
type Error = std::convert::Infallible;
fn try_next_u32(&mut self) -> Result<u32, Self::Error> {
Ok(self.try_next_u64()? as u32)
}

fn next_u64(&mut self) -> u64 {
fn try_next_u64(&mut self) -> Result<u64, Self::Error> {
// https://en.wikipedia.org/wiki/Xorshift#xorshift*
self.a ^= self.a >> 12;
self.a ^= self.a << 25;
self.a ^= self.a >> 27;
self.a.wrapping_mul(0x2545_F491_4F6C_DD1D)
Ok(self.a.wrapping_mul(0x2545_F491_4F6C_DD1D))
}

fn fill_bytes(&mut self, dest: &mut [u8]) {
fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Self::Error> {
for chunk in dest.chunks_mut(8) {
let bytes = self.next_u64().to_le_bytes();
let bytes = self.try_next_u64()?.to_le_bytes();
let slice = &bytes[..chunk.len()];
chunk.copy_from_slice(slice)
chunk.copy_from_slice(slice);
}
Ok(())
}

fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand::Error> {
Ok(self.fill_bytes(dest))
}
// fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand::Error> {
// Ok(self.fill_bytes(dest))
// }
}
18 changes: 9 additions & 9 deletions benches/roots.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#![feature(test)]
#![cfg(feature = "rand")]
#![cfg(feature = "rand_core")]

extern crate test;

Expand All @@ -20,9 +20,9 @@ use rng::get_rng;
fn check(x: &BigUint, n: u32) {
let root = x.nth_root(n);
if n == 2 {
assert_eq!(root, x.sqrt())
assert_eq!(root, x.sqrt());
} else if n == 3 {
assert_eq!(root, x.cbrt())
assert_eq!(root, x.cbrt());
}

let lo = root.pow(n);
Expand All @@ -37,8 +37,8 @@ fn check(x: &BigUint, n: u32) {
}

fn bench_sqrt(b: &mut Bencher, bits: u64) {
let x = get_rng().gen_biguint(bits);
eprintln!("bench_sqrt({})", x);
let x = get_rng().random_biguint(bits);
eprintln!("bench_sqrt({x})");

check(&x, 2);
b.iter(|| x.sqrt());
Expand All @@ -65,8 +65,8 @@ fn big4k_sqrt(b: &mut Bencher) {
}

fn bench_cbrt(b: &mut Bencher, bits: u64) {
let x = get_rng().gen_biguint(bits);
eprintln!("bench_cbrt({})", x);
let x = get_rng().random_biguint(bits);
eprintln!("bench_cbrt({x})");

check(&x, 3);
b.iter(|| x.cbrt());
Expand All @@ -93,8 +93,8 @@ fn big4k_cbrt(b: &mut Bencher) {
}

fn bench_nth_root(b: &mut Bencher, bits: u64, n: u32) {
let x = get_rng().gen_biguint(bits);
eprintln!("bench_{}th_root({})", n, x);
let x = get_rng().random_biguint(bits);
eprintln!("bench_{n}th_root({x})");

check(&x, n);
b.iter(|| x.nth_root(n));
Expand Down
Loading