add miller arbin test + fast modular exponent
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
[package]
|
||||
name = "TPNSM"
|
||||
name = "crypto_test"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
@@ -7,4 +7,5 @@ edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
num = "0.4"
|
||||
rayon = "1.5.3"
|
||||
rayon = "1.5"
|
||||
rand = "0.8"
|
||||
24
rust/algo.md
24
rust/algo.md
@@ -1,2 +1,22 @@
|
||||
Elliptic_curve_primality
|
||||

|
||||
# Primality tests
|
||||
|
||||
<details>
|
||||
<summary>Elliptic curve
|
||||
</summary>
|
||||
|
||||

|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Miller–Rabin
|
||||
</summary>
|
||||
|
||||

|
||||
</details>
|
||||
|
||||
|
||||
Baillie–PSW
|
||||
|
||||
AKS
|
||||
|
||||
Adleman–Pomerance–Rumely
|
||||
BIN
rust/pictures/mrp.png
Normal file
BIN
rust/pictures/mrp.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 51 KiB |
@@ -1,2 +1,2 @@
|
||||
pub mod prime;
|
||||
pub mod utils;
|
||||
pub mod utils;
|
||||
|
||||
@@ -1,15 +1,3 @@
|
||||
use TPNSM::prime::{prime_classical, prime_dumb_rayon};
|
||||
|
||||
fn main() {
|
||||
println!("Hello, world!");
|
||||
|
||||
let max = 1000000;
|
||||
find_prime(prime_classical(max));
|
||||
//find_prime(prime_dumb_rayon(max));
|
||||
}
|
||||
|
||||
fn find_prime(primes: Vec<u32>) {
|
||||
//println!("{:?}", primes);
|
||||
println!("{:?}", primes.last());
|
||||
println!("{}", primes.len());
|
||||
}
|
||||
@@ -1,17 +1,60 @@
|
||||
use crate::utils::fast_exp;
|
||||
use num::integer::sqrt;
|
||||
use rand::{thread_rng, Rng};
|
||||
use rayon::prelude::*;
|
||||
|
||||
pub fn miller_rabbin_gen(max: u32, acr: u32) -> Vec<u32> {
|
||||
let method = |n| miller_rabbin_test(n, acr);
|
||||
prime_gen(max, method)
|
||||
}
|
||||
|
||||
pub fn miller_rabbin_test(n: u32, acr: u32) -> bool {
|
||||
if n % 2 == 0 {
|
||||
false
|
||||
} else {
|
||||
let (k, q) = find_2_k_q(n - 1);
|
||||
let mut random = thread_rng();
|
||||
|
||||
'l: for _ in 0..acr {
|
||||
let a = random.gen_range(1..n - 1);
|
||||
let mut x = fast_exp(a, q, n);
|
||||
|
||||
if x != 1 && x != n - 1 {
|
||||
for _ in 0..k - 1 {
|
||||
x = fast_exp(x, 2, n);
|
||||
if x == n - 1 {
|
||||
continue 'l;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
fn find_2_k_q(mut n: u32) -> (u32, u32) {
|
||||
let mut k = 0;
|
||||
while n % 2 == 0 {
|
||||
n /= 2;
|
||||
k += 1;
|
||||
}
|
||||
(k, n)
|
||||
}
|
||||
|
||||
fn prime_gen<F>(max: u32, method: F) -> Vec<u32>
|
||||
where F: Fn(u32) -> bool {
|
||||
where
|
||||
F: Fn(u32) -> bool,
|
||||
{
|
||||
let mut primes = vec![2_u32];
|
||||
let mut i = 1;
|
||||
let mut i = 3;
|
||||
while i < max {
|
||||
i += 2;
|
||||
let prime = method(i);
|
||||
|
||||
if prime {
|
||||
primes.push(i);
|
||||
}
|
||||
i += 2;
|
||||
}
|
||||
primes
|
||||
}
|
||||
@@ -19,7 +62,7 @@ fn prime_gen<F>(max: u32, method: F) -> Vec<u32>
|
||||
pub fn prime_classical(max: u32) -> Vec<u32> {
|
||||
let mut primes = vec![2_u32];
|
||||
let mut i = 1;
|
||||
'l: while i < max {
|
||||
'l: while i + 2 < max {
|
||||
i += 2;
|
||||
for p in &primes {
|
||||
if i % p == 0 {
|
||||
@@ -35,16 +78,53 @@ pub fn prime_classical(max: u32) -> Vec<u32> {
|
||||
|
||||
pub fn prime_dumb_rayon(max: u32) -> Vec<u32> {
|
||||
let mut primes = vec![2_u32];
|
||||
let mut i = 1;
|
||||
let mut i = 3;
|
||||
while i < max {
|
||||
i += 2;
|
||||
let found = primes.par_iter()
|
||||
.filter(|x| { **x <= sqrt(i) })
|
||||
.any(|x| { i % *x == 0 });
|
||||
let found = primes
|
||||
.par_iter()
|
||||
.filter(|x| **x <= sqrt(i))
|
||||
.any(|x| i % *x == 0);
|
||||
|
||||
if !found {
|
||||
primes.push(i);
|
||||
}
|
||||
i += 2;
|
||||
}
|
||||
primes
|
||||
}
|
||||
}
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
const PRIME_TEST: [(u32, u32); 6] = [
|
||||
(10, 7),
|
||||
(100, 97),
|
||||
(500, 499),
|
||||
(1000, 997),
|
||||
(8300, 8297),
|
||||
(10000, 9973),
|
||||
];
|
||||
|
||||
#[test]
|
||||
fn test_prime_classical() {
|
||||
for (max, prem) in PRIME_TEST {
|
||||
assert_eq!(prime_classical(max).last(), Some(&prem));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_prime_dumb_rayon() {
|
||||
for (max, prem) in PRIME_TEST {
|
||||
assert_eq!(prime_dumb_rayon(max).last(), Some(&prem));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_miller_rabbin() {
|
||||
for (max, prem) in PRIME_TEST {
|
||||
assert_eq!(miller_rabbin_gen(max, 10).last(), Some(&prem));
|
||||
}
|
||||
|
||||
assert!(!miller_rabbin_test(2147483649, 10));
|
||||
assert!(miller_rabbin_test(2147483647, 10));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,7 +48,6 @@ pub fn congruent(a: i32, b: i32, n: i32) -> bool {
|
||||
(a - b) % n == 0
|
||||
}
|
||||
|
||||
|
||||
pub fn gcd_euclid(mut a: u32, mut b: u32) -> u32 {
|
||||
let mut r = a % b;
|
||||
while r != 0 {
|
||||
@@ -79,6 +78,23 @@ pub fn modular_inverse(a: u32, n: u32) -> Option<u32> {
|
||||
Some(t as u32)
|
||||
}
|
||||
|
||||
pub fn fast_exp(mut b: u32, mut e: u32, m: u32) -> u32 {
|
||||
if m == 1 {
|
||||
return 0;
|
||||
}
|
||||
let mut result = 1;
|
||||
|
||||
b %= m;
|
||||
while e > 0 {
|
||||
if e % 2 == 1 {
|
||||
result = (result as u64 * b as u64 % m as u64) as u32;
|
||||
}
|
||||
e >>= 1;
|
||||
b = (b as u64 * b as u64 % m as u64) as u32;
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@@ -124,4 +140,12 @@ mod tests {
|
||||
assert_eq!(modular_inverse(10, 19), Some(2));
|
||||
assert_eq!(modular_inverse(4, 6), None);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fast_exp() {
|
||||
assert_eq!(fast_exp(5, 3, 13), 8);
|
||||
assert_eq!(fast_exp(11, 13, 19), 11);
|
||||
assert_eq!(fast_exp(1234, 754, 452), 392);
|
||||
assert_eq!(fast_exp(76158, 24586, 5364), 576);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user