diff --git a/galois.py b/galois.py index 90dc53f..9750694 100755 --- a/galois.py +++ b/galois.py @@ -23,13 +23,19 @@ class GaloisNumber: The class supports "normal" syntax for the addition, subtraction, multiplication, division, additive inverse (-), and multiplicative inverse (~) operations. ''' - def __init__ (self, x, value=0): + def __init__ (self, x, field=None): if isinstance(x, GaloisNumber): self.field = x.field self.value = x.value + elif type(field) not in (GaloisFieldLog, GaloisFieldDirect): + raise ValueError ("Must specify field") else: - self.field = x - self.assign (value) + self.field = field + if type(x) == bytes: + x = int.from_bytes (x, 'big') + elif type(x) != int: + raise ValueError ("Must be an integer or bytes") + self.assign (x) def assign (self, v): ''' @@ -37,13 +43,13 @@ class GaloisNumber: the field with which the GaloisNumber instance was defined. ''' if v > self.field.size: - raise GaloisException ("Value {0} is outside field".format (v)) + raise ValueError ("Value {0} is outside field".format (v)) self.value = v def __add__ (self, other): if self.field != other.field: raise GaloisException ("Field elements from different fields") - return GaloisNumber (self.field, self.value ^ other.value) + return GaloisNumber (self.value ^ other.value, self.field) def __iadd__ (self, other): if self.field != other.field: @@ -72,11 +78,14 @@ class GaloisNumber: raise GaloisException ("Field elements from different fields") self.value = self.field.direct_multiply (self.value, other.value) - def __div__ (self, other): + def __floordiv__ (self, other): if self.field != other.field: raise GaloisException ("Field elements from different fields") return self.field.divide (self, other) + def __truediv__ (self, other): + return self // other + def __eq__ (self, other): if self.field != other.field: raise GaloisException ("Field elements from different fields") @@ -128,33 +137,32 @@ class GaloisFieldLog: a = v1.value b = v2.value if a == 0 or b == 0: - return GaloisNumber (self, 0) - return GaloisNumber (self, self.antilog_tbl[(self.log_tbl[a] + self.log_tbl[b]) % - (self.size - 1)]) + return GaloisNumber (0, self) + return GaloisNumber (self.antilog_tbl[(self.log_tbl[a] + self.log_tbl[b]) % (self.size - 1)], self) def invert (self, v): if v.value == 0: - return GaloisNumber(self, 0) + return GaloisNumber(0, self) elif v.value == 1: - return GaloisNumber (self, 1) + return GaloisNumber (1, self) else: - return GaloisNumber (self, self.antilog_tbl[self.size - 1 - self.log_tbl[v.value]]) + return GaloisNumber (self.antilog_tbl[self.size - 1 - self.log_tbl[v.value]], self) def divide (self, v1, v2): return self.multiply (v1, self.invert(v2)) def self_test (self): - mul_identity = GaloisNumber (self, 1) - v = GaloisNumber (self) - g_0 = GaloisNumber (self, 0) - g_1 = GaloisNumber (self, 1) + mul_identity = GaloisNumber (1, self) + v = GaloisNumber (0, self) + g_0 = GaloisNumber (0, self) + g_1 = GaloisNumber (1, self) for i in range (self.size): v.assign (i) if i == 0: continue assert v * ~v == mul_identity, "Multiplicative inverse failed at {}".format (i) assert g_0 - v == -v, "Additive inverse failed at {}".format (i) assert v * g_1 == v, "Multiplicative identity failed at {}".format (i) - vb = GaloisNumber (self) + vb = GaloisNumber (0, self) for a in range (1, self.multiply_test_size): v.assign (random.randint (1, self.size - 1)) vb.assign (random.randint (1, self.size - 1)) @@ -184,7 +192,7 @@ class GaloisFieldDirect: self.bits = bits self.size = (1 << bits) self.prim = self.poly_defaults[bits] if not primitive_polynomial else primitive_polynomial - self.value_format = repr_prefix + '{:0>' + str(bits / 4) + 'x}' + self.value_format = repr_prefix + '{:0>' + str(bits // 4) + 'x}' self.alpha = alpha def __eq__ (self, other): @@ -194,7 +202,7 @@ class GaloisFieldDirect: return self.value_format.format (v) def multiply (self, v1, v2): - return GaloisNumber (self, self.direct_multiply (v1.value, v2.value)) + return GaloisNumber (self.direct_multiply (v1.value, v2.value), self) def direct_multiply (self, a, b): # Multiplication is commutative, and it's faster if we use the smaller value as the @@ -223,24 +231,24 @@ class GaloisFieldDirect: to field width in bits. ''' if v.value == 0: - return GaloisNumber(self, 0) + return GaloisNumber(0, self) elif v.value == 1: - return GaloisNumber (self, 1) + return GaloisNumber (1, self) inv = 1 sq = v.value for i in range (1, self.bits): sq = self.direct_multiply (sq, sq) inv = self.direct_multiply (inv, sq) - return GaloisNumber (self, inv) + return GaloisNumber (inv, self) def divide (self, v1, v2): return self.multiply (v1, self.invert(v2)) def self_test (self): - mul_identity = GaloisNumber (self, 1) - v = GaloisNumber (self) - g_0 = GaloisNumber (self, 0) - g_1 = GaloisNumber (self, 1) + mul_identity = GaloisNumber (1, self) + v = GaloisNumber (0, self) + g_0 = GaloisNumber (0, self) + g_1 = GaloisNumber (1, self) small_field = self.size < self.max_test_size n_tests = (self.size - 1) if small_field else self.max_test_size for i in range (0, n_tests): @@ -248,7 +256,7 @@ class GaloisFieldDirect: assert v * ~v == mul_identity, "Multiplicative inverse failed at {}".format (i) assert g_0 - v == -v, "Additive inverse failed at {}".format (i) assert v * g_1 == v, "Multiplicative identity failed at {}".format (i) - vb = GaloisNumber (self) + vb = GaloisNumber (0, self) for a in range (1, self.max_test_size): v.assign (random.randint (1, self.size - 1)) vb.assign (random.randint (1, self.size - 1)) @@ -261,16 +269,16 @@ if __name__ == '__main__': print ('\nTesting direct fields...........') for width in GaloisFieldDirect.field_widths: field = GaloisFieldDirect (width) - g0 = GaloisNumber (field, 2) - g1 = GaloisNumber (field, 7) + g0 = GaloisNumber (2, field) + g1 = GaloisNumber (7, field) print ('{0} + {1} = {2}'.format (g0, g1, g0 + g1)) if field.self_test (): print ("{0} bit field (direct) passed!".format (width)) print ('\nTesting log fields...........') for width in GaloisFieldLog.field_widths: field = GaloisFieldLog (width) - g0 = GaloisNumber (field, 2) - g1 = GaloisNumber (field, 7) + g0 = GaloisNumber (2, field) + g1 = GaloisNumber (7, field) print ('{0} + {1} = {2}'.format (g0, g1, g0 + g1)) if field.self_test (): print ("{0} bit field (log) passed!".format (width))