4
0
Fork 0
WolfBox/addons/qr_code/reed_solomon.gd

77 lines
2.2 KiB
GDScript

# log -> exponent/antilog
static var _anti_log_table: PackedByteArray = []
# exponent/antilog -> log
static var _log_table: PackedByteArray = []
static func _static_init() -> void:
_create_log_anti_log_tables()
static func _anti_log(degree: int) -> int:
var res: int = 1
var alpha: int = 2
while degree != 0:
if degree & 1 == 1:
res = mul(res, alpha)
degree = degree >> 1
alpha = mul(alpha, alpha)
return res
static func _create_log_anti_log_tables() -> void:
_anti_log_table.resize(256)
_anti_log_table.fill(0)
_log_table.resize(256)
_log_table.fill(0)
for degree: int in range(0, 256):
var value: int = _anti_log(degree)
_anti_log_table[degree] = value
_log_table[value] = degree % 255
# Russian Peasant Multiplication algorithm, adapted to reed solomon
static func mul(lhs: int, rhs: int) -> int:
var res: int = 0
while rhs > 0:
if rhs & 1:
res = res ^ lhs
lhs = lhs << 1 # lhs * 2
rhs = rhs >> 1 # rhs / 2
if lhs & 256:
lhs = lhs ^ 0x11D
return res
static func generator_polynom(size: int) -> PackedByteArray:
var res: PackedByteArray = []
res.resize(size + 1)
res.fill(0)
res[0] = 1
var a_j: int = 1
for exp: int in range(0, size):
var cur_val: int = a_j
for cur_exp: int in range(1, exp + 1):
var old_res: int = res[cur_exp]
res[cur_exp] = cur_val ^ old_res
cur_val = mul(old_res, a_j)
res[exp + 1] = cur_val
a_j = mul(a_j, 0x02)
return res
static func encode(data: PackedByteArray, code_words: int) -> PackedByteArray:
assert(len(data) + code_words <= 255, "message to encode is to long")
var gen_poly: PackedByteArray = generator_polynom(code_words)
var enc_msg: PackedByteArray = []
enc_msg.resize(len(data) + len(gen_poly) - 1)
enc_msg.fill(0)
for idx: int in range(len(data)):
enc_msg[idx] = data[idx]
for idx: int in range(len(data)):
var coef: int = enc_msg[idx]
for p_idx: int in range(1, len(gen_poly)):
enc_msg[idx+p_idx] ^= mul(gen_poly[p_idx], coef)
return enc_msg.slice(len(data))