competitive_library/math/
miller_rabin.rs1use crate::math::mod_pow::modpow;
2use crate::other::xorshift::XorShift;
3
4pub fn is_prime(n: i64) -> bool {
5 if n == 2 || n == 3 {
6 return true;
7 } else if n == 1 || (n > 2 && n & 1 == 0) {
8 return false;
9 }
10
11 let (mut s, mut t) = (0, n - 1);
12
13 while t & 1 == 0 {
14 s += 1;
15 t >>= 1;
16 }
17
18 let r = {
19 let mut r = XorShift::<u64>::new().next().unwrap() as i64 % (n - 3);
20 r += 2;
21 r
22 };
23
24 if modpow(r, t, n) == 1 {
25 return true;
26 }
27
28 for i in 0..s {
29 if modpow(r, 2_i64.pow(i) * t, n) == n - 1 {
30 return true;
31 }
32 }
33
34 false
35}
36
37#[cfg(test)]
38mod tests {
39
40 use super::*;
41 #[test]
42 fn test_miller_rabin() {
43 let v = vec![
44 (1, false),
45 (2, true),
46 (3, true),
47 (4, false),
48 (5, true),
49 (6, false),
50 (7, true),
51 (8, false),
52 (9, false),
53 (10, false),
54 (11, true),
55 (1_000_000_007, true),
56 (8191, true),
57 (131_071, true),
58 (524_287, true),
59 (6_700_417, true),
60 (2_147_483_647, true),
61 (67_280_421_310_721, true),
62 (67_280_421_310_722, false),
63 (100_000_000_000_000, false),
64 (68_718_297_093, false), ];
66 for (i, ans) in v {
67 assert_eq!(is_prime(i), ans, "testing {}", i);
68 }
69 }
70 #[test]
71 fn test_miller_rabin_loop() {
72 for _ in 0..100 {
73 test_miller_rabin();
74 }
75 }
76}