ssmr/
check.rs

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
84/// Fast primality in the worst case for all odd integers less than 1099620565341
85pub 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
97/// Fast primality in the average case, for all integers less than 1099620565341
98pub 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}