set f(8) 142
set f(7) 68
set f(6) 33
set f(5) 18
set f(4) 9
set f(3) 5
proc generate_gf {m} {
global f
set n [expr {(1 << $m) - 1}]
set GF 1
for {set i 0} {$i < $n} {incr i} {
set GF_exp($i) $GF
set GF_log($GF) $i
set feedback [expr {($GF >> ($m - 1)) & 1}]
if {$feedback != 0} {
set GF [expr {$GF ^ $f($m)}]
}
set GF [expr {(($GF << 1) | $feedback) & $n}]
}
return [list [array get GF_exp] [array get GF_log] $m $n]
}
proc gf_mul {a b GF} {
array set GF_exp [lindex $GF 0]
array set GF_log [lindex $GF 1]
set n [lindex $GF 3]
if {$a == 0 || $b == 0} {
return 0
}
set sum [expr {($GF_log($a) + $GF_log($b)) % $n}]
return $GF_exp($sum)
}
proc gf_div {a b GF} {
array set GF_exp [lindex $GF 0]
array set GF_log [lindex $GF 1]
set n [lindex $GF 3]
if {$a == 0 || $b == 0} {
return 0
}
set sub [expr {($GF_log($a) - $GF_log($b) + $n) % $n}]
return $GF_exp($sub)
}
proc gen_genpoly {t GF} {
array set GF_exp [lindex $GF 0]
set m [lindex $GF 2]
set y 1
for {set i 1} {$i <= 2 * $t} {incr i} {
set ay {}
for {set j 0} {$j < [llength $y]} {incr j} {
lappend ay [gf_mul $GF_exp($i) [lindex $y $j] $GF]
}
set y [linsert $y 0 0]
for {set j 0} {$j < [llength $ay]} {incr j} {
set y [lreplace $y $j $j [expr {[lindex $ay $j] ^ [lindex $y $j]}]]
}
}
return $y
}
proc encode {d genpoly t GF} {
set m [lindex $GF 2]
set n [lindex $GF 3]
set k [expr {$n - 2 * $t}]
set data $d
if {[llength $data] < $k} {
set lz [expr {$k - [llength $data]}]
for {set i 0} {$i < $lz} {incr i} {
lappend data 0
}
}
for {set i 0} {$i < [llength $genpoly] - 1} {incr i} {lappend reg 0}
for {set i 0} {$i < $k} {incr i} {
set new {}
set data_in [lindex $data [expr {$k - 1 - $i}]]
lappend d $data_in
set feedback [expr {[lindex $reg [expr {2 * $t - 1}]] ^ $data_in}]
lappend new [gf_mul $feedback [lindex $genpoly 0] $GF]
for {set j 1} {$j < [expr {2 * $t}]} {incr j} {
set mul [gf_mul $feedback [lindex $genpoly $j] $GF]
lappend new [expr {$mul ^ [lindex $reg $j-1]}]
}
lset reg $new
}
return [concat $reg $data]
}
proc decode {codeword genpoly t GF} {
set m [lindex $GF 2]
set n [lindex $GF 3]
set k [expr {$n - 2 * $t}]
array set GF_exp [lindex $GF 0]
array set GF_log [lindex $GF 1]
# Вычисление синдрома
for {set i 0} {$i <= [expr {2 * $t}]} {incr i} {set answer($i) 0}
for {set i 1} {$i <= [llength $codeword]} {incr i} {
set input [lindex $codeword [expr {$n - $i}]]
for {set j 0} {$j < [expr {2 * $t}]} {incr j} {
set answer($j) [expr {$input ^ [gf_mul $answer($j) $GF_exp([expr {$j + 1}]) $GF]}]
}
}
for {set j 0} {$j < [expr {2 * $t}]} {incr j} {
#puts "S($j) = $answer($j)"
}
# Вычисление полинома локаторов (методом Б-М)
set Lambda 1
set L 0
set r 0
set B 1
while 1 {
incr r
# Вычисление ошибки в следующей компоненте синдрома
set delta 0
for {set i 0} {$i <= $L} {incr i} {
set f [gf_mul [lindex $Lambda $i] $answer([expr {$r - $i - 1}]) $GF]
set delta [expr {$delta ^ $f}]
}
# Генерирует ли существующий регистр сдвига следующую компоненту синдрома?
if {$delta != 0} {
# Вычислить новый многочлен связей, для которого delta = 0
set xB [linsert $B 0 0]
set T {}
for {set i 0} {$i < [llength $xB]} {incr i} {
set Li [lindex $Lambda $i]
if {$Li == {}} {set Li 0}
lappend T [expr {[gf_mul $delta [lindex $xB $i] $GF] ^ $Li}]
}
# Надо ли увеличивать длину регистра?
if {[expr {2 * $L}] <= [expr {$r - 1}]} {
# Сохранение прежнего регистра после нормализации
set B {}
for {set i 0} {$i < [llength $Lambda]} {incr i} {
lappend B [gf_div [lindex $Lambda $i] $delta $GF]
}
# Модификация регистра сдвига
set Lambda $T
set L [expr {$r - $L}]
} else {
set Lambda $T
set B [linsert $B 0 0]
}
} else {
set B [linsert $B 0 0]
}
if {$r == [expr {2 * $t}]} break
}
#puts "L(x) = $Lambda, L = $L"
if {$Lambda == 1} {
return $codeword
}
# Вычисление корней полинома локаторов
set Lr {}
for {set i 1} {$i <= $n} {incr i} {
set L 0
set aj 1
for {set j 0} {$j < [llength $Lambda]} {incr j} {
set L [gf_mul [expr {$L ^ [lindex $Lambda [expr {[llength $Lambda] - $j - 1}]]}] $i $GF]
}
if {$L == 0} {
lappend U $GF_log([gf_div 1 $i $GF])
lappend Lr $i
}
}
# Вычисление значений ошибок
set msg_recov $codeword
set lambda_ {}
for {set i 1} {$i <= [llength $U]} {incr i} {
if {$i % 2 == 1} {
lappend lambda_ [lindex $Lambda $i]
} else {
lappend lambda_ 0
}
}
set omega {}
for {set q 0} {$q < [llength $U]} {incr q} {
set OMi 0
for {set i 0} {$i <= $q} {incr i} {
set Li [lindex $Lambda [expr {$i}]]
set Sqi $answer([expr {$q - $i}])
set OMi [expr {$OMi ^ [gf_mul $Li $Sqi $GF]}]
}
lappend omega $OMi
}
foreach u $Lr {
set A 0
for {set i 1} {$i <= [llength $omega]} {incr i} {
set A [expr {[lindex $omega [expr {[llength $omega] - $i}]] ^ [gf_mul $A $u $GF]}]
}
set B 0
for {set i 1} {$i <= [llength $lambda_]} {incr i} {
set B [expr {[lindex $lambda_ [expr {[llength $lambda_] - $i}]] ^ [gf_mul $B $u $GF]}]
}
set pos $GF_log([gf_div 1 $u $GF])
set val [expr {[gf_div $A $B $GF] ^ [lindex $msg_recov $pos]}]
set msg_recov [lreplace $msg_recov $pos $pos $val]
puts "исправлено позиция $pos, число $val"
}
return [lreplace $msg_recov 0 [expr {2 * $t - 1}] ]
}
proc print_multiplication_table {GF} {
array set GF_exp [lindex $GF 0]
array set GF_log [lindex $GF 1]
set n [lindex $GF 3]
for {set i 0} {$i <= $n} {incr i} {
for {set j 0} {$j <= $n} {incr j} {
puts "$i * $j = [gf_mul $i $j $GF]"
}
}
}
set m 8
set t 8
set GF [generate_gf $m]
set genpoly [gen_genpoly $t $GF]
puts "genpoly = $genpoly"
set M {122 222 43 74}
puts "Message = $M"
set codeword [encode $M $genpoly $t $GF]
puts "Кодовое слово"
puts "$codeword\n"
# Вносим ошибку
set codeword [lreplace $codeword 16 16 78]
set codeword [lreplace $codeword 17 17 55]
set codeword [lreplace $codeword 18 18 11]
set codeword [lreplace $codeword 19 19 11]
puts "Кодовое слово с внесенными ошибками"
puts "$codeword\n"
# Декодируем.
set decoded_msg [decode $codeword $genpoly $t $GF]
puts "Исправленное сообщение"
puts "$decoded_msg\n"