https://en.wikipedia.org/wiki/Linear-feedback_shift_register
$s_{i+4} = s_i + s_{i+1} + s_{i+3}$, seed/IV $[1, 1, 0, 0]$
seed = [1, 1, 0, 0]
coef = [1, 1, 0, 1]
from numpy import dot
dot(seed, coef) % 2 #dot product modulo 2
#next bit
state = [1, 0, 0, 0]
dot(state, coef) % 2
state = state[1:]+[dot(state, coef) % 2] #next state
state
state = state[1:]+[dot(state, coef) % 2] #next state
state
state = state[1:]+[dot(state, coef) % 2] #next state
state
def lfsr_first(seed, coef, n):
"""
generates first n bits of LFSR with the given seed and coefficients
"""
result = []
state = seed
for i in range(n):
result.append(state[0])
state = state[1:]+[dot(state, coef) % 2] #next state
return result
lfsr_first([1, 1, 0, 0], [1, 1, 0, 1], 10)
#Python iterator
def lfsr(seed, coef):
"""
generates bits of LFSR with the given seed and coefficients
seed and coef can be list/tuple of int or string of digits 0/1
"""
assert len(seed) == len(coef), "Lengths of SEED and COEF differ"
state = list(map(int, seed))
coef = list(map(int, coef))
while True:
yield state[0] #next value from list
state = state[1:]+[dot(state, coef) % 2] #next state
from itertools import islice
islice(lfsr([1, 1, 0, 0], [1, 1, 0, 1]), 30) #creates new iterator
list(islice(lfsr("1100", "1101"), 10))
tuple(islice(lfsr([1, 1, 0, 0], [1, 1, 0, 1]), 10))
print(*islice(lfsr([1, 1, 0, 0], [1, 1, 0, 1]), 30), sep=",")
print(*islice(lfsr([1, 1, 0, 0], [1, 1, 0, 1]), 30))
a = [0,1,0]
b = [1,1,1]
a+b
[ (a[i]+b[i]) % 2 for i in range(len(a))] #by index
[ (x+y) % 2 for x, y in zip(a,b) ] #list comprehension
a = [0,1,0]
b = [1,1,1]
c = [1,0,0]
[ sum(vals) % 2 for vals in zip(a,b,c) ] #a+b+c
print(a)
print(b)
print(*zip(a,b))
print(*zip(a,a[1:]))
[1, 0, 1, 0]
0b1010
def berlekamp_massey(sequence):
s = list(map(int, sequence))
c = [1 if i==0 else 0 for i in range(len(s))]
b = c.copy()
l, m = 0, -1
for n in range(len(s)):
d = s[n]
for i in range(1, l+1):
d ^= c[i] & s[n-i]
if d == 1:
t = c.copy()
for i in range(len(s)-n+m):
c[i+n-m] ^= b[i]
if l <= n >> 1:
l, m = n+1-l, n
b = t
return sequence[:l], c[:l]
berlekamp_massey([1,1,0,0,0,1,1,1,0,0,0,1,1,1,0,0,0,1,1,1,0,0,0,1,1,1,0,0,0,1])
lfsr_first(*berlekamp_massey([1,1,0,0,0,1,1,1,0,0,0,1,1,1,0,0,0,1,1,1,0,0,0,1,1,1,0,0,0,1]), 25)
from operator import xor
from functools import reduce
def berlekamp_massey(sequence):
s = list(map(int, sequence))
c = [1 if i==0 else 0 for i in range(len(s))]
b = c.copy()
l, m = 0, -1
for n in range(len(s)):
if s[n] ^ reduce(xor, [c[i] & s[n-i] for i in range(1, l+1)], 0) == 1:
tmp = c.copy()
for i in range(len(s)-n+m):
c[i+n-m] ^= b[i]
if l <= n >> 1:
l, m = n+1-l, n
b = tmp
return sequence[:l], c[:l]
berlekamp_massey([1,1,0,0,0,1,1,1,0,0,0,1,1,1,0,0,0,1,1,1,0,0,0,1,1,1,0,0,0,1])