diff --git a/Cargo.toml b/Cargo.toml index db939dc..b77b96a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "plexcryptool" authors = ["Christoph J. Scherr "] -version = "0.2.5" +version = "0.2.7" edition = "2021" readme = "README.md" description = "Various tools for use with math and cryptology, includes executable and a library." diff --git a/src/cplex/cli.rs b/src/cplex/cli.rs index 9e5d807..7e69baa 100644 --- a/src/cplex/cli.rs +++ b/src/cplex/cli.rs @@ -70,8 +70,12 @@ pub enum MathActions { Modred(ModredArgs), /// p minus 1 prime test Pm1(PM1Args), - //// calculate in a gallois field + /// calculate in a gallois field Gallois(GalloisAction), + /// Euklidian Algorithm + Gcd(GcdArgs), + /// factorize a natural number + Factorize(FactorizeArgs) } #[derive(Args, Clone, Debug, PartialEq, Eq)] @@ -105,6 +109,25 @@ pub struct GalloisAction { pub action: GalloisActions } +#[derive(Args, Clone, Debug, PartialEq, Eq)] +pub struct GcdArgs { + #[clap(value_parser=maybe_hex::)] + /// first number + pub a: u128, + #[clap(value_parser=maybe_hex::)] + /// second number + pub b: u128, + #[arg(short, long, default_value_t = false)] + /// use extended gcd + pub ext: bool +} + +#[derive(Args, Clone, Debug, PartialEq, Eq)] +pub struct FactorizeArgs { + #[clap(value_parser=maybe_hex::)] + pub n: u128, +} + #[derive(Subcommand, Clone, Debug, PartialEq, Eq)] pub enum GalloisActions { /// draw the root of n diff --git a/src/cplex/printing.rs b/src/cplex/printing.rs index 505fa32..00dbb4a 100644 --- a/src/cplex/printing.rs +++ b/src/cplex/printing.rs @@ -138,10 +138,10 @@ pub fn proc_vec(vec: Vec, args: Cli) seperator(); } if args.machine { - println!("{:#?}", vec); + println!("{:?}", vec); } else { - println!("result is\n{:#?}", vec); + println!("result is\n{:?}", vec); } } diff --git a/src/lib.rs b/src/lib.rs index 23dd9cd..4819520 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -52,6 +52,9 @@ fn register_math_module(py: Python, parent_module: &PyModule) -> PyResult<()> { let math_module = PyModule::new(py, "math")?; math_module.add_function(wrap_pyfunction!(math::modexp::py_modular_exponentiation, math_module)?)?; math_module.add_function(wrap_pyfunction!(math::pm1::py_p_minus_one, math_module)?)?; + math_module.add_function(wrap_pyfunction!(math::gcd::gcd, math_module)?)?; + math_module.add_function(wrap_pyfunction!(math::gcd::egcd, math_module)?)?; + math_module.add_function(wrap_pyfunction!(math::factorise::prime_factors , math_module)?)?; parent_module.add_submodule(math_module)?; Ok(()) } diff --git a/src/main.rs b/src/main.rs index b336675..2e993cd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -77,6 +77,20 @@ pub fn main() { } } } + MathActions::Factorize(fac_args) => { + let vec = math::factorise::prime_factors(fac_args.n, args.verbose); + cplex::printing::proc_vec(vec, args); + } + MathActions::Gcd(gcd_args) => { + if gcd_args.ext { + let vec = math::gcd::egcd(gcd_args.a, gcd_args.b); + cplex::printing::proc_vec(vec, args) + } + else { + let num = math::gcd::gcd(gcd_args.a, gcd_args.b); + cplex::printing::proc_num(num, args) + } + } } } Commands::Binary(action) => { diff --git a/src/math/factorise.rs b/src/math/factorise.rs new file mode 100644 index 0000000..244aec7 --- /dev/null +++ b/src/math/factorise.rs @@ -0,0 +1,38 @@ +#![allow(dead_code)] +/// factorize a large integer +/// +/// Author: Christoph J. Scherr +/// License: MIT +/// Source: + +use pyo3::prelude::*; + +#[pyfunction] +/// find the prime factors of n +pub fn prime_factors(mut n: u128, verbose: bool) -> Vec { + let mut i: u128 = 2; + let mut factors: Vec = Vec::new(); + while i.pow(2) <= n { + if n % i > 0 { + i += 1; + } + else { + n = n.checked_div(i).expect("n / i is not an integer"); + factors.push(i); + } + if verbose { + println!("i={i}\t{:?}", factors); + } + } + if n > 1 { + factors.push(n); + } + return factors; +} + +#[test] +fn test_prime_factors() { + assert_eq!(prime_factors(360, true), vec![2, 2, 2, 3, 3, 5]); + // see https://math.tools/numbers/prime-factors/3603234 + assert_eq!(prime_factors(3603234, true), vec![2, 3, 223, 2693]); +} diff --git a/src/math/gcd.rs b/src/math/gcd.rs new file mode 100644 index 0000000..54d203c --- /dev/null +++ b/src/math/gcd.rs @@ -0,0 +1,30 @@ +#![allow(dead_code)] +/// euclidian algorithm, find greatest common divider +/// +/// This does not implement the euclidian algorithm by itself. +/// +/// Author: Christoph J. Scherr +/// License: MIT +/// Source: + +use num::Integer; + +use pyo3::prelude::*; + +#[pyfunction] +/// extended euclidian algorithm +pub fn egcd(mut a: u128, mut b: u128) -> Vec { + if a > b { + let tmp = a; + a = b; + b = tmp; + } + let egcd = (a as i128).extended_gcd(&(b as i128)); + return vec![egcd.gcd, egcd.x, egcd.y] +} + +#[pyfunction] +/// euclidian algorithm +pub fn gcd(a: u128, b: u128) -> u128 { + a.gcd(&b) +} diff --git a/src/math/mod.rs b/src/math/mod.rs index 3c829fa..e36eccf 100644 --- a/src/math/mod.rs +++ b/src/math/mod.rs @@ -10,3 +10,5 @@ pub mod modexp; pub mod pm1; pub mod modred; pub mod gallois; +pub mod gcd; +pub mod factorise;