-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathAlgebra.cc
98 lines (87 loc) · 1.55 KB
/
Algebra.cc
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
#include "Algebra.h"
int Algebra::mod(int a, size_t Zp)
{
if (a < 0)
{
return Zp - (-a) % Zp;
}
else
{
return a % Zp;
}
}
std::vector<int> Algebra::normalize(const std::vector<int>& vec, size_t Zp)
{
std::vector<int> res(vec);
for (auto& i : res)
i = mod(i, Zp);
return res;
}
int Algebra::randmod(std::function<int()> generator, size_t Zp)
{
return mod(generator(), Zp);
}
size_t Algebra::powmod(int a, size_t pow, size_t Zp)
{
size_t res = 1;
while (pow--)
{
res = mod(res * a, Zp);
}
return res;
}
size_t Algebra::gcd(size_t a, size_t b)
{
if (a < b)
std::swap(a, b);
if (b == 0)
return a;
if (b == 1)
return 1;
if (a == b)
return a;
while (b != 0)
{
auto r = a % b;
a = b;
b = r;
}
return a;
}
size_t Algebra::expanded_gcd(size_t a, size_t b, size_t Zp)
{
a = mod(a, Zp);
b = mod(b, Zp);
if (a == 1)
return b;
auto g = gcd(a, Zp);
if (g != 1)
{
if (b % g)
return -1;
if (g != 1)
{
a /= g;
b /= g;
Zp /= g;
}
}
std::array<std::array<int, 4>, 2> matrix = {{{0, Zp, 1, 0},{0, a, 0, 1}}};
while (matrix[1][1] != 1)
{
int q_i = matrix[0][1] / matrix[1][1]; // q_i = r_i-2 / r_i-1
std::array<int, 4> temp = {
q_i,
matrix[0][1] % matrix[1][1], // r_i = r_i-2 mod r_i-1
matrix[0][2] - q_i * matrix[1][2], // x_i = x_i-2 - q_i-1*x_i-1
matrix[0][3] - q_i * matrix[1][3] // y_i = y_i-2 - q_i-1*y_i-1
};
matrix[0] = matrix[1]; // shift up
matrix[1] = temp;
}
return mod(matrix[1][3] * b, Zp);
}
size_t Algebra::inverse_mod(size_t a, size_t Zp)
{
return expanded_gcd(a, 1, Zp);
}