extern crate num; use std::collections::HashSet; use std::fmt::Display; use std::fs::File; use std::hash::Hash; use std::io::Write; use std::slice::Iter; use std::vec::IntoIter; use num::FromPrimitive; use num::Num; use num::ToPrimitive; #[derive(Clone, Debug)] pub struct Primes { vector: Vec, set: HashSet, } impl Primes where T: Num + ToPrimitive + FromPrimitive + Hash + Eq + PartialEq + Copy + Display, { pub fn get_between(min_value: T, max_value: T) -> Self { let max_value = max_value.to_usize().unwrap(); let min_value = min_value.to_usize().unwrap(); assert!(min_value > 1); assert!(max_value > min_value); Self::from_array( &Self::get_prime_numbers_array(min_value, max_value), min_value, max_value, ) } fn from_array(array: &[bool], min_value: usize, max_value: usize) -> Self { 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 { 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); } } debug_assert_eq!(number_of_primes, vector.len()); Primes { vector, set } } fn get_prime_numbers_array(min_value: usize, max_value: usize) -> Vec { // Sieve of Eratosthenes let length = max_value - min_value; let mut result = vec![true; length]; 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).skip_while(|i| i < &min_value) { 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 } pub fn remove(&mut self, num: &T) { if let Some(index) = self.vector.iter().position(|x| x == num) { self.vector.remove(index); self.set.remove(num); }; } pub fn len(&self) -> usize { debug_assert_eq!(self.vector.len(), self.set.len()); self.vector.len() } pub fn is_empty(&self) -> bool { debug_assert_eq!(self.vector.len(), self.set.len()); self.vector.is_empty() } pub fn contains(&self, val: &T) -> bool { self.set.contains(val) } pub fn save(&self, filename: &str) { let mut f = File::create(filename).unwrap(); for p in &self.vector { writeln!(f, "{p}").unwrap(); } } pub fn iter(&self) -> Iter { self.vector.iter() } pub fn into_vec(self) -> Vec { self.vector } pub fn to_cloned_iter(&self) -> IntoIter { self.vector.clone().into_iter() } } #[cfg(test)] mod test { use super::Primes; #[test] fn test_example_prime() { let primes = Primes::get_between(2, 99_999); assert!(primes.set.contains(&56003)); assert!(primes.set.contains(&56993)); assert!(!primes.set.contains(&56002)); } #[test] fn test_remove() { let mut primes = Primes::get_between(2, 9); assert!(primes.contains(&7)); primes.remove(&7); assert!(!primes.contains(&7)); } #[test] fn test_example_2() { let primes = Primes::get_between(2, 100_000); assert_eq!(primes.len(), 9_592); } }