mirror of
https://github.com/uutils/num-prime.git
synced 2026-06-10 16:12:35 -07:00
Add more benchmarks
This commit is contained in:
@@ -18,6 +18,7 @@ num-primes = { version = "0.3.0", optional = true }
|
||||
primal-check = "0.3.1"
|
||||
number-theory = "0.0.6"
|
||||
is_prime = "2.0.7"
|
||||
glass_pumpkin = "1.2.0"
|
||||
|
||||
[features]
|
||||
default = ["num-primes"]
|
||||
|
||||
+152
-1
@@ -1,11 +1,15 @@
|
||||
#[macro_use]
|
||||
extern crate criterion;
|
||||
use std::iter::repeat_with;
|
||||
|
||||
use criterion::{Criterion, SamplingMode};
|
||||
use num_bigint::RandBigInt;
|
||||
use num_prime::{nt_funcs, RandPrime};
|
||||
#[cfg(feature = "num-primes")]
|
||||
use num_primes::{Generator, Verification};
|
||||
use primal_check::miller_rabin;
|
||||
use number_theory::NumberTheory;
|
||||
use glass_pumpkin::{prime as gprime, safe_prime as safe_gprime};
|
||||
|
||||
pub fn bench_is_prime(c: &mut Criterion) {
|
||||
const N0: u64 = 1_000_000;
|
||||
@@ -17,7 +21,7 @@ pub fn bench_is_prime(c: &mut Criterion) {
|
||||
.step_by(STEP)
|
||||
.chain((N1..N2).step_by(STEP));
|
||||
|
||||
let mut group = c.benchmark_group("is_prime (u64)");
|
||||
let mut group = c.benchmark_group("primality check (u64)");
|
||||
|
||||
group.bench_function("num-prime (this crate)", |b| {
|
||||
b.iter(|| {
|
||||
@@ -34,6 +38,13 @@ pub fn bench_is_prime(c: &mut Criterion) {
|
||||
.count()
|
||||
})
|
||||
});
|
||||
group.bench_function("glass_pumpkin", |b| {
|
||||
b.iter(|| {
|
||||
numbers()
|
||||
.filter(|&n| gprime::check(&n.into()))
|
||||
.count()
|
||||
})
|
||||
});
|
||||
group.bench_function("primal-check", |b| {
|
||||
b.iter(|| {
|
||||
numbers()
|
||||
@@ -52,6 +63,140 @@ pub fn bench_is_prime(c: &mut Criterion) {
|
||||
// we can add a markdown of performance after figuring out this
|
||||
|
||||
group.finish();
|
||||
|
||||
////// 256 bits Bigint /////
|
||||
|
||||
let mut rng = rand::thread_rng();
|
||||
let numbers: Vec<_> = repeat_with(|| rng.gen_biguint(256)).take(32).collect();
|
||||
|
||||
let mut group = c.benchmark_group("primality check (u256)");
|
||||
group.bench_function("num-prime (this crate)", |b| {
|
||||
b.iter(|| {
|
||||
numbers.iter()
|
||||
.filter(|&n| nt_funcs::is_prime(n, None).probably())
|
||||
.count()
|
||||
})
|
||||
});
|
||||
group.bench_function("num-primes", |b| {
|
||||
b.iter(|| {
|
||||
numbers.iter()
|
||||
.filter(|&n| Verification::is_prime(&num_primes::BigUint::from_bytes_le(&n.to_bytes_le())))
|
||||
.count()
|
||||
})
|
||||
});
|
||||
group.bench_function("glass_pumpkin", |b| {
|
||||
b.iter(|| {
|
||||
numbers.iter()
|
||||
.filter(|&n| gprime::check(n))
|
||||
.count()
|
||||
})
|
||||
});
|
||||
group.bench_function("glass_pumpkin (BPSW)", |b| {
|
||||
b.iter(|| {
|
||||
numbers.iter()
|
||||
.filter(|&n| gprime::strong_check(n))
|
||||
.count()
|
||||
})
|
||||
});
|
||||
group.finish();
|
||||
|
||||
let mut group = c.benchmark_group("safe primality check (u256)");
|
||||
group.bench_function("num-prime (this crate)", |b| {
|
||||
b.iter(|| {
|
||||
numbers.iter()
|
||||
.filter(|&n| nt_funcs::is_safe_prime(n).probably())
|
||||
.count()
|
||||
})
|
||||
});
|
||||
group.bench_function("num-primes", |b| {
|
||||
b.iter(|| {
|
||||
numbers.iter()
|
||||
.filter(|&n| Verification::is_safe_prime(&num_primes::BigUint::from_bytes_le(&n.to_bytes_le())))
|
||||
.count()
|
||||
})
|
||||
});
|
||||
group.bench_function("glass_pumpkin", |b| {
|
||||
b.iter(|| {
|
||||
numbers.iter()
|
||||
.filter(|&n| safe_gprime::check(n))
|
||||
.count()
|
||||
})
|
||||
});
|
||||
group.bench_function("glass_pumpkin (BPSW)", |b| {
|
||||
b.iter(|| {
|
||||
numbers.iter()
|
||||
.filter(|&n| safe_gprime::strong_check(n))
|
||||
.count()
|
||||
})
|
||||
});
|
||||
group.finish();
|
||||
|
||||
////// 2048 bits Bigint /////
|
||||
|
||||
let mut rng = rand::thread_rng();
|
||||
let numbers: Vec<_> = repeat_with(|| rng.gen_biguint(2048)).take(8).collect();
|
||||
|
||||
let mut group = c.benchmark_group("primality check (u2048)");
|
||||
group.bench_function("num-prime (this crate)", |b| {
|
||||
b.iter(|| {
|
||||
numbers.iter()
|
||||
.filter(|&n| nt_funcs::is_prime(n, None).probably())
|
||||
.count()
|
||||
})
|
||||
});
|
||||
group.bench_function("num-primes", |b| {
|
||||
b.iter(|| {
|
||||
numbers.iter()
|
||||
.filter(|&n| Verification::is_prime(&num_primes::BigUint::from_bytes_le(&n.to_bytes_le())))
|
||||
.count()
|
||||
})
|
||||
});
|
||||
group.bench_function("glass_pumpkin", |b| {
|
||||
b.iter(|| {
|
||||
numbers.iter()
|
||||
.filter(|&n| gprime::check(n))
|
||||
.count()
|
||||
})
|
||||
});
|
||||
group.bench_function("glass_pumpkin (BPSW)", |b| {
|
||||
b.iter(|| {
|
||||
numbers.iter()
|
||||
.filter(|&n| gprime::strong_check(n))
|
||||
.count()
|
||||
})
|
||||
});
|
||||
group.finish();
|
||||
|
||||
let mut group = c.benchmark_group("safe primality check (u2048)");
|
||||
group.bench_function("num-prime (this crate)", |b| {
|
||||
b.iter(|| {
|
||||
numbers.iter()
|
||||
.filter(|&n| nt_funcs::is_safe_prime(n).probably())
|
||||
.count()
|
||||
})
|
||||
});
|
||||
group.bench_function("num-primes", |b| {
|
||||
b.iter(|| {
|
||||
numbers.iter()
|
||||
.filter(|&n| Verification::is_safe_prime(&num_primes::BigUint::from_bytes_le(&n.to_bytes_le())))
|
||||
.count()
|
||||
})
|
||||
});
|
||||
group.bench_function("glass_pumpkin", |b| {
|
||||
b.iter(|| {
|
||||
numbers.iter()
|
||||
.filter(|&n| safe_gprime::check(n))
|
||||
.count()
|
||||
})
|
||||
});
|
||||
group.bench_function("glass_pumpkin (BPSW)", |b| {
|
||||
b.iter(|| {
|
||||
numbers.iter()
|
||||
.filter(|&n| safe_gprime::strong_check(n))
|
||||
.count()
|
||||
})
|
||||
});
|
||||
group.finish();
|
||||
}
|
||||
|
||||
pub fn bench_factorization(c: &mut Criterion) {
|
||||
@@ -94,6 +239,9 @@ pub fn bench_prime_gen(c: &mut Criterion) {
|
||||
group.bench_function("num-primes", |b| {
|
||||
b.iter(|| Generator::new_prime(256))
|
||||
});
|
||||
group.bench_function("glass_pumpkin", |b| {
|
||||
b.iter(|| gprime::from_rng(256, &mut gen))
|
||||
});
|
||||
group.finish();
|
||||
|
||||
let mut group = c.benchmark_group("safe prime generation (256 bits)");
|
||||
@@ -106,6 +254,9 @@ pub fn bench_prime_gen(c: &mut Criterion) {
|
||||
group.bench_function("num-primes", |b| {
|
||||
b.iter(|| Generator::safe_prime(256))
|
||||
});
|
||||
group.bench_function("glass_pumpkin", |b| {
|
||||
b.iter(|| safe_gprime::from_rng(256, &mut gen))
|
||||
});
|
||||
group.finish();
|
||||
}
|
||||
|
||||
|
||||
+20
-6
@@ -553,6 +553,8 @@ where
|
||||
{
|
||||
let buf = NaiveBuffer::new();
|
||||
let config = Some(PrimalityTestConfig::strict());
|
||||
// TODO: use miller-rabin for large numbers (more than 256 bits?), as BPSW could be too slow
|
||||
// the NIST recommends 5 rounds for 512 and 1024 bits. For 1536 bits, the recommendation is 4 rounds.
|
||||
|
||||
// test (n-1)/2 first since its smaller
|
||||
let sophie_p = buf.is_prime(&(target >> 1), config);
|
||||
@@ -712,7 +714,7 @@ macro_rules! impl_randprime_prim {
|
||||
panic!("The given bit size limit exceeded the capacity of the integer type!")
|
||||
}
|
||||
let t: $T = self.gen();
|
||||
let t = t >> (<$T>::BITS - bit_size as u32);
|
||||
let t = (t >> (<$T>::BITS - bit_size as u32)) | 1; // filter even numbers
|
||||
if is_prime64(t as u64) {
|
||||
t
|
||||
} else {
|
||||
@@ -755,7 +757,7 @@ impl<R: Rng> RandPrime<u128> for R {
|
||||
panic!("The given bit size limit exceeded the capacity of the integer type!")
|
||||
}
|
||||
let t: u128 = self.gen();
|
||||
let t = t >> (u128::BITS - bit_size as u32);
|
||||
let t = (t >> (u128::BITS - bit_size as u32)) | 1; // filter even numbers
|
||||
if is_prime(&t, config).probably() {
|
||||
t
|
||||
} else {
|
||||
@@ -783,11 +785,11 @@ impl<R: Rng> RandPrime<u128> for R {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "big-int")]
|
||||
#[cfg(feature = "num-bigint")]
|
||||
impl<R: Rng> RandPrime<BigUint> for R {
|
||||
#[inline]
|
||||
fn gen_prime(&mut self, bit_size: usize, config: Option<PrimalityTestConfig>) -> BigUint {
|
||||
let t = self.gen_biguint(bit_size as u64);
|
||||
let t = self.gen_biguint(bit_size as u64) | BigUint::from(1u8); // filter even numbers
|
||||
if is_prime(&t, config).probably() {
|
||||
t
|
||||
} else {
|
||||
@@ -967,6 +969,18 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "big-int")]
|
||||
fn is_prime_test() {
|
||||
#[cfg(feature = "num-bigint")]
|
||||
{
|
||||
use num_bigint::BigUint;
|
||||
// https://github.com/AtropineTears/num-primes/issues/1#issuecomment-934629597
|
||||
let p = BigUint::parse_bytes(b"169511182982703321453314585423962898651587669459838234386506572286328885534468792292646838949809616446341407457141008401355628947670484184607678853094537849610289912805960069455687743151708433319901176932959509872662610091644590437761688516626993416011399330087939042347256922771590903190536793274742859624657", 10).unwrap();
|
||||
assert!(is_prime(&p, None).probably());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn is_safe_prime_test() {
|
||||
// OEIS:A005385
|
||||
@@ -1181,12 +1195,12 @@ mod tests {
|
||||
let p: u128 = rng.gen_safe_prime(128);
|
||||
assert!(is_safe_prime(&p).probably());
|
||||
|
||||
#[cfg(feature = "big-int")]
|
||||
#[cfg(feature = "num-bigint")]
|
||||
{
|
||||
let p: BigUint = rng.gen_prime(512, None);
|
||||
assert!(is_prime(&p, None).probably());
|
||||
let p: BigUint = rng.gen_safe_prime(192);
|
||||
assert!(is_prime(&p, None).probably());
|
||||
assert!(is_safe_prime(&p).probably());
|
||||
}
|
||||
|
||||
// test bit size limit
|
||||
|
||||
@@ -33,6 +33,7 @@ pub enum Primality {
|
||||
impl Primality {
|
||||
/// Check whether the resule indicates that the number is
|
||||
/// (very) probably a prime. Return false only on [Primality::No]
|
||||
#[inline(always)]
|
||||
pub fn probably(self) -> bool {
|
||||
match self {
|
||||
Primality::No => false,
|
||||
@@ -276,4 +277,6 @@ pub trait RandPrime<T> {
|
||||
/// Generate a random (Sophie German) safe prime within the given bit size limit. The generated prime
|
||||
/// is guaranteed to pass the [is_safe_prime][crate::nt_funcs::is_safe_prime] test
|
||||
fn gen_safe_prime(&mut self, bit_size: usize) -> T;
|
||||
|
||||
// TODO: add gen_prime_exact and gen_safe_prime_exact for generating primes with exact this bit size
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user