Skip to content

Commit

Permalink
Added a polynomial class def + Berlekamp-Massey alg implementation (b…
Browse files Browse the repository at this point in the history
…oth untested).
  • Loading branch information
mfukar committed Jul 10, 2011
1 parent 2ae56b6 commit cdb7256
Show file tree
Hide file tree
Showing 2 changed files with 164 additions and 31 deletions.
134 changes: 103 additions & 31 deletions lfsr.py
Original file line number Diff line number Diff line change
@@ -1,40 +1,112 @@
#!/usr/bin/env python
# @file /home/mfukar/src/lfsr/lfsr.py
# @author Michael Foukarakis
# @version 1.0
# @date Created: Thu Feb 03, 2011 08:19 GTB Standard Time
# Last Update: Mon Feb 07, 2011 12:22 EET
# -*- coding: utf-8 -*-
# @file /home/mfukar/src/lfsr/lfsr.py
# @author Michael Foukarakis
# @version 1.0
# @date Created: Thu Feb 03, 2011 08:19 GTB Standard Time
# Last Update: Thu Jun 30, 2011 00:33 PDT
#------------------------------------------------------------------------
# Description: Implementation of a Galois LFSR
# Description: Implementation of a Galois LFSR
# The bitstream is provided by the generator function
# GLFSR.states(). The 'repeat' flag controls whether the
# generator stops once the LFSR overflows or whether it
# continues perpetually.
#------------------------------------------------------------------------
# History: None yet
# TODO: Nothing yet
# History: None yet
# TODO: Nothing yet
#------------------------------------------------------------------------
class GLFSR:
def __init__(self, polynomial, seed):
self.polynomial = polynomial | 1
self.seed = seed
self.data = seed
self.mask = 1

temp_mask = polynomial
while temp_mask != 0:
if temp_mask & self.mask != 0:
temp_mask = temp_mask ^ self.mask
if temp_mask == 0: break
self.mask = self.mask << 1

def states(self, repeat=False):
while True:
self.data = self.data << 1
if self.data & self.mask != 0:
self.data = self.data ^ self.polynomial
yield 1
else:
yield 0
if repeat == False and self.data == self.seed:
return
def __init__(self, polynomial, seed):
self.polynomial = polynomial | 1
self.seed = seed
self.data = seed
self.mask = 1

temp_mask = polynomial
while temp_mask != 0:
if temp_mask & self.mask != 0:
temp_mask = temp_mask ^ self.mask
if temp_mask == 0: break
self.mask = self.mask << 1

def states(self, repeat=False):
while True:
self.data = self.data << 1
if self.data & self.mask != 0:
self.data = self.data ^ self.polynomial
yield 1
else:
yield 0
if repeat == False and self.data == self.seed:
return


# Polynomials needed below this point
from polynomial import Polynomial
X = Polynomial([1, 0])
One = Polynomial([1])

def bm(seq):
'''
Implementation of the Berlekamp-Massey algorithm, the purpose
of which is to find a LFSR with the smallest possible length
that generates a given sequence.
A generator is returned that yields the current LFSR at
each call. At the k-th call the yielded LFSR is guaranteed
to generate the first k bits of S.
Input :
Output: A list of coefficients [c0, c1,..., c{m-1}]
Internally, if the state of the LFSR is (x0,x1,...,x{m-1})
then the output bit is x0, the register contents are shifted
to the left, and the new
x{m-1} = c0 * x0 + c1 * x1 +...+c{m-1} * x{m-1}
The generating function G(x) = s_0 + s_1 * x^1 + s_2 * x^2 + ...
of a LFSR is rational and (when written in lowest terms) the
denominator f(x) is called the characteristic polynomial of the
LFSR. Here we have f(x) = c0 * x^m + c1 * x^{m-1} +...+ c{m-1} * x + 1.
'''
# Allow for an input string along with a list or tuple
if type(S)==type("string"):
S = map(int,tuple(S))

m = 0

# N is the index of the current element of the sequence S under consideration
# f is the characteristic polynomial of the current LFSR
N,f = 0,One

# N0 and f0 are the values of N and f when m was last changed
# N0 starts out as -1
N0,f0 = -1,One

n = len(S)
while N < n:
# Does the current LFSR compute the next entry in the
# sequence correctly? If not we need to update the LFSR
if S[N] != f.dot(S[:N]):
# If N is small enough we can get away with just
# updating the coefficients in the LFSR. Note that
# the 'X' occuring below is a global variable and
# is the indeterminant in the polynomials defined
# by the class 'Poly'. That is, X=Poly([1,0])
if 2*m>N:
f = f + f0 * X**(N-N0)

# Otherwise we'll have to update everything
else:
f0, f = f, f + f0 * X**(N-N0)
N0 = N
m = N+1-m

# Next element..
N += 1

# yield the coefficients [c0, ... , c{m-1}] of the
# current LFSR's feedback function
yield f[:-1]
# yield the final LFSR coefficients once again
yield f[:-1]
61 changes: 61 additions & 0 deletions polynomial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#!/usr/bin/env python
# @file /home/mfukar/src/lfsr/polynomial.py
# @author Michael Foukarakis
# @version 0.1
# @date Created: Sun Jul 10, 2011 03:03 PDT
# Last Update: Mon Jan 24, 2011 14:54 GTB Standard Time
#------------------------------------------------------------------------
# Description: A class representing polynomials over GF(2).
# The coefficients are stored in a list.
#------------------------------------------------------------------------
# History: None yet
# TODO: None yet
#------------------------------------------------------------------------

class Polynomial(list):
def __str__(self):
L = ['x^{}'.format(k) for k in enumerate(self[::-1]) if x == 1]
L.reverse()
return '+'.join(L)

def __add__(self, other):
if len(self) < len(other):
return other + self
else:
k = len(self) - len(other)
new = [a^b for (a,b) in zip(self,([0]*k)+other)]
try:
while new[0] == 0:
new.pop(0)
except IndexError:
new = []
return Poly(new)

def dot(self,S):
""" This returns the sum of ck*S{N-k} where N+1 = len(S),
and k runs from 0 to m-1 (m is my degree)
"""
m = len(self)
N = len(S)
C = self[:-1]
S = S[N-m+1:]
return dot(C,S)

def __mul__(self,other):
deg = len(self) + len(other) - 2
prod = [0]*(deg + 1)
for k,x in enumerate(self):
for j,y in enumerate(other):
prod[k+j] ^= (x&y)
return Polynomial(prod)

def __pow__(self,ex):
if ex==0:
return Polynomial([1])
else:
return self*(self**(ex-1))


def dot(x, y):
'''Returns the dot product of two lists.'''
return reduce(xor, [a&b for (a,b) in zip(x,y)], 0)

0 comments on commit cdb7256

Please sign in to comment.