diff --git a/lib/primes/src/lib.rs b/lib/primes/src/lib.rs index a1c406d..4c9b6d5 100644 --- a/lib/primes/src/lib.rs +++ b/lib/primes/src/lib.rs @@ -33,10 +33,14 @@ where } fn from_array(array: Vec, min_value: &usize, max_value: &usize) -> Self { - let mut vector = Vec::new(); - let mut set = HashSet::new(); + let number_of_primes = array.iter().filter(|b| **b).count(); + let mut vector = Vec::with_capacity(number_of_primes); + let mut set = HashSet::with_capacity(number_of_primes); + for number in *min_value..*max_value { - if array[(number - min_value) as usize] { + let idx = number - min_value; + // SAFETY: see considerations in get_prime_numbers_array + if unsafe { *array.get_unchecked(idx) } { let prime = FromPrimitive::from_usize(number).unwrap(); vector.push(prime); set.insert(prime); @@ -51,18 +55,30 @@ where let length = *max_value - *min_value; let mut result = vec![true; length]; - let upper_limit = f64::sqrt(*max_value as f64).ceil() as usize; + let upper_limit = Self::calc_upper_limit(max_value); for i in 2..upper_limit { - for multiple in ((i * i)..*max_value).step_by(i) { - if &multiple < min_value { - continue; - } - result[multiple - min_value] = false; + let skip = Self::find_number_to_skip_until_min_value(min_value, i); + + for multiple in (i * i..*max_value).step_by(i).skip(skip) { + let idx = multiple - min_value; + // SAFETY: `multiple` will always be between min_value and max_value + // (which define the length of the array), therfore idx is always smaller than the + // length of result, therefore this access is always in bounds. + // This is slightly faster than the bounds-checked write. + unsafe { *result.get_unchecked_mut(idx) = false }; } } result } + fn calc_upper_limit(max_value: &usize) -> usize { + f64::sqrt(*max_value as f64).ceil() as usize + } + + fn find_number_to_skip_until_min_value(min_value: &usize, i: usize) -> usize { + ((min_value.saturating_sub(i * i)) as f64 / i as f64).ceil() as usize + } + pub fn remove(&mut self, num: &T) { if let Some(index) = self.vector.iter().position(|x| x == num) { self.vector.remove(index); @@ -75,6 +91,11 @@ where self.vector.len() } + pub fn is_empty(&self) -> bool { + debug_assert_eq!(self.vector.len(), self.set.len()); + self.vector.is_empty() + } + pub fn pop(&mut self) -> Option { let result = self.vector.pop(); if let Some(value) = result { @@ -139,4 +160,11 @@ mod test { let primes = Primes::get_between(2, 10_000_000); assert_eq!(primes.len(), 664_579); } + + // #[ignore] + // #[test] + // fn test_performance_2() { + // let primes = Primes::get_between(2, 1_000_000_000); + // assert_eq!(primes.len(), 50_847_534); + // } }