Skip to content

Commit

Permalink
Change from U512 to U256 (#23)
Browse files Browse the repository at this point in the history
  • Loading branch information
hesampakdaman authored Apr 20, 2024
1 parent 67eab57 commit 71b2675
Show file tree
Hide file tree
Showing 14 changed files with 106 additions and 106 deletions.
4 changes: 2 additions & 2 deletions rustic_factors_derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::U512) -> Vec<bnum::types::U512> {
fn prime_factorization(n: &bnum::types::U256) -> Vec<bnum::types::U256> {
crate::orchestration::RecursivePrimeFactorization::<Self, crate::primality_test::MillerRabin>::prime_factorization(n)
}
}
Expand All @@ -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: &U512) -> String {
fn run(&self, n: &U256) -> String {
crate::Factorization::new(n, Self::prime_factorization(n)).to_string()
}
}
Expand Down
12 changes: 6 additions & 6 deletions src/algorithms/fermats_factorization_method.rs
Original file line number Diff line number Diff line change
@@ -1,32 +1,32 @@
use crate::traits::{Factorize, PrimeFactorization};
use bnum::types::U512;
use bnum::types::U256;
use num_integer::Roots;
use rustic_factors_derive::{FactorizationCommand, RecursivePrimeFactorization};

#[derive(FactorizationCommand, RecursivePrimeFactorization)]
pub struct FermatsFactorizationMethod;

