From d92644b5e8a0cf7f6657ce13768e4aeefb4b4a73 Mon Sep 17 00:00:00 2001 From: Hesam Pakdaman Date: Sun, 7 Apr 2024 00:02:19 +0200 Subject: [PATCH] Use num-bigint in trial_div --- src/algorithms/trial_division.rs | 63 ++++++++++++++++++-------------- 1 file changed, 36 insertions(+), 27 deletions(-) diff --git a/src/algorithms/trial_division.rs b/src/algorithms/trial_division.rs index ded7401..a497326 100644 --- a/src/algorithms/trial_division.rs +++ b/src/algorithms/trial_division.rs @@ -1,4 +1,7 @@ use crate::PrimeFactorization; +use num_bigint::BigUint; +use num_integer::Integer; +use num_traits::One; pub struct TrialDivision; @@ -7,52 +10,58 @@ impl PrimeFactorization for TrialDivision { if n <= 1 { return vec![n]; } - trial_div(n) + trial_div(BigUint::from(n)) + .into_iter() + .map(|d| d.try_into().unwrap()) + .collect() } } -fn trial_div(mut n: u128) -> Vec { +fn trial_div(mut n: BigUint) -> Vec { let mut factors = vec![]; - let mut div = DivisorCandidates::new(); - while div.square() <= n { - while div.divides(n) { - factors.push(div.value()); - n /= div.value(); + let mut divisors = DivisorCandidates::new(); + while let Some(d) = divisors.next() { + if n < d.pow(2) { + break; + } + while n.is_multiple_of(&d) { + n /= &d; + factors.push(d.clone()); } - div.next(); } - if is_still_undivided(n) { + if is_still_undivided(&n) { factors.push(n); } factors } -fn is_still_undivided(n: u128) -> bool { - n > 1 +fn is_still_undivided(n: &BigUint) -> bool { + !n.is_one() } -struct DivisorCandidates(u128); +struct DivisorCandidates { + current: BigUint, +} impl DivisorCandidates { fn new() -> Self { - DivisorCandidates(2) - } - - fn next(&mut self) -> &mut Self { - self.0 += if self.0 == 2 { 1 } else { 2 }; - self - } - - fn value(&self) -> u128 { - self.0 + DivisorCandidates { + current: BigUint::from(2u8), + } } +} - fn square(&self) -> u128 { - self.0 * self.0 - } +impl Iterator for DivisorCandidates { + type Item = BigUint; - fn divides(&self, n: u128) -> bool { - n % self.0 == 0 + fn next(&mut self) -> Option { + let output = self.current.clone(); + self.current = if self.current == BigUint::from(2u8) { + &self.current + 1u8 + } else { + &self.current + 2u8 + }; + Some(output) } }