I am attempting to re-implement a postponed sieve algorithm for generating prime numbers in Rust. I am able to make a solution that works, but I have to use a couple of .clone()
calls which I believe are killing my performance (the Rust solution ends up ~8x slower than the Python solution).
I would love some advice on how I can avoid the .clone()
calls while avoiding errors from the borrow checker.
use std::collections::HashMap; #[derive(Debug, Clone)] struct Primes { i: usize, curr_candidate: u64, next_relevant_prime: u64, next_relevant_prime_squared: u64, sieve: HashMap<u64, u64>, initial_primes: Vec<u64>, internal_primes: Box<Option<Primes>>, } impl Primes { fn new() -> Primes { Primes { i: 0, curr_candidate: 7, next_relevant_prime: 0, next_relevant_prime_squared: 0, sieve: HashMap::new(), initial_primes: vec![2, 3, 5, 7], internal_primes: Box::new(None), } } } impl Iterator for Primes { type Item = u64; fn next(&mut self) -> Option<Self::Item> { let len = self.initial_primes.len(); let mut internal_primes; if self.i < len { self.i += 1; return Some(self.initial_primes[self.i - 1]); } else if self.i == len { self.i += 1; internal_primes = Primes::new(); self.internal_primes = Box::new(Some(internal_primes.clone())); internal_primes.next(); // skip 2 self.next_relevant_prime = internal_primes.next().unwrap(); self.next_relevant_prime_squared = self.next_relevant_prime.pow(2); } else { internal_primes = self.internal_primes.clone().unwrap(); } let mut i = self.curr_candidate; loop { i += 2; let step; if self.sieve.contains_key(&i) { // composite step = self.sieve.remove(&i).unwrap(); } else if i < self.next_relevant_prime_squared { // prime // save state for next round self.curr_candidate = i; self.internal_primes = Box::new(Some(internal_primes)); return Some(i); } else { // i == next_relevant_prime_squared step = 2 * self.next_relevant_prime; self.next_relevant_prime = internal_primes.next().unwrap(); self.next_relevant_prime_squared = self.next_relevant_prime.pow(2); } let mut j = i; j += step; while self.sieve.contains_key(&j) { j += step; } self.sieve.insert(j, step); } } } fn main() { let mut primes = Primes::new(); for _i in 0..99_999 { primes.next(); } println!("The 100,000th prime is {}", primes.next().unwrap()) }