Étape 4

Dans cette étape, nous allons coder les opérations sur le corps fini qui nous intéresse: Nos éléments seront des polynômes aux coefficients binaires modulo un polynôme \(p\) dit primitif. On note ce corps \(\mathbf{F}_2[X]/(p)\).

Pour ce projet, nous utiliserons le polynôme primitif \(p = x^8 + x^4 + x^3 + x^2 + 1\) (représenté en Python par le nombre entier 285, ou 0b100011101 en notation binaire). Comme le degré de ce polynôme primitif est de 8, les éléments de notre corps seront des polynômes aux coefficients binaires de dégré au maximum 7. Au final, nos éléments peuvent être vu comme des nombres sur 8 bits (entre 0 et 255), donc des octets. On note parfois ce corps \(\mathbf{F}_{256}\) ou encore \(GF(256)\).

Le code que vous allez implémenter aujourd'hui nous servira au calcul des octets de correction d'erreur des QR-codes générés par votre programme.

Corps de Galois

Nous allons implémenter une classe (CorpsGalois) pour représenter le corps fini \(\mathbf{F}_2[X]/(p)\). Cette classe prend comme paramètre un polynôme primitif \(p\), représenté par un entier p. Les diverses opérations du corps fini (addition, soustraction, multiplication, division, puissance) correspondent à des méthodes de la classe.

Dans le fichier galois.py, copiez le code suivant:

class CorpsGalois(object):

    def __init__(self, p):
        # Initialisation des champs.
        self.degre_max = (2 ** degre(p)) - 1
        self.exps = [0] * self.degre_max
        self.logs = [0] * (self.degre_max + 1)

        # À compléter.
        # Remplir les listes self.exps et self.logs

    def plus(self, a, b):
        return a ^ b
       
    def moins(self, a, b):
        return a ^ b

    def fois(self, a, b):
        # À implémenter
        pass

    def division(self, a, b):
        # À implémenter
        if b == 0:
            raise ZeroDivisionError()
        pass
    
    def puissance(self, a, b):
        # À implémenter
        pass

Les méthodes plus et moins vous sont données, alors que les méthodes fois, division et puissance sont à implémenter.

La raison pour laquelle nous utilisons une classe est le fait que cela permette de partager facilement des valeurs entre les différentes méthodes. Les valeurs partagées sont: self.degre_max, self.exps, self.logs. Ces valeurs sont calculées dans le constructeur de la classe (la méthode __init__). Ces valeurs servent à faciliter le calcul des opérations fois, division, et puissance, tel que nous allons le discuter.

Générateur

Dans le corps fini \(\mathbf{F}_2[X]/(p)\), si \(p\) est un polynôme primitif (comme ce sera le cas dans le cadre de ce projet), le polynôme \(x\) (soit 0b10 ou 2) est ce qu'on appelle un générateur de \(\mathbf{F}_2[X]/(p)\): tous les éléments du corps, sauf 0, sont des puissances de ce générateur !

