Files
num-prime/examples/profile_factorization.rs
T
Sylvestre Ledru 48c099b7bb fix clippy warnings:
Fixed with:
`
cargo clippy --fix --allow-dirty  -- -W clippy::pedantic
`
2026-02-18 20:43:00 +01:00

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(())
}