Define a field with 256 elements
Python 2, 11 + 45 = 56 bytes
Addition (11 bytes):
int.__xor__
Multiplication (45 bytes):
m=lambda x,y:y and m(x*2^x/128*283,y/2)^y%2*x
Takes input numbers in the range [0 ... 255]
. Addition is just bitwise XOR, multiplication is multiplication of polynomials with coefficients in GF2 with Russian peasant.
And for checking:
a=int.__xor__
m=lambda x,y:y and m(x*2^x/128*283,y/2)^y%2*x
for x in range(256):
assert a(0,x) == a(x,0) == x
assert m(1,x) == m(x,1) == x
assert any(a(x,y) == 0 for y in range(256))
if x != 0:
assert any(m(x,y) == 1 for y in range(256))
for y in range(256):
assert 0 <= a(x,y) < 256
assert 0 <= m(x,y) < 256
assert a(x,y) == a(y,x)
assert m(x,y) == m(y,x)
for z in range(256):
assert a(a(x,y),z) == a(x,a(y,z))
assert m(m(x,y),z) == m(x,m(y,z))
assert m(x,a(y,z)) == a(m(x,y), m(x,z))
JavaScript (ES6), 10 + 49 = 59 bytes
a=(x,y)=>x^y
m=(x,y,p=0)=>x?m(x>>1,2*y^283*(y>>7),p^y*(x&1)):p
Domain is 0 ... 255. Source.
Intel x86-64 + AVX-512 + GFNI, 11 bytes
add:
C5 F0 57 C0 # vxorps xmm0, xmm1, xmm0
C3 # ret
mul:
C4 E2 79 CF C1 # vgf2p8mulb xmm0, xmm0, xmm1
C3 # ret
Uses the new GF2P8MULB
instruction on Ice Lake CPUs.
The instruction multiplies elements in the finite field GF(28), operating on a byte (field element) in the first source operand and the corresponding byte in a second source operand. The field GF(28) is represented in polynomial representation with the reduction polynomial x8 + x4 + x3 + x + 1.