Ci-dessous sont listées les puissances de \(x\) de 0 à 255 (c'est-à-dire \(q-1\)) étant donnée le polynôme primitif \(p = x^8 + x^4 + x^3 + x^2 + 1\). On remarque que tous les nombres entre 1 et 255 correspondent tous à une puissance de \(x\) (vous pouvez vérifier !).

Puissance Polynôme Binaire Nombre
0 \(1\) 0b00000001 1
1 \(x\) 0b00000010 2
2 \(x^{2}\) 0b00000100 4
3 \(x^{3}\) 0b00001000 8
4 \(x^{4}\) 0b00010000 16
5 \(x^{5}\) 0b00100000 32
6 \(x^{6}\) 0b01000000 64
7 \(x^{7}\) 0b10000000 128
8 \(x^{4} + x^{3} + x^{2} + 1\) 0b00011101 29
9 \(x^{5} + x^{4} + x^{3} + x\) 0b00111010 58
10 \(x^{6} + x^{5} + x^{4} + x^{2}\) 0b01110100 116
11 \(x^{7} + x^{6} + x^{5} + x^{3}\) 0b11101000 232
12 \(x^{7} + x^{6} + x^{3} + x^{2} + 1\) 0b11001101 205
13 \(x^{7} + x^{2} + x + 1\) 0b10000111 135
14 \(x^{4} + x + 1\) 0b00010011 19
15 \(x^{5} + x^{2} + x\) 0b00100110 38
16 \(x^{6} + x^{3} + x^{2}\) 0b01001100 76
17 \(x^{7} + x^{4} + x^{3}\) 0b10011000 152
18 \(x^{5} + x^{3} + x^{2} + 1\) 0b00101101 45
19 \(x^{6} + x^{4} + x^{3} + x\) 0b01011010 90
20 \(x^{7} + x^{5} + x^{4} + x^{2}\) 0b10110100 180
21 \(x^{6} + x^{5} + x^{4} + x^{2} + 1\) 0b01110101 117
22 \(x^{7} + x^{6} + x^{5} + x^{3} + x\) 0b11101010 234
23 \(x^{7} + x^{6} + x^{3} + 1\) 0b11001001 201
24 \(x^{7} + x^{3} + x^{2} + x + 1\) 0b10001111 143
25 \(x + 1\) 0b00000011 3
26 \(x^{2} + x\) 0b00000110 6
27 \(x^{3} + x^{2}\) 0b00001100 12
28 \(x^{4} + x^{3}\) 0b00011000 24
29 \(x^{5} + x^{4}\) 0b00110000 48
30 \(x^{6} + x^{5}\) 0b01100000 96
31 \(x^{7} + x^{6}\) 0b11000000 192
32 \(x^{7} + x^{4} + x^{3} + x^{2} + 1\) 0b10011101 157
33 \(x^{5} + x^{2} + x + 1\) 0b00100111 39
34 \(x^{6} + x^{3} + x^{2} + x\) 0b01001110 78
35 \(x^{7} + x^{4} + x^{3} + x^{2}\) 0b10011100 156
36 \(x^{5} + x^{2} + 1\) 0b00100101 37
37 \(x^{6} + x^{3} + x\) 0b01001010 74
38 \(x^{7} + x^{4} + x^{2}\) 0b10010100 148
39 \(x^{5} + x^{4} + x^{2} + 1\) 0b00110101 53
40 \(x^{6} + x^{5} + x^{3} + x\) 0b01101010 106
41 \(x^{7} + x^{6} + x^{4} + x^{2}\) 0b11010100 212
42 \(x^{7} + x^{5} + x^{4} + x^{2} + 1\) 0b10110101 181
43 \(x^{6} + x^{5} + x^{4} + x^{2} + x + 1\) 0b01110111 119
44 \(x^{7} + x^{6} + x^{5} + x^{3} + x^{2} + x\) 0b11101110 238
45 \(x^{7} + x^{6} + 1\) 0b11000001 193
46 \(x^{7} + x^{4} + x^{3} + x^{2} + x + 1\) 0b10011111 159
47 \(x^{5} + x + 1\) 0b00100011 35
48 \(x^{6} + x^{2} + x\) 0b01000110 70
49 \(x^{7} + x^{3} + x^{2}\) 0b10001100 140
50 \(x^{2} + 1\) 0b00000101 5
51 \(x^{3} + x\) 0b00001010 10
52 \(x^{4} + x^{2}\) 0b00010100 20
53 \(x^{5} + x^{3}\) 0b00101000 40
54 \(x^{6} + x^{4}\) 0b01010000 80
55 \(x^{7} + x^{5}\) 0b10100000 160
56 \(x^{6} + x^{4} + x^{3} + x^{2} + 1\) 0b01011101 93
57 \(x^{7} + x^{5} + x^{4} + x^{3} + x\) 0b10111010 186
58 \(x^{6} + x^{5} + x^{3} + 1\) 0b01101001 105
59 \(x^{7} + x^{6} + x^{4} + x\) 0b11010010 210
60 \(x^{7} + x^{5} + x^{4} + x^{3} + 1\) 0b10111001 185
61 \(x^{6} + x^{5} + x^{3} + x^{2} + x + 1\) 0b01101111 111
62 \(x^{7} + x^{6} + x^{4} + x^{3} + x^{2} + x\) 0b11011110 222
63 \(x^{7} + x^{5} + 1\) 0b10100001 161
64 \(x^{6} + x^{4} + x^{3} + x^{2} + x + 1\) 0b01011111 95
65 \(x^{7} + x^{5} + x^{4} + x^{3} + x^{2} + x\) 0b10111110 190
66 \(x^{6} + x^{5} + 1\) 0b01100001 97
67 \(x^{7} + x^{6} + x\) 0b11000010 194
68 \(x^{7} + x^{4} + x^{3} + 1\) 0b10011001 153
69 \(x^{5} + x^{3} + x^{2} + x + 1\) 0b00101111 47
70 \(x^{6} + x^{4} + x^{3} + x^{2} + x\) 0b01011110 94
71 \(x^{7} + x^{5} + x^{4} + x^{3} + x^{2}\) 0b10111100 188
72 \(x^{6} + x^{5} + x^{2} + 1\) 0b01100101 101
73 \(x^{7} + x^{6} + x^{3} + x\) 0b11001010 202
74 \(x^{7} + x^{3} + 1\) 0b10001001 137
75 \(x^{3} + x^{2} + x + 1\) 0b00001111 15
76 \(x^{4} + x^{3} + x^{2} + x\) 0b00011110 30
77 \(x^{5} + x^{4} + x^{3} + x^{2}\) 0b00111100 60
78 \(x^{6} + x^{5} + x^{4} + x^{3}\) 0b01111000 120
79 \(x^{7} + x^{6} + x^{5} + x^{4}\) 0b11110000 240
80 \(x^{7} + x^{6} + x^{5} + x^{4} + x^{3} + x^{2} + 1\) 0b11111101 253
81 \(x^{7} + x^{6} + x^{5} + x^{2} + x + 1\) 0b11100111 231
82 \(x^{7} + x^{6} + x^{4} + x + 1\) 0b11010011 211
83 \(x^{7} + x^{5} + x^{4} + x^{3} + x + 1\) 0b10111011 187
84 \(x^{6} + x^{5} + x^{3} + x + 1\) 0b01101011 107
85 \(x^{7} + x^{6} + x^{4} + x^{2} + x\) 0b11010110 214
86 \(x^{7} + x^{5} + x^{4} + 1\) 0b10110001 177
87 \(x^{6} + x^{5} + x^{4} + x^{3} + x^{2} + x + 1\) 0b01111111 127
88 \(x^{7} + x^{6} + x^{5} + x^{4} + x^{3} + x^{2} + x\) 0b11111110 254
89 \(x^{7} + x^{6} + x^{5} + 1\) 0b11100001 225
90 \(x^{7} + x^{6} + x^{4} + x^{3} + x^{2} + x + 1\) 0b11011111 223
91 \(x^{7} + x^{5} + x + 1\) 0b10100011 163
92 \(x^{6} + x^{4} + x^{3} + x + 1\) 0b01011011 91
93 \(x^{7} + x^{5} + x^{4} + x^{2} + x\) 0b10110110 182
94 \(x^{6} + x^{5} + x^{4} + 1\) 0b01110001 113
95 \(x^{7} + x^{6} + x^{5} + x\) 0b11100010 226
96 \(x^{7} + x^{6} + x^{4} + x^{3} + 1\) 0b11011001 217
97 \(x^{7} + x^{5} + x^{3} + x^{2} + x + 1\) 0b10101111 175
98 \(x^{6} + x + 1\) 0b01000011 67
99 \(x^{7} + x^{2} + x\) 0b10000110 134
100 \(x^{4} + 1\) 0b00010001 17
101 \(x^{5} + x\) 0b00100010 34
102 \(x^{6} + x^{2}\) 0b01000100 68
103 \(x^{7} + x^{3}\) 0b10001000 136
104 \(x^{3} + x^{2} + 1\) 0b00001101 13
105 \(x^{4} + x^{3} + x\) 0b00011010 26
106 \(x^{5} + x^{4} + x^{2}\) 0b00110100 52
107 \(x^{6} + x^{5} + x^{3}\) 0b01101000 104
108 \(x^{7} + x^{6} + x^{4}\) 0b11010000 208
109 \(x^{7} + x^{5} + x^{4} + x^{3} + x^{2} + 1\) 0b10111101 189
110 \(x^{6} + x^{5} + x^{2} + x + 1\) 0b01100111 103
111 \(x^{7} + x^{6} + x^{3} + x^{2} + x\) 0b11001110 206
112 \(x^{7} + 1\) 0b10000001 129
113 \(x^{4} + x^{3} + x^{2} + x + 1\) 0b00011111 31
114 \(x^{5} + x^{4} + x^{3} + x^{2} + x\) 0b00111110 62
115 \(x^{6} + x^{5} + x^{4} + x^{3} + x^{2}\) 0b01111100 124
116 \(x^{7} + x^{6} + x^{5} + x^{4} + x^{3}\) 0b11111000 248
117 \(x^{7} + x^{6} + x^{5} + x^{3} + x^{2} + 1\) 0b11101101 237
118 \(x^{7} + x^{6} + x^{2} + x + 1\) 0b11000111 199
119 \(x^{7} + x^{4} + x + 1\) 0b10010011 147
120 \(x^{5} + x^{4} + x^{3} + x + 1\) 0b00111011 59
121 \(x^{6} + x^{5} + x^{4} + x^{2} + x\) 0b01110110 118
122 \(x^{7} + x^{6} + x^{5} + x^{3} + x^{2}\) 0b11101100 236
123 \(x^{7} + x^{6} + x^{2} + 1\) 0b11000101 197
124 \(x^{7} + x^{4} + x^{2} + x + 1\) 0b10010111 151
125 \(x^{5} + x^{4} + x + 1\) 0b00110011 51
126 \(x^{6} + x^{5} + x^{2} + x\) 0b01100110 102
127 \(x^{7} + x^{6} + x^{3} + x^{2}\) 0b11001100 204
128 \(x^{7} + x^{2} + 1\) 0b10000101 133
129 \(x^{4} + x^{2} + x + 1\) 0b00010111 23
130 \(x^{5} + x^{3} + x^{2} + x\) 0b00101110 46
131 \(x^{6} + x^{4} + x^{3} + x^{2}\) 0b01011100 92
132 \(x^{7} + x^{5} + x^{4} + x^{3}\) 0b10111000 184
133 \(x^{6} + x^{5} + x^{3} + x^{2} + 1\) 0b01101101 109
134 \(x^{7} + x^{6} + x^{4} + x^{3} + x\) 0b11011010 218
135 \(x^{7} + x^{5} + x^{3} + 1\) 0b10101001 169
136 \(x^{6} + x^{3} + x^{2} + x + 1\) 0b01001111 79
137 \(x^{7} + x^{4} + x^{3} + x^{2} + x\) 0b10011110 158
138 \(x^{5} + 1\) 0b00100001 33
139 \(x^{6} + x\) 0b01000010 66
140 \(x^{7} + x^{2}\) 0b10000100 132
141 \(x^{4} + x^{2} + 1\) 0b00010101 21
142 \(x^{5} + x^{3} + x\) 0b00101010 42
143 \(x^{6} + x^{4} + x^{2}\) 0b01010100 84
144 \(x^{7} + x^{5} + x^{3}\) 0b10101000 168
145 \(x^{6} + x^{3} + x^{2} + 1\) 0b01001101 77
146 \(x^{7} + x^{4} + x^{3} + x\) 0b10011010 154
147 \(x^{5} + x^{3} + 1\) 0b00101001 41
148 \(x^{6} + x^{4} + x\) 0b01010010 82
149 \(x^{7} + x^{5} + x^{2}\) 0b10100100 164
150 \(x^{6} + x^{4} + x^{2} + 1\) 0b01010101 85
151 \(x^{7} + x^{5} + x^{3} + x\) 0b10101010 170
152 \(x^{6} + x^{3} + 1\) 0b01001001 73
153 \(x^{7} + x^{4} + x\) 0b10010010 146
154 \(x^{5} + x^{4} + x^{3} + 1\) 0b00111001 57
155 \(x^{6} + x^{5} + x^{4} + x\) 0b01110010 114
156 \(x^{7} + x^{6} + x^{5} + x^{2}\) 0b11100100 228
157 \(x^{7} + x^{6} + x^{4} + x^{2} + 1\) 0b11010101 213
158 \(x^{7} + x^{5} + x^{4} + x^{2} + x + 1\) 0b10110111 183
159 \(x^{6} + x^{5} + x^{4} + x + 1\) 0b01110011 115
160 \(x^{7} + x^{6} + x^{5} + x^{2} + x\) 0b11100110 230
161 \(x^{7} + x^{6} + x^{4} + 1\) 0b11010001 209
162 \(x^{7} + x^{5} + x^{4} + x^{3} + x^{2} + x + 1\) 0b10111111 191
163 \(x^{6} + x^{5} + x + 1\) 0b01100011 99
164 \(x^{7} + x^{6} + x^{2} + x\) 0b11000110 198
165 \(x^{7} + x^{4} + 1\) 0b10010001 145
166 \(x^{5} + x^{4} + x^{3} + x^{2} + x + 1\) 0b00111111 63
167 \(x^{6} + x^{5} + x^{4} + x^{3} + x^{2} + x\) 0b01111110 126
168 \(x^{7} + x^{6} + x^{5} + x^{4} + x^{3} + x^{2}\) 0b11111100 252
169 \(x^{7} + x^{6} + x^{5} + x^{2} + 1\) 0b11100101 229
170 \(x^{7} + x^{6} + x^{4} + x^{2} + x + 1\) 0b11010111 215
171 \(x^{7} + x^{5} + x^{4} + x + 1\) 0b10110011 179
172 \(x^{6} + x^{5} + x^{4} + x^{3} + x + 1\) 0b01111011 123
173 \(x^{7} + x^{6} + x^{5} + x^{4} + x^{2} + x\) 0b11110110 246
174 \(x^{7} + x^{6} + x^{5} + x^{4} + 1\) 0b11110001 241
175 \(x^{7} + x^{6} + x^{5} + x^{4} + x^{3} + x^{2} + x + 1\) 0b11111111 255
176 \(x^{7} + x^{6} + x^{5} + x + 1\) 0b11100011 227
177 \(x^{7} + x^{6} + x^{4} + x^{3} + x + 1\) 0b11011011 219
178 \(x^{7} + x^{5} + x^{3} + x + 1\) 0b10101011 171
179 \(x^{6} + x^{3} + x + 1\) 0b01001011 75
180 \(x^{7} + x^{4} + x^{2} + x\) 0b10010110 150
181 \(x^{5} + x^{4} + 1\) 0b00110001 49
182 \(x^{6} + x^{5} + x\) 0b01100010 98
183 \(x^{7} + x^{6} + x^{2}\) 0b11000100 196
184 \(x^{7} + x^{4} + x^{2} + 1\) 0b10010101 149
185 \(x^{5} + x^{4} + x^{2} + x + 1\) 0b00110111 55
186 \(x^{6} + x^{5} + x^{3} + x^{2} + x\) 0b01101110 110
187 \(x^{7} + x^{6} + x^{4} + x^{3} + x^{2}\) 0b11011100 220
188 \(x^{7} + x^{5} + x^{2} + 1\) 0b10100101 165
189 \(x^{6} + x^{4} + x^{2} + x + 1\) 0b01010111 87
190 \(x^{7} + x^{5} + x^{3} + x^{2} + x\) 0b10101110 174
191 \(x^{6} + 1\) 0b01000001 65
192 \(x^{7} + x\) 0b10000010 130
193 \(x^{4} + x^{3} + 1\) 0b00011001 25
194 \(x^{5} + x^{4} + x\) 0b00110010 50
195 \(x^{6} + x^{5} + x^{2}\) 0b01100100 100
196 \(x^{7} + x^{6} + x^{3}\) 0b11001000 200
197 \(x^{7} + x^{3} + x^{2} + 1\) 0b10001101 141
198 \(x^{2} + x + 1\) 0b00000111 7
199 \(x^{3} + x^{2} + x\) 0b00001110 14
200 \(x^{4} + x^{3} + x^{2}\) 0b00011100 28
201 \(x^{5} + x^{4} + x^{3}\) 0b00111000 56
202 \(x^{6} + x^{5} + x^{4}\) 0b01110000 112
203 \(x^{7} + x^{6} + x^{5}\) 0b11100000 224
204 \(x^{7} + x^{6} + x^{4} + x^{3} + x^{2} + 1\) 0b11011101 221
205 \(x^{7} + x^{5} + x^{2} + x + 1\) 0b10100111 167
206 \(x^{6} + x^{4} + x + 1\) 0b01010011 83
207 \(x^{7} + x^{5} + x^{2} + x\) 0b10100110 166
208 \(x^{6} + x^{4} + 1\) 0b01010001 81
209 \(x^{7} + x^{5} + x\) 0b10100010 162
210 \(x^{6} + x^{4} + x^{3} + 1\) 0b01011001 89
211 \(x^{7} + x^{5} + x^{4} + x\) 0b10110010 178
212 \(x^{6} + x^{5} + x^{4} + x^{3} + 1\) 0b01111001 121
213 \(x^{7} + x^{6} + x^{5} + x^{4} + x\) 0b11110010 242
214 \(x^{7} + x^{6} + x^{5} + x^{4} + x^{3} + 1\) 0b11111001 249
215 \(x^{7} + x^{6} + x^{5} + x^{3} + x^{2} + x + 1\) 0b11101111 239
216 \(x^{7} + x^{6} + x + 1\) 0b11000011 195
217 \(x^{7} + x^{4} + x^{3} + x + 1\) 0b10011011 155
218 \(x^{5} + x^{3} + x + 1\) 0b00101011 43
219 \(x^{6} + x^{4} + x^{2} + x\) 0b01010110 86
220 \(x^{7} + x^{5} + x^{3} + x^{2}\) 0b10101100 172
221 \(x^{6} + x^{2} + 1\) 0b01000101 69
222 \(x^{7} + x^{3} + x\) 0b10001010 138
223 \(x^{3} + 1\) 0b00001001 9
224 \(x^{4} + x\) 0b00010010 18
225 \(x^{5} + x^{2}\) 0b00100100 36
226 \(x^{6} + x^{3}\) 0b01001000 72
227 \(x^{7} + x^{4}\) 0b10010000 144
228 \(x^{5} + x^{4} + x^{3} + x^{2} + 1\) 0b00111101 61
229 \(x^{6} + x^{5} + x^{4} + x^{3} + x\) 0b01111010 122
230 \(x^{7} + x^{6} + x^{5} + x^{4} + x^{2}\) 0b11110100 244
231 \(x^{7} + x^{6} + x^{5} + x^{4} + x^{2} + 1\) 0b11110101 245
232 \(x^{7} + x^{6} + x^{5} + x^{4} + x^{2} + x + 1\) 0b11110111 247
233 \(x^{7} + x^{6} + x^{5} + x^{4} + x + 1\) 0b11110011 243
234 \(x^{7} + x^{6} + x^{5} + x^{4} + x^{3} + x + 1\) 0b11111011 251
235 \(x^{7} + x^{6} + x^{5} + x^{3} + x + 1\) 0b11101011 235
236 \(x^{7} + x^{6} + x^{3} + x + 1\) 0b11001011 203
237 \(x^{7} + x^{3} + x + 1\) 0b10001011 139
238 \(x^{3} + x + 1\) 0b00001011 11
239 \(x^{4} + x^{2} + x\) 0b00010110 22
240 \(x^{5} + x^{3} + x^{2}\) 0b00101100 44
241 \(x^{6} + x^{4} + x^{3}\) 0b01011000 88
242 \(x^{7} + x^{5} + x^{4}\) 0b10110000 176
243 \(x^{6} + x^{5} + x^{4} + x^{3} + x^{2} + 1\) 0b01111101 125
244 \(x^{7} + x^{6} + x^{5} + x^{4} + x^{3} + x\) 0b11111010 250
245 \(x^{7} + x^{6} + x^{5} + x^{3} + 1\) 0b11101001 233
246 \(x^{7} + x^{6} + x^{3} + x^{2} + x + 1\) 0b11001111 207
247 \(x^{7} + x + 1\) 0b10000011 131
248 \(x^{4} + x^{3} + x + 1\) 0b00011011 27
249 \(x^{5} + x^{4} + x^{2} + x\) 0b00110110 54
250 \(x^{6} + x^{5} + x^{3} + x^{2}\) 0b01101100 108
251 \(x^{7} + x^{6} + x^{4} + x^{3}\) 0b11011000 216
252 \(x^{7} + x^{5} + x^{3} + x^{2} + 1\) 0b10101101 173
253 \(x^{6} + x^{2} + x + 1\) 0b01000111 71
254 \(x^{7} + x^{3} + x^{2} + x\) 0b10001110 142

De plus, à la puissance 255, le résultat est le même qu'à la puissance 0, c'est à dire 1 ! Le générateur est la racine-255 de l'unité.

Nous allons faire usage de ce générateur et de ses propriétés pour implémenter très efficacement les opérations qui nous intéressent.

Compléter le constructeur

Votre premier travail consiste à terminer l'implémentation du constructeur (la méthode __init__) de la classe. Le but ici est de remplir les listes self.exps et self.logs (initialement remplies de 0). La liste self.exps devra contenir, pour chaque index \(i\) de 0 à self.max_degre (non-compris), la valeur \(x^i\) prise modulo le polynôme primitif \(p\).

La table présentée dans la section précédente montre le contenu de self.exps dans le cas particulier où le polynôme primitif est \(x^8 + x^4 + x^3 + x^2 + 1\).

Quant à self.logs, il faudra faire en sorte que self.logs[a] == i quand self.exps[i] == a. On ne se souciera pas de la valeur à l'index 0 qui restera inutilisé.

Une fois ces deux listes remplies, vous pouvez procéder à la suite: l'implémentation des méthodes de CorpsGalois. La méthode d'addition vous est directement donnée.

Indices

Pour rappel, pour multiplier un polynôme par \(x\), il suffit simplement de décaler les bits de sa représentation binaire de un cran sur la gauche (ce que vous pouvez faire en utilisant << 1).

Pour calculer le modulo avec le polynôme primitif, vous pouvez simplement faire appel à votre fonction modulo. Il est aussi possible de se passer de cette méthode et de soustraire (^) directement le polynôme primitif p du polynôme résultat de la multiplication par \(x\) lorsque celui-ci atteint le même degré que \(p\). (Voyez-vous pourquoi ?)

Utiliser le générateur et les propriétés des logarithmes pour calculer

L'existence du générateur \(x\), ainsi que les propriétés des logarithmes, nous permettent de calculer très efficacement les différentes opérations du corps fini grâces aux propriétés suivantes:

  1. \(x^a \cdot x^b = x^{a + b}\)
  2. \(x^a / x^b = x^{a - b}\)
  3. \((x^a)^n = x^{a \cdot n}\)
  4. \(x^{q-1} = x^0 = 1\)

Ces propriétés peuvent être utilisées pour implémenter efficacement les différentes méthodes de la classe CorpsGalois. Les détails sont présentés ci-après.

Multiplication

Pour multiplier deux valeurs \(a\) et \(b\), on prend simplement (grâce à self.logs) la puissance de \(x\) correspondant respectivement à \(a\) et à \(b\). Il suffit ensuite de calculer la somme de ces deux puissances, puis de trouver la valeur correspondante (grâce à self.exps).

Un détail subsiste: Comme vous avez uniquement rempli la liste self.exps de 0 à self.degre_max - 1, il faudra s'assurer de retirer self.degre_max de la somme des puissances si celle-ci sort de l'intervalle. Grâce à la 4ième propriété, cette soustraction ne changera rien à la valeur du résultat !

Aussi, il vous faudra traîter à part le cas où a ou b sont égaux à 0. En effet, la valeur 0 n'a pas de puissance associée. Il est donc impossible d'utiliser self.logs dans ce cas.

Division

Le procédé est similaire à celui de la multiplication. À la place d'additionner les puissances, il faudra procéder à une soustraction. De plus, il faudra s'assurer que la puissance résultante soit dans le bon intervalle pour la liste.

Dans le cas où le diviseur b est 0, on lancera une exception. Le cas où a est 0 sera ensuite traité à part.

Puissance

Pour calculer la puissance n d'un élément a, on utilisera la même technique que pour les opérations précédente :

De nouveau, il faudra traiter le cas où a est égal à 0 à part.

Tester votre code

À la fin de cette quatrième étape du projet, vous pouvez exécuter la commande suivante dans le Terminal pour vérifier si vous avez bien implémenté les fonctionnalités attendues:

python3 -m unittest test.Etape4