1 from nmigen_gf
.reference
.state
import ST
2 from nmigen_gf
.reference
.cldivrem
import cldivrem
3 from nmigen_gf
.reference
.clmul
import clmul
4 from nmigen_gf
.reference
.gfbmul
import gfbmul
5 from nmigen_gf
.reference
.gfbmadd
import gfbmadd
6 from nmigen_gf
.reference
.gfbinv
import gfbinv
7 from nmigen_gf
.reference
.gfpadd
import gfpadd
8 from nmigen_gf
.reference
.gfpsub
import gfpsub
9 from nmigen_gf
.reference
.gfpmul
import gfpmul
10 from nmigen_gf
.reference
.gfpinv
import gfpinv
11 from nmigen_gf
.reference
.gfpmadd
import gfpmadd
12 from nmigen_gf
.reference
.gfpmsub
import gfpmsub
13 from nmigen_gf
.reference
.gfpmsubr
import gfpmsubr
14 from nmigen_gf
.reference
.pack_poly
import pack_poly
, unpack_poly
19 """Polynomial with GF(2) coefficients.
21 `self.coefficients`: a list where `coefficients[-1] != 0`.
22 `coefficients[i]` is the coefficient for `x ** i`.
25 def __init__(self
, coefficients
=None):
26 self
.coefficients
= []
27 if coefficients
is not None:
28 if not isinstance(coefficients
, (tuple, list)):
29 coefficients
= list(coefficients
)
30 # reversed to resize self.coefficients once
31 for i
in reversed(range(len(coefficients
))):
32 self
[i
] = coefficients
[i
]
35 return len(self
.coefficients
)
43 """leading coefficient."""
44 return 0 if len(self
) == 0 else self
.coefficients
[-1]
46 def __getitem__(self
, key
):
49 return self
.coefficients
[key
]
52 def __setitem__(self
, key
, value
):
54 assert value
== 0 or value
== 1
56 self
.coefficients
[key
] = value
57 while len(self
) and self
.coefficients
[-1] == 0:
58 self
.coefficients
.pop()
60 self
.coefficients
+= [0] * (key
+ 1 - len(self
))
61 self
.coefficients
[key
] = value
64 return f
"GF2Poly({self.coefficients})"
66 def __iadd__(self
, rhs
):
67 for i
in range(max(len(self
), len(rhs
))):
71 def __add__(self
, rhs
):
72 return GF2Poly(self
).__iadd
__(rhs
)
74 def __isub__(self
, rhs
):
75 return self
.__iadd
__(rhs
)
77 def __sub__(self
, rhs
):
78 return self
.__add
__(rhs
)
81 return iter(self
.coefficients
)
83 def __mul__(self
, rhs
):
85 # reversed to resize retval.coefficients once
86 for i
in reversed(range(len(self
))):
88 for j
in reversed(range(len(rhs
))):
89 retval
[i
+ j
] ^
= rhs
[j
]
92 def __ilshift__(self
, amount
):
93 """multiplies `self` by the polynomial `x**amount`"""
95 self
.coefficients
[:0] = [0] * amount
98 def __lshift__(self
, amount
):
99 """returns the polynomial `self * x**amount`"""
100 return GF2Poly(self
).__ilshift
__(amount
)
102 def __irshift__(self
, amount
):
103 """divides `self` by the polynomial `x**amount`, discarding the
106 if amount
< len(self
):
107 del self
.coefficients
[:amount
]
109 del self
.coefficients
[:]
112 def __rshift__(self
, amount
):
113 """divides `self` by the polynomial `x**amount`, discarding the
116 return GF2Poly(self
).__irshift
__(amount
)
118 def __divmod__(self
, divisor
):
119 # based on https://en.wikipedia.org/wiki/Polynomial_greatest_common_divisor#Euclidean_division
120 assert isinstance(divisor
, GF2Poly
)
121 if len(divisor
) == 0:
122 raise ZeroDivisionError
125 while r
.degree
>= divisor
.degree
:
126 shift
= r
.degree
- divisor
.degree
128 r
-= divisor
<< shift
131 def __floordiv__(self
, divisor
):
132 q
, r
= divmod(self
, divisor
)
135 def __mod__(self
, divisor
):
136 q
, r
= divmod(self
, divisor
)
139 def __pow__(self
, exponent
, modulus
=None):
140 assert isinstance(exponent
, int) and exponent
>= 0
141 assert modulus
is None or isinstance(modulus
, GF2Poly
)
142 retval
= GF2Poly([1])
147 if modulus
is not None:
152 if modulus
is not None:
157 def __eq__(self
, rhs
):
158 if isinstance(rhs
, GF2Poly
):
159 return self
.coefficients
== rhs
.coefficients
160 return NotImplemented
163 class TestGF2Poly(unittest
.TestCase
):
165 a
= GF2Poly([1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1])
166 b
= GF2Poly([0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0])
168 self
.assertEqual(a
, GF2Poly([1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1]))
169 self
.assertEqual(b
, GF2Poly([0, 0, 1, 0, 1, 1, 1, 1, 1]))
170 self
.assertEqual(c
, GF2Poly([1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1]))
172 self
.assertEqual(a
, GF2Poly([1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1]))
173 self
.assertEqual(b
, GF2Poly([0, 0, 1, 0, 1, 1, 1, 1, 1]))
174 self
.assertEqual(c
, GF2Poly([1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1]))
175 a
= GF2Poly([1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1])
176 b
= GF2Poly([0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1])
178 self
.assertEqual(a
, GF2Poly([1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1]))
179 self
.assertEqual(b
, GF2Poly([0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1]))
180 self
.assertEqual(c
, GF2Poly([1, 0, 1, 1, 1, 0, 0, 1]))
182 self
.assertEqual(c
, GF2Poly([1, 0, 1, 1, 1, 0, 0, 1]))
184 self
.assertEqual(c
, GF2Poly([1, 0, 1, 1, 1, 0, 0, 1]))
186 def test_shift(self
):
187 a
= GF2Poly([1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1])
189 self
.assertEqual(a
, GF2Poly([1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1]))
190 self
.assertEqual(c
, GF2Poly([1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1]))
192 self
.assertEqual(a
, GF2Poly([1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1]))
193 self
.assertEqual(c
, GF2Poly(
194 [0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1]))
196 self
.assertEqual(a
, GF2Poly([1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1]))
197 self
.assertEqual(c
, GF2Poly(
198 [0] * 10 + [1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1]))
200 self
.assertEqual(a
, GF2Poly([1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1]))
201 self
.assertEqual(c
, GF2Poly([1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1]))
203 self
.assertEqual(a
, GF2Poly([1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1]))
204 self
.assertEqual(c
, GF2Poly([1, 1, 0, 1, 0, 1]))
206 self
.assertEqual(a
, GF2Poly([1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1]))
207 self
.assertEqual(c
, GF2Poly([1]))
209 self
.assertEqual(a
, GF2Poly([1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1]))
210 self
.assertEqual(c
, GF2Poly([]))
212 self
.assertEqual(a
, GF2Poly([1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1]))
213 self
.assertEqual(c
, GF2Poly([]))
216 a
= GF2Poly([1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1])
217 b
= GF2Poly([0, 0, 1, 0, 1, 1, 1, 1, 1])
219 expected
= GF2Poly([0, 0, 1, 0, 1, 0, 1, 1, 1, 0,
220 0, 1, 0, 1, 1, 0, 0, 1, 1])
221 self
.assertEqual(a
, GF2Poly([1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1]))
222 self
.assertEqual(b
, GF2Poly([0, 0, 1, 0, 1, 1, 1, 1, 1]))
223 self
.assertEqual(c
, expected
)
225 def test_divmod(self
):
226 a
= GF2Poly([1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1])
227 b
= GF2Poly([0, 0, 1, 0, 1, 1, 1, 1, 1])
229 self
.assertEqual(a
, GF2Poly([1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1]))
230 self
.assertEqual(b
, GF2Poly([0, 0, 1, 0, 1, 1, 1, 1, 1]))
231 self
.assertEqual(q
, GF2Poly([1, 1, 1]))
232 self
.assertEqual(r
, GF2Poly([1, 0, 1, 0, 0, 1, 0, 1]))
234 self
.assertEqual(q
, GF2Poly([1, 1, 1]))
236 self
.assertEqual(r
, GF2Poly([1, 0, 1, 0, 0, 1, 0, 1]))
241 expected
= GF2Poly([0] * e
+ [1])
242 with self
.subTest(b
=str(b
), e
=e
, expected
=str(expected
)):
244 self
.assertEqual(b
, GF2Poly([0, 1]))
245 self
.assertEqual(v
, expected
)
247 # AES's finite field reducing polynomial
248 m
= GF2Poly([1, 1, 0, 1, 1, 0, 0, 0, 1])
249 period
= 2 ** m
.degree
- 1
250 b
= GF2Poly([1, 1, 0, 0, 1, 0, 1])
252 expected
= GF2Poly([0, 1, 0, 1, 0, 0, 1, 1])
254 self
.assertEqual(m
, GF2Poly([1, 1, 0, 1, 1, 0, 0, 0, 1]))
255 self
.assertEqual(b
, GF2Poly([1, 1, 0, 0, 1, 0, 1]))
256 self
.assertEqual(v
, expected
)
258 # test that pow doesn't take inordinately long when given a modulus.
259 # adding a multiple of `period` should leave results unchanged.
260 e
+= period
* 10 ** 15
262 self
.assertEqual(m
, GF2Poly([1, 1, 0, 1, 1, 0, 0, 0, 1]))
263 self
.assertEqual(b
, GF2Poly([1, 1, 0, 0, 1, 0, 1]))
264 self
.assertEqual(v
, expected
)
268 def __init__(self
, value
, red_poly
=None):
269 if isinstance(value
, GFB
):
271 assert red_poly
is None
272 self
.red_poly
= GF2Poly(value
.red_poly
)
273 self
.value
= GF2Poly(value
.value
)
275 assert isinstance(value
, GF2Poly
)
276 assert isinstance(red_poly
, GF2Poly
)
277 assert red_poly
.degree
> 0
278 self
.value
= value
% red_poly
279 self
.red_poly
= red_poly
282 return f
"GFB({self.value}, {self.red_poly})"
284 def __add__(self
, rhs
):
285 assert isinstance(rhs
, GFB
)
286 assert self
.red_poly
== rhs
.red_poly
287 return GFB((self
.value
+ rhs
.value
) % self
.red_poly
, self
.red_poly
)
289 def __sub__(self
, rhs
):
290 return self
.__add
__(rhs
)
292 def __eq__(self
, rhs
):
293 if isinstance(rhs
, GFB
):
294 return self
.value
== rhs
.value
and self
.red_poly
== rhs
.red_poly
295 return NotImplemented
297 def __mul__(self
, rhs
):
298 assert isinstance(rhs
, GFB
)
299 assert self
.red_poly
== rhs
.red_poly
300 return GFB((self
.value
* rhs
.value
) % self
.red_poly
, self
.red_poly
)
302 def __div__(self
, rhs
):
303 assert isinstance(rhs
, GFB
)
304 assert self
.red_poly
== rhs
.red_poly
305 return self
* rhs
** -1
308 def __pow_period(self
):
309 period
= (1 << self
.red_poly
.degree
) - 1
310 assert period
> 0, "internal logic error"
313 def __pow__(self
, exponent
):
314 assert isinstance(exponent
, int)
315 if len(self
.value
) == 0:
317 raise ZeroDivisionError
320 exponent
%= self
.__pow
_period
321 return GFB(pow(self
.value
, exponent
, self
.red_poly
), self
.red_poly
)
324 class TestGFBClass(unittest
.TestCase
):
326 # AES's finite field reducing polynomial
327 red_poly
= GF2Poly([1, 1, 0, 1, 1, 0, 0, 0, 1])
328 a
= GFB(GF2Poly([0, 1, 0, 1]), red_poly
)
329 b
= GFB(GF2Poly([0, 0, 0, 0, 0, 0, 1, 1]), red_poly
)
330 expected
= GFB(GF2Poly([0, 1, 0, 1, 0, 0, 1, 1]), red_poly
)
332 self
.assertEqual(red_poly
, GF2Poly([1, 1, 0, 1, 1, 0, 0, 0, 1]))
333 self
.assertEqual(a
, GFB(GF2Poly([0, 1, 0, 1]), red_poly
))
334 self
.assertEqual(b
, GFB(GF2Poly([0, 0, 0, 0, 0, 0, 1, 1]), red_poly
))
335 self
.assertEqual(c
, expected
)
337 self
.assertEqual(red_poly
, GF2Poly([1, 1, 0, 1, 1, 0, 0, 0, 1]))
338 self
.assertEqual(a
, GFB(GF2Poly([0, 1, 0, 1]), red_poly
))
339 self
.assertEqual(b
, GFB(GF2Poly([0, 0, 0, 0, 0, 0, 1, 1]), red_poly
))
340 self
.assertEqual(c
, expected
)
342 self
.assertEqual(red_poly
, GF2Poly([1, 1, 0, 1, 1, 0, 0, 0, 1]))
343 self
.assertEqual(a
, GFB(GF2Poly([0, 1, 0, 1]), red_poly
))
344 self
.assertEqual(b
, GFB(GF2Poly([0, 0, 0, 0, 0, 0, 1, 1]), red_poly
))
345 self
.assertEqual(c
, expected
)
348 # AES's finite field reducing polynomial
349 red_poly
= GF2Poly([1, 1, 0, 1, 1, 0, 0, 0, 1])
350 a
= GFB(GF2Poly([0, 1, 0, 1, 0, 0, 1, 1]), red_poly
)
351 b
= GFB(GF2Poly([1, 1, 0, 0, 1, 0, 1]), red_poly
)
352 expected
= GFB(GF2Poly([1]), red_poly
)
354 self
.assertEqual(red_poly
, GF2Poly([1, 1, 0, 1, 1, 0, 0, 0, 1]))
355 self
.assertEqual(a
, GFB(GF2Poly([0, 1, 0, 1, 0, 0, 1, 1]), red_poly
))
356 self
.assertEqual(b
, GFB(GF2Poly([1, 1, 0, 0, 1, 0, 1]), red_poly
))
357 self
.assertEqual(c
, expected
)
360 # AES's finite field reducing polynomial
361 red_poly
= GF2Poly([1, 1, 0, 1, 1, 0, 0, 0, 1])
362 period
= 2 ** red_poly
.degree
- 1
363 b
= GFB(GF2Poly([1, 1, 0, 0, 1, 0, 1]), red_poly
)
365 expected
= GFB(GF2Poly([0, 1, 0, 1, 0, 0, 1, 1]), red_poly
)
367 self
.assertEqual(red_poly
, GF2Poly([1, 1, 0, 1, 1, 0, 0, 0, 1]))
368 self
.assertEqual(b
, GFB(GF2Poly([1, 1, 0, 0, 1, 0, 1]), red_poly
))
369 self
.assertEqual(v
, expected
)
372 self
.assertEqual(red_poly
, GF2Poly([1, 1, 0, 1, 1, 0, 0, 0, 1]))
373 self
.assertEqual(b
, GFB(GF2Poly([1, 1, 0, 0, 1, 0, 1]), red_poly
))
374 self
.assertEqual(v
, expected
)
376 # test that pow doesn't take inordinately long when given a modulus.
377 # adding a multiple of `period` should leave results unchanged.
378 e
+= period
* 10 ** 15
380 self
.assertEqual(red_poly
, GF2Poly([1, 1, 0, 1, 1, 0, 0, 0, 1]))
381 self
.assertEqual(b
, GFB(GF2Poly([1, 1, 0, 0, 1, 0, 1]), red_poly
))
382 self
.assertEqual(v
, expected
)
386 def __init__(self
, value
, size
):
387 assert isinstance(value
, int)
388 assert isinstance(size
, int) and size
>= 2, "size is not a prime"
389 self
.value
= value
% size
393 return f
"GFP({self.value}, {self.size})"
395 def __eq__(self
, rhs
):
396 if isinstance(rhs
, GFP
):
397 return self
.value
== rhs
.value
and self
.size
== rhs
.size
398 return NotImplemented
400 def __add__(self
, rhs
):
401 assert isinstance(rhs
, GFP
)
402 assert self
.size
== rhs
.size
403 return GFP((self
.value
+ rhs
.value
) % self
.size
, self
.size
)
405 def __sub__(self
, rhs
):
406 assert isinstance(rhs
, GFP
)
407 assert self
.size
== rhs
.size
408 return GFP((self
.value
- rhs
.value
) % self
.size
, self
.size
)
410 def __mul__(self
, rhs
):
411 assert isinstance(rhs
, GFP
)
412 assert self
.size
== rhs
.size
413 return GFP((self
.value
* rhs
.value
) % self
.size
, self
.size
)
415 def __div__(self
, rhs
):
416 assert isinstance(rhs
, GFP
)
417 assert self
.size
== rhs
.size
418 return self
* rhs
** -1
421 def __pow_period(self
):
422 period
= self
.size
- 1
423 assert period
> 0, "internal logic error"
426 def __pow__(self
, exponent
):
427 assert isinstance(exponent
, int)
430 raise ZeroDivisionError
432 return GFP(self
.value
, self
.size
)
433 exponent
%= self
.__pow
_period
434 return GFP(pow(self
.value
, exponent
, self
.size
), self
.size
)
437 PRIMES
= 2, 3, 5, 7, 11, 13, 17, 19
438 """handy list of small primes for testing"""
441 class TestGFPClass(unittest
.TestCase
):
442 def test_add_sub(self
):
444 for av
in range(prime
):
445 for bv
in range(prime
):
446 with self
.subTest(av
=av
, bv
=bv
, prime
=prime
):
449 expected
= GFP((av
+ bv
) % prime
, prime
)
451 self
.assertEqual(a
, GFP(av
, prime
))
452 self
.assertEqual(b
, GFP(bv
, prime
))
453 self
.assertEqual(c
, expected
)
455 self
.assertEqual(a
, GFP(av
, prime
))
456 self
.assertEqual(b
, GFP(bv
, prime
))
457 self
.assertEqual(c
, expected
)
458 expected
= GFP((av
- bv
) % prime
, prime
)
460 self
.assertEqual(a
, GFP(av
, prime
))
461 self
.assertEqual(b
, GFP(bv
, prime
))
462 self
.assertEqual(c
, expected
)
463 expected
= GFP((bv
- av
) % prime
, prime
)
465 self
.assertEqual(a
, GFP(av
, prime
))
466 self
.assertEqual(b
, GFP(bv
, prime
))
467 self
.assertEqual(c
, expected
)
471 for av
in range(prime
):
472 for bv
in range(prime
):
473 with self
.subTest(av
=av
, bv
=bv
, prime
=prime
):
476 expected
= GFP((av
* bv
) % prime
, prime
)
478 self
.assertEqual(a
, GFP(av
, prime
))
479 self
.assertEqual(b
, GFP(bv
, prime
))
480 self
.assertEqual(c
, expected
)
482 self
.assertEqual(a
, GFP(av
, prime
))
483 self
.assertEqual(b
, GFP(bv
, prime
))
484 self
.assertEqual(c
, expected
)
488 for bv
in range(prime
):
489 with self
.subTest(bv
=bv
, prime
=prime
):
493 expected
= GFP(pow(bv
, e
, prime
) if bv
!= 0 else 0, prime
)
495 self
.assertEqual(b
, GFP(bv
, prime
))
496 self
.assertEqual(v
, expected
)
500 self
.assertEqual(b
, GFP(bv
, prime
))
501 self
.assertEqual(v
, expected
)
503 # test that pow doesn't take inordinately long when given
504 # a modulus. adding a multiple of `period` should leave
506 e
+= period
* 10 ** 15
508 self
.assertEqual(b
, GFP(bv
, prime
))
509 self
.assertEqual(v
, expected
)
512 class TestCL(unittest
.TestCase
):
513 def test_cldivrem(self
):
515 for nv
in range(2 ** width
):
516 n
= GF2Poly(unpack_poly(nv
))
517 for dv
in range(1, 2 ** width
):
518 d
= GF2Poly(unpack_poly(dv
))
519 with self
.subTest(n
=str(n
), nv
=nv
, d
=str(d
), dv
=dv
):
520 q_expected
, r_expected
= divmod(n
, d
)
521 self
.assertEqual(q_expected
* d
+ r_expected
, n
)
522 q
, r
= cldivrem(nv
, dv
, width
)
523 q_expected
= pack_poly(q_expected
.coefficients
)
524 r_expected
= pack_poly(r_expected
.coefficients
)
525 self
.assertEqual((q
, r
), (q_expected
, r_expected
))
527 def test_clmul(self
):
530 for av
in range(2 ** a_width
):
531 a
= GF2Poly(unpack_poly(av
))
532 for bv
in range(2 ** b_width
):
533 b
= GF2Poly(unpack_poly(bv
))
534 with self
.subTest(a
=str(a
), av
=av
, b
=str(b
), bv
=bv
):
536 product
= clmul(av
, bv
)
537 expected
= pack_poly(expected
.coefficients
)
538 self
.assertEqual(product
, expected
)
541 class TestGFBInstructions(unittest
.TestCase
):
543 def init_aes_red_poly():
544 # AES's finite field reducing polynomial
545 red_poly
= GF2Poly([1, 1, 0, 1, 1, 0, 0, 0, 1])
546 ST
.reinit(GFBREDPOLY
=pack_poly(red_poly
.coefficients
))
549 def test_gfbmul(self
):
550 # AES's finite field reducing polynomial
551 red_poly
= self
.init_aes_red_poly()
554 for av
in range(2 ** a_width
):
555 a
= GFB(GF2Poly(unpack_poly(av
)), red_poly
)
556 for bv
in range(2 ** b_width
):
557 b
= GFB(GF2Poly(unpack_poly(bv
)), red_poly
)
559 with self
.subTest(a
=str(a
), av
=av
, b
=str(b
), bv
=bv
, expected
=str(expected
)):
560 product
= gfbmul(av
, bv
)
561 expectedv
= pack_poly(expected
.value
.coefficients
)
562 self
.assertEqual(product
, expectedv
)
564 def test_gfbmadd(self
):
565 # AES's finite field reducing polynomial
566 red_poly
= self
.init_aes_red_poly()
570 for av
in range(2 ** a_width
):
571 a
= GFB(GF2Poly(unpack_poly(av
)), red_poly
)
572 for bv
in range(2 ** b_width
):
573 b
= GFB(GF2Poly(unpack_poly(bv
)), red_poly
)
574 for cv
in range(2 ** c_width
):
575 c
= GFB(GF2Poly(unpack_poly(cv
)), red_poly
)
577 with self
.subTest(a
=str(a
), av
=av
,
580 expected
=str(expected
)):
581 result
= gfbmadd(av
, bv
, cv
)
582 expectedv
= pack_poly(expected
.value
.coefficients
)
583 self
.assertEqual(result
, expectedv
)
585 def test_gfbinv(self
):
586 # AES's finite field reducing polynomial
587 red_poly
= self
.init_aes_red_poly()
589 for av
in range(2 ** width
):
590 a
= GFB(GF2Poly(unpack_poly(av
)), red_poly
)
591 expected
= a
** -1 if av
!= 0 else GFB(GF2Poly(), red_poly
)
592 with self
.subTest(a
=str(a
), av
=av
, expected
=str(expected
)):
594 expectedv
= pack_poly(expected
.value
.coefficients
)
595 self
.assertEqual(result
, expectedv
)
598 class TestGFPInstructions(unittest
.TestCase
):
599 def test_gfpadd(self
):
601 for av
in range(prime
):
602 for bv
in range(prime
):
606 with self
.subTest(a
=str(a
), b
=str(b
),
607 expected
=str(expected
)):
608 ST
.reinit(GFPRIME
=prime
)
610 self
.assertEqual(v
, expected
.value
)
612 def test_gfpsub(self
):
614 for av
in range(prime
):
615 for bv
in range(prime
):
619 with self
.subTest(a
=str(a
), b
=str(b
),
620 expected
=str(expected
)):
621 ST
.reinit(GFPRIME
=prime
)
623 self
.assertEqual(v
, expected
.value
)
625 def test_gfpmul(self
):
627 for av
in range(prime
):
628 for bv
in range(prime
):
632 with self
.subTest(a
=str(a
), b
=str(b
),
633 expected
=str(expected
)):
634 ST
.reinit(GFPRIME
=prime
)
636 self
.assertEqual(v
, expected
.value
)
638 def test_gfpinv(self
):
640 for av
in range(prime
):
643 # TODO: determine what's expected for division by zero
647 with self
.subTest(a
=str(a
), expected
=str(expected
)):
648 ST
.reinit(GFPRIME
=prime
)
650 self
.assertEqual(v
, expected
.value
)
652 def test_gfpmadd(self
):
654 for av
in range(prime
):
655 for bv
in range(prime
):
656 for cv
in range(prime
):
661 with self
.subTest(a
=str(a
), b
=str(b
), c
=str(c
),
662 expected
=str(expected
)):
663 ST
.reinit(GFPRIME
=prime
)
664 v
= gfpmadd(av
, bv
, cv
)
665 self
.assertEqual(v
, expected
.value
)
667 def test_gfpmsub(self
):
669 for av
in range(prime
):
670 for bv
in range(prime
):
671 for cv
in range(prime
):
676 with self
.subTest(a
=str(a
), b
=str(b
), c
=str(c
),
677 expected
=str(expected
)):
678 ST
.reinit(GFPRIME
=prime
)
679 v
= gfpmsub(av
, bv
, cv
)
680 self
.assertEqual(v
, expected
.value
)
682 def test_gfpmsubr(self
):
684 for av
in range(prime
):
685 for bv
in range(prime
):
686 for cv
in range(prime
):
691 with self
.subTest(a
=str(a
), b
=str(b
), c
=str(c
),
692 expected
=str(expected
)):
693 ST
.reinit(GFPRIME
=prime
)
694 v
= gfpmsubr(av
, bv
, cv
)
695 self
.assertEqual(v
, expected
.value
)
698 if __name__
== "__main__":