1use crate::hashbase::FERMAT_BASE;
2use crate::primes::{INV_8,PRIME_INV_64};
3
4 fn mod_inv(n: u64) -> u64 {
5 let mut est = INV_8[((n >> 1) & 0x7F) as usize] as u64;
6 est = 2u64.wrapping_sub(est.wrapping_mul(n)).wrapping_mul(est);
7 est = 2u64.wrapping_sub(est.wrapping_mul(n)).wrapping_mul(est);
8 est = 2u64.wrapping_sub(est.wrapping_mul(n)).wrapping_mul(est);
9 est.wrapping_neg()
10 }
11
12 fn mont_sub(x: u64, y: u64, n: u64) -> u64 {
13 if y > x {
14 return n.wrapping_sub(y.wrapping_sub(x));
15 }
16 x.wrapping_sub(y)
17}
18
19 fn mont_prod(x: u64, y: u64, n: u64, npi: u64) -> u64 {
20 let interim = x as u128 * y as u128;
21 let tm = (interim as u64).wrapping_mul(npi);
22 let (t, flag) = interim.overflowing_add((tm as u128) * (n as u128));
23 let t = (t >> 64) as u64;
24
25 if flag {
26 t + n.wrapping_neg()
27 } else if t >= n {
28 t - n
29 } else {
30 t
31 }
32 }
33
34
35 fn mont_pow(mut base: u64, mut one: u64, mut p: u64, n: u64, npi: u64) -> u64 {
36
37 while p > 1 {
38 if p & 1 == 0 {
39 base = mont_prod(base, base, n, npi);
40 p >>= 1;
41 } else {
42 one = mont_prod(one, base, n, npi);
43 base = mont_prod(base, base, n, npi);
44 p = (p - 1) >> 1;
45 }
46 }
47 mont_prod(one, base, n, npi)
48}
49
50fn sprp(p: u64, base: u64, one: u64, npi: u64) -> bool {
51 let p_minus = p - 1;
52 let twofactor = p_minus.trailing_zeros();
53 let d = p_minus >> twofactor;
54
55 let mut result = base.wrapping_mul(one);
56
57 let oneinv = mont_prod(mont_sub(p,one,p),one,p,npi);
58
59 result = mont_pow(result,one,d,p,npi);
60
61
62 if result == one || result == oneinv {
63 return true;
64 }
65
66 for _ in 1..twofactor {
67 result = mont_prod(result, result, p, npi);
68
69 if result == oneinv {
70 return true;
71 }
72 }
73 false
74}
75
76fn core_primality(x: u64) -> bool{
77 let npi = mod_inv(x);
78 let one = (u64::MAX % x) + 1;
79 let idx = (x as u32).wrapping_mul(2202620065).wrapping_shr(19) as usize;
80 sprp(x, FERMAT_BASE[idx] as u64, one,npi)
81
82}
83
84pub fn is_prime_wc(x: u64) -> bool{
86 debug_assert!( (x != 0) && (x < 1099620565341) && ([1,4,14,16,18,90,418,1024,
87 1248,1714,32208,48228,193152,
88 456424,736232,749324,1659364,
89 2037906,2157926,2512078,6510588,
90 36070710,60809772,439998604,754749144,
91 816051496,839707570,929747684,1964560406,
92 2705505948,2722237320,3221225472,4382063290,
93 7419460496,20524842874,28979528078].contains(&x) == false));
94 core_primality(x)
95}
96
97pub fn is_prime(x: u64) -> bool{
99
100 debug_assert!(x < 1099620565341);
101
102 if x == 1{
103 return false
104 }
105 if x == 2{
106 return true
107 }
108
109 if x&1==0{
110 return false
111 }
112 for i in PRIME_INV_64.iter() {
113 let prod = x.wrapping_mul(*i);
114 if prod == 1 {
115 return true;
116 }
117 if prod < x {
118 return false;
119 }
120 }
121
122 core_primality(x)
123
124}