lazy-prime-sieve

Lazy Sieve of Eratosthenes for infinitely generating primes lazily in Rust.

Usage

lazy-prime-sieve is a library crate. You may add it to your Cargo.toml as follows:

toml [dependencies] lazy-prime-sieve = "0.1.2"

lazy-prime-sieve provides iterators for infinitely generating primes. This crate provides a convenience method ::primes() which returns the most efficient iterator (in this crate) for generating primes.

```rust use lazyprimesieve::primes;

for i in primes().take(10) { println!("{i}"); } ```

Design

This crates two kinds of abstractions: sieve(s) and source(s). - source(s) represent infinite sources of integers from which we sample primes. - sieve(s) sample primes from source(s).

Both source(s) and sieve(s) implement Iterator<Item = u64>.

This crate provides the following sieves: - UnfaithfulSieve: Non recursive Iterator based alternative to classic Haskell lazy recursive prime sieve: haskell primes = sieve [2..] sieve (p : xs) = p : sieve [x | x <− xs, x ‘mod‘ p > 0] - TrialDivsionSieve: The modulus based memoized approach of generating primes that we all know and love. - GenuineSieve: Priority Queue based solution true to the original Sieve of Eratosthenes algorithm.

This crate provides the following source: - integer_candidates(): Returns an iterator which yields the sequence 2, 3, 4, 5, 6, 7, … - odds_with_2(): Returns an iterator which yields the sequence 2, 3, 5, 7, 9, … - SpinWheel::default(): Iterator of monotonically increasing integers which are not multiples of 2, 3, 5 and 7.

Mostly, we initialize a sieve with a source and start generating primes:

```rust use lazyprimesieve::{sieve::TrialDivisionSieve, source::oddswith2};

// print the first 10 primes TrialDivisionSieve::withsource(oddswith2()) .take(10) .foreach(|x| println!("{x}")); ```

However some sources start from a high number. So we need to chain the initial primes:

```rust use lazyprimesieve::{source::SpinWheel, sieve::GenuineSieve};

// starts from 11 let source = SpinWheel::default();

// print the first 10 primes [2, 3, 5, 7] .iter() .cloned() .chain(GenuineSieve::withsource(source)) .take(10) .foreach(|x| println!("{x}")); ```

Refer to the documentation for further details.

Benchmarks

prime-sieves-bench

This benchmark shows the time taken by the different (source, sieve) combinations (fmt: "{sieve}_with_{source}") in this crate to generate a certain number of primes. The x-axis shows the number of primes generated, while the y-axis shows the amount of time taken.

The fastest combination is GenuineSieve with SpinWheel::default(). This is the combination used by lazy_prime_sieve::primes().

These benchmarks were run on an AMD Ryzen 7 x86_64 machine in WSL with 8 GB RAM allocated to WSL.

References

This crate heavily draws from the paper The Genuine Sieve of Eratosthenes. This repository attempts to provide non-recursive lazy Rust iterator based alternatives to the Haskell lazy list + recursion based methods proposed in the paper.

License

lazy-prime-sieve is licensed under the MIT License. See License for more details.