from dataclasses import dataclass
from typing import List, Optional, Callable
def int_to_bits(x: int, n: int) -> List[int]:
return [(x >> (n-1-i)) & 1 for i in range(n)]
def xor_all(values: List[int]) -> int:
s = 0
for v in values:
s ^= (v & 1)
return s
@dataclass
class LFSR:
n: int
taps: List[int]
state: List[int]
def step(self) -> int:
fb = 0
for d in self.taps:
fb ^= self.state[self.n - 1 - d]
out_bit = self.state[-1]
self.state = [fb] + self.state[:-1]
return out_bit
def generate(self, length: int) -> List[int]:
return [self.step() for _ in range(length)]
@dataclass
class NFSR:
n: int
feedback_fn: Callable[[List[int]], int]
feedforward_fn: Optional[Callable[[List[int]], int]] = None
state: List[int] = None
def step(self) -> int:
new_bit = self.feedback_fn(self.state)
out_bit = self.feedforward_fn(self.state) if self.feedforward_fn else self.state[-1]
self.state = [new_bit] + self.state[:-1]
return out_bit
def generate(self, length: int) -> List[int]:
return [self.step() for _ in range(length)]
# lfsr_min.py — LFSR for p(x)=x^7 + x^4 + x^2 + 1 (reducible)
# Fibonacci, right-shift; state = [s6..s0], taps at degrees {4,2,0}
def int_to_bits(x, n):
return [(x >> (n-1-i)) & 1 for i in range(n)]
class LFSR:
def __init__(self, n, taps_degrees, seed_bits):
self.n = n
self.taps = taps_degrees[:] # degrees (0..n-1)
self.state = seed_bits[:] # [s6..s0]
def step(self):
# feedback = XOR of degrees d => index = n-1-d
fb = 0
for d in self.taps:
fb ^= self.state[self.n-1-d]
out_bit = self.state[-1] # old LSB
self.state = [fb] + self.state[:-1] # right shift
return out_bit
def period(self, limit_mult=4):
start = self.state[:]
limit = (1 << self.n) * limit_mult
steps = 0
while steps < limit:
self.step()
steps += 1
if self.state == start:
return steps
return -1
if __name__ == "__main__":
n = 7
taps = [4, 2, 0] # x^7 + x^4 + x^2 + 1
seed_int = 0x5A # example non-zero seed = 90 = 0b1011010
seed = int_to_bits(seed_int, n)
l = LFSR(n, taps, seed[:])
per = l.period()
# regenerate one full cycle to show sequence
l = LFSR(n, taps, seed[:])
seq = [l.step() for _ in range(per if per > 0 else 64)]
print(f"Polynomial: x^{n} + x^4 + x^2 + 1 (reducible)")
print(f"n = {n}, seed = 0x{seed_int:X} -> {''.join(map(str, seed))}")
print(f"Measured period: {per} (expected ~63 for non-zero seeds)")
print("First 32 bits:", ''.join(map(str, seq[:32])))