/rust/registry/src/index.crates.io-1949cf8c6b5b557f/num-bigint-dig-0.8.6/src/prime.rs
Line | Count | Source |
1 | | // https://github.com/RustCrypto/RSA/blob/master/src/prime.rs |
2 | | //! Implements probabilistic prime checkers. |
3 | | |
4 | | use alloc::vec; |
5 | | use integer::Integer; |
6 | | use num_traits::{FromPrimitive, One, ToPrimitive, Zero}; |
7 | | use rand::rngs::StdRng; |
8 | | use rand::SeedableRng; |
9 | | |
10 | | use crate::algorithms::jacobi; |
11 | | use crate::big_digit; |
12 | | use crate::bigrand::RandBigInt; |
13 | | use crate::Sign::Plus; |
14 | | use crate::{BigInt, BigUint, IntoBigUint}; |
15 | | |
16 | | lazy_static! { |
17 | | pub(crate) static ref BIG_1: BigUint = BigUint::one(); |
18 | | pub(crate) static ref BIG_2: BigUint = BigUint::from_u64(2).unwrap(); |
19 | | pub(crate) static ref BIG_3: BigUint = BigUint::from_u64(3).unwrap(); |
20 | | pub(crate) static ref BIG_64: BigUint = BigUint::from_u64(64).unwrap(); |
21 | | } |
22 | | |
23 | | const PRIMES_A: u64 = 3 * 5 * 7 * 11 * 13 * 17 * 19 * 23 * 37; |
24 | | const PRIMES_B: u64 = 29 * 31 * 41 * 43 * 47 * 53; |
25 | | |
26 | | /// Records the primes < 64. |
27 | | const PRIME_BIT_MASK: u64 = 1 << 2 |
28 | | | 1 << 3 |
29 | | | 1 << 5 |
30 | | | 1 << 7 |
31 | | | 1 << 11 |
32 | | | 1 << 13 |
33 | | | 1 << 17 |
34 | | | 1 << 19 |
35 | | | 1 << 23 |
36 | | | 1 << 29 |
37 | | | 1 << 31 |
38 | | | 1 << 37 |
39 | | | 1 << 41 |
40 | | | 1 << 43 |
41 | | | 1 << 47 |
42 | | | 1 << 53 |
43 | | | 1 << 59 |
44 | | | 1 << 61; |
45 | | |
46 | | /// ProbablyPrime reports whether x is probably prime, |
47 | | /// applying the Miller-Rabin test with n pseudorandomly chosen bases |
48 | | /// as well as a Baillie-PSW test. |
49 | | /// |
50 | | /// If x is prime, ProbablyPrime returns true. |
51 | | /// If x is chosen randomly and not prime, ProbablyPrime probably returns false. |
52 | | /// The probability of returning true for a randomly chosen non-prime is at most ¼ⁿ. |
53 | | /// |
54 | | /// ProbablyPrime is 100% accurate for inputs less than 2⁶⁴. |
55 | | /// See Menezes et al., Handbook of Applied Cryptography, 1997, pp. 145-149, |
56 | | /// and FIPS 186-4 Appendix F for further discussion of the error probabilities. |
57 | | /// |
58 | | /// ProbablyPrime is not suitable for judging primes that an adversary may |
59 | | /// have crafted to fool the test. |
60 | | /// |
61 | | /// This is a port of `ProbablyPrime` from the go std lib. |
62 | 0 | pub fn probably_prime(x: &BigUint, n: usize) -> bool { |
63 | 0 | if x.is_zero() { |
64 | 0 | return false; |
65 | 0 | } |
66 | | |
67 | 0 | if x < &*BIG_64 { |
68 | 0 | return (PRIME_BIT_MASK & (1 << x.to_u64().unwrap())) != 0; |
69 | 0 | } |
70 | | |
71 | 0 | if x.is_even() { |
72 | 0 | return false; |
73 | 0 | } |
74 | | |
75 | 0 | let r_a = &(x % PRIMES_A); |
76 | 0 | let r_b = &(x % PRIMES_B); |
77 | | |
78 | 0 | if (r_a % 3u32).is_zero() |
79 | 0 | || (r_a % 5u32).is_zero() |
80 | 0 | || (r_a % 7u32).is_zero() |
81 | 0 | || (r_a % 11u32).is_zero() |
82 | 0 | || (r_a % 13u32).is_zero() |
83 | 0 | || (r_a % 17u32).is_zero() |
84 | 0 | || (r_a % 19u32).is_zero() |
85 | 0 | || (r_a % 23u32).is_zero() |
86 | 0 | || (r_a % 37u32).is_zero() |
87 | 0 | || (r_b % 29u32).is_zero() |
88 | 0 | || (r_b % 31u32).is_zero() |
89 | 0 | || (r_b % 41u32).is_zero() |
90 | 0 | || (r_b % 43u32).is_zero() |
91 | 0 | || (r_b % 47u32).is_zero() |
92 | 0 | || (r_b % 53u32).is_zero() |
93 | | { |
94 | 0 | return false; |
95 | 0 | } |
96 | | |
97 | 0 | probably_prime_miller_rabin(x, n + 1, true) && probably_prime_lucas(x) |
98 | 0 | } |
99 | | |
100 | | const NUMBER_OF_PRIMES: usize = 127; |
101 | | const PRIME_GAP: [u64; 167] = [ |
102 | | 2, 2, 4, 2, 4, 2, 4, 6, 2, 6, 4, 2, 4, 6, 6, 2, 6, 4, 2, 6, 4, 6, 8, 4, 2, 4, 2, 4, 14, 4, 6, |
103 | | 2, 10, 2, 6, 6, 4, 6, 6, 2, 10, 2, 4, 2, 12, 12, 4, 2, 4, 6, 2, 10, 6, 6, 6, 2, 6, 4, 2, 10, |
104 | | 14, 4, 2, 4, 14, 6, 10, 2, 4, 6, 8, 6, 6, 4, 6, 8, 4, 8, 10, 2, 10, 2, 6, 4, 6, 8, 4, 2, 4, 12, |
105 | | 8, 4, 8, 4, 6, 12, 2, 18, 6, 10, 6, 6, 2, 6, 10, 6, 6, 2, 6, 6, 4, 2, 12, 10, 2, 4, 6, 6, 2, |
106 | | 12, 4, 6, 8, 10, 8, 10, 8, 6, 6, 4, 8, 6, 4, 8, 4, 14, 10, 12, 2, 10, 2, 4, 2, 10, 14, 4, 2, 4, |
107 | | 14, 4, 2, 4, 20, 4, 8, 10, 8, 4, 6, 6, 14, 4, 6, 6, 8, 6, 12, |
108 | | ]; |
109 | | |
110 | | const INCR_LIMIT: usize = 0x10000; |
111 | | |
112 | | /// Calculate the next larger prime, given a starting number `n`. |
113 | 0 | pub fn next_prime(n: &BigUint) -> BigUint { |
114 | 0 | if n < &*BIG_2 { |
115 | 0 | return 2u32.into_biguint().unwrap(); |
116 | 0 | } |
117 | | |
118 | | // We want something larger than our current number. |
119 | 0 | let mut res = n + &*BIG_1; |
120 | | |
121 | | // Ensure we are odd. |
122 | 0 | res |= &*BIG_1; |
123 | | |
124 | | // Handle values up to 7. |
125 | 0 | if let Some(val) = res.to_u64() { |
126 | 0 | if val < 7 { |
127 | 0 | return res; |
128 | 0 | } |
129 | 0 | } |
130 | | |
131 | 0 | let nbits = res.bits(); |
132 | 0 | let prime_limit = if nbits / 2 >= NUMBER_OF_PRIMES { |
133 | 0 | NUMBER_OF_PRIMES - 1 |
134 | | } else { |
135 | 0 | nbits / 2 |
136 | | }; |
137 | | |
138 | | // Compute the residues modulo small odd primes |
139 | 0 | let mut moduli = vec![BigUint::zero(); prime_limit]; |
140 | | |
141 | | 'outer: loop { |
142 | 0 | let mut prime = 3; |
143 | 0 | for i in 0..prime_limit { |
144 | 0 | moduli[i] = &res % prime; |
145 | 0 | prime += PRIME_GAP[i]; |
146 | 0 | } |
147 | | |
148 | | // Check residues |
149 | 0 | let mut difference: usize = 0; |
150 | 0 | for incr in (0..INCR_LIMIT as u64).step_by(2) { |
151 | 0 | let mut prime: u64 = 3; |
152 | | |
153 | 0 | let mut cancel = false; |
154 | 0 | for i in 0..prime_limit { |
155 | 0 | let r = (&moduli[i] + incr) % prime; |
156 | 0 | prime += PRIME_GAP[i]; |
157 | | |
158 | 0 | if r.is_zero() { |
159 | 0 | cancel = true; |
160 | 0 | break; |
161 | 0 | } |
162 | | } |
163 | | |
164 | 0 | if !cancel { |
165 | 0 | res += difference; |
166 | 0 | difference = 0; |
167 | 0 | if probably_prime(&res, 20) { |
168 | 0 | break 'outer; |
169 | 0 | } |
170 | 0 | } |
171 | | |
172 | 0 | difference += 2; |
173 | | } |
174 | | |
175 | 0 | res += difference; |
176 | | } |
177 | | |
178 | 0 | res |
179 | 0 | } |
180 | | |
181 | | /// Reports whether n passes reps rounds of the Miller-Rabin primality test, using pseudo-randomly chosen bases. |
182 | | /// If `force2` is true, one of the rounds is forced to use base 2. |
183 | | /// |
184 | | /// See Handbook of Applied Cryptography, p. 139, Algorithm 4.24. |
185 | 0 | pub fn probably_prime_miller_rabin(n: &BigUint, reps: usize, force2: bool) -> bool { |
186 | | // println!("miller-rabin: {}", n); |
187 | 0 | let nm1 = n - &*BIG_1; |
188 | | // determine q, k such that nm1 = q << k |
189 | 0 | let k = nm1.trailing_zeros().unwrap() as usize; |
190 | 0 | let q = &nm1 >> k; |
191 | | |
192 | 0 | let nm3 = n - &*BIG_2; |
193 | | |
194 | 0 | let mut rng = StdRng::seed_from_u64(n.get_limb(0) as u64); |
195 | | |
196 | 0 | 'nextrandom: for i in 0..reps { |
197 | 0 | let x = if i == reps - 1 && force2 { |
198 | 0 | BIG_2.clone() |
199 | | } else { |
200 | 0 | rng.gen_biguint_below(&nm3) + &*BIG_2 |
201 | | }; |
202 | | |
203 | 0 | let mut y = x.modpow(&q, n); |
204 | 0 | if y.is_one() || y == nm1 { |
205 | 0 | continue; |
206 | 0 | } |
207 | | |
208 | 0 | for _ in 1..k { |
209 | 0 | y = y.modpow(&*BIG_2, n); |
210 | 0 | if y == nm1 { |
211 | 0 | continue 'nextrandom; |
212 | 0 | } |
213 | 0 | if y.is_one() { |
214 | 0 | return false; |
215 | 0 | } |
216 | | } |
217 | 0 | return false; |
218 | | } |
219 | | |
220 | 0 | true |
221 | 0 | } |
222 | | |
223 | | /// Reports whether n passes the "almost extra strong" Lucas probable prime test, |
224 | | /// using Baillie-OEIS parameter selection. This corresponds to "AESLPSP" on Jacobsen's tables (link below). |
225 | | /// The combination of this test and a Miller-Rabin/Fermat test with base 2 gives a Baillie-PSW test. |
226 | | /// |
227 | | /// |
228 | | /// References: |
229 | | /// |
230 | | /// Baillie and Wagstaff, "Lucas Pseudoprimes", Mathematics of Computation 35(152), |
231 | | /// October 1980, pp. 1391-1417, especially page 1401. |
232 | | /// http://www.ams.org/journals/mcom/1980-35-152/S0025-5718-1980-0583518-6/S0025-5718-1980-0583518-6.pdf |
233 | | /// |
234 | | /// Grantham, "Frobenius Pseudoprimes", Mathematics of Computation 70(234), |
235 | | /// March 2000, pp. 873-891. |
236 | | /// http://www.ams.org/journals/mcom/2001-70-234/S0025-5718-00-01197-2/S0025-5718-00-01197-2.pdf |
237 | | /// |
238 | | /// Baillie, "Extra strong Lucas pseudoprimes", OEIS A217719, https://oeis.org/A217719. |
239 | | /// |
240 | | /// Jacobsen, "Pseudoprime Statistics, Tables, and Data", http://ntheory.org/pseudoprimes.html. |
241 | | /// |
242 | | /// Nicely, "The Baillie-PSW Primality Test", http://www.trnicely.net/misc/bpsw.html. |
243 | | /// (Note that Nicely's definition of the "extra strong" test gives the wrong Jacobi condition, |
244 | | /// as pointed out by Jacobsen.) |
245 | | /// |
246 | | /// Crandall and Pomerance, Prime Numbers: A Computational Perspective, 2nd ed. |
247 | | /// Springer, 2005. |
248 | 0 | pub fn probably_prime_lucas(n: &BigUint) -> bool { |
249 | | // println!("lucas: {}", n); |
250 | | // Discard 0, 1. |
251 | 0 | if n.is_zero() || n.is_one() { |
252 | 0 | return false; |
253 | 0 | } |
254 | | |
255 | | // Two is the only even prime. |
256 | 0 | if n.to_u64() == Some(2) { |
257 | 0 | return false; |
258 | 0 | } |
259 | | |
260 | | // Baillie-OEIS "method C" for choosing D, P, Q, |
261 | | // as in https://oeis.org/A217719/a217719.txt: |
262 | | // try increasing P ≥ 3 such that D = P² - 4 (so Q = 1) |
263 | | // until Jacobi(D, n) = -1. |
264 | | // The search is expected to succeed for non-square n after just a few trials. |
265 | | // After more than expected failures, check whether n is square |
266 | | // (which would cause Jacobi(D, n) = 1 for all D not dividing n). |
267 | 0 | let mut p = 3u64; |
268 | 0 | let n_int = BigInt::from_biguint(Plus, n.clone()); |
269 | | |
270 | | loop { |
271 | 0 | if p > 10000 { |
272 | | // This is widely believed to be impossible. |
273 | | // If we get a report, we'll want the exact number n. |
274 | 0 | panic!("internal error: cannot find (D/n) = -1 for {:?}", n) |
275 | 0 | } |
276 | | |
277 | 0 | let d_int = BigInt::from_u64(p * p - 4).unwrap(); |
278 | 0 | let j = jacobi(&d_int, &n_int); |
279 | | |
280 | 0 | if j == -1 { |
281 | 0 | break; |
282 | 0 | } |
283 | 0 | if j == 0 { |
284 | | // d = p²-4 = (p-2)(p+2). |
285 | | // If (d/n) == 0 then d shares a prime factor with n. |
286 | | // Since the loop proceeds in increasing p and starts with p-2==1, |
287 | | // the shared prime factor must be p+2. |
288 | | // If p+2 == n, then n is prime; otherwise p+2 is a proper factor of n. |
289 | 0 | return n_int.to_i64() == Some(p as i64 + 2); |
290 | 0 | } |
291 | 0 | if p == 40 { |
292 | | // We'll never find (d/n) = -1 if n is a square. |
293 | | // If n is a non-square we expect to find a d in just a few attempts on average. |
294 | | // After 40 attempts, take a moment to check if n is indeed a square. |
295 | 0 | let t1 = n.sqrt(); |
296 | 0 | let t1 = &t1 * &t1; |
297 | 0 | if &t1 == n { |
298 | 0 | return false; |
299 | 0 | } |
300 | 0 | } |
301 | | |
302 | 0 | p += 1; |
303 | | } |
304 | | |
305 | | // Grantham definition of "extra strong Lucas pseudoprime", after Thm 2.3 on p. 876 |
306 | | // (D, P, Q above have become Δ, b, 1): |
307 | | // |
308 | | // Let U_n = U_n(b, 1), V_n = V_n(b, 1), and Δ = b²-4. |
309 | | // An extra strong Lucas pseudoprime to base b is a composite n = 2^r s + Jacobi(Δ, n), |
310 | | // where s is odd and gcd(n, 2*Δ) = 1, such that either (i) U_s ≡ 0 mod n and V_s ≡ ±2 mod n, |
311 | | // or (ii) V_{2^t s} ≡ 0 mod n for some 0 ≤ t < r-1. |
312 | | // |
313 | | // We know gcd(n, Δ) = 1 or else we'd have found Jacobi(d, n) == 0 above. |
314 | | // We know gcd(n, 2) = 1 because n is odd. |
315 | | // |
316 | | // Arrange s = (n - Jacobi(Δ, n)) / 2^r = (n+1) / 2^r. |
317 | 0 | let mut s = n + &*BIG_1; |
318 | 0 | let r = s.trailing_zeros().unwrap() as usize; |
319 | 0 | s = &s >> r; |
320 | 0 | let nm2 = n - &*BIG_2; // n - 2 |
321 | | |
322 | | // We apply the "almost extra strong" test, which checks the above conditions |
323 | | // except for U_s ≡ 0 mod n, which allows us to avoid computing any U_k values. |
324 | | // Jacobsen points out that maybe we should just do the full extra strong test: |
325 | | // "It is also possible to recover U_n using Crandall and Pomerance equation 3.13: |
326 | | // U_n = D^-1 (2V_{n+1} - PV_n) allowing us to run the full extra-strong test |
327 | | // at the cost of a single modular inversion. This computation is easy and fast in GMP, |
328 | | // so we can get the full extra-strong test at essentially the same performance as the |
329 | | // almost extra strong test." |
330 | | |
331 | | // Compute Lucas sequence V_s(b, 1), where: |
332 | | // |
333 | | // V(0) = 2 |
334 | | // V(1) = P |
335 | | // V(k) = P V(k-1) - Q V(k-2). |
336 | | // |
337 | | // (Remember that due to method C above, P = b, Q = 1.) |
338 | | // |
339 | | // In general V(k) = α^k + β^k, where α and β are roots of x² - Px + Q. |
340 | | // Crandall and Pomerance (p.147) observe that for 0 ≤ j ≤ k, |
341 | | // |
342 | | // V(j+k) = V(j)V(k) - V(k-j). |
343 | | // |
344 | | // So in particular, to quickly double the subscript: |
345 | | // |
346 | | // V(2k) = V(k)² - 2 |
347 | | // V(2k+1) = V(k) V(k+1) - P |
348 | | // |
349 | | // We can therefore start with k=0 and build up to k=s in log₂(s) steps. |
350 | 0 | let mut vk = BIG_2.clone(); |
351 | 0 | let mut vk1 = BigUint::from_u64(p).unwrap(); |
352 | | |
353 | 0 | for i in (0..s.bits()).rev() { |
354 | 0 | if is_bit_set(&s, i) { |
355 | 0 | // k' = 2k+1 |
356 | 0 | // V(k') = V(2k+1) = V(k) V(k+1) - P |
357 | 0 | let t1 = (&vk * &vk1) + n - p; |
358 | 0 | vk = &t1 % n; |
359 | 0 | // V(k'+1) = V(2k+2) = V(k+1)² - 2 |
360 | 0 | let t1 = (&vk1 * &vk1) + &nm2; |
361 | 0 | vk1 = &t1 % n; |
362 | 0 | } else { |
363 | 0 | // k' = 2k |
364 | 0 | // V(k'+1) = V(2k+1) = V(k) V(k+1) - P |
365 | 0 | let t1 = (&vk * &vk1) + n - p; |
366 | 0 | vk1 = &t1 % n; |
367 | 0 | // V(k') = V(2k) = V(k)² - 2 |
368 | 0 | let t1 = (&vk * &vk) + &nm2; |
369 | 0 | vk = &t1 % n; |
370 | 0 | } |
371 | | } |
372 | | |
373 | | // Now k=s, so vk = V(s). Check V(s) ≡ ±2 (mod n). |
374 | 0 | if vk.to_u64() == Some(2) || vk == nm2 { |
375 | | // Check U(s) ≡ 0. |
376 | | // As suggested by Jacobsen, apply Crandall and Pomerance equation 3.13: |
377 | | // |
378 | | // U(k) = D⁻¹ (2 V(k+1) - P V(k)) |
379 | | // |
380 | | // Since we are checking for U(k) == 0 it suffices to check 2 V(k+1) == P V(k) mod n, |
381 | | // or P V(k) - 2 V(k+1) == 0 mod n. |
382 | 0 | let mut t1 = &vk * p; |
383 | 0 | let mut t2 = &vk1 << 1; |
384 | | |
385 | 0 | if t1 < t2 { |
386 | 0 | core::mem::swap(&mut t1, &mut t2); |
387 | 0 | } |
388 | | |
389 | 0 | t1 -= t2; |
390 | | |
391 | 0 | if (t1 % n).is_zero() { |
392 | 0 | return true; |
393 | 0 | } |
394 | 0 | } |
395 | | |
396 | | // Check V(2^t s) ≡ 0 mod n for some 0 ≤ t < r-1. |
397 | 0 | for _ in 0..r - 1 { |
398 | 0 | if vk.is_zero() { |
399 | 0 | return true; |
400 | 0 | } |
401 | | |
402 | | // Optimization: V(k) = 2 is a fixed point for V(k') = V(k)² - 2, |
403 | | // so if V(k) = 2, we can stop: we will never find a future V(k) == 0. |
404 | 0 | if vk.to_u64() == Some(2) { |
405 | 0 | return false; |
406 | 0 | } |
407 | | |
408 | | // k' = 2k |
409 | | // V(k') = V(2k) = V(k)² - 2 |
410 | 0 | let t1 = (&vk * &vk) - &*BIG_2; |
411 | 0 | vk = &t1 % n; |
412 | | } |
413 | | |
414 | 0 | false |
415 | 0 | } |
416 | | |
417 | | /// Checks if the i-th bit is set |
418 | | #[inline] |
419 | 0 | fn is_bit_set(x: &BigUint, i: usize) -> bool { |
420 | 0 | get_bit(x, i) == 1 |
421 | 0 | } |
422 | | |
423 | | /// Returns the i-th bit. |
424 | | #[inline] |
425 | 0 | fn get_bit(x: &BigUint, i: usize) -> u8 { |
426 | 0 | let j = i / big_digit::BITS; |
427 | | // if is out of range of the set words, it is always false. |
428 | 0 | if i >= x.bits() { |
429 | 0 | return 0; |
430 | 0 | } |
431 | | |
432 | 0 | (x.get_limb(j) >> (i % big_digit::BITS) & 1) as u8 |
433 | 0 | } |
434 | | |
435 | | #[cfg(test)] |
436 | | mod tests { |
437 | | use super::*; |
438 | | use alloc::vec::Vec; |
439 | | // use RandBigInt; |
440 | | |
441 | | use crate::biguint::ToBigUint; |
442 | | |
443 | | lazy_static! { |
444 | | static ref PRIMES: Vec<&'static str> = vec![ |
445 | | "2", |
446 | | "3", |
447 | | "5", |
448 | | "7", |
449 | | "11", |
450 | | |
451 | | "13756265695458089029", |
452 | | "13496181268022124907", |
453 | | "10953742525620032441", |
454 | | "17908251027575790097", |
455 | | |
456 | | // https://golang.org/issue/638 |
457 | | "18699199384836356663", |
458 | | |
459 | | "98920366548084643601728869055592650835572950932266967461790948584315647051443", |
460 | | "94560208308847015747498523884063394671606671904944666360068158221458669711639", |
461 | | |
462 | | // http://primes.utm.edu/lists/small/small3.html |
463 | | "449417999055441493994709297093108513015373787049558499205492347871729927573118262811508386655998299074566974373711472560655026288668094291699357843464363003144674940345912431129144354948751003607115263071543163", |
464 | | "230975859993204150666423538988557839555560243929065415434980904258310530753006723857139742334640122533598517597674807096648905501653461687601339782814316124971547968912893214002992086353183070342498989426570593", |
465 | | "5521712099665906221540423207019333379125265462121169655563495403888449493493629943498064604536961775110765377745550377067893607246020694972959780839151452457728855382113555867743022746090187341871655890805971735385789993", |
466 | | "203956878356401977405765866929034577280193993314348263094772646453283062722701277632936616063144088173312372882677123879538709400158306567338328279154499698366071906766440037074217117805690872792848149112022286332144876183376326512083574821647933992961249917319836219304274280243803104015000563790123", |
467 | | // ECC primes: http://tools.ietf.org/html/draft-ladd-safecurves-02 |
468 | | "3618502788666131106986593281521497120414687020801267626233049500247285301239", // Curve1174: 2^251-9 |
469 | | "57896044618658097711785492504343953926634992332820282019728792003956564819949", // Curve25519: 2^255-19 |
470 | | "9850501549098619803069760025035903451269934817616361666987073351061430442874302652853566563721228910201656997576599", // E-382: 2^382-105 |
471 | | "42307582002575910332922579714097346549017899709713998034217522897561970639123926132812109468141778230245837569601494931472367", // Curve41417: 2^414-17 |
472 | | "6864797660130609714981900799081393217269435300143305409394463459185543183397656052122559640661454554977296311391480858037121987999716643812574028291115057151", // E-521: 2^521-1 |
473 | | ]; |
474 | | |
475 | | static ref COMPOSITES: Vec<&'static str> = vec![ |
476 | | "0", |
477 | | "1", |
478 | | |
479 | | "21284175091214687912771199898307297748211672914763848041968395774954376176754", |
480 | | "6084766654921918907427900243509372380954290099172559290432744450051395395951", |
481 | | "84594350493221918389213352992032324280367711247940675652888030554255915464401", |
482 | | "82793403787388584738507275144194252681", |
483 | | |
484 | | // Arnault, "Rabin-Miller Primality Test: Composite Numbers Which Pass It", |
485 | | // Mathematics of Computation, 64(209) (January 1995), pp. 335-361. |
486 | | "1195068768795265792518361315725116351898245581", // strong pseudoprime to prime bases 2 through 29 |
487 | | // strong pseudoprime to all prime bases up to 200 |
488 | | "8038374574536394912570796143419421081388376882875581458374889175222974273765333652186502336163960045457915042023603208766569966760987284043965408232928738791850869166857328267761771029389697739470167082304286871099974399765441448453411558724506334092790222752962294149842306881685404326457534018329786111298960644845216191652872597534901", |
489 | | |
490 | | // Extra-strong Lucas pseudoprimes. https://oeis.org/A217719 |
491 | | "989", |
492 | | "3239", |
493 | | "5777", |
494 | | "10877", |
495 | | "27971", |
496 | | "29681", |
497 | | "30739", |
498 | | "31631", |
499 | | "39059", |
500 | | "72389", |
501 | | "73919", |
502 | | "75077", |
503 | | "100127", |
504 | | "113573", |
505 | | "125249", |
506 | | "137549", |
507 | | "137801", |
508 | | "153931", |
509 | | "155819", |
510 | | "161027", |
511 | | "162133", |
512 | | "189419", |
513 | | "218321", |
514 | | "231703", |
515 | | "249331", |
516 | | "370229", |
517 | | "429479", |
518 | | "430127", |
519 | | "459191", |
520 | | "473891", |
521 | | "480689", |
522 | | "600059", |
523 | | "621781", |
524 | | "632249", |
525 | | "635627", |
526 | | |
527 | | "3673744903", |
528 | | "3281593591", |
529 | | "2385076987", |
530 | | "2738053141", |
531 | | "2009621503", |
532 | | "1502682721", |
533 | | "255866131", |
534 | | "117987841", |
535 | | "587861", |
536 | | |
537 | | "6368689", |
538 | | "8725753", |
539 | | "80579735209", |
540 | | "105919633", |
541 | | ]; |
542 | | |
543 | | // Test Cases from #51 |
544 | | static ref ISSUE_51: Vec<&'static str> = vec![ |
545 | | "1579751", |
546 | | "1884791", |
547 | | "3818929", |
548 | | "4080359", |
549 | | "4145951", |
550 | | ]; |
551 | | } |
552 | | |
553 | | #[test] |
554 | | fn test_primes() { |
555 | | for prime in PRIMES.iter() { |
556 | | let p = BigUint::parse_bytes(prime.as_bytes(), 10).unwrap(); |
557 | | for i in [0, 1, 20].iter() { |
558 | | assert!( |
559 | | probably_prime(&p, *i as usize), |
560 | | "{} is a prime ({})", |
561 | | prime, |
562 | | i, |
563 | | ); |
564 | | } |
565 | | } |
566 | | } |
567 | | |
568 | | #[test] |
569 | | fn test_composites() { |
570 | | for comp in COMPOSITES.iter() { |
571 | | let p = BigUint::parse_bytes(comp.as_bytes(), 10).unwrap(); |
572 | | for i in [0, 1, 20].iter() { |
573 | | assert!( |
574 | | !probably_prime(&p, *i as usize), |
575 | | "{} is a composite ({})", |
576 | | comp, |
577 | | i, |
578 | | ); |
579 | | } |
580 | | } |
581 | | } |
582 | | |
583 | | #[test] |
584 | | fn test_issue_51() { |
585 | | for num in ISSUE_51.iter() { |
586 | | let p = BigUint::parse_bytes(num.as_bytes(), 10).unwrap(); |
587 | | assert!(probably_prime(&p, 20), "{} is a prime number", num); |
588 | | } |
589 | | } |
590 | | |
591 | | macro_rules! test_pseudo_primes { |
592 | | ($name:ident, $cond:expr, $want:expr) => { |
593 | | #[test] |
594 | | fn $name() { |
595 | | let mut i = 3; |
596 | | let mut want = $want; |
597 | | while i < 100000 { |
598 | | let n = BigUint::from_u64(i).unwrap(); |
599 | | let pseudo = $cond(&n); |
600 | | if pseudo && (want.is_empty() || i != want[0]) { |
601 | | panic!("cond({}) = true, want false", i); |
602 | | } else if !pseudo && !want.is_empty() && i == want[0] { |
603 | | panic!("cond({}) = false, want true", i); |
604 | | } |
605 | | if !want.is_empty() && i == want[0] { |
606 | | want = want[1..].to_vec(); |
607 | | } |
608 | | i += 2; |
609 | | } |
610 | | |
611 | | if !want.is_empty() { |
612 | | panic!("forgot to test: {:?}", want); |
613 | | } |
614 | | } |
615 | | }; |
616 | | } |
617 | | |
618 | | test_pseudo_primes!( |
619 | | test_probably_prime_miller_rabin, |
620 | | |n| probably_prime_miller_rabin(n, 1, true) && !probably_prime_lucas(n), |
621 | | vec![ |
622 | | 2047, 3277, 4033, 4681, 8321, 15841, 29341, 42799, 49141, 52633, 65281, 74665, 80581, |
623 | | 85489, 88357, 90751, |
624 | | ] |
625 | | ); |
626 | | |
627 | | test_pseudo_primes!( |
628 | | test_probably_prime_lucas, |
629 | | |n| probably_prime_lucas(n) && !probably_prime_miller_rabin(n, 1, true), |
630 | | vec![989, 3239, 5777, 10877, 27971, 29681, 30739, 31631, 39059, 72389, 73919, 75077,] |
631 | | ); |
632 | | |
633 | | #[test] |
634 | | fn test_bit_set() { |
635 | | let v = &vec![0b10101001]; |
636 | | let num = BigUint::from_slice(&v); |
637 | | assert!(is_bit_set(&num, 0)); |
638 | | assert!(!is_bit_set(&num, 1)); |
639 | | assert!(!is_bit_set(&num, 2)); |
640 | | assert!(is_bit_set(&num, 3)); |
641 | | assert!(!is_bit_set(&num, 4)); |
642 | | assert!(is_bit_set(&num, 5)); |
643 | | assert!(!is_bit_set(&num, 6)); |
644 | | assert!(is_bit_set(&num, 7)); |
645 | | } |
646 | | |
647 | | #[test] |
648 | | fn test_next_prime_basics() { |
649 | | let primes1 = (0..2048u32) |
650 | | .map(|i| next_prime(&i.to_biguint().unwrap())) |
651 | | .collect::<Vec<_>>(); |
652 | | let primes2 = (0..2048u32) |
653 | | .map(|i| { |
654 | | let i = i.to_biguint().unwrap(); |
655 | | let p = next_prime(&i); |
656 | | assert!(&p > &i); |
657 | | p |
658 | | }) |
659 | | .collect::<Vec<_>>(); |
660 | | |
661 | | for (p1, p2) in primes1.iter().zip(&primes2) { |
662 | | assert_eq!(p1, p2); |
663 | | assert!(probably_prime(p1, 25)); |
664 | | } |
665 | | } |
666 | | |
667 | | #[test] |
668 | | fn test_next_prime_bug_44() { |
669 | | let i = 1032989.to_biguint().unwrap(); |
670 | | let next = next_prime(&i); |
671 | | assert_eq!(1033001.to_biguint().unwrap(), next); |
672 | | } |
673 | | } |