From 90069e9ab48baed5b76de3b7d970d1a761a2b727 Mon Sep 17 00:00:00 2001 From: code002lover Date: Tue, 23 Jul 2024 01:36:30 +0200 Subject: [PATCH] refactor code --- Cargo.toml | 6 ++++- src/is_prime.rs | 69 ++++++++++++++++++++++++++++++++----------------- src/main.rs | 36 ++++++++++++++++---------- 3 files changed, 72 insertions(+), 39 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 88a669e..ce35c3b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,6 +2,7 @@ name = "isprime" version = "0.1.0" edition = "2021" +default-run = "isprime" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -42,4 +43,7 @@ str_to_string = "deny" cast_possible_truncation = "allow" cast_precision_loss = "allow" cast_sign_loss = "allow" -missing_errors_doc = "allow" \ No newline at end of file +missing_errors_doc = "allow" + +[[bin]] +name = "isprime" \ No newline at end of file diff --git a/src/is_prime.rs b/src/is_prime.rs index 4a201d3..8c56cfd 100644 --- a/src/is_prime.rs +++ b/src/is_prime.rs @@ -7,49 +7,70 @@ pub mod prime_utils { x.bits() - 1 } + static FOUR: Lazy = Lazy::new(|| BigUint::from(4u8)); + static TWO: Lazy = Lazy::new(|| BigUint::from(2u8)); + static ONE: Lazy = Lazy::new(BigUint::one); + const ZERO: BigUint = BigUint::ZERO; + #[must_use] pub fn is_prime(number: &BigUint) -> bool { - const ZERO: BigUint = BigUint::ZERO; - static TWO: Lazy = Lazy::new(|| BigUint::from(2u8)); - - if &BigUint::one() >= number { + if &*ONE >= number { return false; } - if &BigUint::from(4u8) > number { + if &*FOUR > number { return true; } - if number % &*TWO == ZERO { + if !number.bit(0) { return false; } - // number = 2^a - 1 + // mersenne numbers = 2^a - 1 // a = log2(number + 1) let a = log_2(&(number + 1u8)); - //if number isn't a mersenne number - if TWO.pow(a as u32) - BigUint::one() != *number { - let mut i = BigUint::one(); + let is_mersenne = { + let num_p2 = { + let mut num = BigUint::default(); + num.set_bit(a, true); + num + }; + assert!(num_p2 > BigUint::one()); - let sqrtnum = number.sqrt() + BigUint::one(); //fake ceil function + let num_p2 = num_p2 - &*ONE; - 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 - if number % &i == ZERO { - return false; - } - if i >= sqrtnum { - return true; - } - } + &num_p2 == number + }; + + if is_mersenne { + return mersenne_check(number, a); } - //check if it's a mersenne prime - let mut last = BigUint::from(4u8); + let sqrtnum = number.sqrt() + &*ONE; //fake ceil function - for _i in 2..a { + inner_prime(number, &sqrtnum) + } + + fn mersenne_check(number: &BigUint, a: u64) -> bool { + let mut last = FOUR.clone(); + + for _ in 2..a { last = (last.pow(2) - &*TWO) % number; } - last == BigUint::ZERO + last == ZERO + } + + fn inner_prime(number: &BigUint, sqrtnum: &BigUint) -> bool { + let mut i = BigUint::one(); + + 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 + if &i >= sqrtnum { + return true; + } + if number % &i == ZERO { + return false; + } + } } } diff --git a/src/main.rs b/src/main.rs index 52357a2..428d354 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,7 +13,7 @@ use std::{ Arc, Mutex, }, thread, - time::SystemTime, + time::{Instant, SystemTime}, }; fn p(n: f64) -> f64 { @@ -127,24 +127,32 @@ fn main() { scope.spawn(move || worker(workloads, i, progress, &arcclone, threads_done)); } - loop { - let n = progress.load(std::sync::atomic::Ordering::Relaxed); - let threads_completed = threads_done.load(std::sync::atomic::Ordering::Relaxed); + let mut last_progress = Instant::now(); - println!( - "Progress: {:0>width$}/{} ({:>3}%) | {:0>t_width$}", - n, - N, - (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)); + loop { + let threads_completed = threads_done.load(std::sync::atomic::Ordering::Relaxed); if threads_completed == THREADS { break; } + + if last_progress.elapsed().as_millis() >= 500 { + last_progress = Instant::now(); + + let n = progress.load(std::sync::atomic::Ordering::Relaxed); + + println!( + "Progress: {:0>width$}/{} ({:>3}%) | {:0>t_width$}", + n, + N, + (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(100)); } });