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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190 | class Galois:
"""
This class contain the Galois Field (Finite Field)
Attributes:
q (Integer): it's the number of the GF
operation (Function): Function for generating the group
"""
def __init__(self, q, operation):
self._q = q
self._operation = operation
self._add = [[0 for x in range(q)] for y in range(q)]
# TODO: May do we do a deep copy between all groups ?
self._div = [[0 for x in range(q)] for y in range(q)]
self._mul = [[0 for x in range(q)] for y in range(q)]
self._sub = [[0 for x in range(q)] for y in range(q)]
self._primitiveRoot = list()
def primitiveRoot(self):
"""
In this function, we going to find the primitive root modulo n of the galois field
Returns:
Return the list of primitive root of the GF(q)
"""
for x in range(2, self._q):
z = list()
for entry in range(1, self._q):
res = self._operation(x, entry, self._q)
if res not in z:
z.append(res)
if self.isPrimitiveRoot(z, self._q - 1):
if x not in self._primitiveRoot: # It's dirty, need to find why we have duplicate entry
self._primitiveRoot.append(x)
return z
def getPrimitiveRoot(self):
"""
Return the list of primitives root
Returns:
Return the primitive root
"""
return self._primitiveRoot
def isPrimitiveRoot(self, z, length):
"""
Check if z is a primitive root
Args:
z (list): check if z is a primitive root
length (Integer): Length of the GF(q)
"""
if len(z) == length:
return True
return False
def add(self):
"""
This function do the operation + on the Galois Field
Returns:
Return a list of the group with the addition operation
"""
for x in range(0, self._q):
for y in range(0, self._q):
self._add[x][y] = (x + y) % self._q
return self._add
def _inverseModular(self, a, n):
"""
This function find the reverse modular of a by n
Returns:
Return the reverse modular
"""
for b in range(1, n):
if (a * b) % n == 1:
inv = b
break
return inv
def div(self):
"""
This function do the operation / on the Galois Field
Returns:
Return a list of the group with the division operation
"""
for x in range(1, self._q):
for y in range(1, self._q):
inv = self._inverseModular(y, self._q)
self._div[x][y] = (x * inv) % self._q
return self._div
def mul(self):
"""
This function do the operation * on the Galois Field
Returns:
Return a list of the group with the multiplication operation
"""
for x in range(0, self._q):
for y in range(0, self._q):
self._mul[x][y] = (x * y) % self._q
return self._mul
def sub(self):
"""
This function do the operation - on the Galois Field
Returns:
Return a list of the group with the subtraction operation
"""
for x in range(0, self._q):
for y in range(0, self._q):
self._sub[x][y] = (x - y) % self._q
return self._sub
def check_closure_law(self, arithmetic):
"""
This function check the closure law.
By definition, every element in the GF is an abelian group, which respect the closure law: for a and b belongs to G, a + b belongs to G, the operation is a binary operation
Args:
Arithmetics (str): contain the operation to be made, must be '+', '*', '/' or /-'
"""
if arithmetic not in ['+', '*', '/', '-']:
raise Exception("The arithmetic need to be '+', '*', '/' or '-'")
if arithmetic == '+':
G = self._add
elif arithmetic == '*':
G = self._mul
elif arithmetic == '/':
G = self._div
else:
G = self._sub
start = 0
"""
In case of multiplicative, we bypass the first line, because all elements are zero, otherwise the test fail
"""
if arithmetic == '*' or arithmetic == '/':
start = 1
isClosure = True
for x in range(start, self._q):
gr = Group(self._q, G[x], self._operation)
if not gr.closure():
isClosure = False
del gr
if isClosure:
print(f"The group {arithmetic} respect closure law")
else:
print(f"The group {arithmetic} does not respect closure law")
def printMatrice(self, m):
"""
This function print the GF(m)
Args:
m (list): Matrix of the GF
"""
header = str()
header = " "
for x in range(0, self._q):
header += f"{x} "
header += "\n--|" + "-" * (len(header)- 3) +"\n"
s = str()
for x in range(0, self._q):
s += f"{x} | "
for y in range(0, self._q):
s += f"{m[x][y]} "
s += "\n"
s = header + s
print(s)
|