Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generalize sieving #64

Merged
merged 4 commits into from
Dec 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 12 additions & 47 deletions .github/workflows/crypto-primes.yml → .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
target:
- wasm32-unknown-unknown
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: actions-rs/toolchain@v1
with:
profile: minimal
Expand All @@ -31,11 +31,11 @@ jobs:
override: true
- run: cargo build --target ${{ matrix.target }} --release --no-default-features

codecov:
test-and-coverage:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions-rs/toolchain@v1
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@v1
with:
profile: minimal
toolchain: stable
Expand All @@ -44,38 +44,14 @@ jobs:
- name: Install cargo-llvm-cov
uses: taiki-e/install-action@cargo-llvm-cov
- name: Generate code coverage
run: cargo llvm-cov --workspace --lcov --output-path lcov.info
run: cargo llvm-cov --features default-rng,multicore --workspace --lcov --output-path lcov.info
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4
uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: lcov.info
fail_ci_if_error: true

tests:
runs-on: ubuntu-latest
strategy:
matrix:
include:
# 32-bit Linux
- target: i686-unknown-linux-gnu
rust: stable
deps: sudo apt update && sudo apt install gcc-multilib

# 64-bit Linux
- target: x86_64-unknown-linux-gnu
rust: stable
steps:
- uses: actions/checkout@v3
- uses: actions-rs/toolchain@v1
with:
toolchain: ${{ matrix.rust }}
target: ${{ matrix.target }}
profile: minimal
override: true
- run: ${{ matrix.deps }}
- run: cargo test --target ${{ matrix.target }}

slow-tests:
runs-on: ubuntu-latest
strategy:
Expand All @@ -91,23 +67,23 @@ jobs:
rust: stable
deps: sudo apt update && sudo apt install gcc-multilib
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: actions-rs/toolchain@v1
with:
toolchain: ${{ matrix.rust }}
target: ${{ matrix.target }}
profile: minimal
override: true
- run: ${{ matrix.deps }}
- run: cargo test --target ${{ matrix.target }} --release --features tests-all
- run: cargo test --target ${{ matrix.target }} --release --all-features

clippy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: actions-rs/toolchain@v1
with:
toolchain: stable
toolchain: 1.81.0 # MSRV
components: clippy
override: true
profile: minimal
Expand All @@ -116,7 +92,7 @@ jobs:
rustfmt:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: actions-rs/toolchain@v1
with:
toolchain: stable
Expand All @@ -128,21 +104,10 @@ jobs:
command: fmt
args: --all -- --check

# just building them to check that they're up to date with the API
build-benchmarks:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions-rs/toolchain@v1
with:
toolchain: 1.81.0
profile: minimal
- run: cargo build --all-features --benches

cargo-careful:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: actions-rs/toolchain@v1
with:
toolchain: nightly
Expand Down
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## Unreleased

### Changed

