1use 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
34const 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
71const 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
84const FLINT_D_BITS: u64 = 53;
86
87#[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#[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
101fn 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
117fn 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
133fn 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 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
168fn 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 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
203fn 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
218pub(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
238fn 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
248fn 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
271fn 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
288fn is_probable_prime_fibonacci(n: u64) -> bool {
291 if i64::wrapping_from(n).le_abs(&3) {
292 return n >= 2;
293 }
294 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
308fn 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
325fn 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
342fn 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
401fn 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
422fn 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
443fn 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
480fn is_strong_probable_prime_preinverted_float(n: u64, inverse: f64, mut a: u64, d: u64) -> bool {
483 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
504fn 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
528fn 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 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
548fn 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 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 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 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 fn is_prime(&self) -> bool {
625 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 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 fn is_prime(&self) -> bool {
682 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 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 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 fn is_prime(&self) -> bool {
765 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 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 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 #[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}