optimize a bit
... again ...
This commit is contained in:
parent
0dd7ea4e7c
commit
63de9be895
114
Cargo.lock
generated
114
Cargo.lock
generated
@ -14,11 +14,24 @@ version = "1.0.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "getrandom"
|
||||||
|
version = "0.2.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"wasi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "isprime"
|
name = "isprime"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"num",
|
||||||
"num-bigint",
|
"num-bigint",
|
||||||
|
"rand",
|
||||||
"thread-priority",
|
"thread-priority",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -37,6 +50,20 @@ dependencies = [
|
|||||||
"cfg-if",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "43db66d1170d347f9a065114077f7dccb00c1b9478c89384490a3425279a4606"
|
||||||
|
dependencies = [
|
||||||
|
"num-bigint",
|
||||||
|
"num-complex",
|
||||||
|
"num-integer",
|
||||||
|
"num-iter",
|
||||||
|
"num-rational",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-bigint"
|
name = "num-bigint"
|
||||||
version = "0.4.3"
|
version = "0.4.3"
|
||||||
@ -48,6 +75,15 @@ dependencies = [
|
|||||||
"num-traits",
|
"num-traits",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-complex"
|
||||||
|
version = "0.4.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "02e0d21255c828d6f128a1e41534206671e8c3ea0c62f32291e808dc82cff17d"
|
||||||
|
dependencies = [
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-integer"
|
name = "num-integer"
|
||||||
version = "0.1.45"
|
version = "0.1.45"
|
||||||
@ -58,6 +94,29 @@ dependencies = [
|
|||||||
"num-traits",
|
"num-traits",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-iter"
|
||||||
|
version = "0.1.43"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"num-integer",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-rational"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"num-bigint",
|
||||||
|
"num-integer",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-traits"
|
name = "num-traits"
|
||||||
version = "0.2.15"
|
version = "0.2.15"
|
||||||
@ -68,17 +127,66 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thread-priority"
|
name = "ppv-lite86"
|
||||||
version = "0.10.0"
|
version = "0.2.17"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "978519ae4c6891352f964b88da4ab5a3a9b74a40247cda5baee145dae6cd3b71"
|
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand"
|
||||||
|
version = "0.8.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"rand_chacha",
|
||||||
|
"rand_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_chacha"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
||||||
|
dependencies = [
|
||||||
|
"ppv-lite86",
|
||||||
|
"rand_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_core"
|
||||||
|
version = "0.6.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustversion"
|
||||||
|
version = "1.0.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5583e89e108996506031660fe09baa5011b9dd0341b89029313006d1fb508d70"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thread-priority"
|
||||||
|
version = "0.12.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2ee4429f2c3bbeafa7136ea54d75a5f38b02e4f006c0b310f07e35c3b49eb3e7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"libc",
|
"libc",
|
||||||
"log",
|
"log",
|
||||||
|
"rustversion",
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasi"
|
||||||
|
version = "0.11.0+wasi-snapshot-preview1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi"
|
name = "winapi"
|
||||||
version = "0.3.9"
|
version = "0.3.9"
|
||||||
|
@ -6,8 +6,10 @@ edition = "2021"
|
|||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
num-bigint = { default-features = false, version = "0" }
|
num = "0.4.0"
|
||||||
thread-priority = "0"
|
thread-priority = "0.12.0"
|
||||||
|
rand = "0.8.5"
|
||||||
|
num-bigint= { default-features = false, version = "0.4.3" }
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
lto = true # Enable link-time optimization
|
lto = true # Enable link-time optimization
|
||||||
|
2
optimize_dependencies.bat
Normal file
2
optimize_dependencies.bat
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
REM This uses cargo-unused-features
|
||||||
|
unused-features analyze && unused-features prune --input report.json
|
@ -1,13 +1,15 @@
|
|||||||
|
|
||||||
|
|
||||||
pub mod prime_utils {
|
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
|
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 {
|
if BigUint::from(1u8) == *number {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -23,11 +25,11 @@ pub mod prime_utils {
|
|||||||
|
|
||||||
// number = 2^a - 1
|
// number = 2^a - 1
|
||||||
// a = log2(number + 1)
|
// a = log2(number + 1)
|
||||||
let a = log_2(number+1u8);
|
let a = log_2(&(number+1u8));
|
||||||
if BigUint::from(2u8).pow(a as u32)-BigUint::from(1u8) != *number {
|
if BigUint::from(2u8).pow(a as u32)-BigUint::one() != *number {
|
||||||
let mut i = BigUint::from(1u8);
|
let mut i = BigUint::one();
|
||||||
let one = BigUint::from(1u8);
|
let one = BigUint::one();
|
||||||
let zero = BigUint::from(0u8);
|
let zero = BigUint::zero();
|
||||||
|
|
||||||
let sqrtnum = number.sqrt()+&one; //fake ceil function
|
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 {
|
loop {
|
||||||
i += &one;
|
i += &one;
|
||||||
if number%&i == zero {
|
if number%&i == zero {
|
||||||
@ -50,6 +56,8 @@ pub mod prime_utils {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4 12 194
|
// 4 12 194
|
||||||
|
87
src/main.rs
87
src/main.rs
@ -1,9 +1,12 @@
|
|||||||
#![warn(clippy::pedantic)]
|
#![warn(clippy::perf)]
|
||||||
|
#![warn(clippy::all)]
|
||||||
|
|
||||||
|
|
||||||
pub mod is_prime;
|
pub mod is_prime;
|
||||||
|
pub mod primality_test;
|
||||||
|
|
||||||
use std::{time::SystemTime,thread, io::Write};
|
use std::{time::SystemTime,thread, io::Write};
|
||||||
use num_bigint::BigUint;
|
use num::{BigUint, One};
|
||||||
use crate::is_prime::prime_utils;
|
use crate::is_prime::prime_utils;
|
||||||
use thread_priority::{set_current_thread_priority,ThreadPriority};
|
use thread_priority::{set_current_thread_priority,ThreadPriority};
|
||||||
|
|
||||||
@ -20,12 +23,38 @@ fn p(n: f64) -> f64 {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn to_usize(f:f64) -> usize {
|
||||||
fn main() {
|
let rounded_num: i64 = f.round() as i64;
|
||||||
|
if rounded_num >= 0 {
|
||||||
if set_current_thread_priority(ThreadPriority::Max).is_err() {
|
rounded_num as usize
|
||||||
eprintln!("failed to set thread priority to max");
|
} 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 mut buffer = String::new();
|
||||||
@ -43,14 +72,19 @@ fn main() {
|
|||||||
println!("\n{number} is not a prime");
|
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();
|
let sys_time = SystemTime::now();
|
||||||
|
|
||||||
const N:i64 = 100_000;
|
|
||||||
const NU:usize = N as usize;
|
|
||||||
let nf:f64 = 100_000f64;
|
let nf:f64 = 100_000f64;
|
||||||
let nthprime_approx:usize = p(nf*1.02).ceil() as usize;
|
let nthprime_approx:usize = to_usize(p(nf*1.02));
|
||||||
const THREADS: usize = 12;
|
|
||||||
let workloads = nthprime_approx/THREADS;
|
let workloads = nthprime_approx/THREADS;
|
||||||
|
|
||||||
let primecache: Vec<BigUint> = vec![];
|
let primecache: Vec<BigUint> = vec![];
|
||||||
@ -61,20 +95,15 @@ fn main() {
|
|||||||
let arcclone = primearc.clone();
|
let arcclone = primearc.clone();
|
||||||
let handle = thread::spawn(move || {
|
let handle = thread::spawn(move || {
|
||||||
|
|
||||||
if set_current_thread_priority(ThreadPriority::Max).is_err() {
|
try_set_thread_priority();
|
||||||
eprintln!("failed to set thread priority to max");
|
|
||||||
}
|
|
||||||
|
|
||||||
const SPLITTER: u128 = 10000u128;
|
|
||||||
let one_thousand = &BigUint::from(SPLITTER*10);
|
let one_thousand = &BigUint::from(SPLITTER*10);
|
||||||
let one_hundred = &BigUint::from(SPLITTER);
|
let one_hundred = &BigUint::from(SPLITTER);
|
||||||
let ten = &BigUint::from(10u8);
|
let ten = &BigUint::from(10u8);
|
||||||
|
|
||||||
|
|
||||||
let work_uint = BigUint::from(workloads);
|
let work_uint = BigUint::from(workloads);
|
||||||
let mut number = BigUint::from(i)*&work_uint;
|
let mut number = BigUint::from(i)*&work_uint;
|
||||||
let inc = BigUint::from(1u8);
|
let inc = BigUint::one();
|
||||||
// let zero = BigUint::from(0u8);
|
|
||||||
|
|
||||||
let max = BigUint::from(i+1)*work_uint;
|
let max = BigUint::from(i+1)*work_uint;
|
||||||
let mut primecache = vec![];
|
let mut primecache = vec![];
|
||||||
@ -83,13 +112,12 @@ fn main() {
|
|||||||
|
|
||||||
if prime_utils::is_prime(&number,&primecache) {
|
if prime_utils::is_prime(&number,&primecache) {
|
||||||
primecache.push(number.clone());
|
primecache.push(number.clone());
|
||||||
//println!("Found a prime {} {}",number, primecache.len());
|
|
||||||
}
|
}
|
||||||
if (&number * one_thousand)/&max/ten == &number/&max*one_hundred {
|
if (&number * one_thousand)/&max/ten == &number/&max*one_hundred {
|
||||||
let tried_getting = SystemTime::now();
|
let tried_getting = SystemTime::now();
|
||||||
let mut new_primecache = arcclone.lock().unwrap();
|
let mut new_primecache = arcclone.lock().unwrap();
|
||||||
if SystemTime::now().duration_since(tried_getting).unwrap().as_millis() > 50 {
|
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.append(&mut primecache);
|
||||||
new_primecache.sort();
|
new_primecache.sort();
|
||||||
@ -133,9 +161,9 @@ fn main() {
|
|||||||
|
|
||||||
let added = NU-primes.len();
|
let added = NU-primes.len();
|
||||||
if primes.len() < NU {
|
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 mut number = BigUint::from(THREADS)*BigUint::from(workloads);
|
||||||
let inc = BigUint::from(1u8);
|
let inc = BigUint::one();
|
||||||
loop {
|
loop {
|
||||||
number += &inc;
|
number += &inc;
|
||||||
if prime_utils::is_prime(&number, &primes) {
|
if prime_utils::is_prime(&number, &primes) {
|
||||||
@ -153,22 +181,11 @@ fn main() {
|
|||||||
|
|
||||||
assert_eq!(primes.len(),NU);
|
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!("time: {difference:?}");
|
||||||
|
|
||||||
println!("writing primes...");
|
println!("writing primes...");
|
||||||
|
|
||||||
let mut file = std::fs::File::create("primes.json").unwrap();
|
write_primes(&primes);
|
||||||
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();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
60
src/primality_test.rs
Normal file
60
src/primality_test.rs
Normal 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
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user