use 16-bit n and add comments

This commit is contained in:
theBreadCompany 2024-12-04 13:56:14 +01:00
parent b8775f3675
commit 450131c6fa
2 changed files with 48 additions and 26 deletions

View file

@ -1,7 +1,11 @@
mod pollard_rho;
fn main() {
let n = rand::random::<u8>();
let mut n = 0;
while n % 2 == 0 { n = rand::random::<u16>(); }
let n_primediv = pollard_rho::pollard_rho(n.into());
eprintln!("Generated random number {}, got prime divisor {}", n, n_primediv);
eprintln!(
"Generated random number {}, got prime divisor {}",
n, n_primediv
);
}

View file

@ -2,28 +2,43 @@ use gcd::Gcd;
/**
* Calculate the prime divisor for some number `n`
*
* Uses cycle finding
*/
pub fn pollard_rho(n: u16) -> u16 {
if n == 1 { return 1; } // 1 only has 1 as prime divisor
if n % 2 == 0 { return 2; } // even numbers have at least 2 as prime divisor
if is_prime(n) { return n; }
pub fn pollard_rho(n: u32) -> u32 {
if n == 1 {
return 1;
} // 1 only has 1 as prime divisor
if n % 2 == 0 {
return 2;
} // even numbers have at least 2 as prime divisor
if is_prime(n) {
return n;
} // need to detect to be able to decide if we have bad random numbers or the
let mut x = rand::random::<u16>() % 2;
let mut y = x;
let mut x = rand::random::<u32>() % n; // cycle finding: tortoise
let mut y = x; // cycle finding: hare
let c = rand::random::<u16>() % 2;
let mut div = 1;
let c = rand::random::<u32>() % n; // random number to add to the cycle finding moves
let mut div = 1; // divisor - 1 applies to all numbers and is our failed and start value
while div == 1 {
// tortoise move
x = (mod_pow(x, 2, n) + c + n) % n;
// hare move
y = (mod_pow(y, 2, n) + c + n) % n;
y = (mod_pow(y, 2, n) + c + n) % n;
div = u16::try_from((i16::try_from(x).unwrap()-i16::try_from(y).unwrap()).abs()).unwrap().gcd(n);
eprintln!("Got div {}", div);
if div == n { return pollard_rho(n); }
// divisor is the greatest common divisor between |x-y| and n
div = u32::try_from((i32::try_from(x).unwrap() - i32::try_from(y).unwrap()).abs())
.unwrap()
.gcd(n);
// bad random numbers, try again
if div == n {
return pollard_rho(n);
}
}
return div;
div
}
/**
@ -35,19 +50,22 @@ pub fn pollard_rho(n: u16) -> u16 {
*
* Counterpart function to the discrete logarithm.
*/
fn mod_pow(base: u16, exp: u16, r#mod: u16) -> u16 {
fn mod_pow(base: u32, exp: u32, r#mod: u32) -> u32 {
let mut result = 1;
for _ in 0..exp - 1 {
result = (result * base) % r#mod;
}
result
}
fn is_prime(n: u16) -> bool {
for i in (3..=(n as f32).sqrt() as u16).step_by(2) {
if n % i == 0 { return false; }
/**
* very primitive prime checker
*/
fn is_prime(n: u32) -> bool {
for i in (3..=(n as f32).sqrt() as u32).step_by(2) {
if n % i == 0 {
return false;
}
}
true
}