- Renamed `Sieve` to `SmallPrimesSieve`. ([#64])


### Added

- Parallel prime finding methods and a "multicore" feature ([#60])
- Generalized sieving: `SieveFactory` trait, `SieveIterator`, and the convenience functions `sieve_and_find()` and `par_sieve_and_find()`. ([#64])


[#60]: https://github.com/entropyxyz/crypto-primes/pull/60
[#64]: https://github.com/entropyxyz/crypto-primes/pull/64


## [0.6.0-pre.2] - 2024-10-18

Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ The following features are available:
[docs-image]: https://docs.rs/crypto-primes/badge.svg
[docs-link]: https://docs.rs/crypto-primes/
[license-image]: https://img.shields.io/crates/l/crypto-primes
[build-image]: https://github.com/entropyxyz/crypto-primes/workflows/crypto-primes/badge.svg?branch=master&event=push
[build-link]: https://github.com/entropyxyz/crypto-primes/actions?query=workflow%3Acrypto-primes
[build-image]: https://github.com/entropyxyz/crypto-primes/workflows/ci/badge.svg?branch=master&event=push
[build-link]: https://github.com/entropyxyz/crypto-primes/actions?query=workflow%3Aci
[coverage-image]: https://codecov.io/gh/entropyxyz/crypto-primes/branch/master/graph/badge.svg
[coverage-link]: https://codecov.io/gh/entropyxyz/crypto-primes
[hazmat-lnk]: https://docs.rs/crypto-primes/latest/crypto_primes/hazmat
69 changes: 50 additions & 19 deletions benches/bench.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,14 @@ use rug::{integer::Order, Integer as GmpInteger};
#[cfg(feature = "tests-openssl")]
use openssl::bn::BigNum;

#[cfg(feature = "multicore")]
use rand_core::RngCore;

use crypto_primes::{
generate_prime_with_rng, generate_safe_prime_with_rng,
hazmat::{
lucas_test, random_odd_integer, AStarBase, BruteForceBase, LucasCheck, MillerRabin, SelfridgeBase, Sieve,
lucas_test, random_odd_integer, AStarBase, BruteForceBase, LucasCheck, MillerRabin, SelfridgeBase,
SmallPrimesSieve,
},
is_prime_with_rng, is_safe_prime_with_rng,
};
Expand All @@ -25,13 +29,20 @@ fn make_rng() -> ChaCha8Rng {
ChaCha8Rng::from_seed(*b"01234567890123456789012345678901")
}

#[cfg(feature = "multicore")]
fn make_random_rng() -> ChaCha8Rng {
let mut seed = <ChaCha8Rng as SeedableRng>::Seed::default();
OsRng.fill_bytes(&mut seed);
ChaCha8Rng::from_seed(seed)
}

fn random_odd_uint<T: RandomBits + Integer>(rng: &mut impl CryptoRngCore, bit_length: u32) -> Odd<T> {
random_odd_integer::<T>(rng, NonZero::new(bit_length).unwrap())
}

fn make_sieve<const L: usize>(rng: &mut impl CryptoRngCore) -> Sieve<Uint<L>> {
fn make_sieve<const L: usize>(rng: &mut impl CryptoRngCore) -> SmallPrimesSieve<Uint<L>> {
let start = random_odd_uint::<Uint<L>>(rng, Uint::<L>::BITS);
Sieve::new(start.get(), NonZero::new(Uint::<L>::BITS).unwrap(), false)
SmallPrimesSieve::new(start.get(), NonZero::new(Uint::<L>::BITS).unwrap(), false)
}

fn make_presieved_num<const L: usize>(rng: &mut impl CryptoRngCore) -> Odd<Uint<L>> {
Expand All @@ -49,7 +60,7 @@ fn bench_sieve(c: &mut Criterion) {
group.bench_function("(U128) creation", |b| {
b.iter_batched(
|| random_odd_uint::<U128>(&mut OsRng, 128),
|start| Sieve::new(start.get(), NonZero::new(128).unwrap(), false),
|start| SmallPrimesSieve::new(start.get(), NonZero::new(128).unwrap(), false),
BatchSize::SmallInput,
)
});
Expand All @@ -70,7 +81,7 @@ fn bench_sieve(c: &mut Criterion) {
group.bench_function("(U1024) creation", |b| {
b.iter_batched(
|| random_odd_uint::<U1024>(&mut OsRng, 1024),
|start| Sieve::new(start.get(), NonZero::new(1024).unwrap(), false),
|start| SmallPrimesSieve::new(start.get(), NonZero::new(1024).unwrap(), false),
BatchSize::SmallInput,
)
});
Expand Down Expand Up @@ -282,38 +293,58 @@ fn bench_presets(c: &mut Criterion) {
#[cfg(feature = "multicore")]
fn bench_multicore_presets(c: &mut Criterion) {
let mut group = c.benchmark_group("Presets (multicore)");
let mut rng = make_rng();

group.bench_function("(U128) Random prime", |b| {
b.iter(|| par_generate_prime_with_rng::<U128>(&mut rng, 128, num_cpus::get()))
b.iter_batched(
make_random_rng,
|mut rng| par_generate_prime_with_rng::<U128>(&mut rng, 128, num_cpus::get()),
BatchSize::SmallInput,
)
});

let mut rng = make_rng();
group.bench_function("(U1024) Random prime", |b| {
b.iter(|| par_generate_prime_with_rng::<U1024>(&mut rng, 1024, num_cpus::get()))
b.iter_batched(
make_random_rng,
|mut rng| par_generate_prime_with_rng::<U1024>(&mut rng, 1024, num_cpus::get()),
BatchSize::SmallInput,
)
});

let mut rng = make_rng();
group.bench_function("(U128) Random safe prime", |b| {
b.iter(|| par_generate_safe_prime_with_rng::<U128>(&mut rng, 128, num_cpus::get()))
b.iter_batched(
make_random_rng,
|mut rng| par_generate_safe_prime_with_rng::<U128>(&mut rng, 128, num_cpus::get()),
BatchSize::SmallInput,
)
});

group.sample_size(20);
let mut rng = make_rng();
group.bench_function("(U1024) Random safe prime", |b| {
b.iter(|| par_generate_safe_prime_with_rng::<U1024>(&mut rng, 1024, num_cpus::get()))
b.iter_batched(
make_random_rng,
|mut rng| par_generate_safe_prime_with_rng::<U1024>(&mut rng, 1024, num_cpus::get()),
BatchSize::SmallInput,
)
});

let mut rng = make_rng();
group.bench_function("(Boxed128) Random safe prime", |b| {
b.iter(|| par_generate_safe_prime_with_rng::<BoxedUint>(&mut rng, 128, num_cpus::get()))
b.iter_batched(
make_random_rng,
|mut rng| par_generate_safe_prime_with_rng::<BoxedUint>(&mut rng, 128, num_cpus::get()),
BatchSize::SmallInput,
)
});

group.sample_size(20);
let mut rng = make_rng();
group.bench_function("(Boxed1024) Random safe prime", |b| {
b.iter(|| par_generate_safe_prime_with_rng::<BoxedUint>(&mut rng, 1024, num_cpus::get()))
b.iter_batched(
make_random_rng,
|mut rng| par_generate_safe_prime_with_rng::<BoxedUint>(&mut rng, 1024, num_cpus::get()),
BatchSize::SmallInput,
)
});
}

#[cfg(not(feature = "multicore"))]
fn bench_multicore_presets(_c: &mut Criterion) {}

Expand Down Expand Up @@ -419,7 +450,7 @@ fn bench_glass_pumpkin(c: &mut Criterion) {
fn prime_like_gp(bit_length: u32, rng: &mut impl CryptoRngCore) -> BoxedUint {
loop {
let start = random_odd_integer::<BoxedUint>(rng, NonZero::new(bit_length).unwrap()).get();
let sieve = Sieve::new(start, NonZero::new(bit_length).unwrap(), false);
let sieve = SmallPrimesSieve::new(start, NonZero::new(bit_length).unwrap(), false);
for num in sieve {
let odd_num = Odd::new(num.clone()).unwrap();

Expand All @@ -443,7 +474,7 @@ fn bench_glass_pumpkin(c: &mut Criterion) {
fn safe_prime_like_gp(bit_length: u32, rng: &mut impl CryptoRngCore) -> BoxedUint {
loop {
let start = random_odd_integer::<BoxedUint>(rng, NonZero::new(bit_length).unwrap()).get();
let sieve = Sieve::new(start, NonZero::new(bit_length).unwrap(), true);
let sieve = SmallPrimesSieve::new(start, NonZero::new(bit_length).unwrap(), true);
for num in sieve {
let odd_num = Odd::new(num.clone()).unwrap();

Expand Down
Loading
Loading