Implemented LFSR generator with tests and CLI integration

This commit is contained in:
AdrienCos 2019-06-04 15:28:02 -04:00 committed by Adrien Cosson
parent bf094c0361
commit 9f032fffbc
4 changed files with 325 additions and 0 deletions

View file

@ -115,6 +115,12 @@ if arguments.command != 'list-generators':
exit(1) exit(1)
try: try:
if (arguments.generator_function[0] == "LFSR"):
# Compute the size of the image for use by the LFSR generator if needed
tmp = tools.open_image(arguments.input_image_file)
size = tmp.width * tmp.height
tmp.close()
arguments.generator_function.append(size)
if (len(arguments.generator_function) > 1): if (len(arguments.generator_function) > 1):
generator = getattr(generators, arguments.generator_function[0])( generator = getattr(generators, arguments.generator_function[0])(
*[int(e) for e in arguments.generator_function[1:]]) *[int(e) for e in arguments.generator_function[1:]])

View file

@ -173,3 +173,59 @@ def log_gen() -> Iterator[int]:
adder = max(1, math.pow(10, int(math.log10(y)))) adder = max(1, math.pow(10, int(math.log10(y))))
yield int(y) yield int(y)
y = y + int(adder) y = y + int(adder)
polys = {2: [2, 1],
3: [3, 1],
4: [4, 1],
5: [5, 2],
6: [6, 1],
7: [7, 1],
8: [8, 4, 3, 2],
9: [9, 4],
10: [10, 3],
11: [11, 2],
12: [12, 6, 4, 1],
13: [13, 4, 3, 1],
14: [14, 8, 6, 1],
15: [15, 1],
16: [16, 12, 3, 1],
17: [17, 3],
18: [18, 7],
19: [19, 5, 2, 1],
20: [20, 3],
21: [21, 2],
22: [22, 1],
23: [23, 5],
24: [24, 7, 2, 1],
25: [25, 3],
26: [26, 6, 2, 1],
27: [27, 5, 2, 1],
28: [28, 3],
29: [29, 2],
30: [30, 23, 2, 1],
31: [31, 3]}
def LFSR(m: int) -> Iterator[int]:
"""LFSR generator of the given size
https://en.wikipedia.org/wiki/Linear-feedback_shift_register
"""
n: int = m.bit_length() - 1
# Set initial state to {1 0 0 ... 0}
state: List[bool] = [0] * n
state[0] = 1
feedback: bool = 0
poly: List[int] = polys[n]
while True:
# Compute the feedback bit
feedback = 0
for i in range(len(poly)):
feedback = feedback ^ state[poly[i] - 1]
# Roll the registers
state.pop()
# Add the feedback bit
state.insert(0, feedback)
# Convert the registers to an int
out = sum([e * (2**i) for i, e in enumerate(state)])
yield out

256
tests/expected-results/LFSR Normal file
View file

@ -0,0 +1,256 @@
2
5
11
22
44
88
177
99
199
143
30
61
122
244
232
208
161
67
135
15
31
63
127
255
254
252
249
242
228
200
144
33
66
133
10
20
41
83
167
79
159
62
125
250
245
234
213
170
85
171
87
174
92
184
112
224
193
131
6
12
24
49
98
197
138
21
43
86
172
89
179
102
204
153
50
101
203
151
47
95
191
126
253
251
247
239
222
188
121
243
230
205
155
55
110
221
187
119
238
220
185
114
229
202
149
42
84
169
82
165
74
148
40
81
162
68
137
18
37
75
150
45
90
180
104
209
163
70
140
25
51
103
206
156
57
115
231
207
158
60
120
241
227
198
141
27
54
108
216
176
97
194
132
8
17
34
69
139
23
46
93
186
117
235
215
175
94
189
123
246
237
219
183
111
223
190
124
248
240
225
195
134
13
26
52
105
211
166
77
154
53
107
214
173
91
182
109
218
181
106
212
168
80
160
65
130
4
9
19
39
78
157
59
118
236
217
178
100
201
146
36
73
147
38
76
152
48
96
192
129
3
7
14
29
58
116
233
210
164
72
145
35
71
142
28
56
113
226
196
136
16
32
64
128
1
2

View file

@ -128,6 +128,13 @@ class TestGenerators(unittest.TestCase):
self.assertEqual(next(gen), int(f.readline())) self.assertEqual(next(gen), int(f.readline()))
self.assertEqual(next(gen), int(f.readline())) self.assertEqual(next(gen), int(f.readline()))
def test_LFSR(self):
""" Test the LFSR generator
"""
with open('./tests/expected-results/LFSR', 'r') as f:
self.assertEqual(tuple(itertools.islice(generators.LFSR(2**8), 256)),
tuple(int(line) for line in f))
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()