From cde59ea2cc38af1d1c42ea57efe7968813b24894 Mon Sep 17 00:00:00 2001 From: Hesam Pakdaman <14890379+hesampakdaman@users.noreply.github.com> Date: Sat, 20 Apr 2024 12:27:46 +0200 Subject: [PATCH] Change back to U512 (#25) --- rustic_factors_derive/src/lib.rs | 4 +- .../fermats_factorization_method.rs | 12 +++--- src/algorithms/pollards_rho.rs | 8 ++-- src/algorithms/pollards_rho/utils.rs | 14 +++---- src/algorithms/trial_division.rs | 22 +++++----- src/factorization.rs | 16 ++++---- src/main.rs | 8 ++-- src/orchestration/recursive.rs | 36 ++++++++--------- src/primality_test/miller_rabin.rs | 16 ++++---- .../miller_rabin/composite_evidence.rs | 40 +++++++++---------- src/primality_test/miller_rabin/utils.rs | 12 +++--- .../prime_factorization/builder.rs | 10 ++--- .../prime_factorization/check_test.rs | 6 +-- src/traits.rs | 10 ++--- 14 files changed, 107 insertions(+), 107 deletions(-) diff --git a/rustic_factors_derive/src/lib.rs b/rustic_factors_derive/src/lib.rs index e45693b..2999c7d 100644 --- a/rustic_factors_derive/src/lib.rs +++ b/rustic_factors_derive/src/lib.rs @@ -11,7 +11,7 @@ fn impl_recursive_prime_factorization(ast: &syn::DeriveInput) -> TokenStream { let name = &ast.ident; let gen = quote! { impl crate::traits::PrimeFactorization for #name { - fn prime_factorization(n: &bnum::types::U256) -> Vec { + fn prime_factorization(n: &bnum::types::U512) -> Vec { crate::orchestration::RecursivePrimeFactorization::::prime_factorization(n) } } @@ -29,7 +29,7 @@ fn impl_factorization_command(ast: &syn::DeriveInput) -> TokenStream { let name = &ast.ident; let gen = quote! { impl crate::traits::Command for #name { - fn run(&self, n: &U256) -> String { + fn run(&self, n: &U512) -> String { crate::Factorization::new(n, Self::prime_factorization(n)).to_string() } } diff --git a/src/algorithms/fermats_factorization_method.rs b/src/algorithms/fermats_factorization_method.rs index c0f42cd..1e797a5 100644 --- a/src/algorithms/fermats_factorization_method.rs +++ b/src/algorithms/fermats_factorization_method.rs @@ -1,5 +1,5 @@ use crate::traits::{Factorize, PrimeFactorization}; -use bnum::types::U256; +use bnum::types::U512; use num_integer::Roots; use rustic_factors_derive::{FactorizationCommand, RecursivePrimeFactorization}; @@ -7,26 +7,26 @@ use rustic_factors_derive::{FactorizationCommand, RecursivePrimeFactorization}; pub struct FermatsFactorizationMethod; impl Factorize for FermatsFactorizationMethod { - fn factorize(n: &U256) -> U256 { + fn factorize(n: &U512) -> U512 { let mut a = ceil_sqrt(n); let mut b2 = a * a - n; while !is_perfect_square(&b2) { - a += U256::ONE; + a += U512::ONE; b2 = a * a - n; } a + b2.sqrt() } } -fn ceil_sqrt(n: &U256) -> U256 { +fn ceil_sqrt(n: &U512) -> U512 { if is_perfect_square(n) { n.sqrt() } else { - n.sqrt() + U256::ONE + n.sqrt() + U512::ONE } } -fn is_perfect_square(n: &U256) -> bool { +fn is_perfect_square(n: &U512) -> bool { let sqrt = n.sqrt(); sqrt * sqrt == *n } diff --git a/src/algorithms/pollards_rho.rs b/src/algorithms/pollards_rho.rs index 10ae988..7fd0cbe 100644 --- a/src/algorithms/pollards_rho.rs +++ b/src/algorithms/pollards_rho.rs @@ -1,7 +1,7 @@ mod utils; use crate::traits::{Factorize, PrimeFactorization}; -use bnum::types::U256; +use bnum::types::U512; use num_integer::Integer; use rustic_factors_derive::{FactorizationCommand, RecursivePrimeFactorization}; @@ -9,10 +9,10 @@ use rustic_factors_derive::{FactorizationCommand, RecursivePrimeFactorization}; pub struct PollardsRho; impl Factorize for PollardsRho { - fn factorize(n: &U256) -> U256 { - let init = U256::from(2u8); + fn factorize(n: &U512) -> U512 { + let init = U512::from(2u8); let pseudorandom_fn = utils::generate_pseudorandom_fn(n); - let finished = move |x: &U256, y: &U256| x.abs_diff(*y).gcd(n) != U256::from(1u8); + let finished = move |x: &U512, y: &U512| x.abs_diff(*y).gcd(n) != U512::from(1u8); let (tortoise, hare) = utils::floyds_cycle_detection(init, &pseudorandom_fn, &finished); hare.abs_diff(tortoise).gcd(n) } diff --git a/src/algorithms/pollards_rho/utils.rs b/src/algorithms/pollards_rho/utils.rs index 8cb7106..c7b7cc0 100644 --- a/src/algorithms/pollards_rho/utils.rs +++ b/src/algorithms/pollards_rho/utils.rs @@ -1,10 +1,10 @@ -use bnum::types::U256; +use bnum::types::U512; use rand::Rng; -pub fn floyds_cycle_detection(init: U256, next: &F, finished: &P) -> (U256, U256) +pub fn floyds_cycle_detection(init: U512, next: &F, finished: &P) -> (U512, U512) where - F: Fn(&U256) -> U256 + ?Sized, - P: Fn(&U256, &U256) -> bool + ?Sized, + F: Fn(&U512) -> U512 + ?Sized, + P: Fn(&U512, &U512) -> bool + ?Sized, { let mut tortoise = init; let mut hare = next(&tortoise); @@ -15,11 +15,11 @@ where (tortoise, hare) } -pub fn generate_pseudorandom_fn(n: &'_ U256) -> impl Fn(&U256) -> U256 + '_ { +pub fn generate_pseudorandom_fn(n: &'_ U512) -> impl Fn(&U512) -> U512 + '_ { let c = random_integer(n); move |x| (x.pow(2) + c) % n } -fn random_integer(bound: &U256) -> U256 { - rand::thread_rng().gen_range(U256::from(2u8)..*bound) +fn random_integer(bound: &U512) -> U512 { + rand::thread_rng().gen_range(U512::from(2u8)..*bound) } diff --git a/src/algorithms/trial_division.rs b/src/algorithms/trial_division.rs index 6496e96..c142df2 100644 --- a/src/algorithms/trial_division.rs +++ b/src/algorithms/trial_division.rs @@ -1,5 +1,5 @@ use crate::PrimeFactorization; -use bnum::types::U256; +use bnum::types::U512; use num_integer::Integer; use num_traits::One; use rustic_factors_derive::FactorizationCommand; @@ -8,15 +8,15 @@ use rustic_factors_derive::FactorizationCommand; pub struct TrialDivision; impl PrimeFactorization for TrialDivision { - fn prime_factorization(n: &U256) -> Vec { - if n <= &U256::one() { + fn prime_factorization(n: &U512) -> Vec { + if n <= &U512::one() { return vec![*n]; } trial_div(*n) } } -fn trial_div(mut n: U256) -> Vec { +fn trial_div(mut n: U512) -> Vec { let mut factors = vec![]; let divisors = DivisorCandidates::new(); for d in divisors { @@ -34,31 +34,31 @@ fn trial_div(mut n: U256) -> Vec { factors } -fn is_still_undivided(n: &U256) -> bool { +fn is_still_undivided(n: &U512) -> bool { !n.is_one() } struct DivisorCandidates { - current: U256, + current: U512, } impl DivisorCandidates { fn new() -> Self { DivisorCandidates { - current: U256::from(2u8), + current: U512::from(2u8), } } } impl Iterator for DivisorCandidates { - type Item = U256; + type Item = U512; fn next(&mut self) -> Option { let output = self.current; - self.current = if self.current == U256::from(2u8) { - self.current + U256::from(1u8) + self.current = if self.current == U512::from(2u8) { + self.current + U512::from(1u8) } else { - self.current + U256::from(2u8) + self.current + U512::from(2u8) }; Some(output) } diff --git a/src/factorization.rs b/src/factorization.rs index 6550281..7944776 100644 --- a/src/factorization.rs +++ b/src/factorization.rs @@ -1,16 +1,16 @@ -use bnum::types::U256; +use bnum::types::U512; use std::collections::BTreeMap; use std::fmt; static SUPERSCRIPTS: [&str; 10] = ["⁰", "¹", "²", "³", "⁴", "⁵", "⁶", "⁷", "⁸", "⁹"]; pub struct Factorization<'a> { - number: &'a U256, - factors: Vec, + number: &'a U512, + factors: Vec, } impl<'a> Factorization<'a> { - pub fn new(number: &'a U256, factors: Vec) -> Self { + pub fn new(number: &'a U512, factors: Vec) -> Self { Self { number, factors } } @@ -26,7 +26,7 @@ impl<'a> Factorization<'a> { ) } - fn factor_frequencies(&self) -> BTreeMap<&U256, u128> { + fn factor_frequencies(&self) -> BTreeMap<&U512, u128> { self.factors.iter().fold(BTreeMap::new(), |mut bmap, n| { *bmap.entry(n).or_insert(0) += 1; bmap @@ -40,7 +40,7 @@ impl fmt::Display for Factorization<'_> { } } -fn format_factor(base: &U256, exponent: u128) -> String { +fn format_factor(base: &U512, exponent: u128) -> String { fn to_superscript(exp: u128) -> String { if exp <= 1 { return "".to_string(); @@ -60,8 +60,8 @@ mod tests { use super::*; fn check(n: u32, factors: &[u32], expected: &str) { - let n = U256::from(n); - let factors = factors.iter().map(|&d| U256::from(d)).collect(); + let n = U512::from(n); + let factors = factors.iter().map(|&d| U512::from(d)).collect(); let actual = Factorization::new(&n, factors); assert_eq!(format!("{actual}"), expected); } diff --git a/src/main.rs b/src/main.rs index f6acbde..af1339a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,4 @@ -use bnum::types::U256; +use bnum::types::U512; use rustic_factors::commands::CommandMap; use std::env; @@ -6,7 +6,7 @@ fn main() { let args: Vec = env::args().collect(); match cli(&args) { Ok(result) => println!("{result}"), - Err(CliErr::ParseIntErr) => eprintln!("Please provide a number in range [0, 2²⁵⁶)"), + Err(CliErr::ParseIntErr) => eprintln!("Please provide a number in range [0, 2⁵¹²)"), Err(CliErr::IncorrectNumArgs) => eprintln!("Usage: {} ", args[0]), Err(CliErr::CommandNotFound(commands)) => { eprintln!("Unknown command. Available options: {commands}.") @@ -28,7 +28,7 @@ fn cli(args: &[String]) -> Result { fn parse(args: &[String]) -> Result { let command_name = String::from(&args[1]); - let n: U256 = args[2].parse().map_err(|_| CliErr::ParseIntErr)?; + let n: U512 = args[2].parse().map_err(|_| CliErr::ParseIntErr)?; Ok(ParsedInput { number: n, digit_len: args[2].len(), @@ -37,7 +37,7 @@ fn parse(args: &[String]) -> Result { } struct ParsedInput { - number: U256, + number: U512, digit_len: usize, command_name: String, } diff --git a/src/orchestration/recursive.rs b/src/orchestration/recursive.rs index 8986277..e5facb0 100644 --- a/src/orchestration/recursive.rs +++ b/src/orchestration/recursive.rs @@ -1,5 +1,5 @@ use crate::traits::{Factorize, PrimalityTest, PrimeFactorization}; -use bnum::types::U256; +use bnum::types::U512; use num_integer::Integer; use std::marker::PhantomData; @@ -19,7 +19,7 @@ where Factorizer: Factorize, PrimeTester: PrimalityTest, { - fn prime_factorization(n: &U256) -> Vec { + fn prime_factorization(n: &U512) -> Vec { let max_successive_failures = 100; Self::new(max_successive_failures).recursive_factorization(*n) } @@ -38,24 +38,24 @@ where } } - fn recursive_factorization(&self, mut n: U256) -> Vec { + fn recursive_factorization(&self, mut n: U512) -> Vec { let mut factors = vec![]; while n.is_even() { - factors.push(U256::TWO); - n /= &U256::TWO; + factors.push(U512::TWO); + n /= &U512::TWO; } self.recursion_step(n, &mut factors, 0); factors } - fn recursion_step(&self, n: U256, factors: &mut Vec, retried: usize) { + fn recursion_step(&self, n: U512, factors: &mut Vec, retried: usize) { if retried == self.max_successive_fails { panic![ "Failed to find factor after {0} succesive attempts", self.max_successive_fails ] } - if n <= U256::ONE { + if n <= U512::ONE { return; } if PrimeTester::is_prime(&n) { @@ -75,7 +75,7 @@ where } } - fn classify_factor(&self, factor: U256, n: &U256) -> DivisorOfN { + fn classify_factor(&self, factor: U512, n: &U512) -> DivisorOfN { if PrimeTester::is_prime(&factor) { return DivisorOfN::Prime(factor); } @@ -87,9 +87,9 @@ where } enum DivisorOfN { - Prime(U256), - Composite(U256), - Trivial(U256), + Prime(U512), + Composite(U512), + Trivial(U512), } #[cfg(test)] @@ -100,7 +100,7 @@ mod tests { struct FakePrimeTester; impl PrimalityTest for FakePrimeTester { - fn is_prime(n: &U256) -> bool { + fn is_prime(n: &U512) -> bool { [2, 3, 5].contains(&n.to_str_radix(10).parse().unwrap()) } } @@ -108,15 +108,15 @@ mod tests { struct FakeFactorizer; impl Factorize for FakeFactorizer { - fn factorize(n: &U256) -> U256 { + fn factorize(n: &U512) -> U512 { if n.is_even() { - return U256::TWO; + return U512::TWO; } - if n % U256::THREE == U256::ZERO { - return U256::THREE; + if n % U512::THREE == U512::ZERO { + return U512::THREE; } - if n % U256::FIVE == U256::ZERO { - return U256::FIVE; + if n % U512::FIVE == U512::ZERO { + return U512::FIVE; } *n } diff --git a/src/primality_test/miller_rabin.rs b/src/primality_test/miller_rabin.rs index 8998d49..554856a 100644 --- a/src/primality_test/miller_rabin.rs +++ b/src/primality_test/miller_rabin.rs @@ -3,13 +3,13 @@ mod utils; use self::composite_evidence::CompositeEvidence; use crate::traits::{Command, PrimalityTest}; -use bnum::types::U256; +use bnum::types::U512; use num_integer::Integer; pub struct MillerRabin; impl Command for MillerRabin { - fn run(&self, n: &U256) -> String { + fn run(&self, n: &U512) -> String { if MillerRabin::is_prime(n) { format!("{} is prime", n) } else { @@ -19,21 +19,21 @@ impl Command for MillerRabin { } impl PrimalityTest for MillerRabin { - fn is_prime(p: &U256) -> bool { - if p == &U256::TWO || p == &U256::THREE { + fn is_prime(p: &U512) -> bool { + if p == &U512::TWO || p == &U512::THREE { return true; } - if p < &U256::TWO || p.is_multiple_of(&U256::TWO) { + if p < &U512::TWO || p.is_multiple_of(&U512::TWO) { return false; } miller_rabin(p, 50) } } -fn miller_rabin(p: &U256, trials: usize) -> bool { +fn miller_rabin(p: &U512, trials: usize) -> bool { let evidence = CompositeEvidence::new(p); let likely_prime = |witness| !evidence.witnessed_by(&witness); - utils::RandomIntegers::new(U256::TWO..p - U256::ONE) + utils::RandomIntegers::new(U512::TWO..p - U512::ONE) .take(trials) .all(likely_prime) } @@ -44,7 +44,7 @@ mod tests { fn check(p: u32, expected: bool) { assert_eq!( - MillerRabin::is_prime(&U256::from(p)), + MillerRabin::is_prime(&U512::from(p)), expected, "Test failed for {}", p diff --git a/src/primality_test/miller_rabin/composite_evidence.rs b/src/primality_test/miller_rabin/composite_evidence.rs index c8db3c9..245bb57 100644 --- a/src/primality_test/miller_rabin/composite_evidence.rs +++ b/src/primality_test/miller_rabin/composite_evidence.rs @@ -1,56 +1,56 @@ use super::utils; -use bnum::types::U256; +use bnum::types::U512; use num_integer::Integer; use num_traits::One; pub struct CompositeEvidence<'a> { - n: &'a U256, + n: &'a U512, n_minus_1: Decomposed, } impl<'a> CompositeEvidence<'a> { - pub fn new(n: &'a U256) -> Self { - let n_minus_1 = Decomposed::new(n - U256::ONE); + pub fn new(n: &'a U512) -> Self { + let n_minus_1 = Decomposed::new(n - U512::ONE); Self { n, n_minus_1 } } - pub fn witnessed_by(&self, witness: &U256) -> bool { + pub fn witnessed_by(&self, witness: &U512) -> bool { match self.raise_to_n_minus_1_mod_n(witness) { Ok(result) => fails_fermats_condition(result), Err(FoundNonTrivialSqrtOf1) => true, } } - fn raise_to_n_minus_1_mod_n(&self, base: &U256) -> ExponentiationResult { + fn raise_to_n_minus_1_mod_n(&self, base: &U512) -> ExponentiationResult { let odd_factor_in_exp = &self.n_minus_1.odd_factor; let mut result = modpow(base, odd_factor_in_exp, self.n); for _ in 0..self.n_minus_1.exponent_of_2 { if self.is_nontrivial_sqrt_of_1(&result) { return Err(FoundNonTrivialSqrtOf1); } - result = modpow(&result, &U256::TWO, self.n); + result = modpow(&result, &U512::TWO, self.n); } Ok(RaisedToNMinus1ModN(result)) } - pub fn is_nontrivial_sqrt_of_1(&self, solution: &U256) -> bool { - let squared = modpow(solution, &U256::TWO, self.n); - squared == U256::one() - && solution != &U256::ONE - && solution != &(self.n - U256::ONE) + pub fn is_nontrivial_sqrt_of_1(&self, solution: &U512) -> bool { + let squared = modpow(solution, &U512::TWO, self.n); + squared == U512::one() + && solution != &U512::ONE + && solution != &(self.n - U512::ONE) } } -fn modpow(base: &U256, exponent: &U256, modulus: &U256) -> U256 { - let mut result = U256::ONE; +fn modpow(base: &U512, exponent: &U512, modulus: &U512) -> U512 { + let mut result = U512::ONE; let mut base = base % modulus; let mut exp = *exponent; - while exp > U256::ZERO { + while exp > U512::ZERO { if exp.is_odd() { result = result * base % modulus; } base = base * base % modulus; - exp /= U256::TWO; + exp /= U512::TWO; } result } @@ -61,21 +61,21 @@ fn fails_fermats_condition(r: RaisedToNMinus1ModN) -> bool { type ExponentiationResult = Result; -struct RaisedToNMinus1ModN(U256); +struct RaisedToNMinus1ModN(U512); struct FoundNonTrivialSqrtOf1; struct Decomposed { exponent_of_2: u32, - odd_factor: U256, + odd_factor: U512, } impl Decomposed { /// Decomposes `number` into `exponent_of_2` and `odd_factor`, /// where `number = 2^exponent_of_2 * odd_factor`. - pub fn new(number: U256) -> Self { + pub fn new(number: U512) -> Self { let exponent_of_2 = utils::highest_power_of_2_divisor(&number); - let odd_factor = number / U256::TWO.pow(exponent_of_2); + let odd_factor = number / U512::TWO.pow(exponent_of_2); Self { exponent_of_2, odd_factor, diff --git a/src/primality_test/miller_rabin/utils.rs b/src/primality_test/miller_rabin/utils.rs index 105993a..e65c13b 100644 --- a/src/primality_test/miller_rabin/utils.rs +++ b/src/primality_test/miller_rabin/utils.rs @@ -1,32 +1,32 @@ -use bnum::types::U256; +use bnum::types::U512; use num_integer::Integer; use rand::Rng; use std::ops::Range; pub struct RandomIntegers { - range: Range, + range: Range, } impl RandomIntegers { - pub fn new(range: Range) -> Self { + pub fn new(range: Range) -> Self { Self { range } } } impl Iterator for RandomIntegers { - type Item = U256; + type Item = U512; fn next(&mut self) -> Option { Some(rand::thread_rng().gen_range(self.range.clone())) } } -pub fn highest_power_of_2_divisor(base: &U256) -> u32 { +pub fn highest_power_of_2_divisor(base: &U512) -> u32 { let mut exp = 0; let mut base = *base; while base.is_even() { exp += 1; - base /= U256::TWO; + base /= U512::TWO; } exp } diff --git a/src/test_framework/prime_factorization/builder.rs b/src/test_framework/prime_factorization/builder.rs index 25a1ecd..5919914 100644 --- a/src/test_framework/prime_factorization/builder.rs +++ b/src/test_framework/prime_factorization/builder.rs @@ -1,9 +1,9 @@ use super::check_test::CheckTest; use crate::traits::PrimeFactorization; -use bnum::types::U256; +use bnum::types::U512; -type Factors = Vec; -type TestCase = (U256, Factors); +type Factors = Vec; +type TestCase = (U512, Factors); pub struct CheckTestBuilder { cases: Vec, } @@ -14,8 +14,8 @@ impl CheckTestBuilder { } pub fn case(mut self, n: u128, factors: &[u128]) -> Self { - let n_u512 = U256::from(n); - let factors_u512 = factors.iter().map(|&f| U256::from(f)).collect(); + let n_u512 = U512::from(n); + let factors_u512 = factors.iter().map(|&f| U512::from(f)).collect(); self.cases.push((n_u512, factors_u512)); self } diff --git a/src/test_framework/prime_factorization/check_test.rs b/src/test_framework/prime_factorization/check_test.rs index 33ef66e..2e952c4 100644 --- a/src/test_framework/prime_factorization/check_test.rs +++ b/src/test_framework/prime_factorization/check_test.rs @@ -1,8 +1,8 @@ use crate::traits::PrimeFactorization; -use bnum::types::U256; +use bnum::types::U512; use std::marker::PhantomData; -type TestCase = (U256, Vec); +type TestCase = (U512, Vec); pub struct CheckTest { cases: Vec, @@ -23,7 +23,7 @@ impl CheckTest { } } - pub fn check(n: &U256, expected: &[U256]) { + pub fn check(n: &U512, expected: &[U512]) { let mut actual = F::prime_factorization(&n); actual.sort_unstable(); assert_eq!(actual, expected, "Test failed for n = {}", n); diff --git a/src/traits.rs b/src/traits.rs index dc86a91..4668969 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -1,19 +1,19 @@ -use bnum::types::U256; +use bnum::types::U512; pub trait Factorize { - fn factorize(n: &U256) -> U256; + fn factorize(n: &U512) -> U512; } pub trait PrimeFactorization { - fn prime_factorization(n: &U256) -> Vec; + fn prime_factorization(n: &U512) -> Vec; } pub trait PrimalityTest { - fn is_prime(p: &U256) -> bool; + fn is_prime(p: &U512) -> bool; } pub trait Command { - fn run(&self, n: &U256) -> String; + fn run(&self, n: &U512) -> String; } pub trait FactorizationCommand: Command + PrimeFactorization {}