num_bigint_dig/
prime.rs

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