Coverage Report

Created: 2026-06-14 06:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}