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;
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::Num;
use num::ToPrimitive;
use std::collections::HashSet;
use std::hash::Hash;
#[derive(Clone)]
pub struct Primes<T> {
@@ -14,7 +18,7 @@ pub struct Primes<T> {
impl<T> Primes<T>
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 {
let max_value = max_value.to_usize().unwrap();
@@ -47,19 +51,13 @@ where
let length = *max_value - *min_value;
let mut result = vec![true; length];
for number_to_check in 2..(max_value / 2) {
let mut last_number = number_to_check;
loop {
let current_number = last_number + number_to_check;
if current_number < *min_value {
last_number = current_number;
let upper_limit = f64::sqrt(*max_value as f64).ceil() as usize;
for i in 2..upper_limit {
for multiple in ((i * i)..*max_value).step_by(i) {
if &multiple < min_value {
continue;
}
if current_number >= *max_value {
break;
}
result[current_number - min_value] = false;
last_number = current_number;
result[multiple - min_value] = false;
}
}
result
@@ -72,10 +70,10 @@ where
};
}
// pub fn len(&self) -> usize {
// debug_assert_eq!(self.vector.len(), self.set.len());
// self.vector.len()
// }
pub fn len(&self) -> usize {
debug_assert_eq!(self.vector.len(), self.set.len());
self.vector.len()
}
pub fn pop(&mut self) -> Option<T> {
let result = self.vector.pop();
@@ -88,11 +86,18 @@ where
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();
}
}
}
#[cfg(test)]
mod test {
use crate::primes::Primes;
use super::Primes;
#[test]
fn test_example_prime() {
@@ -113,8 +118,25 @@ mod test {
#[test]
fn test_pop() {
let mut primes = Primes::get_between(10, 20);
assert!(primes.contains(&11));
assert_eq!(primes.len(), 4);
assert!(primes.contains(&19));
primes.pop();
assert_eq!(primes.len(), 3);
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);
}
}