pm1 fixes

This commit is contained in:
Christoph J. Scherr 2023-05-13 19:55:29 +02:00
parent ebfce5ac7f
commit e94ee5ad9d
Signed by: PlexSheep
GPG Key ID: 25B4ACF7D88186CC
1 changed files with 51 additions and 35 deletions

View File

@ -11,34 +11,33 @@
use pyo3::{prelude::*, exceptions::PyArithmeticError}; use pyo3::{prelude::*, exceptions::PyArithmeticError};
use num::integer::gcd; use num::integer::gcd;
use num_bigint::BigInt; use num_bigint::BigInt;
use num_traits::ToPrimitive;
use primes::{Sieve, PrimeSet}; use primes::{Sieve, PrimeSet, is_prime};
use crate::math::modexp; use crate::math::modexp;
const MAX_PRIMES: u128 = 80u128;
/// excecute the p minus one calculation /// excecute the p minus one calculation
pub fn p_minus_one(n: u128, max_prime: u128, verbose: bool) -> Result<Vec<u128>, String> { pub fn p_minus_one(n: u128, max_prime: u128, verbose: bool) -> Result<Vec<u128>, String> {
assert!(n > 2); if n < 3 {
let m1: u128 = n -1; return Err(format!("n too small: {n}"));
}
if max_prime > MAX_PRIMES {
return Err(format!("max_prime too large: {max_prime}"));
}
let mut k_parts: Vec<(u128, u32)> = Vec::new(); let mut k_parts: Vec<(u128, u32)> = Vec::new();
let mut prime_parts: Vec<u128> = Vec::new(); let mut prime_parts: Vec<u128> = Vec::new();
//
// get a list of the early primes // get a list of the early primes
let mut pset = Sieve::new(); let mut pset = Sieve::new();
if verbose {
println!("getting list of first {max_prime} primes");
}
for (_i_prime, prime) in pset.iter().enumerate().take(max_prime as usize) { for (_i_prime, prime) in pset.iter().enumerate().take(max_prime as usize) {
let num: u128 = prime as u128; let num: u128 = prime as u128;
if num > max_prime { if num > max_prime {
break; break;
} }
let mut exp: u32 = 1; let mut exp: u32 = 1;
if verbose {
println!("current prime: {num}");
}
loop { loop {
if num.pow(exp + 1) < max_prime { if num.pow(exp + 1) < max_prime {
exp += 1; exp += 1;
@ -47,9 +46,6 @@ pub fn p_minus_one(n: u128, max_prime: u128, verbose: bool) -> Result<Vec<u128>,
break; break;
} }
} }
if verbose {
println!("exponented prime: {}", num.pow(exp));
}
k_parts.push((num, exp)); k_parts.push((num, exp));
} }
let mut k = 1u128; let mut k = 1u128;
@ -62,34 +58,54 @@ pub fn p_minus_one(n: u128, max_prime: u128, verbose: bool) -> Result<Vec<u128>,
if verbose { if verbose {
println!("k: {k}\nk parts: {:?}", k_parts); println!("k: {k}\nk parts: {:?}", k_parts);
} }
let mut a = 2u128;
let a = 2u128; let mut akn1: u128;
let akn1: u128 = ((modexp::modular_exponentiation( let mut g: u128;
let mut q: u128;
let mut n = n;
println!("=======================================================================");
loop {
assert!(n > 1);
dbg!(&n);
if verbose {
println!("modular exponentiation with: a={a} k={k} n={n}");
}
akn1 = modexp::modular_exponentiation(
BigInt::from(a), BigInt::from(a),
BigInt::from(k), BigInt::from(k),
BigInt::from(n), BigInt::from(n),
false) false).to_u128().expect("Number too large") - 1;
) - BigInt::from(1)).try_into().expect("Number too big");
if verbose { if verbose {
println!("a: {a}\na**k-1 {akn1}"); println!("a**k - 1 = {a}**{k} - 1 mod {n} = {akn1}");
} }
let mut next_gcd = gcd(akn1, n); g = gcd(akn1, n);
if next_gcd == 1 {
return Err(format!("P minus one does not offer divisor for {n} with max_prime: {max_prime}"));
}
let mut q: u128;
while next_gcd > 1 {
prime_parts.push(next_gcd);
q = n / next_gcd;
next_gcd = gcd(q, n);
if verbose { if verbose {
println!("nextgcd: {next_gcd}|q: {q}"); println!("g = gcd(akn1, n) = gcd({akn1}, {n}) = {g}");
} }
if prime_parts.contains(&next_gcd) { if g == 1 {
println!("=======================================================================");
return Err(format!("P minus one does not work for this setup. Use another algorithm or choose a higher max prime."));
}
if g == n {
dbg!(&n);
if verbose {
println!("g = {g} = {n} = n");
println!("bad a, using a=a+1");
}
a += 1;
}
else {
n = n / g;
prime_parts.push(g);
if is_prime(n as u64) {
prime_parts.push(n);
break; break;
} }
} }
if verbose {
println!("=======================================================================");
}
}
return Ok(prime_parts); return Ok(prime_parts);
} }