From 5ee76502fad62d40ca07050cd6106303b83f1d51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Ortega=20Froysa?= Date: Wed, 10 Dec 2025 11:46:22 +0100 Subject: [PATCH] Switch to (segmented) sieve of Eratosthenes. --- src/main.rs | 50 ++++++++++++++++++++++++++------------ src/worker.rs | 67 +++++++++++++++------------------------------------ 2 files changed, 54 insertions(+), 63 deletions(-) diff --git a/src/main.rs b/src/main.rs index 6c4a903..b1aef50 100644 --- a/src/main.rs +++ b/src/main.rs @@ -16,9 +16,9 @@ * along with this program. If not, see . */ -//use std::fs::File; -//use std::io::{BufRead, BufReader}; -//use std::path::PathBuf; +use std::fs::File; +use std::io::{BufRead, BufReader}; +use std::path::PathBuf; use std::process; use structopt::StructOpt; @@ -29,8 +29,8 @@ mod worker; struct Opt { #[structopt(short, long, help = "Print all found primes")] verbose:bool, - //#[structopt(short, long, name = "FILE", help = "Import prime numbers from FILE")] - //import:Option, + #[structopt(short, long, name = "FILE", help = "Import prime numbers from FILE")] + import:Option, #[structopt(short, long, help = "Test if num is prime instead of generation")] test:bool, #[structopt(help = "Max of the prime to generate or number to test for primality")] @@ -39,23 +39,47 @@ struct Opt { //jobs:u64, } +const SEGMENT_SIZE:usize = 0x100000000; + fn main() { let opts = Opt::from_args(); + let mut prime_list = Vec::new(); - /*if opts.import.is_some() { + if opts.import.is_some() { let in_file = File::open(opts.import.unwrap()).unwrap(); let reader = BufReader::new(in_file); for p in reader.lines().into_iter() { prime_list.push(p.unwrap().parse().unwrap()); } - }*/ + } if opts.num < 2 { eprintln!("Invalid value for num: {}", opts.num); process::exit(1); } - let prime_list = worker::work_segment(0, opts.num); + let mut start:usize = if prime_list.is_empty() { + 2 + } else { + *prime_list.last().unwrap() as usize + }; + while start < opts.num { + let end = if start + SEGMENT_SIZE < opts.num { + start + SEGMENT_SIZE + } else { + opts.num + 1 + }; + let mut new_primes = worker::work_segment(&prime_list, start, end); + + if opts.verbose { + for p in &new_primes { + println!("{}", *p); + } + } + prime_list.append(&mut new_primes); + + start += SEGMENT_SIZE; + } if opts.test { if *prime_list.last().unwrap() == (opts.num as u64) { @@ -69,13 +93,7 @@ fn main() { } process::exit(1); } - } else { - if !opts.verbose { - println!("{}", prime_list.last().unwrap()); - } else { - for p in prime_list { - println!("{}", p); - } - } + } else if !opts.verbose { + println!("{}", prime_list.last().unwrap()); } } diff --git a/src/worker.rs b/src/worker.rs index 1cd0420..033925c 100644 --- a/src/worker.rs +++ b/src/worker.rs @@ -20,62 +20,35 @@ * @brief Work on a segment. * * @param start:usize Beginning of the segment (inclusive). - * @param end:usize End of the segment (inclusive). + * @param end:usize End of the segment (exclusive). * * @return List of primes found in segment. */ -pub fn work_segment(start:usize, end:usize) -> Vec { - let mut found_primes = Vec::::new(); - let mut arr = vec![false; end - start + 1]; +pub fn work_segment(known_primes:&Vec, start:usize, end:usize) -> Vec { + let mut sieve = vec![true; end - start]; + let mut found_primes = Vec::new(); - if start < 2 && end > 2 { - arr[2] = true; - } - if start < 3 && end > 3 { - arr[3] = true; - } - - let sqrt_of_num = f64::sqrt(end as f64) as usize; - for x in 1..=sqrt_of_num { - let xx4 = 4 * x * x; - let xx3 = 3 * x * x; - for y in 1..=sqrt_of_num { - let yy = y * y; - - let n1 = xx4 + yy; - if n1 <= end && (n1 % 12 == 1 || n1 % 12 == 5) { - arr[n1] = !arr[n1]; - } - - let n2 = xx3 + yy; - if n2 <= end && n2 % 12 == 7 { - arr[n2] = !arr[n2]; - } - - if x > y { - let n3 = xx3 - yy; - if n3 <= end && n3 % 12 == 11 { - arr[n3] = !arr[n3]; - } + for p in known_primes { + let prime = *p as usize; + let mut mult = prime * prime; + while mult < end { + if mult > start { + sieve[mult - start] = false; } + mult += prime; } } - for i in 5..=sqrt_of_num { - if !arr[i] { - continue; - } + for i in 0..(end - start) { + if sieve[i] { + let prime = i + start; + found_primes.push(prime as u64); - let mut j = i * i; - while j <= end { - arr[j] = false; - j += i * i; - } - } - - for i in 2..=end { - if arr[i] { - found_primes.push(i as u64); + let mut mult = prime * prime; + while mult < end { + sieve[mult - start] = false; + mult += prime; + } } }