Skip to content

Commit

Permalink
WIP ugly solution
Browse files Browse the repository at this point in the history
  • Loading branch information
hesampakdaman committed Mar 31, 2024
1 parent 83fee50 commit 3e5b095
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 19 deletions.
59 changes: 44 additions & 15 deletions src/algorithms/pollards_rho.rs
Original file line number Diff line number Diff line change
@@ -1,40 +1,69 @@
use rand::Rng;
mod utils;
use std::collections::VecDeque;

use crate::primality_test::MillerRabin;
use crate::traits::PrimalityTest;
use crate::Factorize;

pub struct PollardsRho;

impl Factorize for PollardsRho {
fn factorize(&self, mut n: u128) -> Vec<u128> {
if n <= 3 {
fn factorize(&self, n: u128) -> Vec<u128> {
if n <= 3 || MillerRabin.is_prime(n) {
return vec![n];
}
let mut factors = vec![];
while let Ok(divisor) = pollards_rho(n) {
while n % divisor == 0 {
factors.push(divisor);
n /= divisor;
let mut queue = VecDeque::from([n]);
while let Some(m) = queue.pop_front() {
if MillerRabin.is_prime(m) {
factors.push(m);
continue;
}
match pollards_rho(m) {
FoundFactor::Prime(x) => {
factors.push(x);
queue.push_front(m / x)
}
FoundFactor::Composite(x) => {
queue.push_front(x);
queue.push_front(m / x)
}
FoundFactor::Trivial(_) => {
continue;
}
}
}
if n > 1 {
factors.push(n);
}
factors.sort_unstable();
factors
}
}

pub fn pollards_rho(n: u128) -> Result<u128, &'static str> {
fn pollards_rho(n: u128) -> FoundFactor {
let init = 2;
let pseudorandom_sequence = |x| (x * x + 1) % n;
let c = rand::thread_rng().gen_range(1..n);
let finished = |x: u128, y: u128| utils::gcd(x.abs_diff(y), n) != 1;
let (tortoise, hare) = utils::floyds_cycle_detection(init, pseudorandom_sequence, finished);
let psuedorandom = |x: u128| (x * x + c) % n;
let (tortoise, hare) = utils::floyds_cycle_detection(init, &psuedorandom, &finished);
let divisor = utils::gcd(tortoise.abs_diff(hare), n);
if n == divisor {
return Err("Failed to find non-trivial factor");
if divisor == 1 || divisor == n {
FoundFactor::Trivial(divisor)
} else if MillerRabin.is_prime(divisor) {
FoundFactor::Prime(divisor)
} else {
FoundFactor::Composite(divisor)
}
Ok(divisor)
}

enum FoundFactor {
Trivial(u128),
Composite(u128),
Prime(u128),
}

#[derive(Debug)]
struct FailedToFindNonTrivialFactor;

#[cfg(test)]
mod tests {
use super::*;
Expand Down
6 changes: 3 additions & 3 deletions src/algorithms/pollards_rho/utils.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
pub fn floyds_cycle_detection<F, P>(init: u128, next: F, finished: P) -> (u128, u128)
pub fn floyds_cycle_detection<F, P>(init: u128, next: &F, finished: &P) -> (u128, u128)
where
F: Fn(u128) -> u128,
P: Fn(u128, u128) -> bool,
F: Fn(u128) -> u128 + ?Sized,
P: Fn(u128, u128) -> bool + ?Sized,
{
let mut tortoise = init;
let mut hare = next(tortoise);
Expand Down
3 changes: 2 additions & 1 deletion src/primality_test.rs
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
pub mod miller_rabin;
mod miller_rabin;
pub use miller_rabin::MillerRabin;

0 comments on commit 3e5b095

Please sign in to comment.