-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfield.py
More file actions
142 lines (112 loc) · 3.35 KB
/
field.py
File metadata and controls
142 lines (112 loc) · 3.35 KB
1
2
3
4
5
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
import random
class ExtensionField:
_irreducible = {
3: 0b1011,
8: 0b100011011, # x^8 + x^4 + x^3 + x + 1
64: 0x1000000000000001B,
}
def __init__(self, m: int) -> None:
# p^m
self.m = m
if m not in [3, 8, 64, 128, 192, 256, 384, 576, 768]:
raise Exception(f"m must be one of {[8, 64, 128, 192, 256, 384, 576, 768]}")
self.irrPoly = self._get_irr_poly(m)
def _get_irr_poly(self, m: int) -> int:
return self._irreducible[m]
def add(self, a: int, b: int) -> int:
"""Add two values
Args:
a (int): first value
b (int): second value
Returns:
a ^ b
"""
return a ^ b
def sub(self, a: int, b: int) -> int:
"""Subtract two values
Args:
a (int): first value
b (int): second value
Returns:
a ^ b
"""
return a ^ b
def mul(self, a: int, b: int) -> int:
"""Multiply two values
Args:
a (int): first value
b (int): second value
Returns:
(a * b) % irreducible polynomial
"""
result = 0
while b:
if b & 1:
result ^= a
b >>= 1
a <<= 1
if a >> self.m:
a ^= self.irrPoly
return result
def inv(self, a: int) -> int:
"""Compute the multiplicative inverse of a value in the field
Uses Fermat's Little Theorem: a^(p^m - 2) ≡ a^(-1) (mod p^m)
Args:
a (int): value to invert
Returns:
int: multiplicative inverse of a
"""
return self.pow(a, (1 << self.m) - 2)
def pow(self, a: int, n: int) -> int:
"""Compute a^n in the field using binary exponentiation
Args:
a (int): base value
n (int): exponent
Returns:
int: a^n mod irreducible polynomial
"""
result = 1
base = a
while n:
if n & 1:
result = self.mul(result, base)
base = self.mul(base, base)
n >>= 1
return result
def bit_dec(self, i: int, d: int) -> list[int]:
"""Decompose an integer into its binary representation
Args:
i (int): integer to decompose
d (int): number of bits in the representation
Returns:
list[int]: list of d bits (LSB first)
"""
b = [0] * d
for j in range(d):
b[j] = i % 2
i = (i - b[j]) // 2
return b
def num_rec(self, d: int, b: list[int]) -> int:
"""Reconstruct an integer from its binary representation
Args:
d (int): number of bits
b (list[int]): list of bits (LSB first)
Returns:
int: reconstructed integer
"""
result = 0
for j in range(d):
result += b[j] * 2**j
return result
def get_random(self) -> int:
"""Generate a random field element
Returns:
int: random value in range [0, 2^m - 1]
"""
return random.randint(0, 2**self.m - 1)
def get_random_bit(self) -> int:
"""Generate a random bit
Returns:
int: random bit (0 or 1)
"""
return random.randint(0, 1)