optimize a bit

... again ...
This commit is contained in:
Mystikfluu
2023-03-03 19:23:15 +01:00
parent 0dd7ea4e7c
commit 63de9be895
6 changed files with 246 additions and 49 deletions
+16 -8
View File
@@ -1,13 +1,15 @@
pub mod prime_utils {
use num_bigint::BigUint;
use num::{BigUint, One, Zero};
pub fn log_2(x: BigUint) -> u64 {
use crate::primality_test::primality_tests::is_probably_prime;
#[must_use] pub fn log_2(x: &BigUint) -> u64 {
x.bits() - 1
}
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;
}
@@ -23,11 +25,11 @@ pub mod prime_utils {
// number = 2^a - 1
// a = log2(number + 1)
let a = log_2(number+1u8);
if BigUint::from(2u8).pow(a as u32)-BigUint::from(1u8) != *number {
let mut i = BigUint::from(1u8);
let one = BigUint::from(1u8);
let zero = BigUint::from(0u8);
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
@@ -41,6 +43,10 @@ pub mod prime_utils {
}
}
if !is_probably_prime(number,5) {
return false;
}
loop {
i += &one;
if number%&i == zero {
@@ -50,6 +56,8 @@ pub mod prime_utils {
return true;
}
}
}
// 4 12 194
+53 -36
View File
@@ -1,9 +1,12 @@
#![warn(clippy::pedantic)]
#![warn(clippy::perf)]
#![warn(clippy::all)]
pub mod is_prime;
pub mod primality_test;
use std::{time::SystemTime,thread, io::Write};
use num_bigint::BigUint;
use num::{BigUint, One};
use crate::is_prime::prime_utils;
use thread_priority::{set_current_thread_priority,ThreadPriority};
@@ -20,14 +23,40 @@ fn p(n: f64) -> f64 {
)
}
fn main() {
if set_current_thread_priority(ThreadPriority::Max).is_err() {
eprintln!("failed to set thread priority to max");
fn to_usize(f:f64) -> usize {
let rounded_num: i64 = f.round() as i64;
if rounded_num >= 0 {
rounded_num as usize
} else {
0
}
}
/*
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() {
eprintln!("[WARN] failed to set thread priority to max");
}
}
fn write_primes(primes: &[BigUint]) {
let mut file = std::fs::File::create("primes.json").unwrap();
file.write_all(b"[").unwrap();
let mut it = primes.iter().peekable();
while let Some(prime) = it.next() {
file.write_all(prime.to_string().as_bytes()).unwrap();
if it.peek().is_some() {
file.write_all(b",").unwrap();
}
}
file.write_all(b"]").unwrap();
}
/*
let mut buffer = String::new();
let stdin = io::stdin();
print!("please enter the number to check: ");
@@ -43,14 +72,19 @@ fn main() {
println!("\n{number} is not a prime");
}
*/
fn main() {
const N:i64 = 100_000;
const NU:usize = N as usize;
const THREADS: usize = 12;
const SPLITTER: u128 = 10000u128;
try_set_thread_priority();
let sys_time = SystemTime::now();
const N:i64 = 100_000;
const NU:usize = N as usize;
let nf:f64 = 100_000f64;
let nthprime_approx:usize = p(nf*1.02).ceil() as usize;
const THREADS: usize = 12;
let nthprime_approx:usize = to_usize(p(nf*1.02));
let workloads = nthprime_approx/THREADS;
let primecache: Vec<BigUint> = vec![];
@@ -61,20 +95,15 @@ fn main() {
let arcclone = primearc.clone();
let handle = thread::spawn(move || {
if set_current_thread_priority(ThreadPriority::Max).is_err() {
eprintln!("failed to set thread priority to max");
}
try_set_thread_priority();
const SPLITTER: u128 = 10000u128;
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;
let inc = BigUint::from(1u8);
// let zero = BigUint::from(0u8);
let inc = BigUint::one();
let max = BigUint::from(i+1)*work_uint;
let mut primecache = vec![];
@@ -83,13 +112,12 @@ fn main() {
if prime_utils::is_prime(&number,&primecache) {
primecache.push(number.clone());
//println!("Found a prime {} {}",number, primecache.len());
}
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!("Waited 0.05+ seconds for lock!");
eprintln!("[WARN] Waited 0.05+ seconds for lock!");
}
new_primecache.append(&mut primecache);
new_primecache.sort();
@@ -133,9 +161,9 @@ fn main() {
let added = NU-primes.len();
if primes.len() < NU {
println!("Less primes than expected!");
println!("[INFO] less primes than expected");
let mut number = BigUint::from(THREADS)*BigUint::from(workloads);
let inc = BigUint::from(1u8);
let inc = BigUint::one();
loop {
number += &inc;
if prime_utils::is_prime(&number, &primes) {
@@ -153,22 +181,11 @@ fn main() {
assert_eq!(primes.len(),NU);
println!("primes added: {} | % added: {}% | removed: {}",added,(added as f64)/primes.len() as f64*100.0,removed);
println!("primes added: {added} | % added: {}% | removed: {removed}",to_f64(added)/to_f64(primes.len())*100.0);
println!("time: {difference:?}");
println!("writing primes...");
let mut file = std::fs::File::create("primes.json").unwrap();
file.write_all(b"[").unwrap();
let mut it = primes.iter().peekable();
while let Some(prime) = it.next() {
file.write_all(prime.to_string().as_bytes()).unwrap();
if it.peek().is_some() {
file.write_all(b",").unwrap();
}
}
file.write_all(b"]").unwrap();
write_primes(&primes);
+60
View File
@@ -0,0 +1,60 @@
pub mod primality_tests {
use num::{BigUint, Integer, One, Zero};
use rand::RngCore;
fn generate_random_biguint(num_bits: usize) -> BigUint {
let mut rng = rand::thread_rng();
let bytes = num_bits / 8 + 1;
let mut buf = vec![0u8; bytes];
rng.fill_bytes(&mut buf);
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;
} else if number <= &BigUint::from(3u32) {
return true;
}
let one = BigUint::one();
let mut d = number - &one;
while d.is_even() {
d /= 2u32;
}
for _ in 0..iterations {
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;
}
let mut continue_loop = false;
for _ in 0..(number.bits() - 1) {
x = mod_exp(x.clone(), &BigUint::from(2u32), number);
if x == number - &one {
continue_loop = true;
break;
}
}
if !continue_loop {
return false;
}
}
true
}
fn mod_exp(mut base: BigUint, ex: &BigUint, modulus: &BigUint) -> BigUint {
let mut exp = ex.clone();
let mut result = BigUint::one();
base %= modulus;
while !exp.is_zero() {
if exp.is_odd() {
result = (&result * &base) % modulus;
}
base = base.pow(2) % modulus;
exp /= 2u32;
}
result
}
}