1package utils
2
3// GaloisField encapsulates galois field arithmetics
4type GaloisField struct {
5	Size    int
6	Base    int
7	ALogTbl []int
8	LogTbl  []int
9}
10
11// NewGaloisField creates a new galois field
12func NewGaloisField(pp, fieldSize, b int) *GaloisField {
13	result := new(GaloisField)
14
15	result.Size = fieldSize
16	result.Base = b
17	result.ALogTbl = make([]int, fieldSize)
18	result.LogTbl = make([]int, fieldSize)
19
20	x := 1
21	for i := 0; i < fieldSize; i++ {
22		result.ALogTbl[i] = x
23		x = x * 2
24		if x >= fieldSize {
25			x = (x ^ pp) & (fieldSize - 1)
26		}
27	}
28
29	for i := 0; i < fieldSize; i++ {
30		result.LogTbl[result.ALogTbl[i]] = int(i)
31	}
32
33	return result
34}
35
36func (gf *GaloisField) Zero() *GFPoly {
37	return NewGFPoly(gf, []int{0})
38}
39
40// AddOrSub add or substract two numbers
41func (gf *GaloisField) AddOrSub(a, b int) int {
42	return a ^ b
43}
44
45// Multiply multiplys two numbers
46func (gf *GaloisField) Multiply(a, b int) int {
47	if a == 0 || b == 0 {
48		return 0
49	}
50	return gf.ALogTbl[(gf.LogTbl[a]+gf.LogTbl[b])%(gf.Size-1)]
51}
52
53// Divide divides two numbers
54func (gf *GaloisField) Divide(a, b int) int {
55	if b == 0 {
56		panic("divide by zero")
57	} else if a == 0 {
58		return 0
59	}
60	return gf.ALogTbl[(gf.LogTbl[a]-gf.LogTbl[b])%(gf.Size-1)]
61}
62
63func (gf *GaloisField) Invers(num int) int {
64	return gf.ALogTbl[(gf.Size-1)-gf.LogTbl[num]]
65}
66