use 16-bit n and add comments
This commit is contained in:
parent
b8775f3675
commit
450131c6fa
2 changed files with 48 additions and 26 deletions
|
@ -1,7 +1,11 @@
|
||||||
mod pollard_rho;
|
mod pollard_rho;
|
||||||
|
|
||||||
fn main() {
|
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());
|
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
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,53 +1,71 @@
|
||||||
use gcd::Gcd;
|
use gcd::Gcd;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate the primedivisor for some number `n`
|
* Calculate the prime divisor for some number `n`
|
||||||
|
*
|
||||||
|
* Uses cycle finding
|
||||||
*/
|
*/
|
||||||
pub fn pollard_rho(n: u16) -> u16 {
|
pub fn pollard_rho(n: u32) -> u32 {
|
||||||
if n == 1 { return 1; } // 1 only has 1 as prime divisor
|
if n == 1 {
|
||||||
if n % 2 == 0 { return 2; } // even numbers have at least 2 as prime divisor
|
return 1;
|
||||||
if is_prime(n) { return n; }
|
} // 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 x = rand::random::<u32>() % n; // cycle finding: tortoise
|
||||||
let mut y = x;
|
let mut y = x; // cycle finding: hare
|
||||||
|
|
||||||
let c = rand::random::<u16>() % 2;
|
let c = rand::random::<u32>() % n; // random number to add to the cycle finding moves
|
||||||
let mut div = 1;
|
let mut div = 1; // divisor - 1 applies to all numbers and is our failed and start value
|
||||||
|
|
||||||
while div == 1 {
|
while div == 1 {
|
||||||
|
// tortoise move
|
||||||
x = (mod_pow(x, 2, n) + c + n) % n;
|
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;
|
||||||
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);
|
// divisor is the greatest common divisor between |x-y| and n
|
||||||
eprintln!("Got div {}", div);
|
div = u32::try_from((i32::try_from(x).unwrap() - i32::try_from(y).unwrap()).abs())
|
||||||
if div == n { return pollard_rho(n); }
|
.unwrap()
|
||||||
|
.gcd(n);
|
||||||
|
// bad random numbers, try again
|
||||||
|
if div == n {
|
||||||
|
return pollard_rho(n);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return div;
|
div
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Discrete/Modular exponentiation
|
* Discrete/Modular exponentiation
|
||||||
*
|
*
|
||||||
* Highly memory efficient because the full result is never stored, but shortened by defined modulo instead.
|
* Highly memory efficient because the full result is never stored, but shortened by defined modulo instead.
|
||||||
* We can use that because the prime divisor required for our algorithm is guarenteed to be smaller
|
* We can use that because the prime divisor required for our algorithm is guarenteed to be smaller
|
||||||
* than n.
|
* than n.
|
||||||
*
|
*
|
||||||
* Counterpart function to the discrete logarithm.
|
* 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;
|
let mut result = 1;
|
||||||
|
for _ in 0..exp - 1 {
|
||||||
for _ in 0..exp-1 {
|
|
||||||
result = (result * base) % r#mod;
|
result = (result * base) % r#mod;
|
||||||
}
|
}
|
||||||
|
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_prime(n: u16) -> bool {
|
/**
|
||||||
for i in (3..=(n as f32).sqrt() as u16).step_by(2) {
|
* very primitive prime checker
|
||||||
if n % i == 0 { return false; }
|
*/
|
||||||
|
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
|
true
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue