clean up code a bit
also reformat
This commit is contained in:
+20
-27
@@ -1,73 +1,66 @@
|
||||
|
||||
|
||||
pub mod prime_utils {
|
||||
use num::{BigUint, One, Zero};
|
||||
|
||||
use crate::primality_test::primality_tests::is_probably_prime;
|
||||
|
||||
#[must_use] pub fn log_2(x: &BigUint) -> u64 {
|
||||
#[must_use]
|
||||
pub fn log_2(x: &BigUint) -> u64 {
|
||||
x.bits() - 1
|
||||
}
|
||||
|
||||
#[must_use] pub fn is_prime(number: &BigUint, g_primes: &Vec<BigUint>) -> bool {
|
||||
|
||||
#[must_use]
|
||||
pub fn is_prime(number: &BigUint, g_primes: &Vec<BigUint>) -> bool {
|
||||
if BigUint::from(1u8) == *number {
|
||||
return false;
|
||||
}
|
||||
if BigUint::from(4u8) > *number {
|
||||
if BigUint::from(4u8) > *number {
|
||||
return true;
|
||||
}
|
||||
|
||||
if number.sqrt().pow(2) == *number {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
let two = BigUint::from(2u8);
|
||||
|
||||
|
||||
// number = 2^a - 1
|
||||
// a = log2(number + 1)
|
||||
let a = log_2(&(number+1u8));
|
||||
if BigUint::from(2u8).pow(a as u32)-BigUint::one() != *number {
|
||||
let a = log_2(&(number + 1u8));
|
||||
if BigUint::from(2u8).pow(a as u32) - BigUint::one() != *number {
|
||||
let mut i = BigUint::one();
|
||||
let one = BigUint::one();
|
||||
let zero = BigUint::zero();
|
||||
|
||||
let sqrtnum = number.sqrt()+&one; //fake ceil function
|
||||
|
||||
if let Some(max_value) = g_primes.iter().max() {
|
||||
if max_value > &sqrtnum {
|
||||
for prime in g_primes {
|
||||
if prime<&sqrtnum && number%prime == zero {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
let sqrtnum = number.sqrt() + &one; //fake ceil function
|
||||
|
||||
for prime in g_primes {
|
||||
if prime < &sqrtnum && number % prime == zero {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if !is_probably_prime(number,5) {
|
||||
if !is_probably_prime(number, 5) {
|
||||
return false;
|
||||
}
|
||||
|
||||
loop {
|
||||
i += &one;
|
||||
if number%&i == zero {
|
||||
if number % &i == zero {
|
||||
return false;
|
||||
}
|
||||
if i == sqrtnum {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
// 4 12 194
|
||||
let mut last = BigUint::from(4u8);
|
||||
|
||||
|
||||
for _i in 2..a {
|
||||
last = (last.pow(2)-&two)%number;
|
||||
last = (last.pow(2) - &two) % number;
|
||||
}
|
||||
|
||||
last == BigUint::from(0u8)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+114
-96
@@ -1,29 +1,33 @@
|
||||
#![warn(clippy::perf)]
|
||||
#![warn(clippy::all)]
|
||||
|
||||
|
||||
pub mod is_prime;
|
||||
pub mod primality_test;
|
||||
|
||||
use std::{time::SystemTime,thread, io::Write};
|
||||
use num::{BigUint, One};
|
||||
use crate::is_prime::prime_utils;
|
||||
use thread_priority::{set_current_thread_priority,ThreadPriority};
|
||||
use num::{BigUint, One};
|
||||
use once_cell::sync::Lazy;
|
||||
use std::{
|
||||
io::Write,
|
||||
sync::atomic::{AtomicI64, AtomicUsize},
|
||||
thread,
|
||||
time::SystemTime,
|
||||
};
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
use thread_priority::{set_current_thread_priority, ThreadPriority};
|
||||
|
||||
fn p(n: f64) -> f64 {
|
||||
let ln_n = n.ln();
|
||||
let ln_ln_n = ln_n.ln();
|
||||
let ln_ln_ln_n = ln_ln_n.ln();
|
||||
|
||||
n * (
|
||||
ln_n + ln_ln_n - 1.0
|
||||
+ (ln_ln_ln_n - 2.0) / ln_n
|
||||
n * (ln_n + ln_ln_n - 1.0 + (ln_ln_ln_n - 2.0) / ln_n
|
||||
- ((ln_ln_n).powi(2) - 6.0 * ln_ln_n + 11.0) / (2.0 * 2.0f64.log2() * ln_n)
|
||||
+ ((ln_ln_n / ln_n).powi(3)) * (1.0 / ln_n)
|
||||
)
|
||||
+ ((ln_ln_n / ln_n).powi(3)) * (1.0 / ln_n))
|
||||
}
|
||||
|
||||
fn to_usize(f:f64) -> usize {
|
||||
fn to_usize(f: f64) -> usize {
|
||||
let rounded_num: i64 = f.round() as i64;
|
||||
if rounded_num >= 0 {
|
||||
rounded_num as usize
|
||||
@@ -32,13 +36,15 @@ fn to_usize(f:f64) -> usize {
|
||||
}
|
||||
}
|
||||
|
||||
fn to_f64(u:usize) -> f64 {
|
||||
fn to_f64(u: usize) -> f64 {
|
||||
f64::from_bits(u as u64)
|
||||
}
|
||||
|
||||
fn try_set_thread_priority() {
|
||||
if set_current_thread_priority(ThreadPriority::Max).is_err() {
|
||||
#[cfg(target_os = "windows")]
|
||||
if let Err(e) = set_current_thread_priority(ThreadPriority::Max) {
|
||||
eprintln!("[WARN] failed to set thread priority to max");
|
||||
eprintln!("{e}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,103 +61,114 @@ fn write_primes(primes: &[BigUint]) {
|
||||
file.write_all(b"]").unwrap();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
let mut buffer = String::new();
|
||||
let stdin = io::stdin();
|
||||
print!("please enter the number to check: ");
|
||||
io::stdout().flush().expect("could not flush");
|
||||
stdin.read_line(&mut buffer).expect("could not read from stdin");
|
||||
buffer = buffer.trim().to_owned();
|
||||
|
||||
let number = BigUint::parse_bytes(&buffer.as_bytes(), 10).expect("expected positive number");
|
||||
|
||||
if is_prime(number.clone()) {
|
||||
println!("\n{number} is a prime");
|
||||
} else {
|
||||
println!("\n{number} is not a prime");
|
||||
}
|
||||
*/
|
||||
fn main() {
|
||||
const N:i64 = 100_000;
|
||||
const NU:usize = N as usize;
|
||||
const N: i64 = 1_000_000;
|
||||
const NF: f64 = N as f64;
|
||||
const NU: usize = N as usize;
|
||||
const THREADS: usize = 12;
|
||||
const SPLITTER: u128 = 10000u128;
|
||||
const SPLITTER: u64 = N as u64 / 10;
|
||||
|
||||
try_set_thread_priority();
|
||||
|
||||
let sys_time = SystemTime::now();
|
||||
|
||||
let nf:f64 = 100_000f64;
|
||||
let nthprime_approx:usize = to_usize(p(nf*1.02));
|
||||
|
||||
let workloads = nthprime_approx/THREADS;
|
||||
let nthprime_approx: usize = to_usize(p(NF * 1.02));
|
||||
|
||||
let primecache: Vec<BigUint> = vec![];
|
||||
let workloads = nthprime_approx / THREADS;
|
||||
|
||||
let primecache: Vec<BigUint> = Vec::with_capacity(NU);
|
||||
let primemutex = std::sync::Mutex::new(primecache);
|
||||
let primearc = std::sync::Arc::new(primemutex);
|
||||
let mut joins = vec![];
|
||||
for i in 0..THREADS {
|
||||
let arcclone = primearc.clone();
|
||||
let handle = thread::spawn(move || {
|
||||
|
||||
try_set_thread_priority();
|
||||
let progress_val = AtomicI64::new(0);
|
||||
let progress = &progress_val;
|
||||
|
||||
let one_thousand = &BigUint::from(SPLITTER*10);
|
||||
let one_hundred = &BigUint::from(SPLITTER);
|
||||
let ten = &BigUint::from(10u8);
|
||||
let threads_done_val = AtomicUsize::new(0);
|
||||
let threads_done = &threads_done_val;
|
||||
|
||||
let work_uint = BigUint::from(workloads);
|
||||
let mut number = BigUint::from(i)*&work_uint;
|
||||
let inc = BigUint::one();
|
||||
|
||||
let max = BigUint::from(i+1)*work_uint;
|
||||
let mut primecache = vec![];
|
||||
loop {
|
||||
number += &inc;
|
||||
|
||||
if prime_utils::is_prime(&number,&primecache) {
|
||||
primecache.push(number.clone());
|
||||
}
|
||||
if (&number * one_thousand)/&max/ten == &number/&max*one_hundred {
|
||||
let tried_getting = SystemTime::now();
|
||||
let mut new_primecache = arcclone.lock().unwrap();
|
||||
if SystemTime::now().duration_since(tried_getting).unwrap().as_millis() > 50 {
|
||||
eprintln!("[WARN] Waited 0.05+ seconds for lock!");
|
||||
thread::scope(|scope| {
|
||||
for i in 0..THREADS {
|
||||
let arcclone = primearc.clone();
|
||||
scope.spawn(move || {
|
||||
try_set_thread_priority();
|
||||
|
||||
let one_thousand = &BigUint::from(SPLITTER * 10);
|
||||
let one_hundred = &BigUint::from(SPLITTER);
|
||||
let ten = &BigUint::from(10u8);
|
||||
|
||||
let work_uint = BigUint::from(workloads);
|
||||
let mut number = BigUint::from(i) * &work_uint;
|
||||
static INC: once_cell::sync::Lazy<BigUint> = Lazy::new(BigUint::one);
|
||||
|
||||
let max = BigUint::from(i + 1) * work_uint;
|
||||
let mut primecache = Vec::with_capacity(NU);
|
||||
let mut primecache_outside_len = 0;
|
||||
loop {
|
||||
number += &*INC;
|
||||
|
||||
if prime_utils::is_prime(&number, &primecache) {
|
||||
primecache.push(number.clone());
|
||||
progress.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
|
||||
}
|
||||
new_primecache.append(&mut primecache);
|
||||
new_primecache.sort();
|
||||
new_primecache.dedup();
|
||||
|
||||
primecache = new_primecache.clone();
|
||||
|
||||
}
|
||||
if number == max {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (&number * one_thousand) / &max / ten == &number / &max * one_hundred {
|
||||
let tried_getting = SystemTime::now();
|
||||
let mut new_primecache = arcclone.lock().unwrap();
|
||||
if SystemTime::now()
|
||||
.duration_since(tried_getting)
|
||||
.unwrap()
|
||||
.as_millis()
|
||||
> 50
|
||||
{
|
||||
eprintln!("[WARN] Waited 0.05+ seconds for lock!");
|
||||
}
|
||||
|
||||
let mut new_primecache = arcclone.lock().unwrap();
|
||||
new_primecache.append(&mut primecache);
|
||||
new_primecache.sort();
|
||||
new_primecache.dedup();
|
||||
});
|
||||
joins.push(handle);
|
||||
}
|
||||
new_primecache.extend_from_slice(&primecache[primecache_outside_len..]);
|
||||
new_primecache.sort_unstable();
|
||||
|
||||
for handle in joins {
|
||||
handle.join().unwrap();
|
||||
}
|
||||
primecache.clone_from(&new_primecache);
|
||||
primecache_outside_len = new_primecache.len();
|
||||
}
|
||||
if number == max {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
let mut new_primecache = arcclone.lock().unwrap();
|
||||
new_primecache.extend_from_slice(&primecache[primecache_outside_len..]);
|
||||
new_primecache.sort_unstable();
|
||||
|
||||
threads_done.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
|
||||
});
|
||||
}
|
||||
|
||||
loop {
|
||||
let n = progress.load(std::sync::atomic::Ordering::Relaxed);
|
||||
let threads_completed = threads_done.load(std::sync::atomic::Ordering::Relaxed);
|
||||
|
||||
println!(
|
||||
"Progress: {}/{} ({:.0}%) | {}",
|
||||
n,
|
||||
N,
|
||||
n as f64 / NF * 100.0,
|
||||
threads_completed
|
||||
);
|
||||
std::thread::sleep(std::time::Duration::from_millis(500));
|
||||
|
||||
if threads_completed == THREADS {
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let mut primes = primearc.lock().unwrap().to_vec();
|
||||
|
||||
let removed:i32 = if primes.len() > NU {
|
||||
let removed: i32 = if primes.len() > NU {
|
||||
let mut rem = 0;
|
||||
loop {
|
||||
if primes.len() <= NU {
|
||||
break;
|
||||
}
|
||||
rem+=1;
|
||||
rem += 1;
|
||||
primes.pop();
|
||||
}
|
||||
rem
|
||||
@@ -159,13 +176,13 @@ fn main() {
|
||||
0
|
||||
};
|
||||
|
||||
let added = NU-primes.len();
|
||||
let added = NU - primes.len();
|
||||
if primes.len() < NU {
|
||||
println!("[INFO] less primes than expected");
|
||||
let mut number = BigUint::from(THREADS)*BigUint::from(workloads);
|
||||
let inc = BigUint::one();
|
||||
let mut number = BigUint::from(THREADS) * BigUint::from(workloads);
|
||||
static INC: once_cell::sync::Lazy<BigUint> = Lazy::new(BigUint::one);
|
||||
loop {
|
||||
number += &inc;
|
||||
number += &*INC;
|
||||
if prime_utils::is_prime(&number, &primes) {
|
||||
primes.push(number.clone());
|
||||
}
|
||||
@@ -176,17 +193,18 @@ fn main() {
|
||||
}
|
||||
|
||||
let new_sys_time = SystemTime::now();
|
||||
let difference = new_sys_time.duration_since(sys_time)
|
||||
.expect("Clock may have gone backwards");
|
||||
let difference = new_sys_time
|
||||
.duration_since(sys_time)
|
||||
.expect("Clock may have gone backwards");
|
||||
|
||||
assert_eq!(primes.len(),NU);
|
||||
assert_eq!(primes.len(), NU);
|
||||
|
||||
println!("primes added: {added} | % added: {}% | removed: {removed}",to_f64(added)/to_f64(primes.len())*100.0);
|
||||
println!(
|
||||
"primes added: {added} | % added: {}% | removed: {removed}",
|
||||
to_f64(added) / to_f64(primes.len()) * 100.0
|
||||
);
|
||||
println!("time: {difference:?}");
|
||||
println!("writing primes...");
|
||||
|
||||
write_primes(&primes);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ pub mod primality_tests {
|
||||
BigUint::from_bytes_be(&buf)
|
||||
}
|
||||
|
||||
|
||||
pub fn is_probably_prime(number: &BigUint, iterations: u32) -> bool {
|
||||
if number <= &BigUint::one() || number == &BigUint::from(4u32) {
|
||||
return false;
|
||||
@@ -23,7 +22,7 @@ pub mod primality_tests {
|
||||
d /= 2u32;
|
||||
}
|
||||
for _ in 0..iterations {
|
||||
let a = generate_random_biguint((number.bits()-1) as usize);
|
||||
let a = generate_random_biguint((number.bits() - 1) as usize);
|
||||
let mut x = mod_exp(a.clone(), &d, number);
|
||||
if x == one || x == number - &one {
|
||||
continue;
|
||||
@@ -42,7 +41,7 @@ pub mod primality_tests {
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
|
||||
fn mod_exp(mut base: BigUint, ex: &BigUint, modulus: &BigUint) -> BigUint {
|
||||
let mut exp = ex.clone();
|
||||
let mut result = BigUint::one();
|
||||
@@ -56,5 +55,4 @@ pub mod primality_tests {
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user