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 rand::rngs::StdRng;
8use rand::SeedableRng;
9
10use crate::algorithms::jacobi;
11use crate::big_digit;
12use crate::bigrand::RandBigInt;
13use crate::Sign::Plus;
14use crate::{BigInt, BigUint, IntoBigUint};
15
16lazy_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
23const PRIMES_A: u64 = 3 * 5 * 7 * 11 * 13 * 17 * 19 * 23 * 37;
24const PRIMES_B: u64 = 29 * 31 * 41 * 43 * 47 * 53;
25
26/// Records the primes < 64.
27const 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.
62pub fn probably_prime(x: &BigUint, n: usize) -> bool {
63    if x.is_zero() {
64        return false;
65    }
66
67    if x < &*BIG_64 {
68        return (PRIME_BIT_MASK & (1 << x.to_u64().unwrap())) != 0;
69    }
70
71    if x.is_even() {
72        return false;
73    }
74
75    let r_a = &(x % PRIMES_A);
76    let r_b = &(x % PRIMES_B);
77
78    if (r_a % 3u32).is_zero()
79        || (r_a % 5u32).is_zero()
80        || (r_a % 7u32).is_zero()
81        || (r_a % 11u32).is_zero()
82        || (r_a % 13u32).is_zero()
83        || (r_a % 17u32).is_zero()
84        || (r_a % 19u32).is_zero()
85        || (r_a % 23u32).is_zero()
86        || (r_a % 37u32).is_zero()
87        || (r_b % 29u32).is_zero()
88        || (r_b % 31u32).is_zero()
89        || (r_b % 41u32).is_zero()
90        || (r_b % 43u32).is_zero()
91        || (r_b % 47u32).is_zero()
92        || (r_b % 53u32).is_zero()
93    {
94        return false;
95    }
96
97    probably_prime_miller_rabin(x, n + 1, true) && probably_prime_lucas(x)
98}
99
100const NUMBER_OF_PRIMES: usize = 127;
101const 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
110const INCR_LIMIT: usize = 0x10000;
111
112/// Calculate the next larger prime, given a starting number `n`.
113pub fn next_prime(n: &BigUint) -> BigUint {
114    if n < &*BIG_2 {
115        return 2u32.into_biguint().unwrap();
116    }
117
118    // We want something larger than our current number.
119    let mut res = n + &*BIG_1;
120
121    // Ensure we are odd.
122    res |= &*BIG_1;
123
124    // Handle values up to 7.
125    if let Some(val) = res.to_u64() {
126        if val < 7 {
127            return res;
128        }
129    }
130
131    let nbits = res.bits();
132    let prime_limit = if nbits / 2 >= NUMBER_OF_PRIMES {
133        NUMBER_OF_PRIMES - 1
134    } else {
135        nbits / 2
136    };
137
138    // Compute the residues modulo small odd primes
139    let mut moduli = vec![BigUint::zero(); prime_limit];
140
141    'outer: loop {
142        let mut prime = 3;
143        for i in 0..prime_limit {
144            moduli[i] = &res % prime;
145            prime += PRIME_GAP[i];
146        }
147
148        // Check residues
149        let mut difference: usize = 0;
150        for incr in (0..INCR_LIMIT as u64).step_by(2) {
151            let mut prime: u64 = 3;
152
153            let mut cancel = false;
154            for i in 0..prime_limit {
155                let r = (&moduli[i] + incr) % prime;
156                prime += PRIME_GAP[i];
157
158                if r.is_zero() {
159                    cancel = true;
160                    break;
161                }
162            }
163
164            if !cancel {
165                res += difference;
166                difference = 0;
167                if probably_prime(&res, 20) {
168                    break 'outer;
169                }
170            }
171
172            difference += 2;
173        }
174
175        res += difference;
176    }
177
178    res
179}
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.
185pub fn probably_prime_miller_rabin(n: &BigUint, reps: usize, force2: bool) -> bool {
186    // println!("miller-rabin: {}", n);
187    let nm1 = n - &*BIG_1;
188    // determine q, k such that nm1 = q << k
189    let k = nm1.trailing_zeros().unwrap() as usize;
190    let q = &nm1 >> k;
191
192    let nm3 = n - &*BIG_2;
193
194    let mut rng = StdRng::seed_from_u64(n.get_limb(0) as u64);
195
196    'nextrandom: for i in 0..reps {
197        let x = if i == reps - 1 && force2 {
198            BIG_2.clone()
199        } else {
200            rng.gen_biguint_below(&nm3) + &*BIG_2
201        };
202
203        let mut y = x.modpow(&q, n);
204        if y.is_one() || y == nm1 {
205            continue;
206        }
207
208        for _ in 1..k {
209            y = y.modpow(&*BIG_2, n);
210            if y == nm1 {
211                continue 'nextrandom;
212            }
213            if y.is_one() {
214                return false;
215            }
216        }
217        return false;
218    }
219
220    true
221}
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.
248pub fn probably_prime_lucas(n: &BigUint) -> bool {
249    // println!("lucas: {}", n);
250    // Discard 0, 1.
251    if n.is_zero() || n.is_one() {
252        return false;
253    }
254
255    // Two is the only even prime.
256    if n.to_u64() == Some(2) {
257        return false;
258    }
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    let mut p = 3u64;
268    let n_int = BigInt::from_biguint(Plus, n.clone());
269
270    loop {
271        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            panic!("internal error: cannot find (D/n) = -1 for {:?}", n)
275        }
276
277        let d_int = BigInt::from_u64(p * p - 4).unwrap();
278        let j = jacobi(&d_int, &n_int);
279
280        if j == -1 {
281            break;
282        }
283        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            return n_int.to_i64() == Some(p as i64 + 2);
290        }
291        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            let t1 = n.sqrt();
296            let t1 = &t1 * &t1;
297            if &t1 == n {
298                return false;
299            }
300        }
301
302        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    let mut s = n + &*BIG_1;
318    let r = s.trailing_zeros().unwrap() as usize;
319    s = &s >> r;
320    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    let mut vk = BIG_2.clone();
351    let mut vk1 = BigUint::from_u64(p).unwrap();
352
353    for i in (0..s.bits()).rev() {
354        if is_bit_set(&s, i) {
355            // k' = 2k+1
356            // V(k') = V(2k+1) = V(k) V(k+1) - P
357            let t1 = (&vk * &vk1) + n - p;
358            vk = &t1 % n;
359            // V(k'+1) = V(2k+2) = V(k+1)² - 2
360            let t1 = (&vk1 * &vk1) + &nm2;
361            vk1 = &t1 % n;
362        } else {
363            // k' = 2k
364            // V(k'+1) = V(2k+1) = V(k) V(k+1) - P
365            let t1 = (&vk * &vk1) + n - p;
366            vk1 = &t1 % n;
367            // V(k') = V(2k) = V(k)² - 2
368            let t1 = (&vk * &vk) + &nm2;
369            vk = &t1 % n;
370        }
371    }
372
373    // Now k=s, so vk = V(s). Check V(s) ≡ ±2 (mod n).
374    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        let mut t1 = &vk * p;
383        let mut t2 = &vk1 << 1;
384
385        if t1 < t2 {
386            core::mem::swap(&mut t1, &mut t2);
387        }
388
389        t1 -= t2;
390
391        if (t1 % n).is_zero() {
392            return true;
393        }
394    }
395
396    // Check V(2^t s) ≡ 0 mod n for some 0 ≤ t < r-1.
397    for _ in 0..r - 1 {
398        if vk.is_zero() {
399            return true;
400        }
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        if vk.to_u64() == Some(2) {
405            return false;
406        }
407
408        // k' = 2k
409        // V(k') = V(2k) = V(k)² - 2
410        let t1 = (&vk * &vk) - &*BIG_2;
411        vk = &t1 % n;
412    }
413
414    false
415}
416
417/// Checks if the i-th bit is set
418#[inline]
419fn is_bit_set(x: &BigUint, i: usize) -> bool {
420    get_bit(x, i) == 1
421}
422
423/// Returns the i-th bit.
424#[inline]
425fn get_bit(x: &BigUint, i: usize) -> u8 {
426    let j = i / big_digit::BITS;
427    // if is out of range of the set words, it is always false.
428    if i >= x.bits() {
429        return 0;
430    }
431
432    (x.get_limb(j) >> (i % big_digit::BITS) & 1) as u8
433}
434
435#[cfg(test)]
436mod 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}