rework sieve of Eratosthenes

This commit is contained in:
Dr. Matthias Ratajczak
2022-08-16 15:11:30 +02:00
parent 332da67bef
commit b68b9f1200
+42 -20
View File
@@ -1,10 +1,14 @@
extern crate num; extern crate num;
use std::collections::HashSet;
use std::fmt::Display;
use std::fs::File;
use std::hash::Hash;
use std::io::Write;
use num::FromPrimitive; use num::FromPrimitive;
use num::Num; use num::Num;
use num::ToPrimitive; use num::ToPrimitive;
use std::collections::HashSet;
use std::hash::Hash;
#[derive(Clone)] #[derive(Clone)]
pub struct Primes<T> { pub struct Primes<T> {
@@ -14,7 +18,7 @@ pub struct Primes<T> {
impl<T> Primes<T> impl<T> Primes<T>
where where
T: Num + ToPrimitive + FromPrimitive + Hash + Eq + PartialEq + Copy, T: Num + ToPrimitive + FromPrimitive + Hash + Eq + PartialEq + Copy + Display,
{ {
pub fn get_between(min_value: T, max_value: T) -> Self { pub fn get_between(min_value: T, max_value: T) -> Self {
let max_value = max_value.to_usize().unwrap(); let max_value = max_value.to_usize().unwrap();
@@ -47,19 +51,13 @@ where
let length = *max_value - *min_value; let length = *max_value - *min_value;
let mut result = vec![true; length]; let mut result = vec![true; length];
for number_to_check in 2..(max_value / 2) { let upper_limit = f64::sqrt(*max_value as f64).ceil() as usize;
let mut last_number = number_to_check; for i in 2..upper_limit {
loop { for multiple in ((i * i)..*max_value).step_by(i) {
let current_number = last_number + number_to_check; if &multiple < min_value {
if current_number < *min_value {
last_number = current_number;
continue; continue;
} }
if current_number >= *max_value { result[multiple - min_value] = false;
break;
}
result[current_number - min_value] = false;
last_number = current_number;
} }
} }
result result
@@ -72,10 +70,10 @@ where
}; };
} }
// pub fn len(&self) -> usize { pub fn len(&self) -> usize {
// debug_assert_eq!(self.vector.len(), self.set.len()); debug_assert_eq!(self.vector.len(), self.set.len());
// self.vector.len() self.vector.len()
// } }
pub fn pop(&mut self) -> Option<T> { pub fn pop(&mut self) -> Option<T> {
let result = self.vector.pop(); let result = self.vector.pop();
@@ -88,11 +86,18 @@ where
pub fn contains(&self, val: &T) -> bool { pub fn contains(&self, val: &T) -> bool {
self.set.contains(val) 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();
}
}
} }
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use crate::primes::Primes; use super::Primes;
#[test] #[test]
fn test_example_prime() { fn test_example_prime() {
@@ -113,8 +118,25 @@ mod test {
#[test] #[test]
fn test_pop() { fn test_pop() {
let mut primes = Primes::get_between(10, 20); let mut primes = Primes::get_between(10, 20);
assert!(primes.contains(&11)); assert_eq!(primes.len(), 4);
assert!(primes.contains(&19));
primes.pop(); primes.pop();
assert_eq!(primes.len(), 3);
assert!(!primes.contains(&11)); assert!(!primes.contains(&11));
} }
#[test]
fn test_example_2() {
let primes = Primes::get_between(2, 100_000);
assert_eq!(primes.len(), 9_592);
}
#[ignore]
#[test]
fn test_performance() {
let primes = Primes::get_between(2, 10_000_000);
assert_eq!(primes.len(), 664_579);
}
} }