This Python class takes a GF2 (finite field mod 2, basically binary) polynomial in string form, converts it to a binary value, then does arithmetic operations, then converts the result back into a polynomial in string form.
There are 2 parts I'd like to direct your attention to. I'll call them exhibits a and b.
For exhibit a, the regex has to be done on the string upon intake, so there were some issues with how class instances were used in terms of still allowing the string format. So that's the reason why the class is being called at the bottom. That should be invisible to the user (unless they actually go looking in the file), and when they call the class in whatever file is being used, then it should just be another class and they go on about their business. Not saying it's good coding, just saying why it looks like that. I'm sure it looks duck-taped from the professional Python coder's perspective, but for me I was pretty glad to solve it any way possible.
Also somewhat duck-taped was the modular inverse function, which I'll give as exhibit b.
I'm teaching myself Python and trying to drop all my beginner bad habits quickly. Just trying to get some good advice on the code.
import re
class gf2pim:
def id(self,lst): #returns modulus 2 (1,0,0,1,1,....) for input lists
return [int(lst[i])%2 for i in range(len(lst))]
def listToInt(self,lst): #converts list to integer for later use
result = obj.id(lst)
return int(''.join(map(str,result)))
def parsePolyToListInput(self,poly):
c = [int(i.group(0)) for i in re.finditer(r'\d+', poly)] #re.finditer returns an iterator
return [1 if x in c else 0 for x in xrange(max(c), -1, -1)]
def prepBinary(self,x,y): #converts to base 2 and orders min and max for use
x = obj.parsePolyToListInput(x); y = obj.parsePolyToListInput(y)
a = obj.listToInt(x); b = obj.listToInt(y)
bina = int(str(a),2); binb = int(str(b),2)
#a = min(bina,binb); b = max(bina,binb);
return bina,binb #bina,binb are binary values like 110100101100.....
def add(self,a,b): # a,b are GF(2) polynomials like x**7 + x**3 + x**0 ....
bina,binb = obj.prepBinary(a,b)
return obj.outFormat(bina^binb) #returns binary string
def subtract(self,x,y): # same as addition in GF(2)
return obj.add(x,y)
def multiply(self,a,b): # a,b are GF(2) polynomials like x**7 + x**3 + x**0 ....
a,b = obj.prepBinary(a,b)
return obj.outFormat(a*b) #returns product of 2 polynomials in gf2
def divide(self,a,b): #a,b are GF(2) polynomials like x**7 + x**3 + x**0 ....
a,b = obj.prepBinary(a,b)
#bitsa = "{0:b}".format(a); bitsb = "{0:b}".format(b)
return obj.outFormat(a/b),obj.outFormat(a%b) #returns remainder and quotient formatted as polynomials
def quotient(self,a,b): #separate quotient function for clarity when calling
return obj.divide(a,b)[1]
def remainder(self,a,b): #separate remainder function for clarity when calling
return obj.divide(a,b)[0]
def outFormat(self,raw): # process resulting values into polynomial format
raw = "{0:b}".format(raw); raw = str(raw[::-1]); g = [] #reverse binary string for enumeration
g = [i for i,c in enumerate(raw) if c == '1']
processed = "x**"+" + x**".join(map(str, g[::-1]))
if len(g) == 0: return 0 #return 0 if list empty
return processed #returns result in gf(2) polynomial form
def extendedEuclideanGF2(self,a,b): # extended euclidean. a,b are values 10110011... in integer form
inita,initb=a,b; x,prevx=0,1; y,prevy = 1,0
while b != 0:
q = int("{0:b}".format(a//b),2)
a,b = b,int("{0:b}".format(a%b),2);
x,prevx = (int("{0:b}".format(prevx-q*x)), int("{0:b}".format(x,2))); y,prevy=(prevy-q*y, y)
#print("%d * %d + %d * %d = %d" % (inita,prevx,initb,prevy,a))
return a,prevx,prevy # returns gcd of (a,b), and factors s and t
def modular_inverse(self,a,mod): # a,mod are GF(2) polynomials like x**7 + x**3 + x**0 ....
a,mod = obj.prepBinary(a,mod)
bitsa = int("{0:b}".format(a),2); bitsb = int("{0:b}".format(mod),2)
#return bitsa,bitsb,type(bitsa),type(bitsb),a,mod,type(a),type(mod)
gcd,s,t = obj.extendedEuclideanGF2(a,mod); s = int("{0:b}".format(s))
initmi = s%mod; mi = int("{0:b}".format(initmi))
print ("%d * %d mod %d = 1"%(a,initmi,mod))
if gcd !=1: return obj.outFormat(mi),False
return obj.outFormat(mi) # returns modular inverse of a,mod
obj = gf2pim()