malachite_base/num/factorization/
is_prime.rs

1// Copyright © 2025 Mikhail Hogrefe
2//
3// Uses code adopted from the FLINT Library.
4//
5//      Copyright © 2008 Peter Shrimpton
6//
7//      Copyright © 2009 Tom Boothby
8//
9//      Copyright © 2009, 2010, 2013, 2015, 2016 William Hart
10//
11//      Copyright © 2010 Fredrik Johansson
12//
13//      Copyright © 2014 Dana Jacobsen
14//
15//      Copyright © 2023 Mathieu Gouttenoire
16//
17// This file is part of Malachite.
18//
19// Malachite is free software: you can redistribute it and/or modify it under the terms of the GNU
20// Lesser General Public License (LGPL) as published by the Free Software Foundation; either version
21// 3 of the License, or (at your option) any later version. See <https://www.gnu.org/licenses/>.
22
23use crate::num::arithmetic::mod_pow::mul_mod_helper;
24use crate::num::arithmetic::traits::{
25    Gcd, JacobiSymbol, ModAdd, ModInverse, ModMulPrecomputed, ModMulPrecomputedAssign, ModSub,
26    Parity, PowerOf2, WrappingAddAssign, WrappingNegAssign, XMulYToZZ, XXAddYYToZZ,
27};
28use crate::num::basic::integers::{PrimitiveInt, USIZE_IS_U32};
29use crate::num::comparison::traits::PartialOrdAbs;
30use crate::num::conversion::traits::WrappingFrom;
31use crate::num::factorization::traits::IsPrime;
32use crate::num::logic::traits::{BitAccess, LeadingZeros, SignificantBits, TrailingZeros};
33
34// This is FLINT_ODD_PRIME_LOOKUP when FLINT64 is true, from ulong_extras/is_oddprime.c, FLINT
35// 3.1.2.
36const ODD_PRIME_LOOKUP_U64: [u64; 32] = [
37    0x816d129a64b4cb6e,
38    0x2196820d864a4c32,
39    0xa48961205a0434c9,
40    0x4a2882d129861144,
41    0x834992132424030,
42    0x148a48844225064b,
43    0xb40b4086c304205,
44    0x65048928125108a0,
45    0x80124496804c3098,
46    0xc02104c941124221,
47    0x804490000982d32,
48    0x220825b082689681,
49    0x9004265940a28948,
50    0x6900924430434006,
51    0x12410da408088210,
52    0x86122d22400c060,
53    0x110d301821b0484,
54    0x14916022c044a002,
55    0x92094d204a6400c,
56    0x4ca2100800522094,
57    0xa48b081051018200,
58    0x34c108144309a25,
59    0x2084490880522502,
60    0x241140a218003250,
61    0xa41a00101840128,
62    0x2926000836004512,
63    0x10100480c0618283,
64    0xc20c26584822006d,
65    0x4520582024894810,
66    0x10c0250219002488,
67    0x802832ca01140868,
68    0x60901300264b0400,
69];
70
71// This is FLINT_ODD_PRIME_LOOKUP when FLINT64 is false, from ulong_extras/is_oddprime.c, FLINT
72// 3.1.2.
73const ODD_PRIME_LOOKUP_U32: [u32; 64] = [
74    0x64b4cb6e, 0x816d129a, 0x864a4c32, 0x2196820d, 0x5a0434c9, 0xa4896120, 0x29861144, 0x4a2882d1,
75    0x32424030, 0x8349921, 0x4225064b, 0x148a4884, 0x6c304205, 0xb40b408, 0x125108a0, 0x65048928,
76    0x804c3098, 0x80124496, 0x41124221, 0xc02104c9, 0x982d32, 0x8044900, 0x82689681, 0x220825b0,
77    0x40a28948, 0x90042659, 0x30434006, 0x69009244, 0x8088210, 0x12410da4, 0x2400c060, 0x86122d2,
78    0x821b0484, 0x110d301, 0xc044a002, 0x14916022, 0x4a6400c, 0x92094d2, 0x522094, 0x4ca21008,
79    0x51018200, 0xa48b0810, 0x44309a25, 0x34c1081, 0x80522502, 0x20844908, 0x18003250, 0x241140a2,
80    0x1840128, 0xa41a001, 0x36004512, 0x29260008, 0xc0618283, 0x10100480, 0x4822006d, 0xc20c2658,
81    0x24894810, 0x45205820, 0x19002488, 0x10c02502, 0x1140868, 0x802832ca, 0x264b0400, 0x60901300,
82];
83
84// This is FLINT_D_BITS when FLINT64 is true, from flint.h, FLINT 3.1.2.
85const FLINT_D_BITS: u64 = 53;
86
87// This is n_is_oddprime_small_u64 when FLINT64 is true, from ulong_extras/is_oddprime.c, FLINT
88// 3.1.2.
89#[inline]
90fn is_odd_prime_small_u64(n: u64) -> bool {
91    ODD_PRIME_LOOKUP_U64[(n >> 7) as usize].get_bit((n >> 1) & u64::WIDTH_MASK)
92}
93
94// This is n_is_oddprime_small_u64 when FLINT64 is false, from ulong_extras/is_oddprime.c, FLINT
95// 3.1.2.
96#[inline]
97fn is_odd_prime_small_u32(n: u32) -> bool {
98    ODD_PRIME_LOOKUP_U32[(n >> 6) as usize].get_bit(u64::from(n >> 1) & u32::WIDTH_MASK)
99}
100
101// This is n_mod2_preinv when FLINT64 is false, from ulong_extras/mod2_preinv.c, FLINT 3.1.2.
102fn mod_preinverted_u32(a: u32, mut n: u32, inverse: u32) -> u32 {
103    assert_ne!(n, 0);
104    let norm = LeadingZeros::leading_zeros(n);
105    n <<= norm;
106    let u1 = a >> (u32::WIDTH - norm);
107    let u0 = a << norm;
108    let (mut q1, mut q0) = u32::x_mul_y_to_zz(inverse, u1);
109    (q1, q0) = u32::xx_add_yy_to_zz(q1, q0, u1, u0);
110    let mut r = u0 - (q1 + 1) * n;
111    if r > q0 {
112        r += n;
113    }
114    if r < n { r >> norm } else { (r - n) >> norm }
115}
116
117// This is n_mod2_preinv when FLINT64 is true, from ulong_extras/mod2_preinv.c, FLINT 3.1.2.
118fn mod_preinverted_u64(a: u64, mut n: u64, inverse: u64) -> u64 {
119    assert_ne!(n, 0);
120    let norm = LeadingZeros::leading_zeros(n);
121    n <<= norm;
122    let u1 = a >> (u64::WIDTH - norm);
123    let u0 = a << norm;
124    let (mut q1, mut q0) = u64::x_mul_y_to_zz(inverse, u1);
125    (q1, q0) = u64::xx_add_yy_to_zz(q1, q0, u1, u0);
126    let mut r = u0 - (q1 + 1) * n;
127    if r > q0 {
128        r += n;
129    }
130    if r < n { r >> norm } else { (r - n) >> norm }
131}
132
133// This is n_powmod2_ui_preinv when FLINT64 is false, from ulong_extras/powmod2_ui_preinv.c, FLINT
134// 3.1.2.
135fn mod_pow_preinverted_u32(mut a: u32, mut exp: u32, mut n: u32, inverse: u32) -> u32 {
136    assert_ne!(n, 0);
137    if exp == 0 {
138        // anything modulo 1 is 0
139        return u32::from(n != 1);
140    }
141    if a == 0 {
142        return 0;
143    }
144    if a >= n {
145        a = mod_preinverted_u32(a, n, inverse);
146    }
147    let norm = LeadingZeros::leading_zeros(n);
148    a <<= norm;
149    n <<= norm;
150    while exp.even() {
151        a = mul_mod_helper::<u32, u64>(a, a, n, inverse, norm);
152        exp >>= 1;
153    }
154    let mut x = a;
155    loop {
156        exp >>= 1;
157        if exp == 0 {
158            break;
159        }
160        a = mul_mod_helper::<u32, u64>(a, a, n, inverse, norm);
161        if exp.odd() {
162            x = mul_mod_helper::<u32, u64>(x, a, n, inverse, norm);
163        }
164    }
165    x >> norm
166}
167
168// This is n_powmod2_ui_preinv when FLINT64 is true, from ulong_extras/powmod2_ui_preinv.c, FLINT
169// 3.1.2.
170fn mod_pow_preinverted_u64(mut a: u64, mut exp: u64, mut n: u64, inverse: u64) -> u64 {
171    assert_ne!(n, 0);
172    if exp == 0 {
173        // anything modulo 1 is 0
174        return u64::from(n != 1);
175    }
176    if a == 0 {
177        return 0;
178    }
179    if a >= n {
180        a = mod_preinverted_u64(a, n, inverse);
181    }
182    let norm = LeadingZeros::leading_zeros(n);
183    a <<= norm;
184    n <<= norm;
185    while exp.even() {
186        a = mul_mod_helper::<u64, u128>(a, a, n, inverse, norm);
187        exp >>= 1;
188    }
189    let mut x = a;
190    loop {
191        exp >>= 1;
192        if exp == 0 {
193            break;
194        }
195        a = mul_mod_helper::<u64, u128>(a, a, n, inverse, norm);
196        if exp.odd() {
197            x = mul_mod_helper::<u64, u128>(x, a, n, inverse, norm);
198        }
199    }
200    x >> norm
201}
202
203// This is n_mulmod_precomp when FLINT64 is true, from ulong_extras/mulmod_precomp.c, FLINT 3.1.2.
204fn mod_mul_preinverted_float(a: u64, b: u64, n: u64, inverse: f64) -> u64 {
205    let q = ((a as f64) * (b as f64) * inverse) as u64;
206    let mut r = (a.wrapping_mul(b)).wrapping_sub(q.wrapping_mul(n));
207    if r.get_highest_bit() {
208        r.wrapping_add_assign(n);
209        if r.get_highest_bit() {
210            return r.wrapping_add(n);
211        }
212    } else if r >= n {
213        return r - n;
214    }
215    r
216}
217
218// This is n_powmod_ui_precomp when FLINT64 is true, from ulong_extras/powmod_precomp.c, FLINT
219// 3.1.2.
220pub(crate) fn mod_pow_preinverted_float(a: u64, mut exp: u64, n: u64, inverse: f64) -> u64 {
221    if n == 1 {
222        return 0;
223    }
224    let mut x = 1;
225    let mut y = a;
226    while exp != 0 {
227        if exp.odd() {
228            x = mod_mul_preinverted_float(x, y, n, inverse);
229        }
230        exp >>= 1;
231        if exp != 0 {
232            y = mod_mul_preinverted_float(y, y, n, inverse);
233        }
234    }
235    x
236}
237
238// This is n_is_probabprime_fermat when FLINT64 is true, from ulong_extras/is_probabprime.c, FLINT
239// 3.1.2.
240fn is_probable_prime_fermat(n: u64, i: u64) -> bool {
241    (if n.significant_bits() <= FLINT_D_BITS {
242        mod_pow_preinverted_float(i, n - 1, n, 1.0 / (n as f64))
243    } else {
244        mod_pow_preinverted_u64(i, n - 1, n, u64::precompute_mod_mul_data(&n))
245    }) == 1
246}
247
248// This is fchain_precomp when FLINT64 is true, from ulong_extras/is_probabprime.c, FLINT 3.1.2.
249fn fibonacci_chain_precomputed(m: u64, n: u64, inverse: f64) -> (u64, u64) {
250    let mut x = 2;
251    let mut y = n - 3;
252    let mut power = u64::power_of_2(m.significant_bits() - 1);
253    while power != 0 {
254        let xy = mod_mul_preinverted_float(x, y, n, inverse).mod_add(3, n);
255        (x, y) = if m & power != 0 {
256            (
257                xy,
258                mod_mul_preinverted_float(y, y, n, inverse).mod_sub(2, n),
259            )
260        } else {
261            (
262                mod_mul_preinverted_float(x, x, n, inverse).mod_sub(2, n),
263                xy,
264            )
265        };
266        power >>= 1;
267    }
268    (x, y)
269}
270
271// This is fchain2_preinv when FLINT64 is true, from ulong_extras/is_probabprime.c, FLINT 3.1.2.
272fn fibonacci_chain_preinvert(m: u64, n: u64, ninv: u64) -> (u64, u64) {
273    let mut x = 2;
274    let mut y = n - 3;
275    let mut power = u64::power_of_2(m.significant_bits() - 1);
276    while power != 0 {
277        let xy = x.mod_mul_precomputed(y, n, &ninv).mod_add(3, n);
278        (x, y) = if m & power != 0 {
279            (xy, y.mod_mul_precomputed(y, n, &ninv).mod_sub(2, n))
280        } else {
281            (x.mod_mul_precomputed(x, n, &ninv).mod_sub(2, n), xy)
282        };
283        power >>= 1;
284    }
285    (x, y)
286}
287
288// This is n_is_probabprime_fibonacci when FLINT64 is true, from ulong_extras/is_probabprime.c,
289// FLINT 3.1.2.
290fn is_probable_prime_fibonacci(n: u64) -> bool {
291    if i64::wrapping_from(n).le_abs(&3) {
292        return n >= 2;
293    }
294    // cannot overflow as (5 / n) = 0 for n = 2 ^ 64 - 1
295    let m = n.wrapping_sub(u64::wrapping_from(5.jacobi_symbol(n))) >> 1;
296    if n.significant_bits() <= FLINT_D_BITS {
297        let inverse = 1.0 / (n as f64);
298        let (x, y) = fibonacci_chain_precomputed(m, n, inverse);
299        mod_mul_preinverted_float(n - 3, x, n, inverse)
300            == mod_mul_preinverted_float(2, y, n, inverse)
301    } else {
302        let inverse = u64::precompute_mod_mul_data(&n);
303        let (x, y) = fibonacci_chain_preinvert(m, n, inverse);
304        (n - 3).mod_mul_precomputed(x, n, &inverse) == 2.mod_mul_precomputed(y, n, &inverse)
305    }
306}
307
308// This is lchain_precomp when FLINT64 is true, from ulong_extras/is_probabprime.c, FLINT 3.1.2.
309fn lucas_chain_precomputed(m: u64, a: u64, n: u64, npre: f64) -> (u64, u64) {
310    let mut x = 2;
311    let mut y = n - 3;
312    let mut power = u64::power_of_2(m.significant_bits() - 1);
313    while power != 0 {
314        let xy = mod_mul_preinverted_float(x, y, n, npre).mod_sub(a, n);
315        (x, y) = if m & power != 0 {
316            (xy, mod_mul_preinverted_float(y, y, n, npre).mod_sub(2, n))
317        } else {
318            (mod_mul_preinverted_float(x, x, n, npre).mod_sub(2, n), xy)
319        };
320        power >>= 1;
321    }
322    (x, y)
323}
324
325// This is lchain2_preinv when FLINT64 is true, from ulong_extras/is_probabprime.c, FLINT 3.1.2.
326fn lucas_chain_preinvert(m: u64, a: u64, n: u64, ninv: u64) -> (u64, u64) {
327    let mut x = 2;
328    let mut y = a;
329    let mut power = u64::power_of_2(m.significant_bits() - 1);
330    while power != 0 {
331        let xy = x.mod_mul_precomputed(y, n, &ninv).mod_sub(a, n);
332        (x, y) = if m & power != 0 {
333            (xy, y.mod_mul_precomputed(y, n, &ninv).mod_sub(2, n))
334        } else {
335            (x.mod_mul_precomputed(x, n, &ninv).mod_sub(2, n), xy)
336        };
337        power >>= 1;
338    }
339    (x, y)
340}
341
342// This is n_is_probabprime_lucas when FLINT64 is true, from ulong_extras/is_probabprime.c, FLINT
343// 3.1.2, where n is odd and greater than 52, and only true or false is returned, rather than 0, 1,
344// or -1.
345fn is_probable_prime_lucas(n: u64) -> bool {
346    let mut d = 0u64;
347    if i64::wrapping_from(n).le_abs(&2) {
348        return n == 2;
349    }
350    let mut neg_d = false;
351    let mut j = 0;
352    for i in 0..100 {
353        d = 5 + (i << 1);
354        neg_d = false;
355        if d.gcd(n % d) == 1 {
356            if i.odd() {
357                neg_d = true;
358            }
359            let jacobi = if neg_d {
360                (-i128::from(d)).jacobi_symbol(i128::from(n))
361            } else {
362                d.jacobi_symbol(n)
363            };
364            if jacobi == -1 {
365                break;
366            }
367        } else if n != d {
368            return false;
369        }
370        j += 1;
371    }
372    if j == 100 {
373        return true;
374    }
375    if neg_d {
376        d.wrapping_neg_assign();
377    }
378    let mut q = u64::wrapping_from(1i64.wrapping_sub(i64::wrapping_from(d)) / 4);
379    if q.get_highest_bit() {
380        q.wrapping_add_assign(n);
381    }
382    let a = q.mod_inverse(n).unwrap().mod_sub(2, n);
383    let (left, right) = if n <= FLINT_D_BITS {
384        let inverse = 1.0 / (n as f64);
385        let (x, y) = lucas_chain_precomputed(n + 1, a, n, inverse);
386        (
387            mod_mul_preinverted_float(a, x, n, inverse),
388            mod_mul_preinverted_float(2, y, n, inverse),
389        )
390    } else {
391        let inverse = u64::precompute_mod_mul_data(&n);
392        let (x, y) = lucas_chain_preinvert(n + 1, a, n, inverse);
393        (
394            a.mod_mul_precomputed(x, n, &inverse),
395            2.mod_mul_precomputed(y, n, &inverse),
396        )
397    };
398    left == right
399}
400
401// This is n_is_strong_probabprime2_preinv when FLINT64 is false, from
402// ulong_extras/is_strong_probabprime2_preinv.c, FLINT 3.1.2.
403fn is_strong_probable_prime_preinverted_u32(n: u32, inverse: u32, a: u32, d: u32) -> bool {
404    assert!(a < n);
405    let nm1 = n - 1;
406    if a <= 1 || a == nm1 {
407        return true;
408    }
409    let mut t = d;
410    let mut y = mod_pow_preinverted_u32(a, t, n, inverse);
411    if y == 1 {
412        return true;
413    }
414    t <<= 1;
415    while t != nm1 && y != nm1 {
416        y.mod_mul_precomputed_assign(y, n, &inverse);
417        t <<= 1;
418    }
419    y == nm1
420}
421
422// This is n_is_strong_probabprime2_preinv when FLINT64 is true, from
423// ulong_extras/is_strong_probabprime2_preinv.c, FLINT 3.1.2.
424fn is_strong_probable_prime_preinverted_u64(n: u64, inverse: u64, a: u64, d: u64) -> bool {
425    assert!(a < n);
426    let nm1 = n - 1;
427    if a <= 1 || a == nm1 {
428        return true;
429    }
430    let mut t = d;
431    let mut y = mod_pow_preinverted_u64(a, t, n, inverse);
432    if y == 1 {
433        return true;
434    }
435    t <<= 1;
436    while t != nm1 && y != nm1 {
437        y.mod_mul_precomputed_assign(y, n, &inverse);
438        t <<= 1;
439    }
440    y == nm1
441}
442
443// This is n_mod2_precomp when FLINT64 is true, from ulong_extras/mod2_precomp.c, FLINT 3.1.2.
444fn mod_preinverted_float(a: u64, n: u64, inverse: f64) -> u64 {
445    if a < n {
446        return a;
447    }
448    let ni = i64::wrapping_from(n);
449    if ni < 0 {
450        return a.wrapping_sub(n);
451    }
452    let (mut q, mut r) = if n == 1 {
453        (a, 0)
454    } else {
455        let q = ((a as f64) * inverse) as u64;
456        (
457            q,
458            i64::wrapping_from(a).wrapping_sub(i64::wrapping_from(q.wrapping_mul(n))),
459        )
460    };
461    if r < ni.wrapping_neg() {
462        q -= ((r.wrapping_neg() as f64) * inverse) as u64;
463    } else if r >= ni {
464        q += ((r as f64) * inverse) as u64;
465    } else if r < 0 {
466        return u64::wrapping_from(r + ni);
467    } else {
468        return u64::wrapping_from(r);
469    }
470    r = i64::wrapping_from(a) - i64::wrapping_from(q.wrapping_mul(n));
471    u64::wrapping_from(if r >= ni {
472        r.wrapping_sub(ni)
473    } else if r < 0 {
474        r.wrapping_add(ni)
475    } else {
476        r
477    })
478}
479
480// This is n_is_strong_probabprime_precomp when FLINT64 is true, from
481// ulong_extras/is_strong_probabprime_precomp.c, FLINT 3.1.2.
482fn is_strong_probable_prime_preinverted_float(n: u64, inverse: f64, mut a: u64, d: u64) -> bool {
483    // Map large base to range 2 ... n - 1
484    if a >= n {
485        a = mod_preinverted_float(a, n, inverse);
486    }
487    let nm1 = n - 1;
488    if a <= 1 || a == nm1 {
489        return true;
490    }
491    let mut t = d;
492    let mut y = mod_pow_preinverted_float(a, t, n, inverse);
493    if y == 1 {
494        return true;
495    }
496    t <<= 1;
497    while t != nm1 && y != nm1 {
498        y = mod_mul_preinverted_float(y, y, n, inverse);
499        t <<= 1;
500    }
501    y == nm1
502}
503
504// This is n_is_probabprime_BPSW when FLINT64 is true, from ulong_extras/is_probabprime.c, FLINT
505// 3.1.2, where n is odd and greater than 1.
506fn is_probable_prime_bpsw(n: u64) -> bool {
507    let nm10 = n % 10;
508    if nm10 == 3 || nm10 == 7 {
509        return is_probable_prime_fermat(n, 2) && is_probable_prime_fibonacci(n);
510    }
511    let mut d = n - 1;
512    while d.even() {
513        d >>= 1;
514    }
515    let result = if n.significant_bits() <= FLINT_D_BITS {
516        is_strong_probable_prime_preinverted_float(n, 1.0 / (n as f64), 2, d)
517    } else {
518        is_strong_probable_prime_preinverted_u64(n, u64::precompute_mod_mul_data(&n), 2, d)
519    };
520    if !result {
521        return false;
522    }
523    is_probable_prime_lucas(n)
524}
525
526const FLINT_ODDPRIME_SMALL_CUTOFF: u32 = 4096;
527
528// This is n_is_probabprime when FLINT64 is false, from ulong_extras/is_probabprime.c, FLINT 3.1.2,
529// assuming n is odd and greater than 2.
530fn is_probable_prime_u32(n: u32) -> bool {
531    if n < FLINT_ODDPRIME_SMALL_CUTOFF {
532        return is_odd_prime_small_u32(n);
533    }
534    let mut d = n - 1;
535    d >>= TrailingZeros::trailing_zeros(d);
536    // For 32-bit, just the 2-base or 3-base Miller-Rabin is enough.
537    let inverse = u32::precompute_mod_mul_data(&n);
538    if n < 9080191 {
539        is_strong_probable_prime_preinverted_u32(n, inverse, 31, d)
540            && is_strong_probable_prime_preinverted_u32(n, inverse, 73, d)
541    } else {
542        is_strong_probable_prime_preinverted_u32(n, inverse, 2, d)
543            && is_strong_probable_prime_preinverted_u32(n, inverse, 7, d)
544            && is_strong_probable_prime_preinverted_u32(n, inverse, 61, d)
545    }
546}
547
548// This is n_is_probabprime when FLINT64 is true, from ulong_extras/is_probabprime.c, FLINT 3.1.2,
549// assuming n is odd and greater than 2.
550fn is_probable_prime_u64(n: u64) -> bool {
551    if n < u64::from(FLINT_ODDPRIME_SMALL_CUTOFF) {
552        return is_odd_prime_small_u64(n);
553    } else if n >= 1050535501 {
554        // Avoid the unnecessary inverse
555        return is_probable_prime_bpsw(n);
556    }
557    let mut d = n - 1;
558    d >>= TrailingZeros::trailing_zeros(d);
559    let inverse = 1.0 / (n as f64);
560    // For 64-bit, BPSW seems to be a little bit faster than 3 bases.
561    if n < 341531 {
562        is_strong_probable_prime_preinverted_float(n, inverse, 9345883071009581737, d)
563    } else {
564        is_strong_probable_prime_preinverted_float(n, inverse, 336781006125, d)
565            && is_strong_probable_prime_preinverted_float(n, inverse, 9639812373923155, d)
566    }
567}
568
569impl IsPrime for u8 {
570    /// Tests whether a `u8` is prime.
571    ///
572    /// This implementation just does a few divisibility checks.
573    ///
574    /// If you want to generate many small primes, try using
575    /// [`u8::primes`][crate::num::factorization::traits::Primes::primes] instead.
576    ///
577    /// # Worst-case complexity
578    /// Constant time and additional memory.
579    ///
580    /// # Examples
581    /// ```
582    /// use malachite_base::num::factorization::traits::IsPrime;
583    ///
584    /// assert_eq!(5u8.is_prime(), true);
585    /// assert_eq!(6u8.is_prime(), false);
586    /// ```
587    fn is_prime(&self) -> bool {
588        let n = *self;
589        if n < 11 {
590            n == 2 || n == 3 || n == 5 || n == 7
591        } else if n % 2 == 0 || n % 3 == 0 || n % 5 == 0 || n % 7 == 0 {
592            false
593        } else {
594            n < 121 || n % 11 != 0 && n % 13 != 0
595        }
596    }
597}
598
599impl IsPrime for u16 {
600    /// Tests whether a `u16` is prime.
601    ///
602    /// This implementation does a few divisibility checks, then performs strong probable prime
603    /// tests with bases 31 and 73, which is enough to prove primality for any integer less than
604    /// $2^{16}$.
605    ///
606    /// If you want to generate many small primes, try using
607    /// [`u16::primes`][crate::num::factorization::traits::Primes::primes] instead.
608    ///
609    /// # Worst-case complexity
610    /// $T(n) = O(n)$
611    ///
612    /// $M(n) = O(1)$
613    ///
614    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
615    ///
616    /// # Examples
617    /// ```
618    /// use malachite_base::num::factorization::traits::IsPrime;
619    ///
620    /// assert_eq!(5u16.is_prime(), true);
621    /// assert_eq!(6u16.is_prime(), false);
622    /// assert_eq!(65521u16.is_prime(), true);
623    /// ```
624    fn is_prime(&self) -> bool {
625        // Flint's "BPSW" (which Malachite's code is based on) checked against Feitsma and Galway's
626        // database [1, 2] up to 2^64 by Dana Jacobsen.
627        // - [1] http://www.janfeitsma.nl/math/psp2/database
628        // - [2] http://www.cecm.sfu.ca/Pseudoprimes/index-2-to-64.html
629        let n = *self;
630        if n < 11 {
631            n == 2 || n == 3 || n == 5 || n == 7
632        } else if n % 2 == 0 || n % 3 == 0 || n % 5 == 0 || n % 7 == 0 {
633            false
634        } else if n < 121 {
635            // 11*11
636            true
637        } else if n % 11 == 0
638            || n % 13 == 0
639            || n % 17 == 0
640            || n % 19 == 0
641            || n % 23 == 0
642            || n % 29 == 0
643            || n % 31 == 0
644            || n % 37 == 0
645            || n % 41 == 0
646            || n % 43 == 0
647            || n % 47 == 0
648            || n % 53 == 0
649        {
650            false
651        } else {
652            n < 3481 || is_probable_prime_u32(u32::from(n))
653        }
654    }
655}
656
657impl IsPrime for u32 {
658    /// Tests whether a `u32` is prime.
659    ///
660    /// This implementation does a few divisibility checks, then performs a few strong probable
661    /// prime tests, which is enough to prove primality for any integer less than $2^{32}$.
662    ///
663    /// If you want to generate many small primes, try using
664    /// [`u32::primes`][crate::num::factorization::traits::Primes::primes] instead.
665    ///
666    /// # Worst-case complexity
667    /// $T(n) = O(n)$
668    ///
669    /// $M(n) = O(1)$
670    ///
671    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
672    ///
673    /// # Examples
674    /// ```
675    /// use malachite_base::num::factorization::traits::IsPrime;
676    ///
677    /// assert_eq!(5u32.is_prime(), true);
678    /// assert_eq!(6u32.is_prime(), false);
679    /// assert_eq!(4294967291u32.is_prime(), true);
680    /// ```
681    fn is_prime(&self) -> bool {
682        // Flint's "BPSW" (which Malachite's code is based on) checked against Feitsma and Galway's
683        // database [1, 2] up to 2^64 by Dana Jacobsen.
684        // - [1] http://www.janfeitsma.nl/math/psp2/database
685        // - [2] http://www.cecm.sfu.ca/Pseudoprimes/index-2-to-64.html
686        let n = *self;
687        if n < 11 {
688            n == 2 || n == 3 || n == 5 || n == 7
689        } else if n % 2 == 0 || n % 3 == 0 || n % 5 == 0 || n % 7 == 0 {
690            false
691        } else if n < 121 {
692            // 11*11
693            true
694        } else if n % 11 == 0
695            || n % 13 == 0
696            || n % 17 == 0
697            || n % 19 == 0
698            || n % 23 == 0
699            || n % 29 == 0
700            || n % 31 == 0
701            || n % 37 == 0
702            || n % 41 == 0
703            || n % 43 == 0
704            || n % 47 == 0
705            || n % 53 == 0
706        {
707            false
708        } else if n < 3481 {
709            // 59*59
710            true
711        } else if n > 1000000
712            && (n % 59 == 0
713                || n % 61 == 0
714                || n % 67 == 0
715                || n % 71 == 0
716                || n % 73 == 0
717                || n % 79 == 0
718                || n % 83 == 0
719                || n % 89 == 0
720                || n % 97 == 0
721                || n % 101 == 0
722                || n % 103 == 0
723                || n % 107 == 0
724                || n % 109 == 0
725                || n % 113 == 0
726                || n % 127 == 0
727                || n % 131 == 0
728                || n % 137 == 0
729                || n % 139 == 0
730                || n % 149 == 0)
731        {
732            false
733        } else {
734            is_probable_prime_u32(n)
735        }
736    }
737}
738
739impl IsPrime for u64 {
740    /// Tests whether a `u64` is prime.
741    ///
742    /// This implementation first does a few divisibility checks. Then, depending on the input, it
743    /// either runs a few strong probable prime tests or the Baillie–PSW test. This is enough to
744    /// prove primality for any integer less than $2^{64}$.
745    ///
746    /// If you want to generate many small primes, try using
747    /// [`u64::primes`][crate::num::factorization::traits::Primes::primes] instead.
748    ///
749    /// # Worst-case complexity
750    /// $T(n) = O(n)$
751    ///
752    /// $M(n) = O(1)$
753    ///
754    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
755    ///
756    /// # Examples
757    /// ```
758    /// use malachite_base::num::factorization::traits::IsPrime;
759    ///
760    /// assert_eq!(5u64.is_prime(), true);
761    /// assert_eq!(6u64.is_prime(), false);
762    /// assert_eq!(5509785649208481923u64.is_prime(), true);
763    /// ```
764    fn is_prime(&self) -> bool {
765        // Flint's "BPSW" (which Malachite's code is based on) checked against Feitsma and Galway's
766        // database [1, 2] up to 2^64 by Dana Jacobsen.
767        // - [1] http://www.janfeitsma.nl/math/psp2/database
768        // - [2] http://www.cecm.sfu.ca/Pseudoprimes/index-2-to-64.html
769        let n = *self;
770        if n < 11 {
771            n == 2 || n == 3 || n == 5 || n == 7
772        } else if n % 2 == 0 || n % 3 == 0 || n % 5 == 0 || n % 7 == 0 {
773            false
774        } else if n < 121 {
775            // 11*11
776            true
777        } else if n % 11 == 0
778            || n % 13 == 0
779            || n % 17 == 0
780            || n % 19 == 0
781            || n % 23 == 0
782            || n % 29 == 0
783            || n % 31 == 0
784            || n % 37 == 0
785            || n % 41 == 0
786            || n % 43 == 0
787            || n % 47 == 0
788            || n % 53 == 0
789        {
790            false
791        } else if n < 3481 {
792            // 59*59
793            true
794        } else if n > 1000000
795            && (n % 59 == 0
796                || n % 61 == 0
797                || n % 67 == 0
798                || n % 71 == 0
799                || n % 73 == 0
800                || n % 79 == 0
801                || n % 83 == 0
802                || n % 89 == 0
803                || n % 97 == 0
804                || n % 101 == 0
805                || n % 103 == 0
806                || n % 107 == 0
807                || n % 109 == 0
808                || n % 113 == 0
809                || n % 127 == 0
810                || n % 131 == 0
811                || n % 137 == 0
812                || n % 139 == 0
813                || n % 149 == 0)
814        {
815            false
816        } else {
817            is_probable_prime_u64(n)
818        }
819    }
820}
821
822impl IsPrime for usize {
823    /// Tests whether a `usize` is prime.
824    ///
825    /// This implementation first does a few divisibility checks. Then, depending on the input, it
826    /// either runs a few strong probable prime tests or the Baillie–PSW test. This is enough to
827    /// prove primality for any integer that fits in a `usize`.
828    ///
829    /// If you want to generate many small primes, try using
830    /// [`usize::primes`][crate::num::factorization::traits::Primes::primes] instead.
831    ///
832    /// # Worst-case complexity
833    /// $T(n) = O(n)$
834    ///
835    /// $M(n) = O(1)$
836    ///
837    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
838    ///
839    /// # Examples
840    /// ```
841    /// use malachite_base::num::factorization::traits::IsPrime;
842    ///
843    /// assert_eq!(5usize.is_prime(), true);
844    /// assert_eq!(6usize.is_prime(), false);
845    /// assert_eq!(4294967291usize.is_prime(), true);
846    /// ```
847    #[inline]
848    fn is_prime(&self) -> bool {
849        if USIZE_IS_U32 {
850            u32::wrapping_from(*self).is_prime()
851        } else {
852            u64::wrapping_from(*self).is_prime()
853        }
854    }
855}