initial commit
This commit is contained in:
95
python/latex_gen/alignment_gen.py
Normal file
95
python/latex_gen/alignment_gen.py
Normal file
@ -0,0 +1,95 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Generates latex table for alignment pattern locations
|
||||
|
||||
(C) 2022 Louis Heredero louis.heredero@edu.vs.ch
|
||||
"""
|
||||
|
||||
LOCATIONS = [
|
||||
[],
|
||||
[6, 18],
|
||||
[6, 22],
|
||||
[6, 26],
|
||||
[6, 30],
|
||||
[6, 34],
|
||||
[6, 22, 38],
|
||||
[6, 24, 42],
|
||||
[6, 26, 46],
|
||||
[6, 28, 50],
|
||||
[6, 30, 54],
|
||||
[6, 32, 58],
|
||||
[6, 34, 62],
|
||||
[6, 26, 46, 66],
|
||||
[6, 26, 48, 70],
|
||||
[6, 26, 50, 74],
|
||||
[6, 30, 54, 78],
|
||||
[6, 30, 56, 82],
|
||||
[6, 30, 58, 86],
|
||||
[6, 34, 62, 90],
|
||||
[6, 28, 50, 72, 94],
|
||||
[6, 26, 50, 74, 98],
|
||||
[6, 30, 54, 78, 102],
|
||||
[6, 28, 54, 80, 106],
|
||||
[6, 32, 58, 84, 110],
|
||||
[6, 30, 58, 86, 114],
|
||||
[6, 34, 62, 90, 118],
|
||||
[6, 26, 50, 74, 98, 122],
|
||||
[6, 30, 54, 78, 102, 126],
|
||||
[6, 26, 52, 78, 104, 130],
|
||||
[6, 30, 56, 82, 108, 134],
|
||||
[6, 34, 60, 86, 112, 138],
|
||||
[6, 30, 58, 86, 114, 142],
|
||||
[6, 34, 62, 90, 118, 146],
|
||||
[6, 30, 54, 78, 102, 126, 150],
|
||||
[6, 24, 50, 76, 102, 128, 154],
|
||||
[6, 28, 54, 80, 106, 132, 158],
|
||||
[6, 32, 58, 84, 110, 136, 162],
|
||||
[6, 26, 54, 82, 110, 138, 166],
|
||||
[6, 30, 58, 86, 114, 142, 170]
|
||||
]
|
||||
|
||||
start = r"""\def\arraystretch{1.2}
|
||||
\begin{center}
|
||||
\begin{longtabu}{|[2pt]c|c|c|c|c|c|c|c|[2pt]}
|
||||
\caption{Alignment pattern locations}
|
||||
\label{tab:qr_alignment}\\
|
||||
\tabucline[2pt]{-}
|
||||
Version & \multicolumn{7}{c|[2pt]}{Central x and y coordinates} \\
|
||||
\tabucline[2pt]{-}
|
||||
\endfirsthead
|
||||
\multicolumn{8}{r}{\emph{Continued from last page}}\\
|
||||
\hline
|
||||
Version & \multicolumn{7}{c|[2pt]}{Central x and y coordinates} \\
|
||||
\endhead
|
||||
Version & \multicolumn{7}{c|[2pt]}{Central x and y coordinates} \\
|
||||
\hline
|
||||
\multicolumn{8}{r}{\emph{Continued on next page}}\\
|
||||
\endfoot
|
||||
\tabucline[2pt]{-}
|
||||
\endlastfoot
|
||||
"""
|
||||
|
||||
end = r""" \hline
|
||||
\end{longtabu}
|
||||
\end{center}
|
||||
\def\arraystretch{1}
|
||||
"""
|
||||
|
||||
if __name__ == "__main__":
|
||||
with open("alignment.tex", "w") as f_tex:
|
||||
f_tex.write(start)
|
||||
|
||||
for i, row in enumerate(LOCATIONS):
|
||||
if i > 0:
|
||||
f_tex.write(" \\hline\n")
|
||||
|
||||
f_tex.write(f" {i+1:2}")
|
||||
|
||||
for j in range(7):
|
||||
val = row[j] if j < len(row) else ""
|
||||
f_tex.write(f" & {val:3}")
|
||||
|
||||
f_tex.write(" \\\\\n")
|
||||
|
||||
f_tex.write(end)
|
104
python/latex_gen/ec_converter.py
Normal file
104
python/latex_gen/ec_converter.py
Normal file
@ -0,0 +1,104 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Generates latex table for error correction information
|
||||
|
||||
(C) 2022 Louis Heredero louis.heredero@edu.vs.ch
|
||||
"""
|
||||
|
||||
levels = "LMQH"
|
||||
|
||||
start = r"""\def\arraystretch{1.5}
|
||||
\begin{table}[H]
|
||||
\centering
|
||||
\begin{longtabu}{|[2pt]c|c|c|c|c|c|c|c|[2pt]}
|
||||
\tabucline[2pt]{-}
|
||||
Version & Correction level & Data codewords & Error correction codewords per block & Blocks in group 1 & Data codewords per group 1 blocks & Blocks in group 2 & Data codewords per group 2 blocks \\
|
||||
\tabucline[2pt]{-}
|
||||
"""
|
||||
|
||||
end = r""" \tabucline[2pt]{-}
|
||||
\end{longtabu}
|
||||
\caption{Error correction characteristics}
|
||||
\label{tab:qr_error_correction}
|
||||
\end{table}
|
||||
\def\arraystretch{1}
|
||||
"""
|
||||
|
||||
|
||||
start = r"""\def\arraystretch{1.2}
|
||||
\begin{center}
|
||||
\begin{longtabu}{|[2pt]c|c|c|c|c|c|c|c|[2pt]}
|
||||
\caption{Error correction characteristics}
|
||||
\label{tab:qr_error_correction}\\
|
||||
\tabucline[2pt]{-}
|
||||
\rot{Version} & \rot{Correction level} & \rot{Data codewords} & \rot{\shortstack[l]{Error correction \\ codewords per block}} & \rot{Blocks in group 1} & \rot{\shortstack[l]{Data codewords per \\ group 1 blocks}} & \rot{Blocks in group 2} & \rot{\shortstack[l]{Data codewords per \\ group 2 blocks}} \\
|
||||
\tabucline[2pt]{-}
|
||||
\endfirsthead
|
||||
\multicolumn{8}{r}{\emph{Continued from last page}}\\
|
||||
\hline
|
||||
Ver & Level & Data CW & EC CW /B & Blocks G1 & CW G1 & Blocks G2 & CW G2 \\
|
||||
\endhead
|
||||
Ver & Level & Data CW & EC CW /B & Blocks G1 & CW G1 & Blocks G2 & CW G2 \\
|
||||
\hline
|
||||
\multicolumn{8}{r}{\emph{Continued on next page}}\\
|
||||
\endfoot
|
||||
\tabucline[2pt]{-}
|
||||
\endlastfoot
|
||||
"""
|
||||
|
||||
end = r""" \hline
|
||||
\end{longtabu}
|
||||
\end{center}
|
||||
\def\arraystretch{1}
|
||||
"""
|
||||
|
||||
if __name__ == "__main__":
|
||||
with open("error_correction.txt", "r") as f_txt, open("error_correction.tex", "w") as f_tex:
|
||||
ecs = f_txt.read().split("\n\n")
|
||||
|
||||
f_tex.write(start)
|
||||
|
||||
"""for i, version in enumerate(versions):
|
||||
lvls = version.split("\n")
|
||||
|
||||
if i > 0:
|
||||
f_tex.write(" \\hline\n")
|
||||
|
||||
f_tex.write(f" \\multirow{{4}}{{*}}{{{i+1:2}}}")
|
||||
# f_tex.write(f" {i+1:2}")
|
||||
|
||||
for j, lvl in enumerate(lvls):
|
||||
values = " & ".join(
|
||||
map(lambda s: f"{s:>4}", lvl.split("\t"))
|
||||
)
|
||||
|
||||
if j > 0:
|
||||
f_tex.write(" ")
|
||||
# f_tex.write(" ")
|
||||
|
||||
f_tex.write(
|
||||
f" & {levels[j]} & {values} \\\\{'*' if j < 3 else ''}\n")"""
|
||||
|
||||
for i, ec in enumerate(ecs):
|
||||
lvls = [list(map(int, lvl.split("\t"))) for lvl in ec.split("\n")]
|
||||
lvls = [lvl + [0]*(6-len(lvl)) for lvl in lvls]
|
||||
|
||||
if i > 0:
|
||||
f_tex.write(" \\hline\n")
|
||||
|
||||
f_tex.write(f" \\multirow{{4}}{{*}}{{{i+1:2}}}")
|
||||
|
||||
for j, lvl in enumerate(lvls):
|
||||
values = " & ".join(
|
||||
map(lambda s: f"{s:>4}", lvl)
|
||||
)
|
||||
|
||||
if j > 0:
|
||||
f_tex.write(" ")
|
||||
# f_tex.write(" ")
|
||||
|
||||
f_tex.write(
|
||||
f" & {levels[j]} & {values} \\\\{'*' if j < 3 else ''}\n")
|
||||
|
||||
f_tex.write(end)
|
199
python/latex_gen/error_correction.txt
Normal file
199
python/latex_gen/error_correction.txt
Normal file
@ -0,0 +1,199 @@
|
||||
19 7 1 19
|
||||
16 10 1 16
|
||||
13 13 1 13
|
||||
9 17 1 9
|
||||
|
||||
34 10 1 34
|
||||
28 16 1 28
|
||||
22 22 1 22
|
||||
16 28 1 16
|
||||
|
||||
55 15 1 55
|
||||
44 26 1 44
|
||||
34 18 2 17
|
||||
26 22 2 13
|
||||
|
||||
80 20 1 80
|
||||
64 18 2 32
|
||||
48 26 2 24
|
||||
36 16 4 9
|
||||
|
||||
108 26 1 108
|
||||
86 24 2 43
|
||||
62 18 2 15 2 16
|
||||
46 22 2 11 2 12
|
||||
|
||||
136 18 2 68
|
||||
108 16 4 27
|
||||
76 24 4 19
|
||||
60 28 4 15
|
||||
|
||||
156 20 2 78
|
||||
124 18 4 31
|
||||
88 18 2 14 4 15
|
||||
66 26 4 13 1 14
|
||||
|
||||
194 24 2 97
|
||||
154 22 2 38 2 39
|
||||
110 22 4 18 2 19
|
||||
86 26 4 14 2 15
|
||||
|
||||
232 30 2 116
|
||||
182 22 3 36 2 37
|
||||
132 20 4 16 4 17
|
||||
100 24 4 12 4 13
|
||||
|
||||
274 18 2 68 2 69
|
||||
216 26 4 43 1 44
|
||||
154 24 6 19 2 20
|
||||
122 28 6 15 2 16
|
||||
|
||||
324 20 4 81
|
||||
254 30 1 50 4 51
|
||||
180 28 4 22 4 23
|
||||
140 24 3 12 8 13
|
||||
|
||||
370 24 2 92 2 93
|
||||
290 22 6 36 2 37
|
||||
206 26 4 20 6 21
|
||||
158 28 7 14 4 15
|
||||
|
||||
428 26 4 107
|
||||
334 22 8 37 1 38
|
||||
244 24 8 20 4 21
|
||||
180 22 12 11 4 12
|
||||
|
||||
461 30 3 115 1 116
|
||||
365 24 4 40 5 41
|
||||
261 20 11 16 5 17
|
||||
197 24 11 12 5 13
|
||||
|
||||
523 22 5 87 1 88
|
||||
415 24 5 41 5 42
|
||||
295 30 5 24 7 25
|
||||
223 24 11 12 7 13
|
||||
|
||||
589 24 5 98 1 99
|
||||
453 28 7 45 3 46
|
||||
325 24 15 19 2 20
|
||||
253 30 3 15 13 16
|
||||
|
||||
647 28 1 107 5 108
|
||||
507 28 10 46 1 47
|
||||
367 28 1 22 15 23
|
||||
283 28 2 14 17 15
|
||||
|
||||
721 30 5 120 1 121
|
||||
563 26 9 43 4 44
|
||||
397 28 17 22 1 23
|
||||
313 28 2 14 19 15
|
||||
|
||||
795 28 3 113 4 114
|
||||
627 26 3 44 11 45
|
||||
445 26 17 21 4 22
|
||||
341 26 9 13 16 14
|
||||
|
||||
861 28 3 107 5 108
|
||||
669 26 3 41 13 42
|
||||
485 30 15 24 5 25
|
||||
385 28 15 15 10 16
|
||||
|
||||
932 28 4 116 4 117
|
||||
714 26 17 42
|
||||
512 28 17 22 6 23
|
||||
406 30 19 16 6 17
|
||||
|
||||
1006 28 2 111 7 112
|
||||
782 28 17 46
|
||||
568 30 7 24 16 25
|
||||
442 24 34 13
|
||||
|
||||
1094 30 4 121 5 122
|
||||
860 28 4 47 14 48
|
||||
614 30 11 24 14 25
|
||||
464 30 16 15 14 16
|
||||
|
||||
1174 30 6 117 4 118
|
||||
914 28 6 45 14 46
|
||||
664 30 11 24 16 25
|
||||
514 30 30 16 2 17
|
||||
|
||||
1276 26 8 106 4 107
|
||||
1000 28 8 47 13 48
|
||||
718 30 7 24 22 25
|
||||
538 30 22 15 13 16
|
||||
|
||||
1370 28 10 114 2 115
|
||||
1062 28 19 46 4 47
|
||||
754 28 28 22 6 23
|
||||
596 30 33 16 4 17
|
||||
|
||||
1468 30 8 122 4 123
|
||||
1128 28 22 45 3 46
|
||||
808 30 8 23 26 24
|
||||
628 30 12 15 28 16
|
||||
|
||||
1531 30 3 117 10 118
|
||||
1193 28 3 45 23 46
|
||||
871 30 4 24 31 25
|
||||
661 30 11 15 31 16
|
||||
|
||||
1631 30 7 116 7 117
|
||||
1267 28 21 45 7 46
|
||||
911 30 1 23 37 24
|
||||
701 30 19 15 26 16
|
||||
|
||||
1735 30 5 115 10 116
|
||||
1373 28 19 47 10 48
|
||||
985 30 15 24 25 25
|
||||
745 30 23 15 25 16
|
||||
|
||||
1843 30 13 115 3 116
|
||||
1455 28 2 46 29 47
|
||||
1033 30 42 24 1 25
|
||||
793 30 23 15 28 16
|
||||
|
||||
1955 30 17 115
|
||||
1541 28 10 46 23 47
|
||||
1115 30 10 24 35 25
|
||||
845 30 19 15 35 16
|
||||
|
||||
2071 30 17 115 1 116
|
||||
1631 28 14 46 21 47
|
||||
1171 30 29 24 19 25
|
||||
901 30 11 15 46 16
|
||||
|
||||
2191 30 13 115 6 116
|
||||
1725 28 14 46 23 47
|
||||
1231 30 44 24 7 25
|
||||
961 30 59 16 1 17
|
||||
|
||||
2306 30 12 121 7 122
|
||||
1812 28 12 47 26 48
|
||||
1286 30 39 24 14 25
|
||||
986 30 22 15 41 16
|
||||
|
||||
2434 30 6 121 14 122
|
||||
1914 28 6 47 34 48
|
||||
1354 30 46 24 10 25
|
||||
1054 30 2 15 64 16
|
||||
|
||||
2566 30 17 122 4 123
|
||||
1992 28 29 46 14 47
|
||||
1426 30 49 24 10 25
|
||||
1096 30 24 15 46 16
|
||||
|
||||
2702 30 4 122 18 123
|
||||
2102 28 13 46 32 47
|
||||
1502 30 48 24 14 25
|
||||
1142 30 42 15 32 16
|
||||
|
||||
2812 30 20 117 4 118
|
||||
2216 28 40 47 7 48
|
||||
1582 30 43 24 22 25
|
||||
1222 30 10 15 67 16
|
||||
|
||||
2956 30 19 118 6 119
|
||||
2334 28 18 47 31 48
|
||||
1666 30 34 24 34 25
|
||||
1276 30 20 15 61 16
|
99
python/latex_gen/hamming_gen.py
Normal file
99
python/latex_gen/hamming_gen.py
Normal file
@ -0,0 +1,99 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Generates latex tables for hamming codes
|
||||
|
||||
(C) 2022 Louis Heredero louis.heredero@edu.vs.ch
|
||||
"""
|
||||
|
||||
start = r""" \begin{tabu}{|[2pt]c|c|c|c|c|c|c|c|[2pt]}
|
||||
\tabucline[2pt]{-}
|
||||
& 1 & 2 & 3 & 4 & 5 & 6 & 7 \\
|
||||
\tabucline[1pt]{-}
|
||||
"""
|
||||
|
||||
end = r""" \tabucline[2pt]{-}
|
||||
\end{tabu}
|
||||
"""
|
||||
|
||||
class HammingError(Exception):
|
||||
pass
|
||||
|
||||
def encode(data, blocksize=7):
|
||||
A = start
|
||||
B = start
|
||||
|
||||
result = []
|
||||
datasize = blocksize-blocksize.bit_length()
|
||||
data = list(map(int, data))
|
||||
if len(data) % datasize:
|
||||
raise HammingError(f"Length of data is not a multiple of {datasize}")
|
||||
|
||||
nblocks = int(len(data)/datasize)
|
||||
|
||||
last = 0
|
||||
for b in range(nblocks):
|
||||
if b > 0:
|
||||
A += " \\hline\n"
|
||||
B += " \\hline\n"
|
||||
A += f" Group {b+1}"
|
||||
B += f" Group {b+1}"
|
||||
count = 0
|
||||
for i in range(blocksize):
|
||||
A += " & "
|
||||
count += data[0]
|
||||
# Power of 2
|
||||
if (i+1)&i == 0 or i == 0:
|
||||
A += "\_"
|
||||
result.append(0)
|
||||
|
||||
else:
|
||||
A += str(data[0])
|
||||
result.append(data.pop(0))
|
||||
A += " \\\\\n"
|
||||
|
||||
for i in range(blocksize.bit_length()):
|
||||
p = 1 << i
|
||||
c = sum([result[b*blocksize+j] for j in range(blocksize) if (j+1)&p])
|
||||
if c%2:
|
||||
result[b*blocksize+p-1] = 1
|
||||
|
||||
for i in range(blocksize):
|
||||
B += " & "
|
||||
B += str(result[b*blocksize+i])
|
||||
B += " \\\\\n"
|
||||
|
||||
if count == 0:
|
||||
if last >= 2:
|
||||
A = A.rsplit("\n",2)[0]
|
||||
A += "\n ... & ... & ... & ... & ... & ... & ... & ... \\\\\n"
|
||||
B = B.rsplit("\n",2)[0]
|
||||
B += "\n ... & ... & ... & ... & ... & ... & ... & ... \\\\\n"
|
||||
break
|
||||
last += 1
|
||||
else:
|
||||
last = 0
|
||||
|
||||
#return "".join(list(map(str, result)))
|
||||
A += end
|
||||
B += end
|
||||
|
||||
return A, B
|
||||
|
||||
if __name__ == "__main__":
|
||||
data = "00000000001111101011000010100110101100111"
|
||||
ds = 4
|
||||
total_bits = (3**2 * 24 - 6)
|
||||
data_bits = total_bits * ds // 7
|
||||
data += "0"*(ds-len(data)%ds)
|
||||
s = ""
|
||||
i = 0
|
||||
left = data_bits-len(data)
|
||||
while len(s) < left:
|
||||
s += f"{i:0b}"
|
||||
i += 1
|
||||
s = s[:left]
|
||||
data += s
|
||||
a, b = encode(data)
|
||||
print(a)
|
||||
print(b)
|
199
python/latex_gen/qr_versions.txt
Normal file
199
python/latex_gen/qr_versions.txt
Normal file
@ -0,0 +1,199 @@
|
||||
41 25 17 10
|
||||
34 20 14 8
|
||||
27 16 11 7
|
||||
17 10 7 4
|
||||
|
||||
77 47 32 20
|
||||
63 38 26 16
|
||||
48 29 20 12
|
||||
34 20 14 8
|
||||
|
||||
127 77 53 32
|
||||
101 61 42 26
|
||||
77 47 32 20
|
||||
58 35 24 15
|
||||
|
||||
187 114 78 48
|
||||
149 90 62 38
|
||||
111 67 46 28
|
||||
82 50 34 21
|
||||
|
||||
255 154 106 65
|
||||
202 122 84 52
|
||||
144 87 60 37
|
||||
106 64 44 27
|
||||
|
||||
322 195 134 82
|
||||
255 154 106 65
|
||||
178 108 74 45
|
||||
139 84 58 36
|
||||
|
||||
370 224 154 95
|
||||
293 178 122 75
|
||||
207 125 86 53
|
||||
154 93 64 39
|
||||
|
||||
461 279 192 118
|
||||
365 221 152 93
|
||||
259 157 108 66
|
||||
202 122 84 52
|
||||
|
||||
552 335 230 141
|
||||
432 262 180 111
|
||||
312 189 130 80
|
||||
235 143 98 60
|
||||
|
||||
652 395 271 167
|
||||
513 311 213 131
|
||||
364 221 151 93
|
||||
288 174 119 74
|
||||
|
||||
772 468 321 198
|
||||
604 366 251 155
|
||||
427 259 177 109
|
||||
331 200 137 85
|
||||
|
||||
883 535 367 226
|
||||
691 419 287 177
|
||||
489 296 203 125
|
||||
374 227 155 96
|
||||
|
||||
1022 619 425 262
|
||||
796 483 331 204
|
||||
580 352 241 149
|
||||
427 259 177 109
|
||||
|
||||
1101 667 458 282
|
||||
871 528 362 223
|
||||
621 376 258 159
|
||||
468 283 194 120
|
||||
|
||||
1250 758 520 320
|
||||
991 600 412 254
|
||||
703 426 292 180
|
||||
530 321 220 136
|
||||
|
||||
1408 854 586 361
|
||||
1082 656 450 277
|
||||
775 470 322 198
|
||||
602 365 250 154
|
||||
|
||||
1548 938 644 397
|
||||
1212 734 504 310
|
||||
876 531 364 224
|
||||
674 408 280 173
|
||||
|
||||
1725 1046 718 442
|
||||
1346 816 560 345
|
||||
948 574 394 243
|
||||
746 452 310 191
|
||||
|
||||
1903 1153 792 488
|
||||
1500 909 624 384
|
||||
1063 644 442 272
|
||||
813 493 338 208
|
||||
|
||||
2061 1249 858 528
|
||||
1600 970 666 410
|
||||
1159 702 482 297
|
||||
919 557 382 235
|
||||
|
||||
2232 1352 929 572
|
||||
1708 1035 711 438
|
||||
1224 742 509 314
|
||||
969 587 403 248
|
||||
|
||||
2409 1460 1003 618
|
||||
1872 1134 779 480
|
||||
1358 823 565 348
|
||||
1056 640 439 270
|
||||
|
||||
2620 1588 1091 672
|
||||
2059 1248 857 528
|
||||
1468 890 611 376
|
||||
1108 672 461 284
|
||||
|
||||
2812 1704 1171 721
|
||||
2188 1326 911 561
|
||||
1588 963 661 407
|
||||
1228 744 511 315
|
||||
|
||||
3057 1853 1273 784
|
||||
2395 1451 997 614
|
||||
1718 1041 715 440
|
||||
1286 779 535 330
|
||||
|
||||
3283 1990 1367 842
|
||||
2544 1542 1059 652
|
||||
1804 1094 751 462
|
||||
1425 864 593 365
|
||||
|
||||
3517 2132 1465 902
|
||||
2701 1637 1125 692
|
||||
1933 1172 805 496
|
||||
1501 910 625 385
|
||||
|
||||
3669 2223 1528 940
|
||||
2857 1732 1190 732
|
||||
2085 1263 868 534
|
||||
1581 958 658 405
|
||||
|
||||
3909 2369 1628 1002
|
||||
3035 1839 1264 778
|
||||
2181 1322 908 559
|
||||
1677 1016 698 430
|
||||
|
||||
4158 2520 1732 1066
|
||||
3289 1994 1370 843
|
||||
2358 1429 982 604
|
||||
1782 1080 742 457
|
||||
|
||||
4417 2677 1840 1132
|
||||
3486 2113 1452 894
|
||||
2473 1499 1030 634
|
||||
1897 1150 790 486
|
||||
|
||||
4686 2840 1952 1201
|
||||
3693 2238 1538 947
|
||||
2670 1618 1112 684
|
||||
2022 1226 842 518
|
||||
|
||||
4965 3009 2068 1273
|
||||
3909 2369 1628 1002
|
||||
2805 1700 1168 719
|
||||
2157 1307 898 553
|
||||
|
||||
5253 3183 2188 1347
|
||||
4134 2506 1722 1060
|
||||
2949 1787 1228 756
|
||||
2301 1394 958 590
|
||||
|
||||
5529 3351 2303 1417
|
||||
4343 2632 1809 1113
|
||||
3081 1867 1283 790
|
||||
2361 1431 983 605
|
||||
|
||||
5836 3537 2431 1496
|
||||
4588 2780 1911 1176
|
||||
3244 1966 1351 832
|
||||
2524 1530 1051 647
|
||||
|
||||
6153 3729 2563 1577
|
||||
4775 2894 1989 1224
|
||||
3417 2071 1423 876
|
||||
2625 1591 1093 673
|
||||
|
||||
6479 3927 2699 1661
|
||||
5039 3054 2099 1292
|
||||
3599 2181 1499 923
|
||||
2735 1658 1139 701
|
||||
|
||||
6743 4087 2809 1729
|
||||
5313 3220 2213 1362
|
||||
3791 2298 1579 972
|
||||
2927 1774 1219 750
|
||||
|
||||
7089 4296 2953 1817
|
||||
5596 3391 2331 1435
|
||||
3993 2420 1663 1024
|
||||
3057 1852 1273 784
|
282
python/latex_gen/reed_solomon_gen.py
Normal file
282
python/latex_gen/reed_solomon_gen.py
Normal file
@ -0,0 +1,282 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Prints steps of Reed-Solomon decoding
|
||||
|
||||
(C) 2022 Louis Heredero louis.heredero@edu.vs.ch
|
||||
"""
|
||||
|
||||
class GF:
|
||||
def __init__(self, val):
|
||||
self.val = val
|
||||
|
||||
def copy(self):
|
||||
return GF(self.val)
|
||||
|
||||
def __add__(self, n):
|
||||
return GF(self.val ^ n.val)
|
||||
|
||||
def __sub__(self, n):
|
||||
return GF(self.val ^ n.val)
|
||||
|
||||
def __mul__(self, n):
|
||||
if self.val == 0 or n.val == 0:
|
||||
return GF(0)
|
||||
|
||||
return GF.EXP[GF.LOG[self.val].val + GF.LOG[n.val].val].copy()
|
||||
|
||||
def __truediv__(self, n):
|
||||
if n.val == 0:
|
||||
raise ZeroDivisionError
|
||||
if self.val == 0:
|
||||
return GF(0)
|
||||
|
||||
return GF.EXP[(GF.LOG[self.val].val + 255 - GF.LOG[n.val].val)%255].copy()
|
||||
|
||||
def __pow__(self, n):
|
||||
return GF.EXP[(GF.LOG[self.val].val * n.val)%255].copy()
|
||||
|
||||
def __repr__(self):
|
||||
return self.val.__repr__()
|
||||
#return f"GF({self.val})"
|
||||
|
||||
def log(self):
|
||||
return GF.LOG[self.val]
|
||||
|
||||
GF.EXP = [GF(0)]*512
|
||||
GF.LOG = [GF(0)]*256
|
||||
value = 1
|
||||
for exponent in range(255):
|
||||
GF.LOG[value] = GF(exponent)
|
||||
GF.EXP[exponent] = GF(value)
|
||||
value = ((value << 1) ^ 285) if value > 127 else value << 1
|
||||
|
||||
for i in range(255, 512):
|
||||
GF.EXP[i] = GF.EXP[i-255].copy()
|
||||
|
||||
|
||||
class Poly:
|
||||
def __init__(self, coefs):
|
||||
self.coefs = coefs.copy()
|
||||
|
||||
@property
|
||||
def deg(self):
|
||||
return len(self.coefs)
|
||||
|
||||
def copy(self):
|
||||
return Poly(self.coefs)
|
||||
|
||||
def __add__(self, p):
|
||||
d1, d2 = self.deg, p.deg
|
||||
deg = max(d1,d2)
|
||||
result = [GF(0) for i in range(deg)]
|
||||
|
||||
for i in range(d1):
|
||||
result[i + deg - d1] = self.coefs[i]
|
||||
|
||||
for i in range(d2):
|
||||
result[i + deg - d2] += p.coefs[i]
|
||||
|
||||
return Poly(result)
|
||||
|
||||
def __mul__(self, p):
|
||||
result = [GF(0) for i in range(self.deg+p.deg-1)]
|
||||
|
||||
for i in range(p.deg):
|
||||
for j in range(self.deg):
|
||||
result[i+j] += self.coefs[j] * p.coefs[i]
|
||||
|
||||
return Poly(result)
|
||||
|
||||
def __truediv__(self, p):
|
||||
dividend = self.coefs.copy()
|
||||
dividend += [GF(0) for i in range(p.deg-1)]
|
||||
quotient = []
|
||||
|
||||
for i in range(self.deg):
|
||||
coef = dividend[i] / p.coefs[0]
|
||||
quotient.append(coef)
|
||||
print("sub:", p*Poly([coef]))
|
||||
|
||||
for j in range(p.deg):
|
||||
dividend[i+j] -= p.coefs[j] * coef
|
||||
|
||||
print("rem:", dividend)
|
||||
print()
|
||||
|
||||
while dividend[0].val == 0:
|
||||
dividend.pop(0)
|
||||
|
||||
return [Poly(quotient), Poly(dividend)]
|
||||
|
||||
def __repr__(self):
|
||||
return f"<Poly {self.coefs}>"
|
||||
|
||||
def eval(self, x):
|
||||
y = GF(0)
|
||||
|
||||
for i in range(self.deg):
|
||||
y += self.coefs[i] * x**GF(self.deg-i-1)
|
||||
|
||||
return y
|
||||
|
||||
def del_lead_zeros(self):
|
||||
while len(self.coefs) > 1 and self.coefs[0].val == 0:
|
||||
self.coefs.pop(0)
|
||||
|
||||
if len(self.coefs) == 0:
|
||||
self.coefs = [GF(0)]
|
||||
|
||||
return self
|
||||
|
||||
def get_generator_poly(n):
|
||||
poly = Poly([GF(1)])
|
||||
|
||||
for i in range(n):
|
||||
poly *= Poly([GF(1), GF(2)**GF(i)])
|
||||
|
||||
return poly
|
||||
|
||||
class ReedSolomonException(Exception):
|
||||
pass
|
||||
|
||||
def correct(data, ec):
|
||||
n = len(ec)
|
||||
|
||||
data = Poly([GF(int(cw, 2)) for cw in data+ec])
|
||||
##print("data", list(map(lambda c:c.val, data.coefs)))
|
||||
print("r(x)", data)
|
||||
|
||||
syndrome = [0]*n
|
||||
corrupted = False
|
||||
for i in range(n):
|
||||
syndrome[i] = data.eval(GF.EXP[i])
|
||||
if syndrome[i].val != 0:
|
||||
corrupted = True
|
||||
|
||||
if not corrupted:
|
||||
print("No errors")
|
||||
return data
|
||||
|
||||
syndrome = Poly(syndrome[::-1])
|
||||
print("syndrome", syndrome)
|
||||
|
||||
#Find locator poly
|
||||
sigma, omega = euclidean_algorithm(Poly([GF(1)]+[GF(0) for i in range(n)]), syndrome, n)
|
||||
print("locator", sigma)
|
||||
print("evaluator", omega)
|
||||
error_loc = find_error_loc(sigma)
|
||||
print("location", error_loc)
|
||||
|
||||
error_mag = find_error_mag(omega, error_loc)
|
||||
print("mag", error_mag)
|
||||
|
||||
for i in range(len(error_loc)):
|
||||
pos = GF(error_loc[i]).log()
|
||||
pos = data.deg - pos.val - 1
|
||||
if pos < 0:
|
||||
raise ReedSolomonException("Bad error location")
|
||||
|
||||
data.coefs[pos] += GF(error_mag[i])
|
||||
|
||||
return data
|
||||
|
||||
def euclidean_algorithm(a, b, R):
|
||||
if a.deg < b.deg:
|
||||
a, b = b, a
|
||||
|
||||
r_last = a
|
||||
r = b
|
||||
t_last = Poly([GF(0)])
|
||||
t = Poly([GF(1)])
|
||||
|
||||
while r.deg-1 >= int(R/2):
|
||||
r_last_last = r_last
|
||||
t_last_last = t_last
|
||||
r_last = r
|
||||
t_last = t
|
||||
if r_last.coefs[0] == 0:
|
||||
raise ReedSolomonException("r_{i-1} was zero")
|
||||
|
||||
r = r_last_last
|
||||
q = Poly([GF(0)])
|
||||
denom_lead_term = r_last.coefs[0]
|
||||
dlt_inv = denom_lead_term ** GF(-1)
|
||||
I = 0
|
||||
while r.deg >= r_last.deg and r.coefs[0] != 0:
|
||||
I += 1
|
||||
deg_diff = r.deg - r_last.deg
|
||||
scale = r.coefs[0] * dlt_inv
|
||||
q += Poly([scale]+[GF(0) for i in range(deg_diff)])
|
||||
r += r_last * Poly([scale]+[GF(0) for i in range(deg_diff)])
|
||||
q.del_lead_zeros()
|
||||
r.del_lead_zeros()
|
||||
|
||||
if I > 100:
|
||||
raise ReedSolomonException("Too long")
|
||||
|
||||
t = (q * t_last).del_lead_zeros() + t_last_last
|
||||
t.del_lead_zeros()
|
||||
if r.deg >= r_last.deg:
|
||||
raise ReedSolomonException("Division algorithm failed to reduce polynomial")
|
||||
|
||||
sigma_tilde_at_zero = t.coefs[-1]
|
||||
if sigma_tilde_at_zero.val == 0:
|
||||
raise ReedSolomonException("sigma_tilde(0) was zero")
|
||||
|
||||
inv = Poly([sigma_tilde_at_zero ** GF(-1)])
|
||||
sigma = t * inv
|
||||
omega = r * inv
|
||||
|
||||
return [sigma, omega]
|
||||
|
||||
def find_error_loc(error_loc):
|
||||
num_errors = error_loc.deg-1
|
||||
if num_errors == 1:
|
||||
return [error_loc.coefs[-2].val]
|
||||
|
||||
result = [0]*num_errors
|
||||
e = 0
|
||||
i = 1
|
||||
while i < 256 and e < num_errors:
|
||||
if error_loc.eval(GF(i)).val == 0:
|
||||
result[e] = (GF(i) ** GF(-1)).val
|
||||
e += 1
|
||||
|
||||
i += 1
|
||||
|
||||
if e != num_errors:
|
||||
raise ReedSolomonException("Error locator degree does not match number of roots")
|
||||
|
||||
return result
|
||||
|
||||
def find_error_mag(error_eval, error_loc):
|
||||
s = len(error_loc)
|
||||
result = [0]*s
|
||||
for i in range(s):
|
||||
xi_inv = GF(error_loc[i]) ** GF(-1)
|
||||
denom = GF(1)
|
||||
for j in range(s):
|
||||
if i != j:
|
||||
denom *= GF(1) + GF(error_loc[j]) * xi_inv
|
||||
|
||||
result[i] = ( error_eval.eval(xi_inv) * (denom ** GF(-1)) ).val
|
||||
|
||||
return result
|
||||
|
||||
if __name__ == "__main__":
|
||||
m = Poly([GF(67),GF(111),GF(100),GF(101),GF(115)])
|
||||
g = get_generator_poly(4)
|
||||
print()
|
||||
print(g)
|
||||
print(m/g)
|
||||
print()
|
||||
|
||||
data = [67,111,110,101,115]
|
||||
#ec = [119,123,82]
|
||||
ec = [50,166,245,58]
|
||||
|
||||
data = [f"{n:08b}" for n in data]
|
||||
ec = [f"{n:08b}" for n in ec]
|
||||
|
||||
print(correct(data, ec))
|
78
python/latex_gen/version_converter.py
Normal file
78
python/latex_gen/version_converter.py
Normal file
@ -0,0 +1,78 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Generates latex table for version capacity information
|
||||
|
||||
(C) 2022 Louis Heredero louis.heredero@edu.vs.ch
|
||||
"""
|
||||
|
||||
levels = "LMQH"
|
||||
|
||||
start = r"""\def\arraystretch{1.5}
|
||||
\begin{table}[H]
|
||||
\centering
|
||||
\begin{longtabu}{|[2pt]c|c|c:c:c:c|[2pt]}
|
||||
\tabucline[2pt]{-}
|
||||
Version & Correction level & Numerical & Alphanumerical & Byte & Kanji \\
|
||||
\tabucline[2pt]{-}
|
||||
"""
|
||||
|
||||
end = r""" \tabucline[2pt]{-}
|
||||
\end{longtabu}
|
||||
\caption{Version capacities}
|
||||
\label{tab:qr_versions}
|
||||
\end{table}
|
||||
\def\arraystretch{1}
|
||||
"""
|
||||
|
||||
|
||||
start = r"""\def\arraystretch{1.2}
|
||||
\begin{center}
|
||||
\begin{longtabu}{|[2pt]c|c|c:c:c:c|[2pt]}
|
||||
\caption{Version capacities}
|
||||
\label{tab:qr_versions}\\
|
||||
\tabucline[2pt]{-}
|
||||
Version & Correction level & Numerical & Alphanumerical & Byte & Kanji \\
|
||||
\tabucline[2pt]{-}
|
||||
\endfirsthead
|
||||
\multicolumn{6}{r}{\emph{Continued from last page}}\\
|
||||
\endhead
|
||||
\multicolumn{6}{r}{\emph{Continued on next page}}\\
|
||||
\endfoot
|
||||
\tabucline[2pt]{-}
|
||||
\endlastfoot
|
||||
"""
|
||||
|
||||
end = r""" \hline
|
||||
\end{longtabu}
|
||||
\end{center}
|
||||
\def\arraystretch{1}
|
||||
"""
|
||||
|
||||
if __name__ == "__main__":
|
||||
with open("qr_versions.txt", "r") as f_txt, open("qr_versions.tex", "w") as f_tex:
|
||||
versions = f_txt.read().split("\n\n")
|
||||
|
||||
f_tex.write(start)
|
||||
|
||||
for i, version in enumerate(versions):
|
||||
lvls = version.split("\n")
|
||||
|
||||
if i > 0:
|
||||
f_tex.write(" \\hline\n")
|
||||
|
||||
f_tex.write(f" \\multirow{{4}}{{*}}{{{i+1:2}}}")
|
||||
#f_tex.write(f" {i+1:2}")
|
||||
|
||||
for j, lvl in enumerate(lvls):
|
||||
values = " & ".join(
|
||||
map(lambda s: f"{s:>4}", lvl.split("\t"))
|
||||
)
|
||||
|
||||
if j > 0:
|
||||
f_tex.write(" ")
|
||||
#f_tex.write(" ")
|
||||
|
||||
f_tex.write(f" & {levels[j]} & {values} \\\\{'*' if j < 3 else ''}\n")
|
||||
|
||||
f_tex.write(end)
|
Reference in New Issue
Block a user