Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adjust traits to be static #3

Merged
merged 1 commit into from
Apr 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 14 additions & 13 deletions src/algorithms/pollards_rho.rs
Original file line number Diff line number Diff line change
@@ -1,28 +1,29 @@
mod utils;

use std::marker::PhantomData;

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

pub struct PollardsRho;
type PrimeTester = Box<dyn PrimalityTest>;

impl Factorize for PollardsRho {
fn factorize(&self, n: u128) -> Vec<u128> {
RecursivePollardsRho::new(n, Box::new(primality_test::MillerRabin))
impl PrimeFactorization for PollardsRho {
fn prime_factorization(n: u128) -> Vec<u128> {
RecursivePollardsRho::<primality_test::MillerRabin>::new(n)
.solve()
.factors
}
}

struct RecursivePollardsRho {
struct RecursivePollardsRho<P: PrimalityTest> {
n: u128,
factors: Vec<u128>,
prime_tester: PrimeTester,
prime_tester: PhantomData<P>,
}

impl RecursivePollardsRho {
fn new(mut n: u128, prime_tester: PrimeTester) -> Self {
impl<P: PrimalityTest> RecursivePollardsRho<P> {
fn new(mut n: u128) -> Self {
let mut factors = vec![];
while n % 2 == 0 {
factors.push(2);
Expand All @@ -31,7 +32,7 @@ impl RecursivePollardsRho {
Self {
n,
factors,
prime_tester,
prime_tester: PhantomData,
}
}

Expand Down Expand Up @@ -59,7 +60,7 @@ impl RecursivePollardsRho {

fn get_divisor_with_pollards_rho(&self, n: u128) -> DivisorOfN {
let d = pollards_rho(n);
if self.prime_tester.is_prime(d) {
if P::is_prime(d) {
return DivisorOfN::Prime(d);
}
if d == 1 || d == n {
Expand Down Expand Up @@ -91,7 +92,7 @@ mod tests {
fn composites() {
let test_cases = [(8051, vec![83, 97]), (15, vec![3, 5]), (4096, vec![2; 12])];
for (n, expected) in test_cases {
let mut actual = PollardsRho.factorize(n);
let mut actual = PollardsRho::prime_factorization(n);
actual.sort_unstable();
assert_eq!(actual, expected);
}
Expand All @@ -101,7 +102,7 @@ mod tests {
fn primes() {
let primes = [3, 5, 19, 29, 37, 7027, 13037];
for p in primes {
let actual = PollardsRho.factorize(p);
let actual = PollardsRho::prime_factorization(p);
assert_eq!(actual, vec![p]);
}
}
Expand Down
10 changes: 5 additions & 5 deletions src/algorithms/trial_division.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use crate::Factorize;
use crate::PrimeFactorization;

pub struct TrialDivision;

impl Factorize for TrialDivision {
fn factorize(&self, n: u128) -> Vec<u128> {
impl PrimeFactorization for TrialDivision {
fn prime_factorization(n: u128) -> Vec<u128> {
if n <= 1 {
return vec![n];
}
Expand Down Expand Up @@ -62,11 +62,11 @@ mod tests {

#[test]
fn factorize_prime() {
assert_eq!(TrialDivision.factorize(13), vec![13]);
assert_eq!(TrialDivision::prime_factorization(13), vec![13]);
}

#[test]
fn factorize_composite() {
assert_eq!(TrialDivision.factorize(12), vec![2, 2, 3]);
assert_eq!(TrialDivision::prime_factorization(12), vec![2, 2, 3]);
}
}
6 changes: 3 additions & 3 deletions src/factorization.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::collections::BTreeMap;
use std::fmt;

use crate::Factorize;
use crate::PrimeFactorization;

static SUPERSCRIPTS: [&str; 10] = ["⁰", "¹", "²", "³", "⁴", "⁵", "⁶", "⁷", "⁸", "⁹"];

Expand All @@ -11,10 +11,10 @@ pub struct Factorization {
}

impl Factorization {
pub fn new(n: u128, f: impl Factorize) -> Self {
pub fn new<F: PrimeFactorization>(n: u128) -> Self {
Factorization {
number: n,
factors: f.factorize(n),
factors: F::prime_factorization(n),
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ pub mod traits;
pub mod primality_test;

pub use factorization::Factorization;
pub use traits::Factorize;
pub use traits::PrimeFactorization;
4 changes: 2 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ fn main() {
.parse()
.expect("Please provide a valid positive integer");
match method.as_str() {
"pollards_rho" => println!("{}", Factorization::new(n, algorithms::PollardsRho)),
"trial_division" => println!("{}", Factorization::new(n, algorithms::TrialDivision)),
"pollards_rho" => println!("{}", Factorization::new::<algorithms::PollardsRho>(n)),
"trial_division" => println!("{}", Factorization::new::<algorithms::TrialDivision>(n)),
_ => eprintln!("Unknown algorithm. Available options: pollards_rho, trial_division"),
}
}
12 changes: 6 additions & 6 deletions src/primality_test/miller_rabin.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
mod composite_evidence;
mod utils;

use crate::traits::PrimalityTest;
use self::composite_evidence::CompositeEvidence;
use crate::traits::PrimalityTest;

pub struct MillerRabin;

impl PrimalityTest for MillerRabin {
fn is_prime(&self, p: u128) -> bool {
fn is_prime(p: u128) -> bool {
if p == 2 || p == 3 {
return true;
}
Expand All @@ -21,7 +21,7 @@ impl PrimalityTest for MillerRabin {
fn miller_rabin(p: u128, trials: usize) -> bool {
let evidence = CompositeEvidence::new(p);
let likely_prime = |witness| !evidence.witnessed_by(witness);
utils::RandomIntegers::new(2..p-1)
utils::RandomIntegers::new(2..p - 1)
.take(trials)
.all(likely_prime)
}
Expand All @@ -43,15 +43,15 @@ mod tests {
2u128.pow(61) - 1,
];
for prime in primes {
assert!(MillerRabin.is_prime(prime), "Failed on prime {prime}");
assert!(MillerRabin::is_prime(prime), "Failed on prime {prime}");
}
}

#[test]
fn test_composite_numbers() {
for composite in [4, 15, 35, 49, 1001] {
assert!(
!MillerRabin.is_prime(composite),
!MillerRabin::is_prime(composite),
"Failed on composite {composite}"
);
}
Expand All @@ -66,7 +66,7 @@ mod tests {
];
for carmichael in carmichaels {
assert!(
!MillerRabin.is_prime(carmichael),
!MillerRabin::is_prime(carmichael),
"Failed on Carmichael number {carmichael}"
);
}
Expand Down
6 changes: 3 additions & 3 deletions src/traits.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
pub trait Factorize {
fn factorize(&self, n: u128) -> Vec<u128>;
pub trait PrimeFactorization {
fn prime_factorization(n: u128) -> Vec<u128>;
}

pub trait PrimalityTest {
fn is_prime(&self, p: u128) -> bool;
fn is_prime(p: u128) -> bool;
}
Loading