-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathAlgorithm.cpp
More file actions
114 lines (90 loc) · 2.33 KB
/
Algorithm.cpp
File metadata and controls
114 lines (90 loc) · 2.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#include "include/IO.h"
#include "include/Algorithm.h"
#include "include/Converter.h"
#include "include/Random.h"
BigInt gcd(BigInt a, BigInt b)
{
BigInt r = 0;
a = abs(a);
b = abs(b);
if (a == 0 && b == 0 || b == 0)
{
io.writeLog("[gcd] gcd(0, 0) or gcd(a, 0) is undefined");
return r;
}
while ((a % b).isPositive()) {
r = a % b;
a = b;
b = r;
}
return b;
}
BigInt powMod(BigInt n, BigInt e, BigInt m)
{
BigInt res = 1;
n = abs(n);
e = abs(e);
while (e.isPositive()) {
if (e.isOdd())
res = (res * n) % m;
n = (n * n) % m;
e >>= 1;
}
return res;
}
tuple<BigInt, BigInt, BigInt> extendedEuclidean(BigInt a, BigInt b)
{
if (a == 0) {
return std::make_tuple(b, 0, 1);
}
BigInt gcd, x, y;
std::tie(gcd, x, y) = extendedEuclidean(b % a, a);
return std::make_tuple(gcd, (y - (b / a) * x), x);
}
BigInt inverseMod(BigInt a, BigInt m)
{
BigInt m0 = m, t, q;
BigInt x0 = 0, x1 = 1;
if (m == 1) return 1;
while (a > 1) {
q = a / m;
t = m, m = a % m, a = t;
t = x0, x0 = x1 - q * x0, x1 = t;
}
if (x1 < 0) x1 += m0;
return x1;
}
bool millerRabinTest(BigInt n, BigInt d)
{
//? Sinh số a ngẫu nhiên a trong nửa đoạn [2, n - 1)
BigInt a = random.next(2, n - 1);
//io.writeLog("[isPrime] random a for checking: " + converter.bigIntToBinaryStr(a));
//? Nếu a và n không nguyên tố cùng nhau thì là hợp số
if (gcd(a, n) != 1) {
io.writeLog("[isPrime] a and n is not relative prime, so n is composite!");
return false;
}
//? Tính x = a^d mod n
BigInt x = powMod(a, d, n);
//io.writeLog("[isPrime] a^d mod n: " + converter.bigIntToBinaryStr(x));
//? Nếu x = 1 hoặc x == n - 1 thì x không phải là cơ sở miller-rabin (miller-rabin witness) của n => không phải là hợp số
if (x == 1 || x == n - 1) {
//io.writeLog("[isPrime] a^d mod n is 1 or n - 1, so n is probably prime");
return true;
}
//? Kiểm tra các điều kiện của một số miller-rabin witness
while (d != n - 1)
{
x = (x * x) % n;
//io.writeLog("[isPrime] x^2 mod n: " + converter.bigIntToBinaryStr(x));
d <<= 1;
//io.writeLog("[isPrime] d: " + converter.bigIntToBinaryStr(d));
if (x == n - 1)
{
//io.writeLog("[isPrime] x == n - 1, so n is propably prime!");
return true;
}
}
//io.writeLog("[isPrime] a is a witness of n, so n is composite!");
return false;
}