mirror of
https://github.com/uutils/num-prime.git
synced 2026-06-10 16:12:35 -07:00
48c099b7bb
Fixed with: ` cargo clippy --fix --allow-dirty -- -W clippy::pedantic `
149 lines
4.7 KiB
Rust
149 lines
4.7 KiB
Rust
use std::fs::File;
|
|
use std::io::{Error, Write};
|
|
use std::time::Instant;
|
|
|
|
use num_prime::factor::{one_line, pollard_rho, squfof, SQUFOF_MULTIPLIERS};
|
|
use num_prime::RandPrime;
|
|
use rand::random;
|
|
|
|
/// Collect the the iteration number of each factorization algorithm with different settings
|
|
fn profile_n(n: u128) -> Vec<(String, usize)> {
|
|
let k_squfof: Vec<u16> = SQUFOF_MULTIPLIERS.iter().take(10).copied().collect();
|
|
let k_oneline: Vec<u16> = vec![1, 360, 480];
|
|
const MAXITER: usize = 1 << 20;
|
|
const POLLARD_REPEATS: usize = 2;
|
|
|
|
let mut n_stats = Vec::new();
|
|
|
|
// pollard rho
|
|
for i in 0..POLLARD_REPEATS {
|
|
n_stats.push((
|
|
format!("pollard_rho{}", i + 1),
|
|
pollard_rho(&n, random(), random(), MAXITER).1,
|
|
));
|
|
}
|
|
|
|
// squfof
|
|
for &k in &k_squfof {
|
|
let key = format!("squfof_k{k}");
|
|
if let Some(kn) = n.checked_mul(u128::from(k)) {
|
|
let n = squfof(&n, kn, MAXITER).1;
|
|
n_stats.push((key, n));
|
|
} else {
|
|
n_stats.push((key, MAXITER));
|
|
};
|
|
}
|
|
|
|
// one line
|
|
for &k in &k_oneline {
|
|
let key = format!("one_line_k{k}");
|
|
if let Some(kn) = n.checked_mul(u128::from(k)) {
|
|
let n = one_line(&n, kn, MAXITER).1;
|
|
n_stats.push((key, n));
|
|
} else {
|
|
n_stats.push((key, MAXITER));
|
|
};
|
|
}
|
|
|
|
n_stats
|
|
}
|
|
|
|
/// Collect the best case of each factorization algorithm
|
|
fn profile_n_min(n: u128) -> Vec<(String, usize)> {
|
|
let k_squfof: Vec<u16> = SQUFOF_MULTIPLIERS.to_vec();
|
|
let k_oneline: Vec<u16> = vec![1, 360, 480];
|
|
const MAXITER: usize = 1 << 24;
|
|
const POLLARD_REPEATS: usize = 4;
|
|
|
|
let mut n_stats = Vec::new();
|
|
|
|
// pollard rho
|
|
let mut pollard_best = (MAXITER, u128::MAX);
|
|
for _ in 0..POLLARD_REPEATS {
|
|
let tstart = Instant::now();
|
|
let (result, iters) = pollard_rho(&n, random(), random(), pollard_best.0);
|
|
if result.is_some() {
|
|
pollard_best = pollard_best.min((iters, tstart.elapsed().as_micros()));
|
|
}
|
|
}
|
|
n_stats.push(("pollard_rho".to_string(), pollard_best.0));
|
|
n_stats.push(("time_pollard_rho".to_string(), pollard_best.1 as usize));
|
|
|
|
// squfof
|
|
let mut squfof_best = (MAXITER, u128::MAX);
|
|
for &k in &k_squfof {
|
|
if let Some(kn) = n.checked_mul(u128::from(k)) {
|
|
let tstart = Instant::now();
|
|
let (result, iters) = squfof(&n, kn, squfof_best.0);
|
|
if result.is_some() {
|
|
squfof_best = squfof_best.min((iters, tstart.elapsed().as_micros()));
|
|
}
|
|
}
|
|
}
|
|
n_stats.push(("squfof".to_string(), squfof_best.0));
|
|
n_stats.push(("time_squfof".to_string(), squfof_best.1 as usize));
|
|
|
|
// one line
|
|
let mut oneline_best = (MAXITER, u128::MAX);
|
|
for &k in &k_oneline {
|
|
if let Some(kn) = n.checked_mul(u128::from(k)) {
|
|
let tstart = Instant::now();
|
|
let (result, iters) = one_line(&n, kn, oneline_best.0);
|
|
if result.is_some() {
|
|
oneline_best = oneline_best.min((iters, tstart.elapsed().as_micros()));
|
|
}
|
|
}
|
|
}
|
|
n_stats.push(("one_line".to_string(), oneline_best.0));
|
|
n_stats.push(("time_one_line".to_string(), squfof_best.1 as usize));
|
|
|
|
n_stats
|
|
}
|
|
|
|
/// This program try various factorization methods, and log down their iterations number into a csv file
|
|
fn main() -> Result<(), Error> {
|
|
let mut rng = rand::thread_rng();
|
|
const REPEATS: u32 = 4;
|
|
|
|
let mut n_list = Vec::<(u128, f32)>::new(); // n and bits of n
|
|
let mut stats: Vec<Vec<(String, usize)>> = Vec::new();
|
|
|
|
for total_bits in 20..120 {
|
|
for _ in 0..REPEATS {
|
|
let p1: u128 = rng.gen_prime(total_bits / 2, None);
|
|
let p2: u128 =
|
|
rng.gen_prime_exact(total_bits - (128 - p1.leading_zeros()) as usize, None);
|
|
if p1 == p2 {
|
|
continue;
|
|
}
|
|
|
|
let n = p1 * p2;
|
|
n_list.push((n, (n as f64).log2() as f32));
|
|
println!("Semiprime ({total_bits}bits): {n} = {p1} * {p2}");
|
|
// stats.push(profile_n(n));
|
|
stats.push(profile_n_min(n));
|
|
}
|
|
}
|
|
|
|
// Log into the CSV file
|
|
let mut fout = File::create("profile_stats.csv")?;
|
|
fout.write(b"n,n_bits")?;
|
|
for k in stats[0].iter().map(|(k, _)| k) {
|
|
fout.write(b",")?;
|
|
fout.write(k.as_bytes())?;
|
|
}
|
|
|
|
for ((n, bits), n_stats) in n_list.iter().zip(stats) {
|
|
fout.write(b"\n")?;
|
|
fout.write(n.to_string().as_bytes())?;
|
|
fout.write(b",")?;
|
|
fout.write(bits.to_string().as_bytes())?;
|
|
for (_, v) in n_stats {
|
|
fout.write(b",")?;
|
|
fout.write(v.to_string().as_bytes())?;
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
}
|