impl Factorize for FermatsFactorizationMethod {
fn factorize(n: &U512) -> U512 {
fn factorize(n: &U256) -> U256 {
let mut a = ceil_sqrt(n);
let mut b2 = a * a - n;
while !is_perfect_square(&b2) {
a += U512::ONE;
a += U256::ONE;
b2 = a * a - n;
}
a + b2.sqrt()
}
}

fn ceil_sqrt(n: &U512) -> U512 {
fn ceil_sqrt(n: &U256) -> U256 {
if is_perfect_square(n) {
n.sqrt()
} else {
n.sqrt() + U512::ONE
n.sqrt() + U256::ONE
}
}

fn is_perfect_square(n: &U512) -> bool {
fn is_perfect_square(n: &U256) -> bool {
let sqrt = n.sqrt();
sqrt * sqrt == *n
}
Expand Down
8 changes: 4 additions & 4 deletions src/algorithms/pollards_rho.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
mod utils;

use crate::traits::{Factorize, PrimeFactorization};
use bnum::types::U512;
use bnum::types::U256;
use num_integer::Integer;
use rustic_factors_derive::{FactorizationCommand, RecursivePrimeFactorization};

#[derive(FactorizationCommand, RecursivePrimeFactorization)]
pub struct PollardsRho;

impl Factorize for PollardsRho {
fn factorize(n: &U512) -> U512 {
let init = U512::from(2u8);
fn factorize(n: &U256) -> U256 {
let init = U256::from(2u8);
let pseudorandom_fn = utils::generate_pseudorandom_fn(n);
let finished = move |x: &U512, y: &U512| x.abs_diff(*y).gcd(n) != U512::from(1u8);
let finished = move |x: &U256, y: &U256| x.abs_diff(*y).gcd(n) != U256::from(1u8);
let (tortoise, hare) = utils::floyds_cycle_detection(init, &pseudorandom_fn, &finished);
hare.abs_diff(tortoise).gcd(n)
}
Expand Down
14 changes: 7 additions & 7 deletions src/algorithms/pollards_rho/utils.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use bnum::types::U512;
use bnum::types::U256;
use rand::Rng;

pub fn floyds_cycle_detection<F, P>(init: U512, next: &F, finished: &P) -> (U512, U512)
pub fn floyds_cycle_detection<F, P>(init: U256, next: &F, finished: &P) -> (U256, U256)
where
F: Fn(&U512) -> U512 + ?Sized,
P: Fn(&U512, &U512) -> bool + ?Sized,
F: Fn(&U256) -> U256 + ?Sized,
P: Fn(&U256, &U256) -> bool + ?Sized,
{
let mut tortoise = init;
let mut hare = next(&tortoise);
Expand All @@ -15,11 +15,11 @@ where
(tortoise, hare)
}

pub fn generate_pseudorandom_fn(n: &'_ U512) -> impl Fn(&U512) -> U512 + '_ {
pub fn generate_pseudorandom_fn(n: &'_ U256) -> impl Fn(&U256) -> U256 + '_ {
let c = random_integer(n);
move |x| (x.pow(2) + c) % n
}

fn random_integer(bound: &U512) -> U512 {
rand::thread_rng().gen_range(U512::from(2u8)..*bound)
fn random_integer(bound: &U256) -> U256 {
rand::thread_rng().gen_range(U256::from(2u8)..*bound)
}
22 changes: 11 additions & 11 deletions src/algorithms/trial_division.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::PrimeFactorization;
use bnum::types::U512;
use bnum::types::U256;
use num_integer::Integer;
use num_traits::One;
use rustic_factors_derive::FactorizationCommand;
Expand All @@ -8,15 +8,15 @@ use rustic_factors_derive::FactorizationCommand;
pub struct TrialDivision;

impl PrimeFactorization for TrialDivision {
fn prime_factorization(n: &U512) -> Vec<U512> {
if n <= &U512::one() {
fn prime_factorization(n: &U256) -> Vec<U256> {
if n <= &U256::one() {
return vec![*n];
}
trial_div(*n)
}
}

fn trial_div(mut n: U512) -> Vec<U512> {
fn trial_div(mut n: U256) -> Vec<U256> {
let mut factors = vec![];
let divisors = DivisorCandidates::new();
for d in divisors {
Expand All @@ -34,31 +34,31 @@ fn trial_div(mut n: U512) -> Vec<U512> {
factors
}

fn is_still_undivided(n: &U512) -> bool {
fn is_still_undivided(n: &U256) -> bool {
!n.is_one()
}

struct DivisorCandidates {
current: U512,
current: U256,
}

impl DivisorCandidates {
fn new() -> Self {
DivisorCandidates {
current: U512::from(2u8),
current: U256::from(2u8),
}
}
}

impl Iterator for DivisorCandidates {
type Item = U512;
type Item = U256;

fn next(&mut self) -> Option<Self::Item> {
let output = self.current;
self.current = if self.current == U512::from(2u8) {
self.current + U512::from(1u8)
self.current = if self.current == U256::from(2u8) {
self.current + U256::from(1u8)
} else {
self.current + U512::from(2u8)
self.current + U256::from(2u8)
};
Some(output)
}
Expand Down
16 changes: 8 additions & 8 deletions src/factorization.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
use bnum::types::U512;
use bnum::types::U256;
use std::collections::BTreeMap;
use std::fmt;

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

pub struct Factorization<'a> {
number: &'a U512,
factors: Vec<U512>,
number: &'a U256,
factors: Vec<U256>,
}

impl<'a> Factorization<'a> {
pub fn new(number: &'a U512, factors: Vec<U512>) -> Self {
pub fn new(number: &'a U256, factors: Vec<U256>) -> Self {
Self { number, factors }
}

Expand All @@ -26,7 +26,7 @@ impl<'a> Factorization<'a> {
)
}

fn factor_frequencies(&self) -> BTreeMap<&U512, u128> {
fn factor_frequencies(&self) -> BTreeMap<&U256, u128> {
self.factors.iter().fold(BTreeMap::new(), |mut bmap, n| {
*bmap.entry(n).or_insert(0) += 1;
bmap
Expand All @@ -40,7 +40,7 @@ impl fmt::Display for Factorization<'_> {
}
}

fn format_factor(base: &U512, exponent: u128) -> String {
fn format_factor(base: &U256, exponent: u128) -> String {
fn to_superscript(exp: u128) -> String {
if exp <= 1 {
return "".to_string();
Expand All @@ -60,8 +60,8 @@ mod tests {
use super::*;

fn check(n: u32, factors: &[u32], expected: &str) {
let n = U512::from(n);
let factors = factors.iter().map(|&d| U512::from(d)).collect();
let n = U256::from(n);
let factors = factors.iter().map(|&d| U256::from(d)).collect();
let actual = Factorization::new(&n, factors);
assert_eq!(format!("{actual}"), expected);
}
Expand Down
8 changes: 4 additions & 4 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
use bnum::types::U512;
use bnum::types::U256;
use rustic_factors::commands::CommandMap;
use std::env;

fn main() {
let args: Vec<String> = 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: {} <command> <number>", args[0]),
Err(CliErr::CommandNotFound(commands)) => {
eprintln!("Unknown command. Available options: {commands}.")
Expand All @@ -28,15 +28,15 @@ fn cli(args: &[String]) -> Result<String, CliErr> {

fn parse(args: &[String]) -> Result<ParsedInput, CliErr> {
let command_name = String::from(&args[1]);
let n: U512 = args[2].parse().map_err(|_| CliErr::ParseIntErr)?;
let n: U256 = args[2].parse().map_err(|_| CliErr::ParseIntErr)?;
Ok(ParsedInput {
number: n,
command_name,
})
}

struct ParsedInput {
number: U512,
number: U256,
command_name: String,
}

Expand Down
34 changes: 17 additions & 17 deletions src/orchestration/recursive.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::traits::{Factorize, PrimalityTest, PrimeFactorization};
use bnum::types::U512;
use bnum::types::U256;
use num_integer::Integer;
use num_traits::One;
use std::marker::PhantomData;
Expand All @@ -20,7 +20,7 @@ where
Factorizer: Factorize,
PrimeTester: PrimalityTest,
{
fn prime_factorization(n: &U512) -> Vec<U512> {
fn prime_factorization(n: &U256) -> Vec<U256> {
let max_successive_failures = 100;
Self::new(max_successive_failures).recursive_factorization(*n)
}
Expand All @@ -39,9 +39,9 @@ where
}
}

fn recursive_factorization(&self, mut n: U512) -> Vec<U512> {
fn recursive_factorization(&self, mut n: U256) -> Vec<U256> {
let mut factors = vec![];
let two = U512::from(2u8);
let two = U256::from(2u8);
while n.is_even() {
factors.push(two);
n /= &two;
Expand All @@ -50,14 +50,14 @@ where
factors
}

fn recursion_step(&self, n: U512, factors: &mut Vec<U512>, retried: usize) {
fn recursion_step(&self, n: U256, factors: &mut Vec<U256>, retried: usize) {
if retried == self.max_successive_fails {
panic![
"Failed to find factor after {0} succesive attempts",
self.max_successive_fails
]
}
if n <= U512::one() {
if n <= U256::one() {
return;
}
match self.classify_factor(Factorizer::factorize(&n), &n) {
Expand All @@ -73,7 +73,7 @@ where
}
}

fn classify_factor(&self, factor: U512, n: &U512) -> DivisorOfN {
fn classify_factor(&self, factor: U256, n: &U256) -> DivisorOfN {
if PrimeTester::is_prime(&factor) {
return DivisorOfN::Prime(factor);
}
Expand All @@ -85,9 +85,9 @@ where
}

enum DivisorOfN {
Prime(U512),
Composite(U512),
Trivial(U512),
Prime(U256),
Composite(U256),
Trivial(U256),
}

#[cfg(test)]
Expand All @@ -99,23 +99,23 @@ mod tests {
struct FakePrimeTester;

impl PrimalityTest for FakePrimeTester {
fn is_prime(n: &U512) -> bool {
fn is_prime(n: &U256) -> bool {
[2, 3, 5].contains(&n.to_str_radix(10).parse().unwrap())
}
}

struct FakeFactorizer;

impl Factorize for FakeFactorizer {
fn factorize(n: &U512) -> U512 {
fn factorize(n: &U256) -> U256 {
if n.is_even() {
return U512::from(2u8);
return U256::from(2u8);
}
if n % U512::from(3u8) == U512::zero() {
return U512::from(3u8);
if n % U256::from(3u8) == U256::zero() {
return U256::from(3u8);
}
if n % U512::from(5u8) == U512::zero() {
return U512::from(5u8);
if n % U256::from(5u8) == U256::zero() {
return U256::from(5u8);
}
n.to_owned()
}
Expand Down
Loading

0 comments on commit 71b2675

Please sign in to comment.