diff --git a/src/is_prime.rs b/src/is_prime.rs index a509379..4a201d3 100644 --- a/src/is_prime.rs +++ b/src/is_prime.rs @@ -1,5 +1,6 @@ pub mod prime_utils { use num::{BigUint, One}; + use once_cell::sync::Lazy; #[must_use] pub fn log_2(x: &BigUint) -> u64 { @@ -8,32 +9,31 @@ pub mod prime_utils { #[must_use] pub fn is_prime(number: &BigUint) -> bool { - if BigUint::one() == *number { + const ZERO: BigUint = BigUint::ZERO; + static TWO: Lazy = Lazy::new(|| BigUint::from(2u8)); + + if &BigUint::one() >= number { return false; } - if BigUint::from(4u8) > *number { + if &BigUint::from(4u8) > number { return true; } + if number % &*TWO == ZERO { + return false; + } // number = 2^a - 1 // a = log2(number + 1) let a = log_2(&(number + 1u8)); //if number isn't a mersenne number - if BigUint::from(2u8).pow(a as u32) - BigUint::one() != *number { - const ZERO: BigUint = BigUint::ZERO; + if TWO.pow(a as u32) - BigUint::one() != *number { let mut i = BigUint::one(); - let one = BigUint::one(); - let two = &one + &one; - if number % &two == ZERO { - return false; - } - - let sqrtnum = number.sqrt() + one; //fake ceil function + let sqrtnum = number.sqrt() + BigUint::one(); //fake ceil function loop { - i += &two; //we begin checking 3 and then continue with every second number as every even number is divisible by 2 and we already checked that + i += &*TWO; //we begin checking 3 and then continue with every second number as every even number is divisible by 2 and we already checked that if number % &i == ZERO { return false; } @@ -44,14 +44,12 @@ pub mod prime_utils { } //check if it's a mersenne prime - // 4 12 194 let mut last = BigUint::from(4u8); - let two = BigUint::from(2u8); for _i in 2..a { - last = (last.pow(2) - &two) % number; + last = (last.pow(2) - &*TWO) % number; } - last == BigUint::from(0u8) + last == BigUint::ZERO } } diff --git a/src/main.rs b/src/main.rs index 105345c..3aa3eb2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,7 +12,7 @@ use std::{ io::Write, sync::{ atomic::{AtomicU64, AtomicUsize}, - Arc, RwLock, + Arc, Mutex, }, thread, time::SystemTime, @@ -67,7 +67,7 @@ fn worker( workloads: usize, i: usize, progress: &AtomicU64, - arcclone: &Arc>>, + arcclone: &Arc>>, threads_done: &AtomicUsize, ) { #[cfg(target_os = "windows")] @@ -90,7 +90,7 @@ fn worker( } } - arcclone.write().unwrap().append(&mut primecache); + arcclone.lock().unwrap().append(&mut primecache); threads_done.fetch_add(1, std::sync::atomic::Ordering::Relaxed); } @@ -100,11 +100,11 @@ fn main() { if args.len() == 2 { use std::str::FromStr; let prime = args.nth(1).unwrap(); + let prime = BigUint::from_str(&prime).unwrap(); - println!( - "Number is prime: {}", - is_prime::prime_utils::is_prime(&BigUint::from_str(&prime).unwrap()) - ); + let is_prime = is_prime::prime_utils::is_prime(&prime); + + println!("Number is {}a prime", if is_prime { "" } else { "not " }); return; } @@ -116,7 +116,7 @@ fn main() { let workloads = nthprime_approx / THREADS; let primecache: Vec = Vec::with_capacity(NU); - let primemutex = std::sync::RwLock::new(primecache); + let primemutex = std::sync::Mutex::new(primecache); let primearc = std::sync::Arc::new(primemutex); let progress_val = AtomicU64::new(0); @@ -136,11 +136,13 @@ fn main() { let threads_completed = threads_done.load(std::sync::atomic::Ordering::Relaxed); println!( - "Progress: {}/{} ({:.0}%) | {}", + "Progress: {:0>width$}/{} ({:>3}%) | {:0>t_width$}", n, N, - n as f64 / NF * 100.0, - threads_completed + (n as f64 / NF * 100.0).min(100.0).floor(), + threads_completed, + width = N.to_string().len(), + t_width = THREADS.to_string().len() ); std::thread::sleep(std::time::Duration::from_millis(500)); @@ -150,7 +152,7 @@ fn main() { } }); - let mut primes = primearc.write().unwrap(); + let mut primes = primearc.lock().unwrap(); primes.sort_unstable(); #[allow(clippy::cast_possible_wrap)]