From edf28dde00a64f501f65291e02d681ff381b4d9c Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Thu, 4 Apr 2024 07:33:42 +0500 Subject: [PATCH 01/70] adding Reed-Solomon codes to the ECC Module --- CHANGELOG.md | 4 + src/ecc/ECC.jl | 1 + src/ecc/codes/classical/reedsolomon.jl | 225 +++++++++++++++++++++++++ test/runtests.jl | 1 + test/test_ecc_reedsolomon.jl | 16 ++ 5 files changed, 247 insertions(+) create mode 100644 src/ecc/codes/classical/reedsolomon.jl create mode 100644 test/test_ecc_reedsolomon.jl diff --git a/CHANGELOG.md b/CHANGELOG.md index d7d162719..b6887fbca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,10 @@ # News +## v0.9.3 - 2024-04-04 + +- Added the classical Reed-Solomon code in the ECC module + ## v0.9.2 - 2024-04-02 - Provide more configuration options in the `PyBeliefProp` decoders. diff --git a/src/ecc/ECC.jl b/src/ecc/ECC.jl index dc3db969a..9f6a08e96 100644 --- a/src/ecc/ECC.jl +++ b/src/ecc/ECC.jl @@ -347,4 +347,5 @@ include("codes/toric.jl") include("codes/gottesman.jl") include("codes/surface.jl") include("codes/classical/reedmuller.jl") +include("codes/classical/reedsolomon.jl") end #module diff --git a/src/ecc/codes/classical/reedsolomon.jl b/src/ecc/codes/classical/reedsolomon.jl new file mode 100644 index 000000000..6fb098806 --- /dev/null +++ b/src/ecc/codes/classical/reedsolomon.jl @@ -0,0 +1,225 @@ +import Base: length, iterate, ==, <<, +, *, ÷, %, copy, zero, eltype + +# Define a structure for Reed-Solomon code +struct ReedSolomon{T<:Integer} + m::Int + e::Int +end + +# Constructor for Reed-Solomon +function ReedSolomon(m::Int, e::Int) + return ReedSolomon{Int}(m, e) +end + +# Define a structure for polynomials +struct Poly{T<:Integer} + coeff::Vector{T} +end + +# Precompute powers of 2 in GF(2^8) +const GF256 = let + tab = ones(UInt8, 255) + v = 1 + for i in 2:255 + v <<= 1 + if v > 255 + v = xor(v, 285) + end + tab[i] = v + end + tab +end + +# Precompute inverse of powers of 2 in GF(2^8) +const INV_GF256 = let + tab = Vector{UInt8}(undef, 255) + tab[GF256] .= 0:254 + tab +end + +# Compute power of 2 in GF(2^8) +GF256_POW2(n::Integer) = GF256[mod(n, 255) + 1] +GF256_POW2(n::UInt8) = GF256[n + 0x1 + (n == 0xff)] + +# Compute logarithm of a number in GF(2^8) +GF256_LOG2(n::Integer) = INV_GF256[n] + +# Compute inverse in GF(2^8) +G256INV(a::Integer) = GF256_POW2(0xff-GF256_LOG2(a)) + +# Precompute multiplication table in GF(2^8) +const GF256_MULT = [iszero(i * j) ? 0x0 : GF256_POW2(Int(GF256_LOG2(i)) + GF256_LOG2(j)) for i in 0:255, j in 0:255] + +# Precompute division table in GF(2^8) +const GF256_DIV = [iszero(i) ? 0x0 : GF256_POW2(Int(GF256_LOG2(i)) - GF256_LOG2(j)) for i in 0:255, j in 1:255] + +# Multiplication in GF(2^8) +function G256MULT(a::Integer, b::Integer) + return GF256_MULT[a + 1, b + 1] +end + +# Division in GF(2^8) +function G256DIV(a::Integer, b::Integer) + iszero(b) && throw(DivideError()) + return GF256_DIV[a + 1, b] +end + +# Check if polynomial is zero +iszeropoly(p::Poly) = all(iszero, p) + +# Remove trailing zeros from polynomial +rtrailingzeros(p::Poly) = rtrailingzeros!(copy(p)) +function rtrailingzeros!(p::Poly{T}) where T + iszeropoly(p) && return zero(Poly{T}) + deleteat!(p.coeff, findlast(!iszero, p.coeff) + 1:length(p)) + return p +end + +# Pad polynomial with zeros to a specified length +rpadzeros(p::Poly, n::Int) = rpadzeros!(copy(p), n) +function rpadzeros!(p::Poly{T}, n::Int) where T + length(p) > n && throw("rpadzeros: length(p) > n") + append!(p.coeff, zeros(T, n - length(p))) + return p +end + +# Get degree of polynomial +function deg(p::Poly) + iszeropoly(p) && return -1 + return findlast(!iszero, p.coeff) - 1 +end + +# Zero polynomial constructor +zero(::Type{Poly{T}}) where T = Poly{T}(zeros(T, 1)) + +# Unit polynomial constructor +unit(::Type{Poly{T}}) where T = Poly{T}(ones(T, 1)) + +# Copy polynomial +copy(p::Poly{T}) where T = Poly{T}(copy(p.coeff)) + +# Get length of polynomial +length(p::Poly) = length(p.coeff) + +# Iterator for polynomial +iterate(p::Poly) = iterate(p.coeff) +iterate(p::Poly, i) = iterate(p.coeff, i) + +# Element type of polynomial +eltype(::Poly{T}) where T = T + +# Check equality of polynomials +==(a::Poly, b::Poly)::Bool = iszeropoly(a + b) + +# Left shift for polynomial +<<(p::Poly{T}, n::Int) where T = Poly{T}(vcat(zeros(T, n), p.coeff)) + +# Addition of polynomials +function +(a::Poly{T}, b::Poly{T}) where T + l, o = max(length(a), length(b)), zero(T) + return Poly{T}([xor(get(a.coeff, i, o), get(b.coeff, i, o)) for i in 1:l]) +end + +# Scalar multiplication with polynomial +*(a::Integer, p::Poly{T}) where T = Poly{T}(G256MULT.(a, p.coeff)) +*(p::Poly{T}, a::Integer) where T = Poly{T}(G256MULT.(a, p.coeff)) + +# Multiplication of polynomials +function *(a::Poly{T}, b::Poly{T}) where T + polyproduct = Poly(zeros(T, length(a) + length(b) - 1)) + for (i, c1) in enumerate(a.coeff), (j, c2) in enumerate(b.coeff) + @inbounds polyproduct.coeff[i + j - 1] ⊻= G256MULT(c2, c1) + end + return polyproduct +end + +# Construct polynomial x^n +polynomial_xn(::Type{T}, n::Int) where T = Poly{T}(push!(zeros(T, n), one(T))) +polynomial_xn(n::Int) = polynomial_xn(UInt8, n) + +# Construct polynomial x^n padded to a specific length +function polynomial_xn(::Type{T}, n::Int, pad::Int) where T + pad > n || throw(DomainError("pad length $pad should be greater than the power $n")) + coef = zeros(T, pad) + coef[n+1] = one(T) + return Poly{T}(coef) +end +polynomial_xn(n::Int, pad::Int) = polynomial_xn(UInt8, n, pad) + +# Euclidean division of polynomials +euclidean_division(f::Poly, g::Poly) = euclidean_division!(copy(f), copy(g)) +function euclidean_division!(f::Poly{T}, g::Poly{T}) where T + g, f = rtrailingzeros!(g), rtrailingzeros!(f) + iszeropoly(g) && throw(DivideError()) + fcoef, gcoef, lf, lg = f.coeff, g.coeff, length(f), length(g) + gn = last(gcoef) + if isone(lg) + fcoef .= G256DIV.(fcoef, gn) + return f, zero(Poly{T}) + end + quodeg = lf - lg + quodeg < 0 && return zero(Poly{T}), f + @inbounds for i in 0:quodeg + leadterm = G256DIV(fcoef[end-i], gn) + for (j, c) in enumerate(gcoef) + fcoef[quodeg - i + j] ⊻= G256MULT(leadterm, c) + end + fcoef[end-i] = leadterm + end + quo = Poly{T}(fcoef[end-quodeg:end]) + deleteat!(fcoef, lf-quodeg:lf) + return quo, f +end + +# Division operator for polynomials +÷(f::Poly, g::Poly) = first(euclidean_division(f, g)) + +# Modulus operator for polynomials +%(f::Poly, g::Poly) = last(euclidean_division(f, g)) + +# Generate generator polynomial for Reed-Solomon code +generator(n::Int) = generator(UInt8, n) +generator(::Type{T}, n::Int) where T = prod([Poly{T}([GF256[i], one(T)]) for i in 1:n]) + +# Encode a message polynomial for Reed-Solomon code +function encodepoly(msgpoly::Poly{T}, n::Int) where T + f = msgpoly << n + f + f % generator(T, n) +end + +# Get error code from received polynomial for Reed-Solomon code +geterrcode(f::Poly{T}, n::Int) where T = rpadzeros!(f << n % generator(T, n), n) + +# Multiply matrices in GF(2^8) +function G256multmat(A::AbstractMatrix{T}, B::AbstractMatrix{T}) where T + (n, m), (p, q) = size(A), size(B) + m == p || throw(DimensionMismatch("A and B have different size")) + C = Array{T}(undef, n, q) + @inbounds for i in 1:n, j in 1:q + C[i, j] = @views reduce(xor, G256MULT.(A[i, :], B[:, j])) + end + return C +end + +# Multiply matrix with vector in GF(2^8) +function G256multmat(A::AbstractMatrix{T}, b::AbstractVector{T}) where T + (n, m) = size(A) + m == length(b) || throw(DimensionMismatch("A and b have different size")) + c = Vector{T}(undef, n) + @inbounds for i in 1:n + c[i] = @views reduce(xor, G256MULT.(A[i, :], b)) + end + return c +end + +# Generate generator matrix for Reed-Solomon code +function generator(rs::ReedSolomon) + G = Array{UInt8}(undef, rs.m + rs.e, rs.m) + g = generator(UInt8, rs.e) + @inbounds for i in 1:rs.m + xi = polynomial_xn(UInt8, i-1, rs.m) << rs.e + G[:, i] = (xi + xi % g).coeff + end + G = map(x -> x == 0 ? 0 : 1, G) + return G +end diff --git a/test/runtests.jl b/test/runtests.jl index b4846e7cb..90c8fa7c0 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -64,6 +64,7 @@ end @doset "ecc_encoding" @doset "ecc_gottesman" @doset "ecc_reedmuller" +@doset "ecc_reedsolomon" @doset "ecc_syndromes" @doset "ecc_throws" @doset "precompile" diff --git a/test/test_ecc_reedsolomon.jl b/test/test_ecc_reedsolomon.jl new file mode 100644 index 000000000..5723e1996 --- /dev/null +++ b/test/test_ecc_reedsolomon.jl @@ -0,0 +1,16 @@ +using Test +using Nemo +using Combinatorics +using LinearAlgebra +using QuantumClifford +using QuantumClifford.ECC +using QuantumClifford.ECC: AbstractECC, ReedSolomon + +test_cases = [(5, 3), (8, 2), (6, 4), (10, 5), (7, 2)] +@testset "# Test for the defining property of a Reed-Solomon codes" begin + for (i, (m, e)) in enumerate(test_cases) + rs_code = ReedSolomon(m, e) + G = generator(rs_code) + @test rank(G) == m + end +end From 04d0dc66355da7ecc917480a8cd0e869f1eb2f44 Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Thu, 4 Apr 2024 08:03:46 +0500 Subject: [PATCH 02/70] Polishing up tests --- src/ecc/ECC.jl | 4 +++- src/ecc/codes/classical/reedsolomon.jl | 7 +++++-- test/test_ecc_reedsolomon.jl | 3 +-- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/ecc/ECC.jl b/src/ecc/ECC.jl index 9f6a08e96..657f24cb7 100644 --- a/src/ecc/ECC.jl +++ b/src/ecc/ECC.jl @@ -12,7 +12,7 @@ using Nemo: ZZ, residue_ring, matrix abstract type AbstractECC end -export parity_checks, parity_checks_x, parity_checks_z, iscss, +export parity_checks, parity_checks_x, parity_checks_z, iscss, generator_matrix, code_n, code_s, code_k, rate, distance, isdegenerate, faults_matrix, naive_syndrome_circuit, shor_syndrome_circuit, naive_encoding_circuit, @@ -57,6 +57,8 @@ function iscss(c::AbstractECC) return iscss(typeof(c)) end +function generator_matrix end + parity_checks(s::Stabilizer) = s Stabilizer(c::AbstractECC) = parity_checks(c) MixedDestabilizer(c::AbstractECC; kwarg...) = MixedDestabilizer(Stabilizer(c); kwarg...) diff --git a/src/ecc/codes/classical/reedsolomon.jl b/src/ecc/codes/classical/reedsolomon.jl index 6fb098806..9b51a8a50 100644 --- a/src/ecc/codes/classical/reedsolomon.jl +++ b/src/ecc/codes/classical/reedsolomon.jl @@ -1,7 +1,10 @@ import Base: length, iterate, ==, <<, +, *, ÷, %, copy, zero, eltype # Define a structure for Reed-Solomon code -struct ReedSolomon{T<:Integer} + +abstract type ClassicalCode end + +struct ReedSolomon{T<:Integer} <: ClassicalCode m::Int e::Int end @@ -213,7 +216,7 @@ function G256multmat(A::AbstractMatrix{T}, b::AbstractVector{T}) where T end # Generate generator matrix for Reed-Solomon code -function generator(rs::ReedSolomon) +function generator_matrix(rs::ReedSolomon) G = Array{UInt8}(undef, rs.m + rs.e, rs.m) g = generator(UInt8, rs.e) @inbounds for i in 1:rs.m diff --git a/test/test_ecc_reedsolomon.jl b/test/test_ecc_reedsolomon.jl index 5723e1996..3e483e804 100644 --- a/test/test_ecc_reedsolomon.jl +++ b/test/test_ecc_reedsolomon.jl @@ -9,8 +9,7 @@ using QuantumClifford.ECC: AbstractECC, ReedSolomon test_cases = [(5, 3), (8, 2), (6, 4), (10, 5), (7, 2)] @testset "# Test for the defining property of a Reed-Solomon codes" begin for (i, (m, e)) in enumerate(test_cases) - rs_code = ReedSolomon(m, e) - G = generator(rs_code) + G = generator_matrix(ReedSolomon(m, e)) @test rank(G) == m end end From cba1d522335b1c773ebdda846945d781fc75615f Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Thu, 4 Apr 2024 16:46:36 +0500 Subject: [PATCH 03/70] Ordinary view of generator and full test --- src/ecc/codes/classical/reedsolomon.jl | 1 + test/test_ecc_reedsolomon.jl | 15 +++++++-------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/ecc/codes/classical/reedsolomon.jl b/src/ecc/codes/classical/reedsolomon.jl index 9b51a8a50..f6e6acfdb 100644 --- a/src/ecc/codes/classical/reedsolomon.jl +++ b/src/ecc/codes/classical/reedsolomon.jl @@ -223,6 +223,7 @@ function generator_matrix(rs::ReedSolomon) xi = polynomial_xn(UInt8, i-1, rs.m) << rs.e G[:, i] = (xi + xi % g).coeff end + G = G[end:-1:1, end:-1:1] G = map(x -> x == 0 ? 0 : 1, G) return G end diff --git a/test/test_ecc_reedsolomon.jl b/test/test_ecc_reedsolomon.jl index 3e483e804..df3631d1e 100644 --- a/test/test_ecc_reedsolomon.jl +++ b/test/test_ecc_reedsolomon.jl @@ -1,15 +1,14 @@ using Test -using Nemo -using Combinatorics using LinearAlgebra using QuantumClifford using QuantumClifford.ECC using QuantumClifford.ECC: AbstractECC, ReedSolomon -test_cases = [(5, 3), (8, 2), (6, 4), (10, 5), (7, 2)] -@testset "# Test for the defining property of a Reed-Solomon codes" begin - for (i, (m, e)) in enumerate(test_cases) - G = generator_matrix(ReedSolomon(m, e)) - @test rank(G) == m - end +@testset "Test ReedSolomon(m, e) Matrix Rank" begin + for m in 5:20 + for e in 2:10 + G = generator_matrix(ReedSolomon(m, e)) + @test rank(G) == m + end + end end From 258fc306b65f4e21a9deff8e47ee82f22eaafd5a Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Sat, 6 Apr 2024 06:20:51 +0500 Subject: [PATCH 04/70] using Nemo Finite Fields --- src/ecc/codes/classical/reedsolomon.jl | 238 ++----------------------- test/test_ecc_reedsolomon.jl | 41 ++++- 2 files changed, 51 insertions(+), 228 deletions(-) diff --git a/src/ecc/codes/classical/reedsolomon.jl b/src/ecc/codes/classical/reedsolomon.jl index f6e6acfdb..75029a117 100644 --- a/src/ecc/codes/classical/reedsolomon.jl +++ b/src/ecc/codes/classical/reedsolomon.jl @@ -1,229 +1,25 @@ -import Base: length, iterate, ==, <<, +, *, ÷, %, copy, zero, eltype -# Define a structure for Reed-Solomon code +struct ReedSolomon <: ClassicalCode + n::Int + k::Int + j::Int -abstract type ClassicalCode end - -struct ReedSolomon{T<:Integer} <: ClassicalCode - m::Int - e::Int -end - -# Constructor for Reed-Solomon -function ReedSolomon(m::Int, e::Int) - return ReedSolomon{Int}(m, e) -end - -# Define a structure for polynomials -struct Poly{T<:Integer} - coeff::Vector{T} -end - -# Precompute powers of 2 in GF(2^8) -const GF256 = let - tab = ones(UInt8, 255) - v = 1 - for i in 2:255 - v <<= 1 - if v > 255 - v = xor(v, 285) - end - tab[i] = v - end - tab -end - -# Precompute inverse of powers of 2 in GF(2^8) -const INV_GF256 = let - tab = Vector{UInt8}(undef, 255) - tab[GF256] .= 0:254 - tab -end - -# Compute power of 2 in GF(2^8) -GF256_POW2(n::Integer) = GF256[mod(n, 255) + 1] -GF256_POW2(n::UInt8) = GF256[n + 0x1 + (n == 0xff)] - -# Compute logarithm of a number in GF(2^8) -GF256_LOG2(n::Integer) = INV_GF256[n] - -# Compute inverse in GF(2^8) -G256INV(a::Integer) = GF256_POW2(0xff-GF256_LOG2(a)) - -# Precompute multiplication table in GF(2^8) -const GF256_MULT = [iszero(i * j) ? 0x0 : GF256_POW2(Int(GF256_LOG2(i)) + GF256_LOG2(j)) for i in 0:255, j in 0:255] - -# Precompute division table in GF(2^8) -const GF256_DIV = [iszero(i) ? 0x0 : GF256_POW2(Int(GF256_LOG2(i)) - GF256_LOG2(j)) for i in 0:255, j in 1:255] - -# Multiplication in GF(2^8) -function G256MULT(a::Integer, b::Integer) - return GF256_MULT[a + 1, b + 1] -end - -# Division in GF(2^8) -function G256DIV(a::Integer, b::Integer) - iszero(b) && throw(DivideError()) - return GF256_DIV[a + 1, b] -end - -# Check if polynomial is zero -iszeropoly(p::Poly) = all(iszero, p) - -# Remove trailing zeros from polynomial -rtrailingzeros(p::Poly) = rtrailingzeros!(copy(p)) -function rtrailingzeros!(p::Poly{T}) where T - iszeropoly(p) && return zero(Poly{T}) - deleteat!(p.coeff, findlast(!iszero, p.coeff) + 1:length(p)) - return p -end - -# Pad polynomial with zeros to a specified length -rpadzeros(p::Poly, n::Int) = rpadzeros!(copy(p), n) -function rpadzeros!(p::Poly{T}, n::Int) where T - length(p) > n && throw("rpadzeros: length(p) > n") - append!(p.coeff, zeros(T, n - length(p))) - return p -end - -# Get degree of polynomial -function deg(p::Poly) - iszeropoly(p) && return -1 - return findlast(!iszero, p.coeff) - 1 -end - -# Zero polynomial constructor -zero(::Type{Poly{T}}) where T = Poly{T}(zeros(T, 1)) - -# Unit polynomial constructor -unit(::Type{Poly{T}}) where T = Poly{T}(ones(T, 1)) - -# Copy polynomial -copy(p::Poly{T}) where T = Poly{T}(copy(p.coeff)) - -# Get length of polynomial -length(p::Poly) = length(p.coeff) - -# Iterator for polynomial -iterate(p::Poly) = iterate(p.coeff) -iterate(p::Poly, i) = iterate(p.coeff, i) - -# Element type of polynomial -eltype(::Poly{T}) where T = T - -# Check equality of polynomials -==(a::Poly, b::Poly)::Bool = iszeropoly(a + b) - -# Left shift for polynomial -<<(p::Poly{T}, n::Int) where T = Poly{T}(vcat(zeros(T, n), p.coeff)) - -# Addition of polynomials -function +(a::Poly{T}, b::Poly{T}) where T - l, o = max(length(a), length(b)), zero(T) - return Poly{T}([xor(get(a.coeff, i, o), get(b.coeff, i, o)) for i in 1:l]) -end - -# Scalar multiplication with polynomial -*(a::Integer, p::Poly{T}) where T = Poly{T}(G256MULT.(a, p.coeff)) -*(p::Poly{T}, a::Integer) where T = Poly{T}(G256MULT.(a, p.coeff)) - -# Multiplication of polynomials -function *(a::Poly{T}, b::Poly{T}) where T - polyproduct = Poly(zeros(T, length(a) + length(b) - 1)) - for (i, c1) in enumerate(a.coeff), (j, c2) in enumerate(b.coeff) - @inbounds polyproduct.coeff[i + j - 1] ⊻= G256MULT(c2, c1) - end - return polyproduct -end - -# Construct polynomial x^n -polynomial_xn(::Type{T}, n::Int) where T = Poly{T}(push!(zeros(T, n), one(T))) -polynomial_xn(n::Int) = polynomial_xn(UInt8, n) - -# Construct polynomial x^n padded to a specific length -function polynomial_xn(::Type{T}, n::Int, pad::Int) where T - pad > n || throw(DomainError("pad length $pad should be greater than the power $n")) - coef = zeros(T, pad) - coef[n+1] = one(T) - return Poly{T}(coef) -end -polynomial_xn(n::Int, pad::Int) = polynomial_xn(UInt8, n, pad) - -# Euclidean division of polynomials -euclidean_division(f::Poly, g::Poly) = euclidean_division!(copy(f), copy(g)) -function euclidean_division!(f::Poly{T}, g::Poly{T}) where T - g, f = rtrailingzeros!(g), rtrailingzeros!(f) - iszeropoly(g) && throw(DivideError()) - fcoef, gcoef, lf, lg = f.coeff, g.coeff, length(f), length(g) - gn = last(gcoef) - if isone(lg) - fcoef .= G256DIV.(fcoef, gn) - return f, zero(Poly{T}) - end - quodeg = lf - lg - quodeg < 0 && return zero(Poly{T}), f - @inbounds for i in 0:quodeg - leadterm = G256DIV(fcoef[end-i], gn) - for (j, c) in enumerate(gcoef) - fcoef[quodeg - i + j] ⊻= G256MULT(leadterm, c) - end - fcoef[end-i] = leadterm - end - quo = Poly{T}(fcoef[end-quodeg:end]) - deleteat!(fcoef, lf-quodeg:lf) - return quo, f -end - -# Division operator for polynomials -÷(f::Poly, g::Poly) = first(euclidean_division(f, g)) - -# Modulus operator for polynomials -%(f::Poly, g::Poly) = last(euclidean_division(f, g)) - -# Generate generator polynomial for Reed-Solomon code -generator(n::Int) = generator(UInt8, n) -generator(::Type{T}, n::Int) where T = prod([Poly{T}([GF256[i], one(T)]) for i in 1:n]) - -# Encode a message polynomial for Reed-Solomon code -function encodepoly(msgpoly::Poly{T}, n::Int) where T - f = msgpoly << n - f + f % generator(T, n) -end - -# Get error code from received polynomial for Reed-Solomon code -geterrcode(f::Poly{T}, n::Int) where T = rpadzeros!(f << n % generator(T, n), n) - -# Multiply matrices in GF(2^8) -function G256multmat(A::AbstractMatrix{T}, B::AbstractMatrix{T}) where T - (n, m), (p, q) = size(A), size(B) - m == p || throw(DimensionMismatch("A and B have different size")) - C = Array{T}(undef, n, q) - @inbounds for i in 1:n, j in 1:q - C[i, j] = @views reduce(xor, G256MULT.(A[i, :], B[:, j])) - end - return C -end - -# Multiply matrix with vector in GF(2^8) -function G256multmat(A::AbstractMatrix{T}, b::AbstractVector{T}) where T - (n, m) = size(A) - m == length(b) || throw(DimensionMismatch("A and b have different size")) - c = Vector{T}(undef, n) - @inbounds for i in 1:n - c[i] = @views reduce(xor, G256MULT.(A[i, :], b)) + function ReedSolomon(n, k, j) + if n < 0 || k < 0 || j < 0 || n >= 500 + throw(ArgumentError("Invalid parameters: n, k, j must be non-negative and n >= 500 in order to obtain a valid code and to remain tractable")) + end + new(n, k, j) end - return c end -# Generate generator matrix for Reed-Solomon code function generator_matrix(rs::ReedSolomon) - G = Array{UInt8}(undef, rs.m + rs.e, rs.m) - g = generator(UInt8, rs.e) - @inbounds for i in 1:rs.m - xi = polynomial_xn(UInt8, i-1, rs.m) << rs.e - G[:, i] = (xi + xi % g).coeff + r = ceil(Int, log2(rs.n + 1)) + t = div(rs.n - rs.k, 2) + GF2ͬ, a = finite_field(2, r, "a") + P, x = GF2ͬ[:x] + polynomial = x - a^rs.j + for i in 1:(2*t - 1) + polynomial *= (x - a^(rs.j + i)) end - G = G[end:-1:1, end:-1:1] - G = map(x -> x == 0 ? 0 : 1, G) - return G + return polynomial end diff --git a/test/test_ecc_reedsolomon.jl b/test/test_ecc_reedsolomon.jl index df3631d1e..d86789187 100644 --- a/test/test_ecc_reedsolomon.jl +++ b/test/test_ecc_reedsolomon.jl @@ -1,14 +1,41 @@ using Test -using LinearAlgebra +using Nemo using QuantumClifford using QuantumClifford.ECC using QuantumClifford.ECC: AbstractECC, ReedSolomon -@testset "Test ReedSolomon(m, e) Matrix Rank" begin - for m in 5:20 - for e in 2:10 - G = generator_matrix(ReedSolomon(m, e)) - @test rank(G) == m +@testset "Test ReedSolomon(n, k, j) Matrix Degree" begin + #RS (7, 3) code + for n in 7:7 + for k in 3:3 + for j in 2:500 + deg = ceil(Int, log2(n + 1)) + t = div(n - k, 2) + GF2ͬ, a = finite_field(2, deg, "a") + P, x = GF2ͬ[:x] + poly = x - a^j + for i in 1:(2*t - 1) + poly *= (x - a^(j + i)) + end + @test degree(poly) - div(deg, 2) == n - k - 1 + end end end -end + + # RS(255, 223) code + for n in 255:255 + for k in 223:223 + for j in 2:500 + deg = ceil(Int, log2(n + 1)) + t = div(n - k, 2) + GF2ͬ, a = finite_field(2, deg, "a") + P, x = GF2ͬ[:x] + poly = x - a^j + for i in 1:(2*t - 1) + poly *= (x - a^(j + i)) + end + @test degree(poly) == n - k + end + end + end +end \ No newline at end of file From af5b0783c0fe36c68e306f11199c5aa70ccc5c62 Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Sat, 6 Apr 2024 07:27:08 +0500 Subject: [PATCH 05/70] adding references, polishing up --- docs/src/references.bib | 37 ++++++++++++++++++++ docs/src/references.md | 4 +++ src/ecc/ECC.jl | 2 +- src/ecc/codes/classical/reedsolomon.jl | 5 +++ test/test_ecc_reedsolomon.jl | 48 ++++++++------------------ 5 files changed, 62 insertions(+), 34 deletions(-) diff --git a/docs/src/references.bib b/docs/src/references.bib index 9b550181a..2015c0406 100644 --- a/docs/src/references.bib +++ b/docs/src/references.bib @@ -337,3 +337,40 @@ @book{djordjevic2021quantum year={2021}, publisher={Academic Press} } + +@article{reed1960polynomial, + title={Polynomial codes over certain finite fields}, + author={Reed, Irving S and Solomon, Gustave}, + journal={Journal of the society for industrial and applied mathematics}, + volume={8}, + number={2}, + pages={300--304}, + year={1960}, + publisher={SIAM} +} + +@article{berlekamp1978readable, + title={Readable erasures improve the performance of Reed-Solomon codes (Corresp.)}, + author={Berlekamp, E and Ramsey, J}, + journal={IEEE Transactions on Information Theory}, + volume={24}, + number={5}, + pages={632--633}, + year={1978}, + publisher={IEEE} +} + +@book{wicker1999reed, + title={Reed-Solomon codes and their applications}, + author={Wicker, Stephen B and Bhargava, Vijay K}, + year={1999}, + publisher={John Wiley \& Sons} +} + +@article{sklar2001reed, + title={Reed-solomon codes}, + author={Sklar, Bernard}, + journal={Downloaded from URL http://www. informit. com/content/images/art. sub.--sklar7. sub.--reed-solomo-n/elementLinks/art. sub.--sklar7. sub.--reed-solomon. pdf}, + pages={1--33}, + year={2001} +} diff --git a/docs/src/references.md b/docs/src/references.md index eaaf7cb51..ade668948 100644 --- a/docs/src/references.md +++ b/docs/src/references.md @@ -43,6 +43,10 @@ For classical code construction routines: - [raaphorst2003reed](@cite) - [abbe2020reed](@cite) - [djordjevic2021quantum](@cite) +- [reed1960polynomial](@cite) +- [berlekamp1978readable](@cite) +- [wicker1999reed](cite) +- [sklar2001reed](cite) # References diff --git a/src/ecc/ECC.jl b/src/ecc/ECC.jl index 657f24cb7..b58e170c7 100644 --- a/src/ecc/ECC.jl +++ b/src/ecc/ECC.jl @@ -12,7 +12,7 @@ using Nemo: ZZ, residue_ring, matrix abstract type AbstractECC end -export parity_checks, parity_checks_x, parity_checks_z, iscss, generator_matrix, +export parity_checks, parity_checks_x, parity_checks_z, iscss, code_n, code_s, code_k, rate, distance, isdegenerate, faults_matrix, naive_syndrome_circuit, shor_syndrome_circuit, naive_encoding_circuit, diff --git a/src/ecc/codes/classical/reedsolomon.jl b/src/ecc/codes/classical/reedsolomon.jl index 75029a117..1868790b9 100644 --- a/src/ecc/codes/classical/reedsolomon.jl +++ b/src/ecc/codes/classical/reedsolomon.jl @@ -1,4 +1,9 @@ +"""The family of Reed-Solomon codes, as discovered by Reed and Solomon in their 1960 paper [reed1960polynomial](@cite). +You might be interested in consulting [wicker1999reed](@cite), [sklar2001reed](@cite), [berlekamp1978readable](cite) and [https://youtu.be/K26Ssr8H3ec?si=QOeohq_6I0Oyd8qu](@cite) as well. + +The ECC Zoo has an [entry for this family](https://errorcorrectionzoo.org/c/reed_solomon) +""" struct ReedSolomon <: ClassicalCode n::Int k::Int diff --git a/test/test_ecc_reedsolomon.jl b/test/test_ecc_reedsolomon.jl index d86789187..20b001ffd 100644 --- a/test/test_ecc_reedsolomon.jl +++ b/test/test_ecc_reedsolomon.jl @@ -4,38 +4,20 @@ using QuantumClifford using QuantumClifford.ECC using QuantumClifford.ECC: AbstractECC, ReedSolomon -@testset "Test ReedSolomon(n, k, j) Matrix Degree" begin - #RS (7, 3) code - for n in 7:7 - for k in 3:3 - for j in 2:500 - deg = ceil(Int, log2(n + 1)) - t = div(n - k, 2) - GF2ͬ, a = finite_field(2, deg, "a") - P, x = GF2ͬ[:x] - poly = x - a^j - for i in 1:(2*t - 1) - poly *= (x - a^(j + i)) - end - @test degree(poly) - div(deg, 2) == n - k - 1 +@testset "Test ReedSolomon(n, k, j) Polynomial Generator Degree" begin + # RS(7, 3), RS(255, 223), and RS(160, 128) codes + test_cases = [(7, 3), (225, 223), (160, 128)] + for (n, k) in test_cases + for j in 2:500 + deg = ceil(Int, log2(n + 1)) + t = div(n - k, 2) + GF2ͬ, a = finite_field(2, deg, "a") + P, x = GF2ͬ[:x] + poly = x - a^j + for i in 1:(2*t - 1) + poly *= (x - a^(j + i)) end - end + @test degree(poly) == n - k + end end - - # RS(255, 223) code - for n in 255:255 - for k in 223:223 - for j in 2:500 - deg = ceil(Int, log2(n + 1)) - t = div(n - k, 2) - GF2ͬ, a = finite_field(2, deg, "a") - P, x = GF2ͬ[:x] - poly = x - a^j - for i in 1:(2*t - 1) - poly *= (x - a^(j + i)) - end - @test degree(poly) == n - k - end - end - end -end \ No newline at end of file +end From d00cb319f1744ad39b6ccc5329325bdbf8c412cc Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Sat, 6 Apr 2024 14:38:26 +0500 Subject: [PATCH 06/70] adding message polynomial, parity check polynomial, codeword polynomial, references, and all known test cases --- docs/src/references.bib | 9 ++++++ docs/src/references.md | 1 + src/ecc/ECC.jl | 2 +- src/ecc/codes/classical/reedsolomon.jl | 38 ++++++++++++++++++++++---- test/test_ecc_reedsolomon.jl | 8 +++--- 5 files changed, 47 insertions(+), 11 deletions(-) diff --git a/docs/src/references.bib b/docs/src/references.bib index 2015c0406..30dbc31a8 100644 --- a/docs/src/references.bib +++ b/docs/src/references.bib @@ -349,6 +349,15 @@ @article{reed1960polynomial publisher={SIAM} } +@book{geisel1990tutorial, + title={Tutorial on Reed-Solomon Error Correction Coding}, + author={Geisel, W.A. and United States. National Aeronautics and Space Administration and Lyndon B. Johnson Space Center}, + series={NASA technical memorandum}, + url={https://books.google.com.pk/books?id=Uys2AQAAMAAJ}, + year={1990}, + publisher={National Aeronautics and Space Administration, Lyndon B. Johnson Space Center} +} + @article{berlekamp1978readable, title={Readable erasures improve the performance of Reed-Solomon codes (Corresp.)}, author={Berlekamp, E and Ramsey, J}, diff --git a/docs/src/references.md b/docs/src/references.md index ade668948..19af19c12 100644 --- a/docs/src/references.md +++ b/docs/src/references.md @@ -44,6 +44,7 @@ For classical code construction routines: - [abbe2020reed](@cite) - [djordjevic2021quantum](@cite) - [reed1960polynomial](@cite) +- [geisel1990tutorial](@cite) - [berlekamp1978readable](@cite) - [wicker1999reed](cite) - [sklar2001reed](cite) diff --git a/src/ecc/ECC.jl b/src/ecc/ECC.jl index b58e170c7..c7ae74ad8 100644 --- a/src/ecc/ECC.jl +++ b/src/ecc/ECC.jl @@ -57,7 +57,7 @@ function iscss(c::AbstractECC) return iscss(typeof(c)) end -function generator_matrix end +function generator_polynomial end parity_checks(s::Stabilizer) = s Stabilizer(c::AbstractECC) = parity_checks(c) diff --git a/src/ecc/codes/classical/reedsolomon.jl b/src/ecc/codes/classical/reedsolomon.jl index 1868790b9..f1060af25 100644 --- a/src/ecc/codes/classical/reedsolomon.jl +++ b/src/ecc/codes/classical/reedsolomon.jl @@ -1,6 +1,6 @@ """The family of Reed-Solomon codes, as discovered by Reed and Solomon in their 1960 paper [reed1960polynomial](@cite). -You might be interested in consulting [wicker1999reed](@cite), [sklar2001reed](@cite), [berlekamp1978readable](cite) and [https://youtu.be/K26Ssr8H3ec?si=QOeohq_6I0Oyd8qu](@cite) as well. +You might be interested in consulting [geisel1990tutorial](cite), [wicker1999reed](@cite), [sklar2001reed](@cite), [berlekamp1978readable](cite) and [https://youtu.be/K26Ssr8H3ec?si=QOeohq_6I0Oyd8qu](@cite) as well. The ECC Zoo has an [entry for this family](https://errorcorrectionzoo.org/c/reed_solomon) """ @@ -12,19 +12,45 @@ struct ReedSolomon <: ClassicalCode function ReedSolomon(n, k, j) if n < 0 || k < 0 || j < 0 || n >= 500 throw(ArgumentError("Invalid parameters: n, k, j must be non-negative and n >= 500 in order to obtain a valid code and to remain tractable")) - end + end new(n, k, j) end end -function generator_matrix(rs::ReedSolomon) +#section 3.3.2 [geisel1990tutorial](cite) for constructing custom message polynomial m(x) +function _message_polynomial_rs(k, a, an, x, positions) + message = 0*x + for pos in positions + if pos <= k + message += a^(an)*x^(pos) + else + throw(DomainError("Invalid bit positions: The number of bit positions [0th,..., kth] to assign coefficient values should be <= k")) + end + end + return message +end + +#section 3.3.2 [geisel1990tutorial](cite) for constructing parity_check polynomial ck(x) given m(x) and g(x) +function _parity_check_polynomial_rs(n, k, x, message, gx) + x_nminusk = x^(n - k) + ck = mod(x_nminusk*message, gx) + return ck +end + +#section 3.3.2 [geisel1990tutorial](cite) for constructing codeword polynomial c(x) given m(x) and ck(x) +function _codeword_polynomial_rs(message, ck) + cx = message + ck + return cx +end + +function generator_polynomial(rs::ReedSolomon) r = ceil(Int, log2(rs.n + 1)) t = div(rs.n - rs.k, 2) GF2ͬ, a = finite_field(2, r, "a") P, x = GF2ͬ[:x] - polynomial = x - a^rs.j + gx = x - a^rs.j for i in 1:(2*t - 1) - polynomial *= (x - a^(rs.j + i)) + gx *= (x - a^(rs.j + i)) end - return polynomial + return gx end diff --git a/test/test_ecc_reedsolomon.jl b/test/test_ecc_reedsolomon.jl index 20b001ffd..0cff58a4c 100644 --- a/test/test_ecc_reedsolomon.jl +++ b/test/test_ecc_reedsolomon.jl @@ -4,9 +4,9 @@ using QuantumClifford using QuantumClifford.ECC using QuantumClifford.ECC: AbstractECC, ReedSolomon -@testset "Test ReedSolomon(n, k, j) Polynomial Generator Degree" begin - # RS(7, 3), RS(255, 223), and RS(160, 128) codes - test_cases = [(7, 3), (225, 223), (160, 128)] +@testset "Test ReedSolomon(n, k, j) generator polynomial g(x) degree" begin + # RS(7, 3), RS((15, 9), RS(255, 223), RS(160, 128), RS(255, 251), (255, 239) and (255, 249) codes + test_cases = [(7, 3), (15, 9), (225, 223), (160, 128), (255, 251), (255, 239), (255, 249)] for (n, k) in test_cases for j in 2:500 deg = ceil(Int, log2(n + 1)) @@ -18,6 +18,6 @@ using QuantumClifford.ECC: AbstractECC, ReedSolomon poly *= (x - a^(j + i)) end @test degree(poly) == n - k - end + end end end From deb9750fdb78ed5579ad24ada11bb69e119bc0b6 Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Sat, 6 Apr 2024 18:18:06 +0500 Subject: [PATCH 07/70] Removing j from RS(paramaters list), n and k are sufficient --- src/ecc/codes/classical/reedsolomon.jl | 16 ++++++++-------- test/test_ecc_reedsolomon.jl | 25 ++++++++++++------------- 2 files changed, 20 insertions(+), 21 deletions(-) diff --git a/src/ecc/codes/classical/reedsolomon.jl b/src/ecc/codes/classical/reedsolomon.jl index f1060af25..c4b2c9761 100644 --- a/src/ecc/codes/classical/reedsolomon.jl +++ b/src/ecc/codes/classical/reedsolomon.jl @@ -7,13 +7,12 @@ The ECC Zoo has an [entry for this family](https://errorcorrectionzoo.org/c/reed struct ReedSolomon <: ClassicalCode n::Int k::Int - j::Int - function ReedSolomon(n, k, j) - if n < 0 || k < 0 || j < 0 || n >= 500 - throw(ArgumentError("Invalid parameters: n, k, j must be non-negative and n >= 500 in order to obtain a valid code and to remain tractable")) + function ReedSolomon(n, k) + if n < 0 || k < 0 || n > 500 + throw(ArgumentError("Invalid parameters: n and k must be non-negative and n > 500 in order to obtain a valid code and to remain tractable")) end - new(n, k, j) + new(n, k) end end @@ -48,9 +47,10 @@ function generator_polynomial(rs::ReedSolomon) t = div(rs.n - rs.k, 2) GF2ͬ, a = finite_field(2, r, "a") P, x = GF2ͬ[:x] - gx = x - a^rs.j - for i in 1:(2*t - 1) - gx *= (x - a^(rs.j + i)) + poly_zeros = 2*t + gx = x - a^poly_zeros + for i in poly_zeros:(poly_zeros + 2*t - 1) + gx *= (x - a^(poly_zeros + i)) end return gx end diff --git a/test/test_ecc_reedsolomon.jl b/test/test_ecc_reedsolomon.jl index 0cff58a4c..9330bae92 100644 --- a/test/test_ecc_reedsolomon.jl +++ b/test/test_ecc_reedsolomon.jl @@ -4,20 +4,19 @@ using QuantumClifford using QuantumClifford.ECC using QuantumClifford.ECC: AbstractECC, ReedSolomon -@testset "Test ReedSolomon(n, k, j) generator polynomial g(x) degree" begin - # RS(7, 3), RS((15, 9), RS(255, 223), RS(160, 128), RS(255, 251), (255, 239) and (255, 249) codes +@testset "Test ReedSolomon(n, k) generator polynomial g(x) degree" begin + # RS(7, 3), RS(15, 9), RS(255, 223), RS(160, 128), RS(255, 251), (255, 239) and (255, 249) codes test_cases = [(7, 3), (15, 9), (225, 223), (160, 128), (255, 251), (255, 239), (255, 249)] for (n, k) in test_cases - for j in 2:500 - deg = ceil(Int, log2(n + 1)) - t = div(n - k, 2) - GF2ͬ, a = finite_field(2, deg, "a") - P, x = GF2ͬ[:x] - poly = x - a^j - for i in 1:(2*t - 1) - poly *= (x - a^(j + i)) - end - @test degree(poly) == n - k - end + deg = ceil(Int, log2(n + 1)) + t = div(n - k, 2) + GF2ͬ, a = finite_field(2, deg, "a") + P, x = GF2ͬ[:x] + poly_zeros = 2*t + poly = x - a^poly_zeros + for i in poly_zeros:(poly_zeros + 2*t - 1) + poly *= (x - a^(poly_zeros + i)) + end + @test degree(poly) == n - k + 1 end end From dd91a68753fb618a4b4e09b0eb808bb0cf8a96fc Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Sat, 6 Apr 2024 18:57:33 +0500 Subject: [PATCH 08/70] Final Furbish --- src/ecc/codes/classical/reedsolomon.jl | 8 ++++---- test/test_ecc_reedsolomon.jl | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/ecc/codes/classical/reedsolomon.jl b/src/ecc/codes/classical/reedsolomon.jl index c4b2c9761..6c303882f 100644 --- a/src/ecc/codes/classical/reedsolomon.jl +++ b/src/ecc/codes/classical/reedsolomon.jl @@ -47,10 +47,10 @@ function generator_polynomial(rs::ReedSolomon) t = div(rs.n - rs.k, 2) GF2ͬ, a = finite_field(2, r, "a") P, x = GF2ͬ[:x] - poly_zeros = 2*t - gx = x - a^poly_zeros - for i in poly_zeros:(poly_zeros + 2*t - 1) - gx *= (x - a^(poly_zeros + i)) + pzeros = 2*t + gx = x - a^pzeros + for i in 1:(2*t - 1) + gx *= (x - a^(pzeros + i)) end return gx end diff --git a/test/test_ecc_reedsolomon.jl b/test/test_ecc_reedsolomon.jl index 9330bae92..9672a3809 100644 --- a/test/test_ecc_reedsolomon.jl +++ b/test/test_ecc_reedsolomon.jl @@ -12,11 +12,11 @@ using QuantumClifford.ECC: AbstractECC, ReedSolomon t = div(n - k, 2) GF2ͬ, a = finite_field(2, deg, "a") P, x = GF2ͬ[:x] - poly_zeros = 2*t - poly = x - a^poly_zeros - for i in poly_zeros:(poly_zeros + 2*t - 1) - poly *= (x - a^(poly_zeros + i)) + pzeros = 2*t + poly = x - a^pzeros + for i in 1:(2*t - 1) + poly *= (x - a^(pzeros + i)) end - @test degree(poly) == n - k + 1 + @test degree(poly) == n - k end end From 127461039ba118eb1ecfd8bd02a65a954b26c6b5 Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Sun, 7 Apr 2024 13:17:16 +0500 Subject: [PATCH 09/70] Adding Tests of BCH codes --- CHANGELOG.md | 5 +++-- docs/src/references.bib | 31 +++++++++++++++++++++++++++++++ docs/src/references.md | 7 +++++-- src/ecc/ECC.jl | 1 + src/ecc/codes/classical/bch.jl | 31 +++++++++++++++++++++++++++++++ test/runtests.jl | 1 + test/test_ecc_bch.jl | 24 ++++++++++++++++++++++++ test/test_ecc_reedsolomon.jl | 2 +- 8 files changed, 97 insertions(+), 5 deletions(-) create mode 100644 src/ecc/codes/classical/bch.jl create mode 100644 test/test_ecc_bch.jl diff --git a/CHANGELOG.md b/CHANGELOG.md index b6887fbca..dae5f9f67 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,9 +5,10 @@ # News -## v0.9.3 - 2024-04-04 +## v0.9.3 - 2024-04-07 -- Added the classical Reed-Solomon code in the ECC module +- Added the classical Reed-Solomon code to the ECC module +- Added the classical Bose–Chaudhuri–Hocquenghem (BCH) code to the ECC module ## v0.9.2 - 2024-04-02 diff --git a/docs/src/references.bib b/docs/src/references.bib index 30dbc31a8..5159de8bb 100644 --- a/docs/src/references.bib +++ b/docs/src/references.bib @@ -383,3 +383,34 @@ @article{sklar2001reed pages={1--33}, year={2001} } + +@article{hocquenghem1959codes, + title={Codes correcteurs d'erreurs}, + author={Hocquenghem, Alexis}, + journal={Chiffers}, + volume={2}, + pages={147--156}, + year={1959} +} + +@article{bose1960class, + title={On a class of error correcting binary group codes}, + author={Bose, Raj Chandra and Ray-Chaudhuri, Dwijendra K}, + journal={Information and control}, + volume={3}, + number={1}, + pages={68--79}, + year={1960}, + publisher={Elsevier} +} + +@article{bose1960further, + title={Further results on error correcting binary group codes}, + author={Bose, Raj Chandra and Ray-Chaudhuri, Dwijendra K}, + journal={Information and Control}, + volume={3}, + number={3}, + pages={279--290}, + year={1960}, + publisher={Elsevier} +} diff --git a/docs/src/references.md b/docs/src/references.md index 19af19c12..b9a04eb5f 100644 --- a/docs/src/references.md +++ b/docs/src/references.md @@ -46,8 +46,11 @@ For classical code construction routines: - [reed1960polynomial](@cite) - [geisel1990tutorial](@cite) - [berlekamp1978readable](@cite) -- [wicker1999reed](cite) -- [sklar2001reed](cite) +- [wicker1999reed](@cite) +- [sklar2001reed](@cite) +- [hocquenghem1959codes](@cite) +- [bose1960class](@cite) +- [bose1960further](@cite) # References diff --git a/src/ecc/ECC.jl b/src/ecc/ECC.jl index c7ae74ad8..8c4de738e 100644 --- a/src/ecc/ECC.jl +++ b/src/ecc/ECC.jl @@ -350,4 +350,5 @@ include("codes/gottesman.jl") include("codes/surface.jl") include("codes/classical/reedmuller.jl") include("codes/classical/reedsolomon.jl") +include("codes/classical/bch.jl") end #module diff --git a/src/ecc/codes/classical/bch.jl b/src/ecc/codes/classical/bch.jl new file mode 100644 index 000000000..90ef7f461 --- /dev/null +++ b/src/ecc/codes/classical/bch.jl @@ -0,0 +1,31 @@ +"""The family of Bose–Chaudhuri–Hocquenghem (BCH) codes discovered in 1959 by Alexis Hocquenghem [hocquenghem1959codes](@cite), and independently in 1960 by Raj Chandra Bose and D.K. Ray-Chaudhuri [bose1960class](@cite). + +You might be interested in consulting [bose1960further](@cite) as well. + +The ECC Zoo has an [entry for this family](https://errorcorrectionzoo.org/c/q-ary_bch) +""" +struct BCH <: ClassicalCode + n::Int + t::Int + + function BCH(n, t) + if n < 0 || t < 1 || n > 500 || t > 500 + throw(ArgumentError("Invalid parameters: n and t must be non-negative and < 500 in order to obtain a valid code and to remain tractable")) + end + new(n, t) + end +end + +function generator_polynomial(rs::BCH) + r = ceil(Int, log2(rs.n + 1)) + GF2同, a = finite_field(2, r, "a") + GF2x, x = GF(2)["x"]; + minimal_poly = FqPolyRingElem[] + for i in 1:(2*rs.t - 1) + if i % 2 != 0 + minimal_poly = [minimal_poly; minpoly(GF2x, a^i)] + end + end + gx = lcm(minimal_poly) + return gx +end diff --git a/test/runtests.jl b/test/runtests.jl index 90c8fa7c0..039f0d68b 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -65,6 +65,7 @@ end @doset "ecc_gottesman" @doset "ecc_reedmuller" @doset "ecc_reedsolomon" +@doset "ecc_bch" @doset "ecc_syndromes" @doset "ecc_throws" @doset "precompile" diff --git a/test/test_ecc_bch.jl b/test/test_ecc_bch.jl new file mode 100644 index 000000000..a38f98914 --- /dev/null +++ b/test/test_ecc_bch.jl @@ -0,0 +1,24 @@ +using Test +using Nemo +using QuantumClifford +using QuantumClifford.ECC +using QuantumClifford.ECC: AbstractECC + +@testset "Test BCH(n, t) generator polynomial g(x) universal property: mod(x^n - 1, g(x)) == 0" begin + n_cases = [7, 15, 31, 63, 127, 255] + for n in n_cases + for t in 1:20 + r = ceil(Int, log2(n + 1)) + GF2同, a = finite_field(2, r, "a") + GF2x, x = GF(2)["x"] + mx = FqPolyRingElem[] + for i in 1:(2*t - 1) + if i % 2 != 0 + mx = [mx; minpoly(GF2x, a^i)] + end + end + gx = lcm(mx) + @test mod(x^n - 1, gx) == 0 + end + end +end diff --git a/test/test_ecc_reedsolomon.jl b/test/test_ecc_reedsolomon.jl index 9672a3809..25d76d9d7 100644 --- a/test/test_ecc_reedsolomon.jl +++ b/test/test_ecc_reedsolomon.jl @@ -4,7 +4,7 @@ using QuantumClifford using QuantumClifford.ECC using QuantumClifford.ECC: AbstractECC, ReedSolomon -@testset "Test ReedSolomon(n, k) generator polynomial g(x) degree" begin +@testset "Test ReedSolomon(n, k) generator polynomial g(x) degree" begin # RS(7, 3), RS(15, 9), RS(255, 223), RS(160, 128), RS(255, 251), (255, 239) and (255, 249) codes test_cases = [(7, 3), (15, 9), (225, 223), (160, 128), (255, 251), (255, 239), (255, 249)] for (n, k) in test_cases From 3028039b1564ad96b35e7334d8c98c14d2b70a5f Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Sun, 7 Apr 2024 14:19:22 +0500 Subject: [PATCH 10/70] classical BCH codes --- src/ecc/codes/classical/bch.jl | 6 +++--- test/test_ecc_bch.jl | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ecc/codes/classical/bch.jl b/src/ecc/codes/classical/bch.jl index 90ef7f461..7867e20df 100644 --- a/src/ecc/codes/classical/bch.jl +++ b/src/ecc/codes/classical/bch.jl @@ -1,4 +1,4 @@ -"""The family of Bose–Chaudhuri–Hocquenghem (BCH) codes discovered in 1959 by Alexis Hocquenghem [hocquenghem1959codes](@cite), and independently in 1960 by Raj Chandra Bose and D.K. Ray-Chaudhuri [bose1960class](@cite). +"""The family of Bose–Chaudhuri–Hocquenghem (BCH) codes, as discovered in 1959 by Alexis Hocquenghem [hocquenghem1959codes](@cite), and independently in 1960 by Raj Chandra Bose and D.K. Ray-Chaudhuri [bose1960class](@cite). You might be interested in consulting [bose1960further](@cite) as well. @@ -18,8 +18,8 @@ end function generator_polynomial(rs::BCH) r = ceil(Int, log2(rs.n + 1)) - GF2同, a = finite_field(2, r, "a") - GF2x, x = GF(2)["x"]; + GF2ͬ, a = finite_field(2, r, "a") + GF2x, x = GF(2)["x"] minimal_poly = FqPolyRingElem[] for i in 1:(2*rs.t - 1) if i % 2 != 0 diff --git a/test/test_ecc_bch.jl b/test/test_ecc_bch.jl index a38f98914..76e132ba7 100644 --- a/test/test_ecc_bch.jl +++ b/test/test_ecc_bch.jl @@ -9,7 +9,7 @@ using QuantumClifford.ECC: AbstractECC for n in n_cases for t in 1:20 r = ceil(Int, log2(n + 1)) - GF2同, a = finite_field(2, r, "a") + GF2ͬ, a = finite_field(2, r, "a") GF2x, x = GF(2)["x"] mx = FqPolyRingElem[] for i in 1:(2*t - 1) From 323caf3efeb8dcb4117b027972389712293c5ce2 Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Sun, 14 Apr 2024 14:55:19 +0500 Subject: [PATCH 11/70] Proper lower and upper bounds for n and t for BCH codes --- CHANGELOG.md | 2 +- src/ecc/codes/classical/bch.jl | 9 +++++---- test/test_ecc_bch.jl | 3 ++- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dae5f9f67..73966d132 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ # News -## v0.9.3 - 2024-04-07 +## v0.9.3 - 2024-04-14 - Added the classical Reed-Solomon code to the ECC module - Added the classical Bose–Chaudhuri–Hocquenghem (BCH) code to the ECC module diff --git a/src/ecc/codes/classical/bch.jl b/src/ecc/codes/classical/bch.jl index 7867e20df..cf1a144a7 100644 --- a/src/ecc/codes/classical/bch.jl +++ b/src/ecc/codes/classical/bch.jl @@ -5,12 +5,13 @@ You might be interested in consulting [bose1960further](@cite) as well. The ECC Zoo has an [entry for this family](https://errorcorrectionzoo.org/c/q-ary_bch) """ struct BCH <: ClassicalCode - n::Int - t::Int + n::Int + t::Int #Error correction capability; t bits can be corrected function BCH(n, t) - if n < 0 || t < 1 || n > 500 || t > 500 - throw(ArgumentError("Invalid parameters: n and t must be non-negative and < 500 in order to obtain a valid code and to remain tractable")) + if n < 6 || n > 500 || t < 0 || t > 2^(ceil(Int, log2(n + 1)) - 1) + throw(ArgumentError("Invalid parameters: 'n' and 't' must be positive, and 'r' must be >= to 3. Additionally, 'n' is >= to 7 since n = 2ͬ - 1 and 't' < 2^(r - 1), to obtain a valid code and to tractable.")) + end new(n, t) end diff --git a/test/test_ecc_bch.jl b/test/test_ecc_bch.jl index 76e132ba7..345930813 100644 --- a/test/test_ecc_bch.jl +++ b/test/test_ecc_bch.jl @@ -7,7 +7,8 @@ using QuantumClifford.ECC: AbstractECC @testset "Test BCH(n, t) generator polynomial g(x) universal property: mod(x^n - 1, g(x)) == 0" begin n_cases = [7, 15, 31, 63, 127, 255] for n in n_cases - for t in 1:20 + #Testing all 1 Bit, 2 Bit, 3 Bit and 4 Bit BCH codes for n_cases + for t in 1:4 r = ceil(Int, log2(n + 1)) GF2ͬ, a = finite_field(2, r, "a") GF2x, x = GF(2)["x"] From 34ff28b49e3a02fbeba5878ff4bcca93366b525c Mon Sep 17 00:00:00 2001 From: Feroz <93876775+Fe-r-oz@users.noreply.github.com> Date: Thu, 18 Apr 2024 22:38:15 +0500 Subject: [PATCH 12/70] Update src/ecc/codes/classical/reedsolomon.jl Co-authored-by: Stefan Krastanov --- src/ecc/codes/classical/reedsolomon.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ecc/codes/classical/reedsolomon.jl b/src/ecc/codes/classical/reedsolomon.jl index 6c303882f..1ad8fd7e9 100644 --- a/src/ecc/codes/classical/reedsolomon.jl +++ b/src/ecc/codes/classical/reedsolomon.jl @@ -12,7 +12,7 @@ struct ReedSolomon <: ClassicalCode if n < 0 || k < 0 || n > 500 throw(ArgumentError("Invalid parameters: n and k must be non-negative and n > 500 in order to obtain a valid code and to remain tractable")) end - new(n, k) + new(n, k) end end From 88bb42d6cab922deb9a3aaca3862ab7babe4e218 Mon Sep 17 00:00:00 2001 From: Feroz <93876775+Fe-r-oz@users.noreply.github.com> Date: Thu, 18 Apr 2024 22:38:28 +0500 Subject: [PATCH 13/70] Update src/ecc/codes/classical/bch.jl Co-authored-by: Stefan Krastanov --- src/ecc/codes/classical/bch.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ecc/codes/classical/bch.jl b/src/ecc/codes/classical/bch.jl index cf1a144a7..317437d95 100644 --- a/src/ecc/codes/classical/bch.jl +++ b/src/ecc/codes/classical/bch.jl @@ -13,7 +13,7 @@ struct BCH <: ClassicalCode throw(ArgumentError("Invalid parameters: 'n' and 't' must be positive, and 'r' must be >= to 3. Additionally, 'n' is >= to 7 since n = 2ͬ - 1 and 't' < 2^(r - 1), to obtain a valid code and to tractable.")) end - new(n, t) + new(n, t) end end From 976dd45c44b06c2d0f6e19b19e9306a200a085c9 Mon Sep 17 00:00:00 2001 From: Feroz <93876775+Fe-r-oz@users.noreply.github.com> Date: Thu, 18 Apr 2024 22:38:41 +0500 Subject: [PATCH 14/70] Update src/ecc/codes/classical/bch.jl Co-authored-by: Stefan Krastanov --- src/ecc/codes/classical/bch.jl | 1 - 1 file changed, 1 deletion(-) diff --git a/src/ecc/codes/classical/bch.jl b/src/ecc/codes/classical/bch.jl index 317437d95..b92254ff4 100644 --- a/src/ecc/codes/classical/bch.jl +++ b/src/ecc/codes/classical/bch.jl @@ -11,7 +11,6 @@ struct BCH <: ClassicalCode function BCH(n, t) if n < 6 || n > 500 || t < 0 || t > 2^(ceil(Int, log2(n + 1)) - 1) throw(ArgumentError("Invalid parameters: 'n' and 't' must be positive, and 'r' must be >= to 3. Additionally, 'n' is >= to 7 since n = 2ͬ - 1 and 't' < 2^(r - 1), to obtain a valid code and to tractable.")) - end new(n, t) end From ae952de45d256ed79dab98940e97f57ebf6dcdeb Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Fri, 19 Apr 2024 16:07:00 +0500 Subject: [PATCH 15/70] parity check matrix for BCH --- CHANGELOG.md | 4 +++- src/ecc/ECC.jl | 3 ++- src/ecc/codes/classical/bch.jl | 25 +++++++++++++++++++++++++ 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9ac98a713..b53bdcf82 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,10 +5,12 @@ # News -## v0.9.4 - 2024-04-14 +## v0.9.4 - dev - Added the classical Reed-Solomon code to the ECC module - Added the classical Bose–Chaudhuri–Hocquenghem (BCH) code to the ECC module +- Gate errors are now conveniently supported by the various ECC benchmark setups in the `ECC` module. +- Remove printing of spurious debug info from the PyBP decoder. ## v0.9.3 - 2024-04-10 diff --git a/src/ecc/ECC.jl b/src/ecc/ECC.jl index eb023d31b..79fb48c05 100644 --- a/src/ecc/ECC.jl +++ b/src/ecc/ECC.jl @@ -18,7 +18,7 @@ export parity_checks, parity_checks_x, parity_checks_z, iscss, naive_syndrome_circuit, shor_syndrome_circuit, naive_encoding_circuit, RepCode, CSS, - Shor9, Steane7, Cleve8, Perfect5, Bitflip3, + Shor9, Steane7, Cleve8, Perfect5, Bitflip3, SteaneReedMuller, Toric, Gottesman, Surface, evaluate_decoder, CommutationCheckECCSetup, NaiveSyndromeECCSetup, ShorSyndromeECCSetup, @@ -351,4 +351,5 @@ include("codes/surface.jl") include("codes/classical/reedmuller.jl") include("codes/classical/reedsolomon.jl") include("codes/classical/bch.jl") +include("codes/steanereedmuller.jl") end #module diff --git a/src/ecc/codes/classical/bch.jl b/src/ecc/codes/classical/bch.jl index cf1a144a7..b8b2186f2 100644 --- a/src/ecc/codes/classical/bch.jl +++ b/src/ecc/codes/classical/bch.jl @@ -30,3 +30,28 @@ function generator_polynomial(rs::BCH) gx = lcm(minimal_poly) return gx end + +function parity_checks(rs::BCH) + r = ceil(Int, log2(rs.n + 1)) + GF2ͬ, a = finite_field(2, r, "a") + HField = Matrix{FqFieldElem}(undef, rs.t, rs.n) + for i in 1:rs.t + for j in 1:rs.n + base = 2*i - 1 + HField[i, j] = base^(j-1) * a^(j-1) + end + end + H = Matrix{Bool}(undef, r*rs.t, rs.n) + for i in 1:rs.t + row_start = (i - 1) * r + 1 + row_end = row_start + r - 1 + for j in 1:rs.n + t_tuple = Bool[] + for k in 0:r - 1 + t_tuple = [t_tuple; !is_zero(coeff(HField[i, j], k))] + end + H[row_start:row_end, :] .= vec(t_tuple') + end + end + return H +end From 1f277434accf48339c322ba989236d3f26080ebf Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Fri, 19 Apr 2024 16:18:48 +0500 Subject: [PATCH 16/70] solving conflicts --- src/ecc/ECC.jl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/ecc/ECC.jl b/src/ecc/ECC.jl index 79fb48c05..eb023d31b 100644 --- a/src/ecc/ECC.jl +++ b/src/ecc/ECC.jl @@ -18,7 +18,7 @@ export parity_checks, parity_checks_x, parity_checks_z, iscss, naive_syndrome_circuit, shor_syndrome_circuit, naive_encoding_circuit, RepCode, CSS, - Shor9, Steane7, Cleve8, Perfect5, Bitflip3, SteaneReedMuller, + Shor9, Steane7, Cleve8, Perfect5, Bitflip3, Toric, Gottesman, Surface, evaluate_decoder, CommutationCheckECCSetup, NaiveSyndromeECCSetup, ShorSyndromeECCSetup, @@ -351,5 +351,4 @@ include("codes/surface.jl") include("codes/classical/reedmuller.jl") include("codes/classical/reedsolomon.jl") include("codes/classical/bch.jl") -include("codes/steanereedmuller.jl") end #module From de21bc9b977750a84bbb8e2671a3cce0adb2ca7f Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Fri, 19 Apr 2024 19:09:42 +0500 Subject: [PATCH 17/70] improving docstring of g(x), adding parity_check function for BCH code --- CHANGELOG.md | 5 +++++ src/ecc/ECC.jl | 12 ++++++++++++ src/ecc/codes/classical/bch.jl | 29 +++++++++++++++++++++++++++-- 3 files changed, 44 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2e2a1f076..75c4fd6a8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,11 @@ # News +## v0.9.4 - dev + +- Gate errors are now conveniently supported by the various ECC benchmark setups in the `ECC` module. +- Remove printing of spurious debug info from the PyBP decoder. + ## v0.9.3 - 2024-04-10 - **(fix)** One of `random_pauli`'s methods was disregarding the error probability and had incorrect kwarg defaults. diff --git a/src/ecc/ECC.jl b/src/ecc/ECC.jl index eb023d31b..a025642b3 100644 --- a/src/ecc/ECC.jl +++ b/src/ecc/ECC.jl @@ -57,6 +57,18 @@ function iscss(c::AbstractECC) return iscss(typeof(c)) end +""" +Generator Polynomial + +In a polynomial code, the generator polynomial `g(x)` is a polynomial of the minimal degree over a finite field F. The set of valid codewords in the code consists of all polynomials that are divisible by `g(x)` without remainder. + +Description + +- Defines the valid codewords in a polynomial code. +- Has minimal degree among polynomials with this property. +- Coefficients belong to a finite field (e.g., GF(2) for binary codes). + +""" function generator_polynomial end parity_checks(s::Stabilizer) = s diff --git a/src/ecc/codes/classical/bch.jl b/src/ecc/codes/classical/bch.jl index 0f2fe34d9..d6ca4d081 100644 --- a/src/ecc/codes/classical/bch.jl +++ b/src/ecc/codes/classical/bch.jl @@ -16,6 +16,31 @@ struct BCH <: ClassicalCode end end +""" +Generator Polynomial of BCH Codes + +This function calculates the generator polynomial `g(x)` of a t-bit error-correcting BCH code of length `2^m - 1` over the finite Galois field GF(2). + +Input Arguments: +- `m` (Integer): The positive integer defining the code length (`2^m - 1`). +- `t` (Integer): The positive integer specifying the number of correctable errors (`t`). + +Description: + +The generator polynomial `g(x)` is the fundamental polynomial used for encoding and decoding BCH codes. It has the following properties: + +1. Roots: It has `α`, `α^2`, `α^3`, ..., `α^(2^t)` as its roots, where `α` is a primitive element of the Galois Field GF(2^m). +2. Error Correction: A BCH code with generator polynomial `g(x)` can correct up to `t` errors in a codeword of length `2^m - 1`. +3. Minimal Polynomials: `g(x)` is the least common multiple (LCM) of the minimal polynomials `φ_i(x)` of `α^i` for `i = 1` to `2^t`. + +Minimal Polynomial: + +- The minimal polynomial of a field element `α` in GF(2^m) is the polynomial of the lowest degree over GF(2) that has `α` as a root. It represents the simplest polynomial relationship between `α` and the elements of GF(2). + +Least Common Multiple (LCM): + +- The LCM of two or more polynomials `f_i(x)` is the polynomial with the lowest degree that is a multiple of all `f_i(x)`. It ensures that `g(x)` has all the roots of `φ_i(x)` for `i = 1` to `2^t`. +""" function generator_polynomial(rs::BCH) r = ceil(Int, log2(rs.n + 1)) GF2ͬ, a = finite_field(2, r, "a") @@ -37,7 +62,7 @@ function parity_checks(rs::BCH) for i in 1:rs.t for j in 1:rs.n base = 2*i - 1 - HField[i, j] = base^(j-1) * a^(j-1) + HField[i, j] = (a^base)^(j - 1) end end H = Matrix{Bool}(undef, r*rs.t, rs.n) @@ -49,7 +74,7 @@ function parity_checks(rs::BCH) for k in 0:r - 1 t_tuple = [t_tuple; !is_zero(coeff(HField[i, j], k))] end - H[row_start:row_end, :] .= vec(t_tuple') + H[row_start:row_end, j] .= vec(t_tuple') end end return H From 34f4d2c92cd8860b02183b20b396d05239830a3f Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Fri, 19 Apr 2024 21:20:53 +0500 Subject: [PATCH 18/70] improving docstring for BCH --- src/ecc/codes/classical/bch.jl | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/ecc/codes/classical/bch.jl b/src/ecc/codes/classical/bch.jl index d6ca4d081..164329d1d 100644 --- a/src/ecc/codes/classical/bch.jl +++ b/src/ecc/codes/classical/bch.jl @@ -1,5 +1,17 @@ """The family of Bose–Chaudhuri–Hocquenghem (BCH) codes, as discovered in 1959 by Alexis Hocquenghem [hocquenghem1959codes](@cite), and independently in 1960 by Raj Chandra Bose and D.K. Ray-Chaudhuri [bose1960class](@cite). +The binary parity check matrix can be obtained from the following matrix over field elements, after each field element is expressed as a binary column vector over GF(2). + +1 a^1 a^2 a^3 ... a^(n - 1) +1 (a^3)^1 (a^3)^2 (a^3)^3 ... (a^3)^(n - 1) +1 (a^5)^1 (a^5)^2 (a^5)^3 ... (a^5)^(n - 1) +. . . . . +. . . . . +. . . . . +1 a^(2*t - 1) a^(2*t - 1)^2 a^(2*t - 1)^3 ... a^(2*t - 1)^(n -1) + +Note: The entries of matrix over field elements are in GF(2^m). Each element in GF(2^m) can be represented by a m-tuple/binary column of length m over GF(2). If each entry of H is replaced by its corresponding m-tuple/binary column of length m over GF(2) arranged in column form, we obtain a binary parity check matrix for the code. + You might be interested in consulting [bose1960further](@cite) as well. The ECC Zoo has an [entry for this family](https://errorcorrectionzoo.org/c/q-ary_bch) From 1e83ab170bec733629d39ac6e44a73d5ccc3bbac Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Fri, 19 Apr 2024 23:41:00 +0500 Subject: [PATCH 19/70] separating BCH and Reed Solomon codes: clean-up --- docs/src/references.bib | 31 ------------ docs/src/references.md | 3 -- src/ecc/ECC.jl | 1 - src/ecc/codes/classical/bch.jl | 93 ---------------------------------- test/runtests.jl | 1 - test/test_ecc_bch.jl | 25 --------- 6 files changed, 154 deletions(-) delete mode 100644 src/ecc/codes/classical/bch.jl delete mode 100644 test/test_ecc_bch.jl diff --git a/docs/src/references.bib b/docs/src/references.bib index 863258ab4..84687c09f 100644 --- a/docs/src/references.bib +++ b/docs/src/references.bib @@ -387,34 +387,3 @@ @article{sklar2001reed pages={1--33}, year={2001} } - -@article{hocquenghem1959codes, - title={Codes correcteurs d'erreurs}, - author={Hocquenghem, Alexis}, - journal={Chiffers}, - volume={2}, - pages={147--156}, - year={1959} -} - -@article{bose1960class, - title={On a class of error correcting binary group codes}, - author={Bose, Raj Chandra and Ray-Chaudhuri, Dwijendra K}, - journal={Information and control}, - volume={3}, - number={1}, - pages={68--79}, - year={1960}, - publisher={Elsevier} -} - -@article{bose1960further, - title={Further results on error correcting binary group codes}, - author={Bose, Raj Chandra and Ray-Chaudhuri, Dwijendra K}, - journal={Information and Control}, - volume={3}, - number={3}, - pages={279--290}, - year={1960}, - publisher={Elsevier} -} diff --git a/docs/src/references.md b/docs/src/references.md index b9a04eb5f..b672fd9b4 100644 --- a/docs/src/references.md +++ b/docs/src/references.md @@ -48,9 +48,6 @@ For classical code construction routines: - [berlekamp1978readable](@cite) - [wicker1999reed](@cite) - [sklar2001reed](@cite) -- [hocquenghem1959codes](@cite) -- [bose1960class](@cite) -- [bose1960further](@cite) # References diff --git a/src/ecc/ECC.jl b/src/ecc/ECC.jl index a025642b3..3d64edfee 100644 --- a/src/ecc/ECC.jl +++ b/src/ecc/ECC.jl @@ -362,5 +362,4 @@ include("codes/gottesman.jl") include("codes/surface.jl") include("codes/classical/reedmuller.jl") include("codes/classical/reedsolomon.jl") -include("codes/classical/bch.jl") end #module diff --git a/src/ecc/codes/classical/bch.jl b/src/ecc/codes/classical/bch.jl deleted file mode 100644 index 164329d1d..000000000 --- a/src/ecc/codes/classical/bch.jl +++ /dev/null @@ -1,93 +0,0 @@ -"""The family of Bose–Chaudhuri–Hocquenghem (BCH) codes, as discovered in 1959 by Alexis Hocquenghem [hocquenghem1959codes](@cite), and independently in 1960 by Raj Chandra Bose and D.K. Ray-Chaudhuri [bose1960class](@cite). - -The binary parity check matrix can be obtained from the following matrix over field elements, after each field element is expressed as a binary column vector over GF(2). - -1 a^1 a^2 a^3 ... a^(n - 1) -1 (a^3)^1 (a^3)^2 (a^3)^3 ... (a^3)^(n - 1) -1 (a^5)^1 (a^5)^2 (a^5)^3 ... (a^5)^(n - 1) -. . . . . -. . . . . -. . . . . -1 a^(2*t - 1) a^(2*t - 1)^2 a^(2*t - 1)^3 ... a^(2*t - 1)^(n -1) - -Note: The entries of matrix over field elements are in GF(2^m). Each element in GF(2^m) can be represented by a m-tuple/binary column of length m over GF(2). If each entry of H is replaced by its corresponding m-tuple/binary column of length m over GF(2) arranged in column form, we obtain a binary parity check matrix for the code. - -You might be interested in consulting [bose1960further](@cite) as well. - -The ECC Zoo has an [entry for this family](https://errorcorrectionzoo.org/c/q-ary_bch) -""" -struct BCH <: ClassicalCode - n::Int - t::Int #Error correction capability; t bits can be corrected - - function BCH(n, t) - if n < 6 || n > 500 || t < 0 || t > 2^(ceil(Int, log2(n + 1)) - 1) - throw(ArgumentError("Invalid parameters: 'n' and 't' must be positive, and 'r' must be >= to 3. Additionally, 'n' is >= to 7 since n = 2ͬ - 1 and 't' < 2^(r - 1), to obtain a valid code and to tractable.")) - end - new(n, t) - end -end - -""" -Generator Polynomial of BCH Codes - -This function calculates the generator polynomial `g(x)` of a t-bit error-correcting BCH code of length `2^m - 1` over the finite Galois field GF(2). - -Input Arguments: -- `m` (Integer): The positive integer defining the code length (`2^m - 1`). -- `t` (Integer): The positive integer specifying the number of correctable errors (`t`). - -Description: - -The generator polynomial `g(x)` is the fundamental polynomial used for encoding and decoding BCH codes. It has the following properties: - -1. Roots: It has `α`, `α^2`, `α^3`, ..., `α^(2^t)` as its roots, where `α` is a primitive element of the Galois Field GF(2^m). -2. Error Correction: A BCH code with generator polynomial `g(x)` can correct up to `t` errors in a codeword of length `2^m - 1`. -3. Minimal Polynomials: `g(x)` is the least common multiple (LCM) of the minimal polynomials `φ_i(x)` of `α^i` for `i = 1` to `2^t`. - -Minimal Polynomial: - -- The minimal polynomial of a field element `α` in GF(2^m) is the polynomial of the lowest degree over GF(2) that has `α` as a root. It represents the simplest polynomial relationship between `α` and the elements of GF(2). - -Least Common Multiple (LCM): - -- The LCM of two or more polynomials `f_i(x)` is the polynomial with the lowest degree that is a multiple of all `f_i(x)`. It ensures that `g(x)` has all the roots of `φ_i(x)` for `i = 1` to `2^t`. -""" -function generator_polynomial(rs::BCH) - r = ceil(Int, log2(rs.n + 1)) - GF2ͬ, a = finite_field(2, r, "a") - GF2x, x = GF(2)["x"] - minimal_poly = FqPolyRingElem[] - for i in 1:(2*rs.t - 1) - if i % 2 != 0 - minimal_poly = [minimal_poly; minpoly(GF2x, a^i)] - end - end - gx = lcm(minimal_poly) - return gx -end - -function parity_checks(rs::BCH) - r = ceil(Int, log2(rs.n + 1)) - GF2ͬ, a = finite_field(2, r, "a") - HField = Matrix{FqFieldElem}(undef, rs.t, rs.n) - for i in 1:rs.t - for j in 1:rs.n - base = 2*i - 1 - HField[i, j] = (a^base)^(j - 1) - end - end - H = Matrix{Bool}(undef, r*rs.t, rs.n) - for i in 1:rs.t - row_start = (i - 1) * r + 1 - row_end = row_start + r - 1 - for j in 1:rs.n - t_tuple = Bool[] - for k in 0:r - 1 - t_tuple = [t_tuple; !is_zero(coeff(HField[i, j], k))] - end - H[row_start:row_end, j] .= vec(t_tuple') - end - end - return H -end diff --git a/test/runtests.jl b/test/runtests.jl index 039f0d68b..90c8fa7c0 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -65,7 +65,6 @@ end @doset "ecc_gottesman" @doset "ecc_reedmuller" @doset "ecc_reedsolomon" -@doset "ecc_bch" @doset "ecc_syndromes" @doset "ecc_throws" @doset "precompile" diff --git a/test/test_ecc_bch.jl b/test/test_ecc_bch.jl deleted file mode 100644 index 345930813..000000000 --- a/test/test_ecc_bch.jl +++ /dev/null @@ -1,25 +0,0 @@ -using Test -using Nemo -using QuantumClifford -using QuantumClifford.ECC -using QuantumClifford.ECC: AbstractECC - -@testset "Test BCH(n, t) generator polynomial g(x) universal property: mod(x^n - 1, g(x)) == 0" begin - n_cases = [7, 15, 31, 63, 127, 255] - for n in n_cases - #Testing all 1 Bit, 2 Bit, 3 Bit and 4 Bit BCH codes for n_cases - for t in 1:4 - r = ceil(Int, log2(n + 1)) - GF2ͬ, a = finite_field(2, r, "a") - GF2x, x = GF(2)["x"] - mx = FqPolyRingElem[] - for i in 1:(2*t - 1) - if i % 2 != 0 - mx = [mx; minpoly(GF2x, a^i)] - end - end - gx = lcm(mx) - @test mod(x^n - 1, gx) == 0 - end - end -end From b6f120930e68dc94f5c7171def8ec6140f3d2d9f Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Mon, 22 Apr 2024 14:30:02 +0500 Subject: [PATCH 20/70] adding the binary expansion of Reed-Solomon codes along with proper docstring and references --- docs/src/references.bib | 7 ++ docs/src/references.md | 1 + src/ecc/codes/classical/reedsolomon.jl | 122 ++++++++++++++++++++++++- 3 files changed, 129 insertions(+), 1 deletion(-) diff --git a/docs/src/references.bib b/docs/src/references.bib index 84687c09f..943a6a325 100644 --- a/docs/src/references.bib +++ b/docs/src/references.bib @@ -387,3 +387,10 @@ @article{sklar2001reed pages={1--33}, year={2001} } + +@book{tomlinson2017error, + title={Error-correction coding and decoding: bounds, codes, decoders, analysis and applications}, + author={Tomlinson, Martin and Tjhai, Cen Jung and Ambroze, Marcel A and Ahmed, Mohammed and Jibril, Mubarak}, + year={2017}, + publisher={Springer Nature} +} diff --git a/docs/src/references.md b/docs/src/references.md index b672fd9b4..07fb8b6eb 100644 --- a/docs/src/references.md +++ b/docs/src/references.md @@ -48,6 +48,7 @@ For classical code construction routines: - [berlekamp1978readable](@cite) - [wicker1999reed](@cite) - [sklar2001reed](@cite) +- [tomlinson2017error](@cite) # References diff --git a/src/ecc/codes/classical/reedsolomon.jl b/src/ecc/codes/classical/reedsolomon.jl index 1ad8fd7e9..f0c1cd5c1 100644 --- a/src/ecc/codes/classical/reedsolomon.jl +++ b/src/ecc/codes/classical/reedsolomon.jl @@ -1,6 +1,20 @@ """The family of Reed-Solomon codes, as discovered by Reed and Solomon in their 1960 paper [reed1960polynomial](@cite). -You might be interested in consulting [geisel1990tutorial](cite), [wicker1999reed](@cite), [sklar2001reed](@cite), [berlekamp1978readable](cite) and [https://youtu.be/K26Ssr8H3ec?si=QOeohq_6I0Oyd8qu](@cite) as well. +Reed Solomon codes are maximum distance separable (MDS) codes and have the highest possible minimum Hamming distance. The codes have symbols from F_q with parameters [[q - 1, k, q - k]]. + +They are not binary codes but frequently are used with q = 2 ^ m, and so there is a mapping of residue classes of a primitive polynomial with binary coefficients and each element of GF(2 ^ m) is represented as a binary m-tuple. Denoting the q field elements as 0, α ^ 0, α ^ 1, α ^ 2,... α ^ q - 1, +the shortened Field parity-check matrix (`HSeed`) is given by + +(α ^ 0) ^ (j) (α ^ 1) ^ (j) (α ^ 2) ^ (j) ... (α ^ (q - 1)) ^ (j) +(α ^ 0) ^ (j + 1) (α ^ 1) ^ (j + 1) (α ^ 2) ^ (j + 1) ... (α ^ (q - 1)) ^ (j + 1) +(α ^ 0) ^ (j + 2) (α ^ 1) ^ (j + 2) (α ^ 2) ^ (j + 2) ... (α ^ (q - 1)) ^ (j + 2) + . . . ... . + . . . ... . + . . . ... . +(α ^ 0) ^ (j + q - k - 1) (α ^ 1) ^ (j + q - k - 1) (α ^ 2) ^ (j + q - k - 1) ... (α ^ (q - 1)) ^ (j + q - k - 1) +(α ^ 0) ^ (j + q - k) (α ^ 1) ^ (j + q - k) (α ^ 2) ^ (j + q - k) ... (α ^ (q - 1)) ^ (j + q - k) + +You might be interested in consulting [geisel1990tutorial](cite), [wicker1999reed](@cite), [sklar2001reed](@cite), [berlekamp1978readable](cite), [tomlinson2017error](@cite) and [https://youtu.be/K26Ssr8H3ec?si=QOeohq_6I0Oyd8qu](@cite) as well. The ECC Zoo has an [entry for this family](https://errorcorrectionzoo.org/c/reed_solomon) """ @@ -54,3 +68,109 @@ function generator_polynomial(rs::ReedSolomon) end return gx end + +# Reed-Solomon Codes and Binary Transmission with soft decisions +""" +This function applies Reed-Solomon (RS) codes with soft decision decoding for binary transmission channels. + +Challenges of Standard RS Codes: + +- While efficient as MDS codes, standard RS codes are not ideal for binary channels. +- As demonstrated in the results (see section 7.2)[tomlinson2017error](@cite), their performance suffers due to a mismatch between the code structure (symbol-based) and the channel (binary). +- A single bit error can lead to a symbol error, negating the code's benefits. + +Improved Binary Codes through Concatenation: + +- This method enhances RS codes for binary channels through code concatenation. +- It adds a single overall binary parity check to each m-tuple representing a symbol. +- This approach transforms the original RS code [[n, k, n - k - 1]] into a new binary code with parameters [[n[m + 1], k*m, 2[n - k -1]]]. +- The resulting binary code boasts a minimum symbol weight of 2, effectively doubling the minimum Hamming distance compared to the original RS code. + +Key Points: + +- Uses unquantized soft decision decoding for improved performance. +- Modified Dorsch decoder is recommended for near maximum likelihood decoding. +- Code length limitations: For significant coding gain, code length is typically restricted to less than 200 bits. + +Augmented Extended RS Codes: + +- Constructed from Galois Field GF(2 ^ m). +- Length: 2 ^ m + 1 (Maximum Distance Separable (MDS) codes). +- Parameters: [[2 ^(m) + 1, k, 2 ^ (m + 1) - k]]. +- Generalization: Applicable to any Galois Field GF(q) with parameters [[q + 1, k, q + 2 - k]]. + +Field Parity-Check Matrix (`HField`) Properties: + +(α_0) ^ (j) (α_1) ^ (j) (α_2) ^ (j) ... (α_(q - 2)) ^ (j) 1 0 +(α_0) ^ (j + 1) (α_1) ^ (j + 1) (α_2) ^ (j + 1) ... (α_(q - 2)) ^ (j + 1) 0 0 +(α_0) ^ (j + 2) (α_1) ^ (j + 2) (α_2) ^ (j + 2) ... (α_(q - 2)) ^ (j + 2) 0 0 + . . . ... . . . + . . . ... . . . + . . . ... . . . +(α_0) ^ (j + q - k - 1) (α_1) ^ (j + q - k - 1) (α_2) ^ (j + q - k - 1) ... (α_(q - 2)) ^ (j + q - k - 1) 0 0 +(α_0) ^ (j + q - k) (α_1) ^ (j + q - k) (α_2) ^ (j + q - k) ... (α_(q - 2)) ^ (j + q - k) 0 1 + + +- The matrix has q - k + 1 rows corresponding to the code's parity symbols. +- Any q - k + 1 columns form a Vandermonde matrix (non-singular). +- This ensures correction of up to q - k + 1 symbol erasures in a codeword. +- Permutation: We can re-arrange the columns of the `HField` matrix in any desired order. +- Parity symbols (s) deletion: Any set of `s` symbols within a codeword can be designated as parity symbols and permanently removed. This important property leads to construction of Shortened MDS codes. + +Shortened MDS Codes: + +- Corresponding columns of the field parity-check matrix `HField` can be deleted to form a shortened [[2 ^(m) + 1 - s, k, 2 ^ (m + 1) - s - k]] MDS code. +- This is an important property of MDS codes, particularly for their practical realisation in the form of augmented, extended RS codes because it enables efficient implementation in applications such as incremental redundancy systems, and network coding. +- 3 - level quantization of the received channel bits meaning 3 symbols deleted + +Cyclic Code Construction: + +- Using the first q - 1 columns of the field parity-check matrix (HField), using j = 0, and setting α_0, α_1, α_2, ..., α_q - 1 to α ^ 0, α ^ 1, α ^ 2, ..., α ^ q - 1 in the parity-check matrix are set equal to the powers of a primitive element α of the Galois Field GF(q), a cyclic code can be constructed for efficient encoding and decoding. The resulting matrix is represented by `HSeed`. + +- `HSeed` Matrix element expansion: + 1. Row expansion: Each row of in the `HField` matrix is replaced with an `m`-by-`m` Field matrix defined over the base field GF (2 ^ m). This expansion is repesented by `HFieldExpanded`. + 2. Column expansion: The elements in each column of `HFieldExpanded` matrix are converted to binary representations by substituting powers of a primitive element (`α`) in the Galois Field GF(2 ^ m) with their corresponding m-tuples over the Boolean/Binary Field GF(2). +""" +function parity_checks(rs::ReedSolomon) + r = ceil(Int, log2(rs.n + 1)) + GF2ͬ, a = finite_field(2, r, "a") + q = 2^r + 1 - 3 # 3-level quantization + HField = Matrix{FqFieldElem}(undef, q - rs.k + 1, q) + for j in 1: q + HField[1, j] = a ^ 0 + end + HTemp2 = Matrix{FqFieldElem}(undef, r, q) + for i in 1: q - rs.k + 1 + HField[i, 1] = a ^ 0 + end + for i in 2:q - rs.k + 1 + for j in 2: q + HField[i, j] = (a ^ (j - 1)) ^ (i - 2) + end + end + HSeed = vcat(HField[1:1, :], HField[3:end, :]) + HFieldExpanded = Matrix{FqFieldElem}(undef, r * rs.k, q) + g = 1 + while g <= r * rs.k + for i in 1:q - rs.k + for p in 1:r + HTemp2[p:p, :] = reshape(HSeed[i, :].*a ^ (p - 1) , 1, :) + end + HFieldExpanded[g:g + r - 1, :] .= HTemp2 + g = g + r + end + end + H = Matrix{Bool}(undef, r * rs.k, r * q) + for i in 1:r * rs.k + for j in 1:q + col_start = (j - 1) * r + 1 + col_end = col_start + r - 1 + t_tuple = Bool[] + for k in 0:r - 1 + t_tuple = [t_tuple; !is_zero(coeff(HFieldExpanded[i, j], k))] + end + H[i, col_start:col_end] .= vec(t_tuple) + end + end + return H +end From 9103c0c9fca208436760e04cd1c31c6ef498db95 Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Mon, 22 Apr 2024 14:34:58 +0500 Subject: [PATCH 21/70] improving docstring --- src/ecc/codes/classical/reedsolomon.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ecc/codes/classical/reedsolomon.jl b/src/ecc/codes/classical/reedsolomon.jl index f0c1cd5c1..644342df7 100644 --- a/src/ecc/codes/classical/reedsolomon.jl +++ b/src/ecc/codes/classical/reedsolomon.jl @@ -128,7 +128,7 @@ Cyclic Code Construction: - Using the first q - 1 columns of the field parity-check matrix (HField), using j = 0, and setting α_0, α_1, α_2, ..., α_q - 1 to α ^ 0, α ^ 1, α ^ 2, ..., α ^ q - 1 in the parity-check matrix are set equal to the powers of a primitive element α of the Galois Field GF(q), a cyclic code can be constructed for efficient encoding and decoding. The resulting matrix is represented by `HSeed`. - `HSeed` Matrix element expansion: - 1. Row expansion: Each row of in the `HField` matrix is replaced with an `m`-by-`m` Field matrix defined over the base field GF (2 ^ m). This expansion is repesented by `HFieldExpanded`. + 1. Row expansion: Each row of in the `HField` matrix is replaced with an `m`-by-`m` Field matrix defined over the base field GF (2 ^ m). This expansion is represented by `HFieldExpanded`. 2. Column expansion: The elements in each column of `HFieldExpanded` matrix are converted to binary representations by substituting powers of a primitive element (`α`) in the Galois Field GF(2 ^ m) with their corresponding m-tuples over the Boolean/Binary Field GF(2). """ function parity_checks(rs::ReedSolomon) From 15f733177641a2121bbb0d2516fee08a4d3fb0b9 Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Sat, 27 Apr 2024 23:54:16 +0500 Subject: [PATCH 22/70] Adding more tests and important check during binary expansion of Field Matrix. --- src/ecc/ECC.jl | 3 ++- src/ecc/codes/classical/reedsolomon.jl | 3 +++ test/test_ecc_reedsolomon.jl | 26 +++++++++++++++++++++++++- 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/src/ecc/ECC.jl b/src/ecc/ECC.jl index 3d64edfee..8d4df40d7 100644 --- a/src/ecc/ECC.jl +++ b/src/ecc/ECC.jl @@ -8,7 +8,7 @@ using DocStringExtensions using Combinatorics: combinations using SparseArrays: sparse using Statistics: std -using Nemo: ZZ, residue_ring, matrix +using Nemo: ZZ, residue_ring, matrix, finite_field, GF, FqFieldElem, coeff, is_zero abstract type AbstractECC end @@ -20,6 +20,7 @@ export parity_checks, parity_checks_x, parity_checks_z, iscss, CSS, Shor9, Steane7, Cleve8, Perfect5, Bitflip3, Toric, Gottesman, Surface, + ReedSolomon, evaluate_decoder, CommutationCheckECCSetup, NaiveSyndromeECCSetup, ShorSyndromeECCSetup, TableDecoder, diff --git a/src/ecc/codes/classical/reedsolomon.jl b/src/ecc/codes/classical/reedsolomon.jl index 644342df7..e947c16e3 100644 --- a/src/ecc/codes/classical/reedsolomon.jl +++ b/src/ecc/codes/classical/reedsolomon.jl @@ -156,6 +156,9 @@ function parity_checks(rs::ReedSolomon) for p in 1:r HTemp2[p:p, :] = reshape(HSeed[i, :].*a ^ (p - 1) , 1, :) end + if g > r * rs.k + break + end HFieldExpanded[g:g + r - 1, :] .= HTemp2 g = g + r end diff --git a/test/test_ecc_reedsolomon.jl b/test/test_ecc_reedsolomon.jl index 25d76d9d7..7487b4896 100644 --- a/test/test_ecc_reedsolomon.jl +++ b/test/test_ecc_reedsolomon.jl @@ -1,9 +1,33 @@ using Test -using Nemo +using LinearAlgebra +using Combinatorics +using Nemo: finite_field, GF, FqFieldElem, coeff, is_zero, degree using QuantumClifford using QuantumClifford.ECC using QuantumClifford.ECC: AbstractECC, ReedSolomon +function designed_distance(matrix, k, n, r) + for row in eachrow(matrix) + count = sum(row) + # Employing 3-level quantization of the channel bits and erasing entire symbols if any of their constituent bits are erased can improve the performance of RS codes. Refer to chapter: 07, section: 03, pages: 172 to 175 [tomlinson2017error](@cite). + if count >= 2 ^ (r + 1) - 3 - k + return true + end + end + return false +end + +@testset "Testing Shortened and Expanded Maximum Distance Separable (MDS) Reed Solomon codes's binary parity check matrices" begin + n_cases = [31, 63, 127, 255] + for n in n_cases + r = ceil(Int, log2(n + 1)) + for k in 5:15 + @test rank(parity_checks(ReedSolomon(n, k))) == r * k + @test designed_distance(parity_checks(ReedSolomon(n, k)), k, n, r) == true + end + end +end + @testset "Test ReedSolomon(n, k) generator polynomial g(x) degree" begin # RS(7, 3), RS(15, 9), RS(255, 223), RS(160, 128), RS(255, 251), (255, 239) and (255, 249) codes test_cases = [(7, 3), (15, 9), (225, 223), (160, 128), (255, 251), (255, 239), (255, 249)] From 28b63c860f15752e920d8eb7d33e0d2b235fc49a Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Sun, 28 Apr 2024 00:19:24 +0500 Subject: [PATCH 23/70] adding docstring to tests along with MacWilliams 1977 paper on Error Correcting Codes --- docs/src/references.bib | 8 ++++++++ docs/src/references.md | 1 + src/ecc/codes/classical/reedsolomon.jl | 2 +- test/test_ecc_reedsolomon.jl | 8 +++++++- 4 files changed, 17 insertions(+), 2 deletions(-) diff --git a/docs/src/references.bib b/docs/src/references.bib index 943a6a325..7e16c8321 100644 --- a/docs/src/references.bib +++ b/docs/src/references.bib @@ -394,3 +394,11 @@ @book{tomlinson2017error year={2017}, publisher={Springer Nature} } + +@book{macwilliams1977theory, + title={The theory of error-correcting codes}, + author={MacWilliams, Florence Jessie and Sloane, Neil James Alexander}, + volume={16}, + year={1977}, + publisher={Elsevier} +} diff --git a/docs/src/references.md b/docs/src/references.md index 07fb8b6eb..71b1c33af 100644 --- a/docs/src/references.md +++ b/docs/src/references.md @@ -49,6 +49,7 @@ For classical code construction routines: - [wicker1999reed](@cite) - [sklar2001reed](@cite) - [tomlinson2017error](@cite) +- [macwilliams1977theory](@cite) # References diff --git a/src/ecc/codes/classical/reedsolomon.jl b/src/ecc/codes/classical/reedsolomon.jl index e947c16e3..63069cf1a 100644 --- a/src/ecc/codes/classical/reedsolomon.jl +++ b/src/ecc/codes/classical/reedsolomon.jl @@ -14,7 +14,7 @@ the shortened Field parity-check matrix (`HSeed`) is given by (α ^ 0) ^ (j + q - k - 1) (α ^ 1) ^ (j + q - k - 1) (α ^ 2) ^ (j + q - k - 1) ... (α ^ (q - 1)) ^ (j + q - k - 1) (α ^ 0) ^ (j + q - k) (α ^ 1) ^ (j + q - k) (α ^ 2) ^ (j + q - k) ... (α ^ (q - 1)) ^ (j + q - k) -You might be interested in consulting [geisel1990tutorial](cite), [wicker1999reed](@cite), [sklar2001reed](@cite), [berlekamp1978readable](cite), [tomlinson2017error](@cite) and [https://youtu.be/K26Ssr8H3ec?si=QOeohq_6I0Oyd8qu](@cite) as well. +You might be interested in consulting [geisel1990tutorial](cite), [wicker1999reed](@cite), [sklar2001reed](@cite), [berlekamp1978readable](cite), [tomlinson2017error](@cite), [macwilliams1977theory](@cite) and [https://youtu.be/K26Ssr8H3ec?si=QOeohq_6I0Oyd8qu](@cite) as well. The ECC Zoo has an [entry for this family](https://errorcorrectionzoo.org/c/reed_solomon) """ diff --git a/test/test_ecc_reedsolomon.jl b/test/test_ecc_reedsolomon.jl index 7487b4896..679bf0413 100644 --- a/test/test_ecc_reedsolomon.jl +++ b/test/test_ecc_reedsolomon.jl @@ -6,10 +6,16 @@ using QuantumClifford using QuantumClifford.ECC using QuantumClifford.ECC: AbstractECC, ReedSolomon +""" +Employing `3-level` quantization of the channel bits and erasing entire symbols if any of their constituent bits are erased can improve the performance of RS codes. + +Shortened Maximum Distance Separable (MDS) codes have the following parameters - code length `(n)`, codesize `(k)` and minimum Hamming distance `(d)` represented by [[n, k, d]] as follows: [[2 ^ (m) + 1 - s, k, 2 ^ (m + 1) - s - k]]. Thus, the designed distance `d` = is 2 ^ (m + 1) - s - k. Refer to chapter: 07, section: 03, pages: 172 to 175 [tomlinson2017error](@cite). + +The designed distance for binary expanded parity check matrix remains same as symbol based parity check matrix. According to [macwilliams1977theory](@cite), changing the basis `j` can increase the designed distance `(dmin)` of the resulting binary code. +""" function designed_distance(matrix, k, n, r) for row in eachrow(matrix) count = sum(row) - # Employing 3-level quantization of the channel bits and erasing entire symbols if any of their constituent bits are erased can improve the performance of RS codes. Refer to chapter: 07, section: 03, pages: 172 to 175 [tomlinson2017error](@cite). if count >= 2 ^ (r + 1) - 3 - k return true end From 352d85efa45cc41526650fd908f30a5df20b6b6e Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Sun, 28 Apr 2024 00:26:27 +0500 Subject: [PATCH 24/70] Polising up docstring --- test/test_ecc_reedsolomon.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_ecc_reedsolomon.jl b/test/test_ecc_reedsolomon.jl index 679bf0413..9a3dc72c7 100644 --- a/test/test_ecc_reedsolomon.jl +++ b/test/test_ecc_reedsolomon.jl @@ -9,7 +9,7 @@ using QuantumClifford.ECC: AbstractECC, ReedSolomon """ Employing `3-level` quantization of the channel bits and erasing entire symbols if any of their constituent bits are erased can improve the performance of RS codes. -Shortened Maximum Distance Separable (MDS) codes have the following parameters - code length `(n)`, codesize `(k)` and minimum Hamming distance `(d)` represented by [[n, k, d]] as follows: [[2 ^ (m) + 1 - s, k, 2 ^ (m + 1) - s - k]]. Thus, the designed distance `d` = is 2 ^ (m + 1) - s - k. Refer to chapter: 07, section: 03, pages: 172 to 175 [tomlinson2017error](@cite). +Shortened Maximum Distance Separable (MDS) codes have the following parameters - code length `(n)`, codesize `(k)` and minimum Hamming distance `(d)` represented by [[n, k, d]] as follows: [[2 ^ (m) + 1 - s, k, 2 ^ (m + 1) - s - k]]. Thus, the designed minimum distance `d` is 2 ^ (m + 1) - s - k. Refer to chapter: 07, section: 03, pages: 172 to 175 [tomlinson2017error](@cite). The designed distance for binary expanded parity check matrix remains same as symbol based parity check matrix. According to [macwilliams1977theory](@cite), changing the basis `j` can increase the designed distance `(dmin)` of the resulting binary code. """ From b2bd424ba3e26e51e5bad55381a728fb77088432 Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Sun, 28 Apr 2024 23:07:00 +0500 Subject: [PATCH 25/70] Adding Test Throws and polishing docstring --- CHANGELOG.md | 1 + src/ecc/ECC.jl | 2 +- src/ecc/codes/classical/reedsolomon.jl | 5 ++--- test/test_ecc_reedsolomon.jl | 2 +- test/test_ecc_throws.jl | 3 +++ 5 files changed, 8 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 75c4fd6a8..bd2b9010b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ - Gate errors are now conveniently supported by the various ECC benchmark setups in the `ECC` module. - Remove printing of spurious debug info from the PyBP decoder. +- Adding classical Reed-Solomon code to the ECC module. ## v0.9.3 - 2024-04-10 diff --git a/src/ecc/ECC.jl b/src/ecc/ECC.jl index 8d4df40d7..3121804b4 100644 --- a/src/ecc/ECC.jl +++ b/src/ecc/ECC.jl @@ -8,7 +8,7 @@ using DocStringExtensions using Combinatorics: combinations using SparseArrays: sparse using Statistics: std -using Nemo: ZZ, residue_ring, matrix, finite_field, GF, FqFieldElem, coeff, is_zero +using Nemo: ZZ, residue_ring, matrix, finite_field, GF, FqFieldElem, FqPolyRingElem, coeff, is_zero abstract type AbstractECC end diff --git a/src/ecc/codes/classical/reedsolomon.jl b/src/ecc/codes/classical/reedsolomon.jl index 63069cf1a..33ec656b2 100644 --- a/src/ecc/codes/classical/reedsolomon.jl +++ b/src/ecc/codes/classical/reedsolomon.jl @@ -14,7 +14,7 @@ the shortened Field parity-check matrix (`HSeed`) is given by (α ^ 0) ^ (j + q - k - 1) (α ^ 1) ^ (j + q - k - 1) (α ^ 2) ^ (j + q - k - 1) ... (α ^ (q - 1)) ^ (j + q - k - 1) (α ^ 0) ^ (j + q - k) (α ^ 1) ^ (j + q - k) (α ^ 2) ^ (j + q - k) ... (α ^ (q - 1)) ^ (j + q - k) -You might be interested in consulting [geisel1990tutorial](cite), [wicker1999reed](@cite), [sklar2001reed](@cite), [berlekamp1978readable](cite), [tomlinson2017error](@cite), [macwilliams1977theory](@cite) and [https://youtu.be/K26Ssr8H3ec?si=QOeohq_6I0Oyd8qu](@cite) as well. +You might be interested in consulting [geisel1990tutorial](@cite), [wicker1999reed](@cite), [sklar2001reed](@cite), [berlekamp1978readable](@cite), [tomlinson2017error](@cite), [macwilliams1977theory](@cite) and [https://youtu.be/K26Ssr8H3ec?si=QOeohq_6I0Oyd8qu] as well. The ECC Zoo has an [entry for this family](https://errorcorrectionzoo.org/c/reed_solomon) """ @@ -23,7 +23,7 @@ struct ReedSolomon <: ClassicalCode k::Int function ReedSolomon(n, k) - if n < 0 || k < 0 || n > 500 + if n < 0 || k < 0 || n > 500 || k > n throw(ArgumentError("Invalid parameters: n and k must be non-negative and n > 500 in order to obtain a valid code and to remain tractable")) end new(n, k) @@ -110,7 +110,6 @@ Field Parity-Check Matrix (`HField`) Properties: (α_0) ^ (j + q - k - 1) (α_1) ^ (j + q - k - 1) (α_2) ^ (j + q - k - 1) ... (α_(q - 2)) ^ (j + q - k - 1) 0 0 (α_0) ^ (j + q - k) (α_1) ^ (j + q - k) (α_2) ^ (j + q - k) ... (α_(q - 2)) ^ (j + q - k) 0 1 - - The matrix has q - k + 1 rows corresponding to the code's parity symbols. - Any q - k + 1 columns form a Vandermonde matrix (non-singular). - This ensures correction of up to q - k + 1 symbol erasures in a codeword. diff --git a/test/test_ecc_reedsolomon.jl b/test/test_ecc_reedsolomon.jl index 9a3dc72c7..a4b0706ba 100644 --- a/test/test_ecc_reedsolomon.jl +++ b/test/test_ecc_reedsolomon.jl @@ -1,7 +1,7 @@ using Test using LinearAlgebra using Combinatorics -using Nemo: finite_field, GF, FqFieldElem, coeff, is_zero, degree +using Nemo: finite_field, GF, FqFieldElem, FqPolyRingElem, coeff, is_zero, degree using QuantumClifford using QuantumClifford.ECC using QuantumClifford.ECC: AbstractECC, ReedSolomon diff --git a/test/test_ecc_throws.jl b/test/test_ecc_throws.jl index 82e02303b..ff8d808ed 100644 --- a/test/test_ecc_throws.jl +++ b/test/test_ecc_throws.jl @@ -5,3 +5,6 @@ using QuantumClifford.ECC: ReedMuller @test_throws ArgumentError ReedMuller(-1, 3) @test_throws ArgumentError ReedMuller(1, 0) + +@test_throws ArgumentError ReedSolomon(-1, -1) +@test_throws ArgumentError ReedSolomon(31, 35) \ No newline at end of file From e4f31f5a8106cde1b4e3fa91122d6cf205eb3cbc Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Fri, 3 May 2024 19:18:18 +0500 Subject: [PATCH 26/70] adding pre code-review suggestions from BCH --- CHANGELOG.md | 1 - src/ecc/ECC.jl | 3 +- src/ecc/codes/classical/reedsolomon.jl | 141 +++++++++++-------------- test/test_ecc_reedsolomon.jl | 108 ++++++++++++++++--- test/test_ecc_throws.jl | 7 +- 5 files changed, 158 insertions(+), 102 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bd2b9010b..75c4fd6a8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,6 @@ - Gate errors are now conveniently supported by the various ECC benchmark setups in the `ECC` module. - Remove printing of spurious debug info from the PyBP decoder. -- Adding classical Reed-Solomon code to the ECC module. ## v0.9.3 - 2024-04-10 diff --git a/src/ecc/ECC.jl b/src/ecc/ECC.jl index 3121804b4..1cb964707 100644 --- a/src/ecc/ECC.jl +++ b/src/ecc/ECC.jl @@ -9,6 +9,7 @@ using Combinatorics: combinations using SparseArrays: sparse using Statistics: std using Nemo: ZZ, residue_ring, matrix, finite_field, GF, FqFieldElem, FqPolyRingElem, coeff, is_zero +using ILog2 abstract type AbstractECC end @@ -20,7 +21,7 @@ export parity_checks, parity_checks_x, parity_checks_z, iscss, CSS, Shor9, Steane7, Cleve8, Perfect5, Bitflip3, Toric, Gottesman, Surface, - ReedSolomon, + generator_polynomial, evaluate_decoder, CommutationCheckECCSetup, NaiveSyndromeECCSetup, ShorSyndromeECCSetup, TableDecoder, diff --git a/src/ecc/codes/classical/reedsolomon.jl b/src/ecc/codes/classical/reedsolomon.jl index 33ec656b2..9a2c2f2c0 100644 --- a/src/ecc/codes/classical/reedsolomon.jl +++ b/src/ecc/codes/classical/reedsolomon.jl @@ -1,70 +1,48 @@ """The family of Reed-Solomon codes, as discovered by Reed and Solomon in their 1960 paper [reed1960polynomial](@cite). -Reed Solomon codes are maximum distance separable (MDS) codes and have the highest possible minimum Hamming distance. The codes have symbols from F_q with parameters [[q - 1, k, q - k]]. +Reed Solomon codes are maximum distance separable (MDS) codes and have the highest possible minimum Hamming distance. The codes have symbols from F_q with parameters [[x - 1, k, x - k]]. -They are not binary codes but frequently are used with q = 2 ^ m, and so there is a mapping of residue classes of a primitive polynomial with binary coefficients and each element of GF(2 ^ m) is represented as a binary m-tuple. Denoting the q field elements as 0, α ^ 0, α ^ 1, α ^ 2,... α ^ q - 1, -the shortened Field parity-check matrix (`HSeed`) is given by +They are not binary codes but frequently are used with x = 2ᵐ, and so there is a mapping of residue classes of a primitive polynomial with binary coefficients and each element of GF(2ᵐ) is represented as a binary m-tuple. Denoting the x field elements as 0, α⁰, α¹, α²,... αˣ ⁻ ¹, the shortened Field parity-check matrix (`HSeed`) is given by -(α ^ 0) ^ (j) (α ^ 1) ^ (j) (α ^ 2) ^ (j) ... (α ^ (q - 1)) ^ (j) -(α ^ 0) ^ (j + 1) (α ^ 1) ^ (j + 1) (α ^ 2) ^ (j + 1) ... (α ^ (q - 1)) ^ (j + 1) -(α ^ 0) ^ (j + 2) (α ^ 1) ^ (j + 2) (α ^ 2) ^ (j + 2) ... (α ^ (q - 1)) ^ (j + 2) - . . . ... . - . . . ... . - . . . ... . -(α ^ 0) ^ (j + q - k - 1) (α ^ 1) ^ (j + q - k - 1) (α ^ 2) ^ (j + q - k - 1) ... (α ^ (q - 1)) ^ (j + q - k - 1) -(α ^ 0) ^ (j + q - k) (α ^ 1) ^ (j + q - k) (α ^ 2) ^ (j + q - k) ... (α ^ (q - 1)) ^ (j + q - k) +``` +(α⁰)ʲ (α¹)ʲ (α²)ʲ ... (αˣ ⁻ ¹)ʲ +(α⁰)ʲ ⁺ ¹ (α¹)ʲ ⁺ ¹ (α²)ʲ ⁺ ¹ ... (αˣ ⁻ ¹)ʲ ⁺ ¹ +(α⁰)ʲ ⁺ ² (α¹)ʲ ⁺ ² (α²)ʲ ⁺ ² ... (αˣ ⁻ ¹)ʲ ⁺ ² +(α⁰)ʲ ⁺ ˣ ⁻ ᵏ ⁻ ¹ (α¹)ʲ ⁺ ˣ ⁻ ᵏ ⁻ ¹ (α²)ʲ ⁺ ˣ ⁻ ᵏ ⁻ ¹ ... (αˣ ⁻ ¹)ʲ ⁺ ˣ ⁻ ᵏ ⁻ ¹ + . . . ... . + . . . ... . + . . . ... . +(α⁰)ʲ ⁺ ˣ ⁻ ᵏ (α¹)ʲ ⁺ ˣ ⁻ ᵏ (α²)ʲ ⁺ ˣ ⁻ ᵏ (αˣ ⁻ ¹)ʲ ⁺ ˣ ⁻ ᵏ +``` You might be interested in consulting [geisel1990tutorial](@cite), [wicker1999reed](@cite), [sklar2001reed](@cite), [berlekamp1978readable](@cite), [tomlinson2017error](@cite), [macwilliams1977theory](@cite) and [https://youtu.be/K26Ssr8H3ec?si=QOeohq_6I0Oyd8qu] as well. The ECC Zoo has an [entry for this family](https://errorcorrectionzoo.org/c/reed_solomon) """ -struct ReedSolomon <: ClassicalCode + +abstract type AbstractPolynomialCode <: ClassicalCode end + +struct ReedSolomon <: AbstractPolynomialCode n::Int k::Int function ReedSolomon(n, k) - if n < 0 || k < 0 || n > 500 || k > n - throw(ArgumentError("Invalid parameters: n and k must be non-negative and n > 500 in order to obtain a valid code and to remain tractable")) + if n < 0 || k < 2 || n > 500 || k > n + throw(ArgumentError("Invalid parameters: n and k must be non-negative. Also, 1 < k < n / 2 and n < 500 in order to obtain a valid code and to remain tractable")) end new(n, k) end end -#section 3.3.2 [geisel1990tutorial](cite) for constructing custom message polynomial m(x) -function _message_polynomial_rs(k, a, an, x, positions) - message = 0*x - for pos in positions - if pos <= k - message += a^(an)*x^(pos) - else - throw(DomainError("Invalid bit positions: The number of bit positions [0th,..., kth] to assign coefficient values should be <= k")) - end - end - return message -end - -#section 3.3.2 [geisel1990tutorial](cite) for constructing parity_check polynomial ck(x) given m(x) and g(x) -function _parity_check_polynomial_rs(n, k, x, message, gx) - x_nminusk = x^(n - k) - ck = mod(x_nminusk*message, gx) - return ck -end - -#section 3.3.2 [geisel1990tutorial](cite) for constructing codeword polynomial c(x) given m(x) and ck(x) -function _codeword_polynomial_rs(message, ck) - cx = message + ck - return cx -end - function generator_polynomial(rs::ReedSolomon) - r = ceil(Int, log2(rs.n + 1)) + m = ilog2(rs.n + 1) t = div(rs.n - rs.k, 2) - GF2ͬ, a = finite_field(2, r, "a") - P, x = GF2ͬ[:x] + GF2ʳ, a = finite_field(2, m, "a") + P, x = GF2ʳ[:x] pzeros = 2*t gx = x - a^pzeros for i in 1:(2*t - 1) - gx *= (x - a^(pzeros + i)) + gx *= (x - a ^ (pzeros + i)) end return gx end @@ -94,51 +72,54 @@ Key Points: Augmented Extended RS Codes: -- Constructed from Galois Field GF(2 ^ m). -- Length: 2 ^ m + 1 (Maximum Distance Separable (MDS) codes). -- Parameters: [[2 ^(m) + 1, k, 2 ^ (m + 1) - k]]. -- Generalization: Applicable to any Galois Field GF(q) with parameters [[q + 1, k, q + 2 - k]]. +- Constructed from Galois Field GF(2ᵐ). +- Length: 2ᵐ + 1 (Maximum Distance Separable (MDS) codes). +- Parameters: [[2ᵐ + 1, k, 2ᵐ ⁺ ¹ - k]]. +- Generalization: Applicable to any Galois Field GF(q) with parameters [[x + 1, k, x + 2 - k]]. Field Parity-Check Matrix (`HField`) Properties: -(α_0) ^ (j) (α_1) ^ (j) (α_2) ^ (j) ... (α_(q - 2)) ^ (j) 1 0 -(α_0) ^ (j + 1) (α_1) ^ (j + 1) (α_2) ^ (j + 1) ... (α_(q - 2)) ^ (j + 1) 0 0 -(α_0) ^ (j + 2) (α_1) ^ (j + 2) (α_2) ^ (j + 2) ... (α_(q - 2)) ^ (j + 2) 0 0 - . . . ... . . . - . . . ... . . . - . . . ... . . . -(α_0) ^ (j + q - k - 1) (α_1) ^ (j + q - k - 1) (α_2) ^ (j + q - k - 1) ... (α_(q - 2)) ^ (j + q - k - 1) 0 0 -(α_0) ^ (j + q - k) (α_1) ^ (j + q - k) (α_2) ^ (j + q - k) ... (α_(q - 2)) ^ (j + q - k) 0 1 - -- The matrix has q - k + 1 rows corresponding to the code's parity symbols. -- Any q - k + 1 columns form a Vandermonde matrix (non-singular). -- This ensures correction of up to q - k + 1 symbol erasures in a codeword. +``` +(α₀)ʲ (α₁)ʲ (α₂)ʲ ... (αₓ₋₂)ʲ 1 0 +(α₀)ʲ ⁺ ¹ (α₁)ʲ ⁺ ¹ (α₂)ʲ ⁺ ¹ ... (αₓ₋₂)ʲ ⁺ ¹ 0 0 +(α₀)ʲ ⁺ ² (α₁)ʲ ⁺ ² (α₂)ʲ ⁺ ² ... (αₓ₋₂)ʲ ⁺ ² 0 0 + . . . ... . . . + . . . ... . . . + . . . ... . . . +(α₀)ʲ ⁺ ˣ ⁻ ᵏ ⁻ ¹ (α₁)ʲ ⁺ ˣ ⁻ ᵏ ⁻ ¹ (α₂)ʲ ⁺ ˣ ⁻ ᵏ ⁻ ¹ ... (αₓ₋₂)ʲ ⁺ ˣ ⁻ ᵏ ⁻ ¹ 0 0 +(α₀)ʲ ⁺ ˣ ⁻ ᵏ (α₁)ʲ ⁺ ˣ ⁻ ᵏ (α₂)ʲ ⁺ ˣ ⁻ ᵏ ... (αₓ₋₂)ʲ ⁺ ˣ ⁻ ᵏ 0 1 +``` + +- The matrix has x - k + 1 rows corresponding to the code's parity symbols. +- Any x - k + 1 columns form a Vandermonde matrix (non-singular). +- This ensures correction of up to x - k + 1 symbol erasures in a codeword. - Permutation: We can re-arrange the columns of the `HField` matrix in any desired order. - Parity symbols (s) deletion: Any set of `s` symbols within a codeword can be designated as parity symbols and permanently removed. This important property leads to construction of Shortened MDS codes. Shortened MDS Codes: -- Corresponding columns of the field parity-check matrix `HField` can be deleted to form a shortened [[2 ^(m) + 1 - s, k, 2 ^ (m + 1) - s - k]] MDS code. +- Corresponding columns of the field parity-check matrix `HField` can be deleted to form a shortened [[2ᵐ + 1 - s, k, 2ᵐ ⁺ ¹ - s - k]] MDS code. - This is an important property of MDS codes, particularly for their practical realisation in the form of augmented, extended RS codes because it enables efficient implementation in applications such as incremental redundancy systems, and network coding. - 3 - level quantization of the received channel bits meaning 3 symbols deleted Cyclic Code Construction: -- Using the first q - 1 columns of the field parity-check matrix (HField), using j = 0, and setting α_0, α_1, α_2, ..., α_q - 1 to α ^ 0, α ^ 1, α ^ 2, ..., α ^ q - 1 in the parity-check matrix are set equal to the powers of a primitive element α of the Galois Field GF(q), a cyclic code can be constructed for efficient encoding and decoding. The resulting matrix is represented by `HSeed`. +- Using the first x - 1 columns of the field parity-check matrix (HField), using j = 0, and setting α₀, α₁, α₂, ..., αₓ ₋ ₁ to α⁰, α¹, α², ..., αˣ ⁻ ¹ in the parity-check matrix are set equal to the powers of a primitive element α of the Galois Field GF(q), a cyclic code can be constructed for efficient encoding and decoding. The resulting matrix is represented by `HSeed`. - `HSeed` Matrix element expansion: - 1. Row expansion: Each row of in the `HField` matrix is replaced with an `m`-by-`m` Field matrix defined over the base field GF (2 ^ m). This expansion is represented by `HFieldExpanded`. - 2. Column expansion: The elements in each column of `HFieldExpanded` matrix are converted to binary representations by substituting powers of a primitive element (`α`) in the Galois Field GF(2 ^ m) with their corresponding m-tuples over the Boolean/Binary Field GF(2). + 1. Row expansion: Each row of in the `HField` matrix is replaced with an `m`-by-`m` Field matrix defined over the base field GF (2ᵐ). This expansion is represented by `HFieldExpanded`. + 2. Column expansion: The elements in each column of `HFieldExpanded` matrix are converted to binary representations by substituting powers of a primitive element (`α`) in the Galois Field GF(2ᵐ) with their corresponding m-tuples over the Boolean/Binary Field GF(2). """ function parity_checks(rs::ReedSolomon) - r = ceil(Int, log2(rs.n + 1)) - GF2ͬ, a = finite_field(2, r, "a") - q = 2^r + 1 - 3 # 3-level quantization + m = ilog2(rs.n + 1) + GF2ʳ, a = finite_field(2, m, "a") + # 3-level quantization, q is same as x. + q = 2 ^ m + 1 - 3 HField = Matrix{FqFieldElem}(undef, q - rs.k + 1, q) for j in 1: q HField[1, j] = a ^ 0 end - HTemp2 = Matrix{FqFieldElem}(undef, r, q) + HTemp2 = Matrix{FqFieldElem}(undef, m, q) for i in 1: q - rs.k + 1 HField[i, 1] = a ^ 0 end @@ -148,28 +129,28 @@ function parity_checks(rs::ReedSolomon) end end HSeed = vcat(HField[1:1, :], HField[3:end, :]) - HFieldExpanded = Matrix{FqFieldElem}(undef, r * rs.k, q) + HFieldExpanded = Matrix{FqFieldElem}(undef, m * rs.k, q) g = 1 - while g <= r * rs.k + while g <= m * rs.k for i in 1:q - rs.k - for p in 1:r + for p in 1:m HTemp2[p:p, :] = reshape(HSeed[i, :].*a ^ (p - 1) , 1, :) end - if g > r * rs.k + if g > m * rs.k break end - HFieldExpanded[g:g + r - 1, :] .= HTemp2 - g = g + r + HFieldExpanded[g:g + m - 1, :] .= HTemp2 + g = g + m end end - H = Matrix{Bool}(undef, r * rs.k, r * q) - for i in 1:r * rs.k + H = Matrix{Bool}(undef, m * rs.k, m * q) + for i in 1:m * rs.k for j in 1:q - col_start = (j - 1) * r + 1 - col_end = col_start + r - 1 + col_start = (j - 1) * m + 1 + col_end = col_start + m - 1 t_tuple = Bool[] - for k in 0:r - 1 - t_tuple = [t_tuple; !is_zero(coeff(HFieldExpanded[i, j], k))] + for k in 0:m - 1 + push!(t_tuple, !is_zero(coeff(HFieldExpanded[i, j], k))) end H[i, col_start:col_end] .= vec(t_tuple) end diff --git a/test/test_ecc_reedsolomon.jl b/test/test_ecc_reedsolomon.jl index a4b0706ba..cbffaae61 100644 --- a/test/test_ecc_reedsolomon.jl +++ b/test/test_ecc_reedsolomon.jl @@ -1,7 +1,8 @@ using Test +using ILog2 using LinearAlgebra using Combinatorics -using Nemo: finite_field, GF, FqFieldElem, FqPolyRingElem, coeff, is_zero, degree +using Nemo: finite_field, GF, FqFieldElem, FqPolyRingElem, coeff, is_zero, degree, matrix using QuantumClifford using QuantumClifford.ECC using QuantumClifford.ECC: AbstractECC, ReedSolomon @@ -26,27 +27,100 @@ end @testset "Testing Shortened and Expanded Maximum Distance Separable (MDS) Reed Solomon codes's binary parity check matrices" begin n_cases = [31, 63, 127, 255] for n in n_cases - r = ceil(Int, log2(n + 1)) - for k in 5:15 - @test rank(parity_checks(ReedSolomon(n, k))) == r * k + r = ilog2(n + 1) + for k in 2:15 + mat = matrix(GF(2), parity_checks(ReedSolomon(n, k))) + computed_rank = rank(mat) + @test computed_rank == r * k @test designed_distance(parity_checks(ReedSolomon(n, k)), k, n, r) == true end end -end -@testset "Test ReedSolomon(n, k) generator polynomial g(x) degree" begin - # RS(7, 3), RS(15, 9), RS(255, 223), RS(160, 128), RS(255, 251), (255, 239) and (255, 249) codes + # RS(7, 3), RS(15, 9), RS(255, 223), RS(160, 128), RS(255, 251), (255, 239) and (255, 249) codes. test_cases = [(7, 3), (15, 9), (225, 223), (160, 128), (255, 251), (255, 239), (255, 249)] for (n, k) in test_cases - deg = ceil(Int, log2(n + 1)) - t = div(n - k, 2) - GF2ͬ, a = finite_field(2, deg, "a") - P, x = GF2ͬ[:x] - pzeros = 2*t - poly = x - a^pzeros - for i in 1:(2*t - 1) - poly *= (x - a^(pzeros + i)) - end - @test degree(poly) == n - k + @test degree(generator_polynomial(ReedSolomon(n, k))) == n - k end + #examples taken from [https://www.youtube.com/watch?v=K26Ssr8H3ec]. + GF2ʳ, a = finite_field(2, 3, "a") + P, x = GF2ʳ[:x] + @test generator_polynomial(ReedSolomon(7, 2)) == x ^ 4 + (a ^ 2 + 1) * x ^ 3 + (a ^ 2 + 1) * x ^ 2 + (a + 1) * x + a + + #example taken from page 175 of [tomlinson2017error](@cite). + @test size(parity_checks(ReedSolomon(31, 15))) == (75, 150) + @test parity_checks(ReedSolomon(31, 15)) == [1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0; + 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0; + 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0; + 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0; + 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1; + 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 1 0 1 0 0 0 1 0 1 0 0 0 1 0 1 1 0 1 1 0 0 1 0 1 1 1 0 0 0 1 1 1 1 0 0 0 1 1 1 0 0 0 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 0 0 1 1 1 0 0 0 0 1 1 0 0 0 0 1 1 0 0 0 0 1 1 1 0 1 0 1 1 1 1 1 0 0 1 1 1 1 1 0 0 1 1 1 1 1 0 1 1 1 0 1 0 0 1 1 0 1 1 0 0 1 0; + 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 1 0 1 0 0 0 1 0 1 0 0 0 1 0 1 1 0 1 1 0 0 1 0 1 1 1 0 0 0 1 1 1 1 0 0 0 1 1 1 0 0 0 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 0 0 1 1 1 0 0 0 0 1 1 0 0 0 0 1 1 0 0 0 0 1 1 1 0 1 0 1 1 1 1 1 0 0 1 1 1 1 1 0 0 1 1 1 1 1 0 1 1 1 0 1 0 0 1 1 0 1 1 0 0 1 0 0 1 0 0 1; + 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 1 0 1 0 0 0 1 0 1 0 0 0 1 0 1 1 0 1 1 0 0 1 0 1 1 1 0 0 0 1 1 1 1 0 0 0 1 1 1 0 0 0 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 0 0 1 1 1 0 0 0 0 1 1 0 0 0 0 1 1 0 0 0 0 1 1 1 0 1 0 1 1 1 1 1 0 0 1 1 1 1 1 0 0 1 1 1 1 1 0 1 1 1 0 1 0 0 1 1 0 1 1 0 0 1 0 0 1 0 0 1 1 0 0 0 0; + 0 0 0 1 0 0 0 0 0 1 1 0 1 0 0 0 1 0 1 0 0 0 1 0 1 1 0 1 1 0 0 1 0 1 1 1 0 0 0 1 1 1 1 0 0 0 1 1 1 0 0 0 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 0 0 1 1 1 0 0 0 0 1 1 0 0 0 0 1 1 0 0 0 0 1 1 1 0 1 0 1 1 1 1 1 0 0 1 1 1 1 1 0 0 1 1 1 1 1 0 1 1 1 0 1 0 0 1 1 0 1 1 0 0 1 0 0 1 0 0 1 1 0 0 0 0 0 1 0 0 0; + 0 0 0 0 1 1 0 1 0 0 0 1 0 1 0 0 0 1 0 1 1 0 1 1 0 0 1 0 1 1 1 0 0 0 1 1 1 1 0 0 0 1 1 1 0 0 0 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 0 0 1 1 1 0 0 0 0 1 1 0 0 0 0 1 1 0 0 0 0 1 1 1 0 1 0 1 1 1 1 1 0 0 1 1 1 1 1 0 0 1 1 1 1 1 0 1 1 1 0 1 0 0 1 1 0 1 1 0 0 1 0 0 1 0 0 1 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0; + 1 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 1 0 1 0 1 0 1 1 0 1 0 0 0 1 0 1 1 1 0 1 0 1 1 1 1 1 0 1 1 1 1 0 0 0 0 0 1 1 0 1 0 1 0 1 0 1 1 1 1 1 1 1 0 1 0 1 1 0 1 0 1 0 0 1 0 1 0 0 0 0 0 0 1 0 1 0 1 0 0 0 0 1 0 1 0 1 0 1 1 1 1 1 0 0 0 0 1 1 1 1 1 1 1 1 1 1 0 0 1 0 1 1 0 0 0 0 0 1 1 1 1 1 1 0 1 0 0 1 1 1 1 0 1 0; + 0 1 0 0 0 0 0 0 1 0 1 0 1 0 0 0 0 1 0 1 0 1 0 1 1 1 1 1 0 0 0 0 1 1 1 1 1 1 1 1 1 1 0 0 1 0 1 1 0 0 0 0 0 1 1 1 1 1 1 0 1 0 0 1 1 1 1 0 1 0 1 0 0 1 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 1 0 1 0 1 0 1 1 0 1 0 0 0 1 0 1 1 1 0 1 0 1 1 1 1 1 0 1 1 1 1 0 0 0 0 0 1 1 0 1 0 1 0 1 0 1 1 1 1 1 1 1 0 1 0 1 1 0 1; + 0 0 1 0 0 0 0 0 0 1 0 1 0 1 0 1 0 1 1 0 1 0 0 0 1 0 1 1 1 0 1 0 1 1 1 1 1 0 1 1 1 1 0 0 0 0 0 1 1 0 1 0 1 0 1 0 1 1 1 1 1 1 1 0 1 0 1 1 0 1 0 1 0 0 1 0 1 0 0 0 0 0 0 1 0 1 0 1 0 0 0 0 1 0 1 0 1 0 1 1 1 1 1 0 0 0 0 1 1 1 1 1 1 1 1 1 1 0 0 1 0 1 1 0 0 0 0 0 1 1 1 1 1 1 0 1 0 0 1 1 1 1 0 1 0 1 0 0 1 0; + 0 0 0 1 0 1 0 1 0 0 0 0 1 0 1 0 1 0 1 1 1 1 1 0 0 0 0 1 1 1 1 1 1 1 1 1 1 0 0 1 0 1 1 0 0 0 0 0 1 1 1 1 1 1 0 1 0 0 1 1 1 1 0 1 0 1 0 0 1 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 1 0 1 0 1 0 1 1 0 1 0 0 0 1 0 1 1 1 0 1 0 1 1 1 1 1 0 1 1 1 1 0 0 0 0 0 1 1 0 1 0 1 0 1 0 1 1 1 1 1 1 1 0 1 0 1 1 0 1 0 1 0 0 1; + 0 0 0 0 1 0 1 0 1 0 1 0 1 1 0 1 0 0 0 1 0 1 1 1 0 1 0 1 1 1 1 1 0 1 1 1 1 0 0 0 0 0 1 1 0 1 0 1 0 1 0 1 1 1 1 1 1 1 0 1 0 1 1 0 1 0 1 0 0 1 0 1 0 0 0 0 0 0 1 0 1 0 1 0 0 0 0 1 0 1 0 1 0 1 1 1 1 1 0 0 0 0 1 1 1 1 1 1 1 1 1 1 0 0 1 0 1 1 0 0 0 0 0 1 1 1 1 1 1 0 1 0 0 1 1 1 1 0 1 0 1 0 0 1 0 1 0 0 0 0; + 1 0 0 0 0 0 0 0 1 0 0 1 0 1 0 0 1 0 1 1 0 1 1 1 0 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 0 1 1 1 1 1 1 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 1 0 0 1 0 1 1 0 1 1 1 0 0 1 0 1 1 1 1 1 0 0 1 0 0 1 1 0 1 1 1 1 0 1 1 1 0 1 1 0 0 1 0 0 1 0 0 0 0 0 0 0 1 0 0 1 0 1 1 0 0 0 1 0 0 1 1 1 1 1 0 1 1 0 1 1 0 0 1 0 1 0 1 1 0 0 1 1; + 0 1 0 0 0 0 0 0 0 1 0 0 1 0 1 1 0 0 0 1 0 0 1 1 1 1 1 0 1 1 0 1 1 0 0 1 0 1 0 1 1 0 0 1 1 0 1 1 0 1 1 0 0 0 0 0 0 0 1 0 0 1 0 1 0 0 1 0 1 1 0 1 1 1 0 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 0 1 1 1 1 1 1 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 1 0 0 1 0 1 1 0 1 1 1 0 0 1 0 1 1 1 1 1 0 0 1 0 0 1 1 0 1 1 1 1 0 1 1 1 0 1; + 0 0 1 0 0 1 0 1 0 0 1 0 1 1 0 1 1 1 0 0 1 0 1 1 1 1 1 0 0 1 0 0 1 1 0 1 1 1 1 0 1 1 1 0 1 1 0 0 1 0 0 1 0 0 0 0 0 0 0 1 0 0 1 0 1 1 0 0 0 1 0 0 1 1 1 1 1 0 1 1 0 1 1 0 0 1 0 1 0 1 1 0 0 1 1 0 1 1 0 1 1 0 0 0 0 0 0 0 1 0 0 1 0 1 0 0 1 0 1 1 0 1 1 1 0 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 0 1 1 1 1 1 1 0 1 0; + 0 0 0 1 0 0 1 0 1 0 0 1 0 1 1 0 1 1 1 0 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 0 1 1 1 1 1 1 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 1 0 0 1 0 1 1 0 1 1 1 0 0 1 0 1 1 1 1 1 0 0 1 0 0 1 1 0 1 1 1 1 0 1 1 1 0 1 1 0 0 1 0 0 1 0 0 0 0 0 0 0 1 0 0 1 0 1 1 0 0 0 1 0 0 1 1 1 1 1 0 1 1 0 1 1 0 0 1 0 1 0 1 1 0 0 1 1 0 1 1 0 1; + 0 0 0 0 1 0 0 1 0 1 1 0 0 0 1 0 0 1 1 1 1 1 0 1 1 0 1 1 0 0 1 0 1 0 1 1 0 0 1 1 0 1 1 0 1 1 0 0 0 0 0 0 0 1 0 0 1 0 1 0 0 1 0 1 1 0 1 1 1 0 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 0 1 1 1 1 1 1 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 1 0 0 1 0 1 1 0 1 1 1 0 0 1 0 1 1 1 1 1 0 0 1 0 0 1 1 0 1 1 1 1 0 1 1 1 0 1 1 0 0 1 0; + 1 0 0 0 0 0 0 0 0 1 1 0 1 1 0 0 1 1 1 0 1 1 0 1 1 0 0 1 1 0 0 1 1 1 1 0 1 1 0 1 0 1 0 0 0 1 0 1 0 0 0 1 0 1 1 0 0 1 1 1 1 1 0 0 1 0 0 0 1 1 1 0 0 1 1 1 0 0 1 0 0 0 1 0 0 0 1 0 1 0 1 0 0 0 1 1 0 1 1 1 1 1 0 0 0 1 0 1 0 1 1 1 1 0 1 0 1 0 0 1 0 0 0 1 0 0 0 1 0 1 1 1 1 0 0 1 1 1 1 1 0 1 1 0 0 1 1 1 1 0; + 0 1 0 0 0 1 0 1 0 0 0 1 0 1 1 0 0 1 1 1 1 1 0 0 1 0 0 0 1 1 1 0 0 1 1 1 0 0 1 0 0 0 1 0 0 0 1 0 1 0 1 0 0 0 1 1 0 1 1 1 1 1 0 0 0 1 0 1 0 1 1 1 1 0 1 0 1 0 0 1 0 0 0 1 0 0 0 1 0 1 1 1 1 0 0 1 1 1 1 1 0 1 1 0 0 1 1 1 1 0 1 1 0 1 0 1 0 0 0 0 0 0 0 0 1 1 0 1 1 0 0 1 1 1 0 1 1 0 1 1 0 0 1 1 0 0 1 1 1 1; + 0 0 1 0 0 0 1 0 1 0 1 0 0 0 1 1 0 1 1 1 1 1 0 0 0 1 0 1 0 1 1 1 1 0 1 0 1 0 0 1 0 0 0 1 0 0 0 1 0 1 1 1 1 0 0 1 1 1 1 1 0 1 1 0 0 1 1 1 1 0 1 1 0 1 0 1 0 0 0 0 0 0 0 0 1 1 0 1 1 0 0 1 1 1 0 1 1 0 1 1 0 0 1 1 0 0 1 1 1 1 0 1 1 0 1 0 1 0 0 0 1 0 1 0 0 0 1 0 1 1 0 0 1 1 1 1 1 0 0 1 0 0 0 1 1 1 0 0 1 1; + 0 0 0 1 0 0 0 1 0 1 1 1 1 0 0 1 1 1 1 1 0 1 1 0 0 1 1 1 1 0 1 1 0 1 0 1 0 0 0 0 0 0 0 0 1 1 0 1 1 0 0 1 1 1 0 1 1 0 1 1 0 0 1 1 0 0 1 1 1 1 0 1 1 0 1 0 1 0 0 0 1 0 1 0 0 0 1 0 1 1 0 0 1 1 1 1 1 0 0 1 0 0 0 1 1 1 0 0 1 1 1 0 0 1 0 0 0 1 0 0 0 1 0 1 0 1 0 0 0 1 1 0 1 1 1 1 1 0 0 0 1 0 1 0 1 1 1 1 0 1; + 0 0 0 0 1 1 0 1 1 0 0 1 1 1 0 1 1 0 1 1 0 0 1 1 0 0 1 1 1 1 0 1 1 0 1 0 1 0 0 0 1 0 1 0 0 0 1 0 1 1 0 0 1 1 1 1 1 0 0 1 0 0 0 1 1 1 0 0 1 1 1 0 0 1 0 0 0 1 0 0 0 1 0 1 0 1 0 0 0 1 1 0 1 1 1 1 1 0 0 0 1 0 1 0 1 1 1 1 0 1 0 1 0 0 1 0 0 0 1 0 0 0 1 0 1 1 1 1 0 0 1 1 1 1 1 0 1 1 0 0 1 1 1 1 0 1 1 0 1 0; + 1 0 0 0 0 1 0 1 0 0 1 0 0 0 1 1 1 1 1 1 0 0 1 1 0 1 0 0 1 1 0 1 0 0 1 0 0 0 0 1 0 1 0 1 1 1 0 1 1 1 0 1 1 0 0 0 1 1 1 1 1 0 0 1 0 0 0 0 1 0 1 0 1 1 0 0 0 1 1 1 1 1 0 0 0 1 1 1 1 0 0 1 1 0 1 0 0 1 0 0 0 0 1 0 1 0 1 1 1 0 1 1 0 0 1 1 0 1 0 1 1 1 0 1 0 0 1 0 0 0 0 1 0 1 0 1 1 1 0 0 1 1 0 1 1 0 0 0 1 1; + 0 1 0 0 0 0 1 0 1 0 1 1 1 0 0 1 1 0 1 1 0 0 0 1 1 1 1 1 0 1 1 0 0 0 0 1 0 1 0 0 1 0 0 0 1 1 1 1 1 1 0 0 1 1 0 1 0 0 1 1 0 1 0 0 1 0 0 0 0 1 0 1 0 1 1 1 0 1 1 1 0 1 1 0 0 0 1 1 1 1 1 0 0 1 0 0 0 0 1 0 1 0 1 1 0 0 0 1 1 1 1 1 0 0 0 1 1 1 1 0 0 1 1 0 1 0 0 1 0 0 0 0 1 0 1 0 1 1 1 0 1 1 0 0 1 1 0 1 0 1; + 0 0 1 0 0 0 0 1 0 1 0 1 1 1 0 1 1 0 0 1 1 0 1 0 1 1 1 0 1 0 0 1 0 0 0 0 1 0 1 0 1 1 1 0 0 1 1 0 1 1 0 0 0 1 1 1 1 1 0 1 1 0 0 0 0 1 0 1 0 0 1 0 0 0 1 1 1 1 1 1 0 0 1 1 0 1 0 0 1 1 0 1 0 0 1 0 0 0 0 1 0 1 0 1 1 1 0 1 1 1 0 1 1 0 0 0 1 1 1 1 1 0 0 1 0 0 0 0 1 0 1 0 1 1 0 0 0 1 1 1 1 1 0 0 0 1 1 1 1 0; + 0 0 0 1 0 1 0 1 1 0 0 0 1 1 1 1 1 0 0 0 1 1 1 1 0 0 1 1 0 1 0 0 1 0 0 0 0 1 0 1 0 1 1 1 0 1 1 0 0 1 1 0 1 0 1 1 1 0 1 0 0 1 0 0 0 0 1 0 1 0 1 1 1 0 0 1 1 0 1 1 0 0 0 1 1 1 1 1 0 1 1 0 0 0 0 1 0 1 0 0 1 0 0 0 1 1 1 1 1 1 0 0 1 1 0 1 0 0 1 1 0 1 0 0 1 0 0 0 0 1 0 1 0 1 1 1 0 1 1 1 0 1 1 0 0 0 1 1 1 1; + 0 0 0 0 1 0 1 0 1 1 1 0 1 1 1 0 1 1 0 0 0 1 1 1 1 1 0 0 1 0 0 0 0 1 0 1 0 1 1 0 0 0 1 1 1 1 1 0 0 0 1 1 1 1 0 0 1 1 0 1 0 0 1 0 0 0 0 1 0 1 0 1 1 1 0 1 1 0 0 1 1 0 1 0 1 1 1 0 1 0 0 1 0 0 0 0 1 0 1 0 1 1 1 0 0 1 1 0 1 1 0 0 0 1 1 1 1 1 0 1 1 0 0 0 0 1 0 1 0 0 1 0 0 0 1 1 1 1 1 1 0 0 1 1 0 1 0 0 1 1; + 1 0 0 0 0 0 1 0 1 0 0 1 1 1 0 1 1 0 0 0 0 1 1 1 1 0 1 0 0 1 1 0 1 0 0 1 1 1 0 0 1 1 0 0 1 1 1 1 1 0 1 0 0 1 0 0 0 0 0 1 1 0 0 0 1 1 1 0 1 1 1 0 1 0 1 0 1 1 0 1 0 0 0 1 0 0 1 0 1 1 1 1 1 1 1 0 0 0 1 1 1 1 0 1 0 0 0 1 0 0 1 0 1 1 0 1 0 1 1 1 0 0 1 1 0 1 1 1 0 1 0 1 0 0 0 0 0 1 0 1 0 0 1 1 1 0 1 1 0 0; + 0 1 0 0 0 0 0 1 0 1 0 0 1 1 1 0 1 1 0 0 1 0 0 1 1 1 0 0 0 0 0 1 0 1 0 0 1 1 1 0 1 1 0 0 0 0 1 1 1 1 0 1 0 0 1 1 0 1 0 0 1 1 1 0 0 1 1 0 0 1 1 1 1 1 0 1 0 0 1 0 0 0 0 0 1 1 0 0 0 1 1 1 0 1 1 1 0 1 0 1 0 1 1 0 1 0 0 0 1 0 0 1 0 1 1 1 1 1 1 1 0 0 0 1 1 1 1 0 1 0 0 0 1 0 0 1 0 1 1 0 1 0 1 1 1 0 0 1 1 0; + 0 0 1 0 0 1 0 1 1 0 1 0 1 1 1 0 0 1 1 0 1 1 1 0 1 0 1 0 0 0 0 0 1 0 1 0 0 1 1 1 0 1 1 0 0 1 0 0 1 1 1 0 0 0 0 0 1 0 1 0 0 1 1 1 0 1 1 0 0 0 0 1 1 1 1 0 1 0 0 1 1 0 1 0 0 1 1 1 0 0 1 1 0 0 1 1 1 1 1 0 1 0 0 1 0 0 0 0 0 1 1 0 0 0 1 1 1 0 1 1 1 0 1 0 1 0 1 1 0 1 0 0 0 1 0 0 1 0 1 1 1 1 1 1 1 0 0 0 1 1; + 0 0 0 1 0 0 1 0 1 1 1 1 1 1 1 0 0 0 1 1 1 1 0 1 0 0 0 1 0 0 1 0 1 1 0 1 0 1 1 1 0 0 1 1 0 1 1 1 0 1 0 1 0 0 0 0 0 1 0 1 0 0 1 1 1 0 1 1 0 0 1 0 0 1 1 1 0 0 0 0 0 1 0 1 0 0 1 1 1 0 1 1 0 0 0 0 1 1 1 1 0 1 0 0 1 1 0 1 0 0 1 1 1 0 0 1 1 0 0 1 1 1 1 1 0 1 0 0 1 0 0 0 0 0 1 1 0 0 0 1 1 1 0 1 1 1 0 1 0 1; + 0 0 0 0 1 1 0 0 0 1 1 1 0 1 1 1 0 1 0 1 0 1 1 0 1 0 0 0 1 0 0 1 0 1 1 1 1 1 1 1 0 0 0 1 1 1 1 0 1 0 0 0 1 0 0 1 0 1 1 0 1 0 1 1 1 0 0 1 1 0 1 1 1 0 1 0 1 0 0 0 0 0 1 0 1 0 0 1 1 1 0 1 1 0 0 1 0 0 1 1 1 0 0 0 0 0 1 0 1 0 0 1 1 1 0 1 1 0 0 0 0 1 1 1 1 0 1 0 0 1 1 0 1 0 0 1 1 1 0 0 1 1 0 0 1 1 1 1 1 0; + 1 0 0 0 0 0 0 1 0 1 1 0 1 1 1 0 0 0 1 1 0 1 1 0 1 0 0 0 0 1 1 1 1 0 0 1 1 0 0 0 1 0 0 1 1 0 1 0 0 0 1 0 1 1 0 1 1 1 1 1 1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0 1 1 1 0 0 1 1 0 0 1 1 1 0 1 0 0 1 0 0 0 1 0 1 1 1 1 0 1 1 1 1 1 1 0 0 1 0 0 1 0 1 0 1 0 0 0 1 1 1 0 0 1 1 0 1 1 0 1 0 0 0 0 1 0 1 0 0 0 1 1 1 0 0 1; + 0 1 0 0 0 1 0 1 1 0 1 1 1 1 1 1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0 1 1 1 0 0 1 1 0 0 1 1 1 0 1 0 0 1 0 0 0 1 0 1 1 1 1 0 1 1 1 1 1 1 0 0 1 0 0 1 0 1 0 1 0 0 0 1 1 1 0 0 1 1 0 1 1 0 1 0 0 0 0 1 0 1 0 0 0 1 1 1 0 0 1 0 1 1 1 1 1 0 0 0 0 0 0 1 0 1 1 0 1 1 1 0 0 0 1 1 0 1 1 0 1 0 0 0 0 1 1 1 1 0 0 1 1 0 0 0; + 0 0 1 0 0 0 1 0 1 1 1 1 0 1 1 1 1 1 1 0 0 1 0 0 1 0 1 0 1 0 0 0 1 1 1 0 0 1 1 0 1 1 0 1 0 0 0 0 1 0 1 0 0 0 1 1 1 0 0 1 0 1 1 1 1 1 0 0 0 0 0 0 1 0 1 1 0 1 1 1 0 0 0 1 1 0 1 1 0 1 0 0 0 0 1 1 1 1 0 0 1 1 0 0 0 1 0 0 1 1 0 1 0 0 0 1 0 1 1 0 1 1 1 1 1 1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0 1 1 1 0 0 1 1 0 0; + 0 0 0 1 0 1 0 0 0 1 1 1 0 0 1 0 1 1 1 1 1 0 0 0 0 0 0 1 0 1 1 0 1 1 1 0 0 0 1 1 0 1 1 0 1 0 0 0 0 1 1 1 1 0 0 1 1 0 0 0 1 0 0 1 1 0 1 0 0 0 1 0 1 1 0 1 1 1 1 1 1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0 1 1 1 0 0 1 1 0 0 1 1 1 0 1 0 0 1 0 0 0 1 0 1 1 1 1 0 1 1 1 1 1 1 0 0 1 0 0 1 0 1 0 1 0 0 0 1 1 1 0 0 1 1 0; + 0 0 0 0 1 1 1 1 0 0 1 1 0 0 0 1 0 0 1 1 0 1 0 0 0 1 0 1 1 0 1 1 1 1 1 1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0 1 1 1 0 0 1 1 0 0 1 1 1 0 1 0 0 1 0 0 0 1 0 1 1 1 1 0 1 1 1 1 1 1 0 0 1 0 0 1 0 1 0 1 0 0 0 1 1 1 0 0 1 1 0 1 1 0 1 0 0 0 0 1 0 1 0 0 0 1 1 1 0 0 1 0 1 1 1 1 1 0 0 0 0 0 0 1 0 1 1 0 1 1 1 0 0 0 1 1; + 1 0 0 0 0 1 0 1 1 0 1 1 0 1 1 0 1 1 1 1 0 1 0 0 0 0 1 0 1 1 1 1 0 0 1 1 0 0 1 1 0 0 1 0 0 1 0 0 0 1 1 1 0 0 0 1 1 1 0 1 0 0 0 1 0 1 1 1 0 0 0 1 1 0 0 1 1 0 1 0 0 0 0 0 1 0 1 1 1 0 0 0 1 1 0 0 1 1 0 1 1 0 1 0 0 0 0 1 1 1 0 0 0 1 1 1 0 0 1 0 0 1 0 1 0 1 0 1 1 1 1 0 1 0 1 0 1 0 0 1 0 0 1 0 1 1 1 1 1 1; + 0 1 0 0 0 0 1 0 1 1 1 1 0 0 1 1 0 0 1 1 0 0 1 0 0 1 0 0 0 1 1 1 0 0 0 1 1 1 0 1 0 0 0 1 0 1 1 1 0 0 0 1 1 0 0 1 1 0 1 0 0 0 0 0 1 0 1 1 1 0 0 0 1 1 0 0 1 1 0 1 1 0 1 0 0 0 0 1 1 1 0 0 0 1 1 1 0 0 1 0 0 1 0 1 0 1 0 1 1 1 1 0 1 0 1 0 1 0 0 1 0 0 1 0 1 1 1 1 1 1 1 1 1 1 0 1 0 0 0 0 1 0 1 1 0 1 1 0 1 1; + 0 0 1 0 0 1 0 0 0 1 1 1 0 0 0 1 1 1 0 1 0 0 0 1 0 1 1 1 0 0 0 1 1 0 0 1 1 0 1 0 0 0 0 0 1 0 1 1 1 0 0 0 1 1 0 0 1 1 0 1 1 0 1 0 0 0 0 1 1 1 0 0 0 1 1 1 0 0 1 0 0 1 0 1 0 1 0 1 1 1 1 0 1 0 1 0 1 0 0 1 0 0 1 0 1 1 1 1 1 1 1 1 1 1 0 1 0 0 0 0 1 0 1 1 0 1 1 0 1 1 0 1 1 1 1 0 1 0 0 0 0 1 0 1 1 1 1 0 0 1; + 0 0 0 1 0 1 1 1 0 0 0 1 1 0 0 1 1 0 1 0 0 0 0 0 1 0 1 1 1 0 0 0 1 1 0 0 1 1 0 1 1 0 1 0 0 0 0 1 1 1 0 0 0 1 1 1 0 0 1 0 0 1 0 1 0 1 0 1 1 1 1 0 1 0 1 0 1 0 0 1 0 0 1 0 1 1 1 1 1 1 1 1 1 1 0 1 0 0 0 0 1 0 1 1 0 1 1 0 1 1 0 1 1 1 1 0 1 0 0 0 0 1 0 1 1 1 1 0 0 1 1 0 0 1 1 0 0 1 0 0 1 0 0 0 1 1 1 0 0 0; + 0 0 0 0 1 0 1 1 1 0 0 0 1 1 0 0 1 1 0 1 1 0 1 0 0 0 0 1 1 1 0 0 0 1 1 1 0 0 1 0 0 1 0 1 0 1 0 1 1 1 1 0 1 0 1 0 1 0 0 1 0 0 1 0 1 1 1 1 1 1 1 1 1 1 0 1 0 0 0 0 1 0 1 1 0 1 1 0 1 1 0 1 1 1 1 0 1 0 0 0 0 1 0 1 1 1 1 0 0 1 1 0 0 1 1 0 0 1 0 0 1 0 0 0 1 1 1 0 0 0 1 1 1 0 1 0 0 0 1 0 1 1 1 0 0 0 1 1 0 0; + 1 0 0 0 0 0 1 0 1 1 1 1 0 0 0 1 1 0 1 0 1 0 1 0 0 1 0 1 1 1 1 1 1 1 0 0 1 0 0 0 1 0 0 0 1 0 1 1 0 0 0 1 1 0 1 0 1 0 1 0 1 1 1 1 1 0 1 1 1 1 0 0 1 0 0 1 1 1 0 0 0 0 1 1 0 1 0 0 1 0 0 0 1 0 1 1 1 0 1 1 1 0 0 1 1 0 0 0 1 0 0 1 1 1 0 0 0 0 1 1 0 1 0 0 1 1 0 1 1 0 1 1 0 0 1 1 1 1 0 1 0 0 0 0 1 0 0 1 1 1; + 0 1 0 0 0 1 0 0 0 1 0 1 1 0 0 0 1 1 0 1 0 1 0 1 0 1 1 1 1 1 0 1 1 1 1 0 0 1 0 0 1 1 1 0 0 0 0 1 1 0 1 0 0 1 0 0 0 1 0 1 1 1 0 1 1 1 0 0 1 1 0 0 0 1 0 0 1 1 1 0 0 0 0 1 1 0 1 0 0 1 1 0 1 1 0 1 1 0 0 1 1 1 1 0 1 0 0 0 0 1 0 0 1 1 1 1 0 1 0 1 1 0 0 0 0 0 1 0 1 1 1 1 0 0 0 1 1 0 1 0 1 0 1 0 0 1 0 1 1 1; + 0 0 1 0 0 1 1 1 0 0 0 0 1 1 0 1 0 0 1 0 0 0 1 0 1 1 1 0 1 1 1 0 0 1 1 0 0 0 1 0 0 1 1 1 0 0 0 0 1 1 0 1 0 0 1 1 0 1 1 0 1 1 0 0 1 1 1 1 0 1 0 0 0 0 1 0 0 1 1 1 1 0 1 0 1 1 0 0 0 0 0 1 0 1 1 1 1 0 0 0 1 1 0 1 0 1 0 1 0 0 1 0 1 1 1 1 1 1 1 0 0 1 0 0 0 1 0 0 0 1 0 1 1 0 0 0 1 1 0 1 0 1 0 1 0 1 1 1 1 1; + 0 0 0 1 0 0 1 1 1 0 0 0 0 1 1 0 1 0 0 1 1 0 1 1 0 1 1 0 0 1 1 1 1 0 1 0 0 0 0 1 0 0 1 1 1 1 0 1 0 1 1 0 0 0 0 0 1 0 1 1 1 1 0 0 0 1 1 0 1 0 1 0 1 0 0 1 0 1 1 1 1 1 1 1 0 0 1 0 0 0 1 0 0 0 1 0 1 1 0 0 0 1 1 0 1 0 1 0 1 0 1 1 1 1 1 0 1 1 1 1 0 0 1 0 0 1 1 1 0 0 0 0 1 1 0 1 0 0 1 0 0 0 1 0 1 1 1 0 1 1; + 0 0 0 0 1 0 0 1 1 1 1 0 1 0 1 1 0 0 0 0 0 1 0 1 1 1 1 0 0 0 1 1 0 1 0 1 0 1 0 0 1 0 1 1 1 1 1 1 1 0 0 1 0 0 0 1 0 0 0 1 0 1 1 0 0 0 1 1 0 1 0 1 0 1 0 1 1 1 1 1 0 1 1 1 1 0 0 1 0 0 1 1 1 0 0 0 0 1 1 0 1 0 0 1 0 0 0 1 0 1 1 1 0 1 1 1 0 0 1 1 0 0 0 1 0 0 1 1 1 0 0 0 0 1 1 0 1 0 0 1 1 0 1 1 0 1 1 0 0 1; + 1 0 0 0 0 1 0 0 0 1 0 0 1 1 0 0 1 0 0 1 0 1 0 1 1 0 1 1 0 0 1 0 0 1 0 1 0 1 1 0 1 1 0 0 0 0 1 1 0 1 0 0 1 0 1 1 1 0 0 1 1 1 0 1 0 0 1 0 1 0 1 1 0 1 1 1 1 1 0 1 1 0 1 0 0 1 1 1 1 1 1 0 0 1 1 0 0 0 0 1 1 0 1 1 1 0 1 1 1 1 0 0 0 1 0 0 0 1 1 1 1 1 1 1 0 0 0 1 0 0 0 1 1 1 0 1 0 1 0 1 0 1 0 0 0 1 1 1 0 0; + 0 1 0 0 0 1 1 1 0 0 0 0 0 1 1 1 0 0 0 0 1 0 0 0 1 0 0 1 1 0 0 1 0 0 1 0 1 0 1 1 0 1 1 0 0 1 0 0 1 0 1 0 1 1 0 1 1 0 0 0 0 1 1 0 1 0 0 1 0 1 1 1 0 0 1 1 1 0 1 0 0 1 0 1 0 1 1 0 1 1 1 1 1 0 1 1 0 1 0 0 1 1 1 1 1 1 0 0 1 1 0 0 0 0 1 1 0 1 1 1 0 1 1 1 1 0 0 0 1 0 0 0 1 1 1 1 1 1 1 0 0 0 1 0 0 0 1 1 1 0; + 0 0 1 0 0 0 1 1 1 0 1 0 1 0 1 0 1 0 0 0 1 1 1 0 0 0 0 0 1 1 1 0 0 0 0 1 0 0 0 1 0 0 1 1 0 0 1 0 0 1 0 1 0 1 1 0 1 1 0 0 1 0 0 1 0 1 0 1 1 0 1 1 0 0 0 0 1 1 0 1 0 0 1 0 1 1 1 0 0 1 1 1 0 1 0 0 1 0 1 0 1 1 0 1 1 1 1 1 0 1 1 0 1 0 0 1 1 1 1 1 1 0 0 1 1 0 0 0 0 1 1 0 1 1 1 0 1 1 1 1 0 0 0 1 0 0 0 1 1 1; + 0 0 0 1 0 0 0 1 1 1 1 1 1 1 0 0 0 1 0 0 0 1 1 1 0 1 0 1 0 1 0 1 0 0 0 1 1 1 0 0 0 0 0 1 1 1 0 0 0 0 1 0 0 0 1 0 0 1 1 0 0 1 0 0 1 0 1 0 1 1 0 1 1 0 0 1 0 0 1 0 1 0 1 1 0 1 1 0 0 0 0 1 1 0 1 0 0 1 0 1 1 1 0 0 1 1 1 0 1 0 0 1 0 1 0 1 1 0 1 1 1 1 1 0 1 1 0 1 0 0 1 1 1 1 1 1 0 0 1 1 0 0 0 0 1 1 0 1 1 1; + 0 0 0 0 1 1 0 1 1 1 0 1 1 1 1 0 0 0 1 0 0 0 1 1 1 1 1 1 1 0 0 0 1 0 0 0 1 1 1 0 1 0 1 0 1 0 1 0 0 0 1 1 1 0 0 0 0 0 1 1 1 0 0 0 0 1 0 0 0 1 0 0 1 1 0 0 1 0 0 1 0 1 0 1 1 0 1 1 0 0 1 0 0 1 0 1 0 1 1 0 1 1 0 0 0 0 1 1 0 1 0 0 1 0 1 1 1 0 0 1 1 1 0 1 0 0 1 0 1 0 1 1 0 1 1 1 1 1 0 1 1 0 1 0 0 1 1 1 1 1; + 1 0 0 0 0 1 1 1 0 0 1 0 1 0 1 0 0 1 0 0 0 0 1 1 1 0 1 1 1 1 0 0 0 0 1 1 1 1 1 1 1 1 1 0 1 0 1 0 1 0 1 1 0 0 1 0 1 1 0 1 1 0 1 1 0 0 1 1 0 0 0 1 0 0 1 1 0 0 0 1 0 0 0 1 1 0 1 0 0 0 0 1 1 1 0 1 1 1 1 0 0 0 0 1 0 1 0 1 1 1 1 0 0 1 1 1 0 1 0 0 1 1 0 1 1 1 1 0 1 0 0 0 1 0 1 1 1 0 0 0 1 0 0 1 0 0 1 0 1 1; + 0 1 0 0 0 0 1 1 1 0 1 1 1 1 0 0 0 0 1 0 1 0 1 1 1 1 0 0 1 1 1 0 1 0 0 1 1 0 1 1 1 1 0 1 0 0 0 1 0 1 1 1 0 0 0 1 0 0 1 0 0 1 0 1 1 0 0 1 1 0 1 0 0 0 0 1 1 1 0 0 1 0 1 0 1 0 0 1 0 0 0 0 1 1 1 0 1 1 1 1 0 0 0 0 1 1 1 1 1 1 1 1 1 0 1 0 1 0 1 0 1 1 0 0 1 0 1 1 0 1 1 0 1 1 0 0 1 1 0 0 0 1 0 0 1 1 0 0 0 1; + 0 0 1 0 0 0 0 1 1 1 0 1 1 1 1 0 0 0 0 1 1 1 1 1 1 1 1 1 0 1 0 1 0 1 0 1 1 0 0 1 0 1 1 0 1 1 0 1 1 0 0 1 1 0 0 0 1 0 0 1 1 0 0 0 1 0 0 0 1 1 0 1 0 0 0 0 1 1 1 0 1 1 1 1 0 0 0 0 1 0 1 0 1 1 1 1 0 0 1 1 1 0 1 0 0 1 1 0 1 1 1 1 0 1 0 0 0 1 0 1 1 1 0 0 0 1 0 0 1 0 0 1 0 1 1 0 0 1 1 0 1 0 0 0 0 1 1 1 0 0; + 0 0 0 1 0 1 0 1 1 1 1 0 0 1 1 1 0 1 0 0 1 1 0 1 1 1 1 0 1 0 0 0 1 0 1 1 1 0 0 0 1 0 0 1 0 0 1 0 1 1 0 0 1 1 0 1 0 0 0 0 1 1 1 0 0 1 0 1 0 1 0 0 1 0 0 0 0 1 1 1 0 1 1 1 1 0 0 0 0 1 1 1 1 1 1 1 1 1 0 1 0 1 0 1 0 1 1 0 0 1 0 1 1 0 1 1 0 1 1 0 0 1 1 0 0 0 1 0 0 1 1 0 0 0 1 0 0 0 1 1 0 1 0 0 0 0 1 1 1 0; + 0 0 0 0 1 1 1 1 1 1 1 1 1 0 1 0 1 0 1 0 1 1 0 0 1 0 1 1 0 1 1 0 1 1 0 0 1 1 0 0 0 1 0 0 1 1 0 0 0 1 0 0 0 1 1 0 1 0 0 0 0 1 1 1 0 1 1 1 1 0 0 0 0 1 0 1 0 1 1 1 1 0 0 1 1 1 0 1 0 0 1 1 0 1 1 1 1 0 1 0 0 0 1 0 1 1 1 0 0 0 1 0 0 1 0 0 1 0 1 1 0 0 1 1 0 1 0 0 0 0 1 1 1 0 0 1 0 1 0 1 0 0 1 0 0 0 0 1 1 1; + 1 0 0 0 0 0 1 1 1 0 0 1 1 1 1 1 0 1 0 0 1 1 0 0 1 1 0 0 1 0 1 0 0 0 1 1 0 1 0 1 0 0 0 1 0 1 1 1 1 1 1 1 0 1 0 1 0 1 1 0 0 0 1 1 0 0 1 0 0 0 0 0 1 1 1 1 0 0 1 1 0 1 0 1 0 1 1 0 0 0 0 1 0 0 1 1 1 1 0 0 1 1 1 1 0 0 0 0 0 1 1 1 0 1 1 0 1 1 0 1 0 1 0 1 1 0 0 0 1 1 0 0 1 0 0 1 0 1 1 1 1 1 1 0 1 0 0 1 0 1; + 0 1 0 0 0 0 0 1 1 1 1 0 0 1 1 0 1 0 1 0 1 1 0 0 0 0 1 0 0 1 1 1 1 0 0 1 1 1 1 0 0 0 0 0 1 1 1 0 1 1 0 1 1 0 1 0 1 0 1 1 0 0 0 1 1 0 0 1 0 0 1 0 1 1 1 1 1 1 0 1 0 0 1 0 1 0 1 1 0 0 1 0 0 0 0 0 1 1 1 0 0 1 1 1 1 1 0 1 0 0 1 1 0 0 1 1 0 0 1 0 1 0 0 0 1 1 0 1 0 1 0 0 0 1 0 1 1 1 1 1 1 1 0 1 0 1 0 1 1 0; + 0 0 1 0 0 1 0 1 1 1 1 1 1 0 1 0 0 1 0 1 0 1 1 0 0 1 0 0 0 0 0 1 1 1 0 0 1 1 1 1 1 0 1 0 0 1 1 0 0 1 1 0 0 1 0 1 0 0 0 1 1 0 1 0 1 0 0 0 1 0 1 1 1 1 1 1 1 0 1 0 1 0 1 1 0 0 0 1 1 0 0 1 0 0 0 0 0 1 1 1 1 0 0 1 1 0 1 0 1 0 1 1 0 0 0 0 1 0 0 1 1 1 1 0 0 1 1 1 1 0 0 0 0 0 1 1 1 0 1 1 0 1 1 0 1 0 1 0 1 1; + 0 0 0 1 0 1 1 1 1 1 1 1 0 1 0 1 0 1 1 0 0 0 1 1 0 0 1 0 0 0 0 0 1 1 1 1 0 0 1 1 0 1 0 1 0 1 1 0 0 0 0 1 0 0 1 1 1 1 0 0 1 1 1 1 0 0 0 0 0 1 1 1 0 1 1 0 1 1 0 1 0 1 0 1 1 0 0 0 1 1 0 0 1 0 0 1 0 1 1 1 1 1 1 0 1 0 0 1 0 1 0 1 1 0 0 1 0 0 0 0 0 1 1 1 0 0 1 1 1 1 1 0 1 0 0 1 1 0 0 1 1 0 0 1 0 1 0 0 0 1; + 0 0 0 0 1 1 1 0 1 1 0 1 1 0 1 0 1 0 1 1 0 0 0 1 1 0 0 1 0 0 1 0 1 1 1 1 1 1 0 1 0 0 1 0 1 0 1 1 0 0 1 0 0 0 0 0 1 1 1 0 0 1 1 1 1 1 0 1 0 0 1 1 0 0 1 1 0 0 1 0 1 0 0 0 1 1 0 1 0 1 0 0 0 1 0 1 1 1 1 1 1 1 0 1 0 1 0 1 1 0 0 0 1 1 0 0 1 0 0 0 0 0 1 1 1 1 0 0 1 1 0 1 0 1 0 1 1 0 0 0 0 1 0 0 1 1 1 1 0 0; + 1 0 0 0 0 0 0 1 1 1 1 1 1 0 1 1 0 1 1 0 0 0 0 1 1 0 0 0 1 0 1 1 0 1 1 1 0 0 1 0 1 1 1 0 0 0 1 1 1 1 0 1 0 1 0 0 1 1 0 0 0 1 0 0 0 1 0 1 1 1 1 1 0 1 0 0 1 0 1 1 1 0 1 0 1 0 0 0 0 1 1 1 0 0 1 0 1 0 0 1 0 1 1 1 0 1 0 0 1 1 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 1 1 1 1 1 0 1 1 0 1 1 0 0 0 1 1 1 1 1 0 1 0 1 0 0; + 0 1 0 0 0 1 0 1 1 1 1 1 0 1 0 0 1 0 1 1 1 0 1 0 1 0 0 0 0 1 1 1 0 0 1 0 1 0 0 1 0 1 1 1 0 1 0 0 1 1 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 1 1 1 1 1 0 1 1 0 1 1 0 0 0 1 1 1 1 1 0 1 0 1 0 0 1 1 0 0 0 1 0 0 0 0 0 0 1 1 1 1 1 1 0 1 1 0 1 1 0 0 0 0 1 1 0 0 0 1 0 1 1 0 1 1 1 0 0 1 0 1 1 1 0 0 0 1 1 1 1 0 1 0 1 0; + 0 0 1 0 0 1 1 1 1 1 0 1 1 0 1 1 0 0 0 1 1 1 1 1 0 1 0 1 0 0 1 1 0 0 0 1 0 0 0 0 0 0 1 1 1 1 1 1 0 1 1 0 1 1 0 0 0 0 1 1 0 0 0 1 0 1 1 0 1 1 1 0 0 1 0 1 1 1 0 0 0 1 1 1 1 0 1 0 1 0 0 1 1 0 0 0 1 0 0 0 1 0 1 1 1 1 1 0 1 0 0 1 0 1 1 1 0 1 0 1 0 0 0 0 1 1 1 0 0 1 0 1 0 0 1 0 1 1 1 0 1 0 0 1 1 0 0 1 0 1; + 0 0 0 1 0 1 1 0 1 1 1 0 0 1 0 1 1 1 0 0 0 1 1 1 1 0 1 0 1 0 0 1 1 0 0 0 1 0 0 0 1 0 1 1 1 1 1 0 1 0 0 1 0 1 1 1 0 1 0 1 0 0 0 0 1 1 1 0 0 1 0 1 0 0 1 0 1 1 1 0 1 0 0 1 1 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 1 1 1 1 1 0 1 1 0 1 1 0 0 0 1 1 1 1 1 0 1 0 1 0 0 1 1 0 0 0 1 0 0 0 0 0 0 1 1 1 1 1 1 0 1 1 0 1 1 0; + 0 0 0 0 1 1 1 0 0 1 0 1 0 0 1 0 1 1 1 0 1 0 0 1 1 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 1 1 1 1 1 0 1 1 0 1 1 0 0 0 1 1 1 1 1 0 1 0 1 0 0 1 1 0 0 0 1 0 0 0 0 0 0 1 1 1 1 1 1 0 1 1 0 1 1 0 0 0 0 1 1 0 0 0 1 0 1 1 0 1 1 1 0 0 1 0 1 1 1 0 0 0 1 1 1 1 0 1 0 1 0 0 1 1 0 0 0 1 0 0 0 1 0 1 1 1 1 1 0 1 0 0 1 0 1 1; + 1 0 0 0 0 1 0 1 1 1 0 1 1 0 1 1 1 1 0 0 1 0 0 1 1 1 0 1 1 0 1 0 1 0 1 1 0 1 0 0 0 1 1 0 0 0 0 1 0 0 1 1 0 1 1 0 1 0 0 1 0 0 1 1 1 1 1 0 1 0 1 0 0 0 1 0 1 1 1 1 0 0 1 0 1 0 0 0 1 1 0 0 0 0 1 1 1 0 0 0 0 1 0 0 0 1 1 1 1 1 1 0 0 1 0 0 1 1 1 0 1 1 1 0 1 0 1 0 1 1 1 1 1 1 0 0 1 0 1 0 0 0 1 1 0 0 0 0 1 0; + 0 1 0 0 0 1 1 1 1 1 1 0 0 1 0 0 1 1 1 0 1 1 1 0 1 0 1 0 1 1 1 1 1 1 0 0 1 0 1 0 0 0 1 1 0 0 0 0 1 0 1 1 0 0 1 1 0 0 0 0 1 0 1 1 1 0 1 1 0 1 1 1 1 0 0 1 0 0 1 1 1 0 1 1 0 1 0 1 0 1 1 0 1 0 0 0 1 1 0 0 0 0 1 0 0 1 1 0 1 1 0 1 0 0 1 0 0 1 1 1 1 1 0 1 0 1 0 0 0 1 0 1 1 1 1 0 0 1 0 1 0 0 0 1 1 0 0 0 0 1; + 0 0 1 0 0 1 1 0 1 1 0 1 0 0 1 0 0 1 1 1 1 1 0 1 0 1 0 0 0 1 0 1 1 1 1 0 0 1 0 1 0 0 0 1 1 0 0 0 0 1 1 1 0 0 0 0 1 0 0 0 1 1 1 1 1 1 0 0 1 0 0 1 1 1 0 1 1 1 0 1 0 1 0 1 1 1 1 1 1 0 0 1 0 1 0 0 0 1 1 0 0 0 0 1 0 1 1 0 0 1 1 0 0 0 0 1 0 1 1 1 0 1 1 0 1 1 1 1 0 0 1 0 0 1 1 1 0 1 1 0 1 0 1 0 1 1 0 1 0 0; + 0 0 0 1 0 1 1 0 0 1 1 0 0 0 0 1 0 1 1 1 0 1 1 0 1 1 1 1 0 0 1 0 0 1 1 1 0 1 1 0 1 0 1 0 1 1 0 1 0 0 0 1 1 0 0 0 0 1 0 0 1 1 0 1 1 0 1 0 0 1 0 0 1 1 1 1 1 0 1 0 1 0 0 0 1 0 1 1 1 1 0 0 1 0 1 0 0 0 1 1 0 0 0 0 1 1 1 0 0 0 0 1 0 0 0 1 1 1 1 1 1 0 0 1 0 0 1 1 1 0 1 1 1 0 1 0 1 0 1 1 1 1 1 1 0 0 1 0 1 0; + 0 0 0 0 1 1 1 0 0 0 0 1 0 0 0 1 1 1 1 1 1 0 0 1 0 0 1 1 1 0 1 1 1 0 1 0 1 0 1 1 1 1 1 1 0 0 1 0 1 0 0 0 1 1 0 0 0 0 1 0 1 1 0 0 1 1 0 0 0 0 1 0 1 1 1 0 1 1 0 1 1 1 1 0 0 1 0 0 1 1 1 0 1 1 0 1 0 1 0 1 1 0 1 0 0 0 1 1 0 0 0 0 1 0 0 1 1 0 1 1 0 1 0 0 1 0 0 1 1 1 1 1 0 1 0 1 0 0 0 1 0 1 1 1 1 0 0 1 0 1] end diff --git a/test/test_ecc_throws.jl b/test/test_ecc_throws.jl index ff8d808ed..e0785fd92 100644 --- a/test/test_ecc_throws.jl +++ b/test/test_ecc_throws.jl @@ -1,10 +1,11 @@ using Test using QuantumClifford using QuantumClifford.ECC -using QuantumClifford.ECC: ReedMuller +using QuantumClifford.ECC: ReedMuller, ReedSolomon @test_throws ArgumentError ReedMuller(-1, 3) @test_throws ArgumentError ReedMuller(1, 0) -@test_throws ArgumentError ReedSolomon(-1, -1) -@test_throws ArgumentError ReedSolomon(31, 35) \ No newline at end of file +@test_throws ArgumentError ReedSolomon(31, 1) +@test_throws ArgumentError ReedSolomon(31, 35) +@test_throws ArgumentError ReedSolomon(-1, 1) From 91e4201c3ca6a62f4634587140ba68b6b980e30a Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Sat, 4 May 2024 02:03:45 +0500 Subject: [PATCH 27/70] adding pre-code review suggestions from BCH --- src/ecc/codes/classical/reedsolomon.jl | 38 +++++++++++----------- test/test_ecc_reedsolomon.jl | 45 +++++++++++++++++++++++++- 2 files changed, 63 insertions(+), 20 deletions(-) diff --git a/src/ecc/codes/classical/reedsolomon.jl b/src/ecc/codes/classical/reedsolomon.jl index 9a2c2f2c0..44d3127c8 100644 --- a/src/ecc/codes/classical/reedsolomon.jl +++ b/src/ecc/codes/classical/reedsolomon.jl @@ -5,14 +5,14 @@ Reed Solomon codes are maximum distance separable (MDS) codes and have the highe They are not binary codes but frequently are used with x = 2ᵐ, and so there is a mapping of residue classes of a primitive polynomial with binary coefficients and each element of GF(2ᵐ) is represented as a binary m-tuple. Denoting the x field elements as 0, α⁰, α¹, α²,... αˣ ⁻ ¹, the shortened Field parity-check matrix (`HSeed`) is given by ``` -(α⁰)ʲ (α¹)ʲ (α²)ʲ ... (αˣ ⁻ ¹)ʲ -(α⁰)ʲ ⁺ ¹ (α¹)ʲ ⁺ ¹ (α²)ʲ ⁺ ¹ ... (αˣ ⁻ ¹)ʲ ⁺ ¹ -(α⁰)ʲ ⁺ ² (α¹)ʲ ⁺ ² (α²)ʲ ⁺ ² ... (αˣ ⁻ ¹)ʲ ⁺ ² -(α⁰)ʲ ⁺ ˣ ⁻ ᵏ ⁻ ¹ (α¹)ʲ ⁺ ˣ ⁻ ᵏ ⁻ ¹ (α²)ʲ ⁺ ˣ ⁻ ᵏ ⁻ ¹ ... (αˣ ⁻ ¹)ʲ ⁺ ˣ ⁻ ᵏ ⁻ ¹ - . . . ... . - . . . ... . - . . . ... . -(α⁰)ʲ ⁺ ˣ ⁻ ᵏ (α¹)ʲ ⁺ ˣ ⁻ ᵏ (α²)ʲ ⁺ ˣ ⁻ ᵏ (αˣ ⁻ ¹)ʲ ⁺ ˣ ⁻ ᵏ +(α⁰)ʲ (α¹)ʲ (α²)ʲ ... (αˣ ⁻ ¹)ʲ +(α⁰)ʲ ⁺ ¹ (α¹)ʲ ⁺ ¹ (α²)ʲ ⁺ ¹ ... (αˣ ⁻ ¹)ʲ ⁺ ¹ +(α⁰)ʲ ⁺ ² (α¹)ʲ ⁺ ² (α²)ʲ ⁺ ² ... (αˣ ⁻ ¹)ʲ ⁺ ² +(α⁰)ʲ ⁺ ˣ ⁻ ᵏ ⁻ ¹ (α¹)ʲ ⁺ ˣ ⁻ ᵏ ⁻ ¹ (α²)ʲ ⁺ ˣ ⁻ ᵏ ⁻ ¹ ... (αˣ ⁻ ¹)ʲ ⁺ ˣ ⁻ ᵏ ⁻ ¹ + . . . . + . . . . + . . . . +(α⁰)ʲ ⁺ ˣ ⁻ ᵏ (α¹)ʲ ⁺ ˣ ⁻ ᵏ (α²)ʲ ⁺ ˣ ⁻ ᵏ ... (αˣ ⁻ ¹)ʲ ⁺ ˣ ⁻ ᵏ ``` You might be interested in consulting [geisel1990tutorial](@cite), [wicker1999reed](@cite), [sklar2001reed](@cite), [berlekamp1978readable](@cite), [tomlinson2017error](@cite), [macwilliams1977theory](@cite) and [https://youtu.be/K26Ssr8H3ec?si=QOeohq_6I0Oyd8qu] as well. @@ -28,7 +28,7 @@ struct ReedSolomon <: AbstractPolynomialCode function ReedSolomon(n, k) if n < 0 || k < 2 || n > 500 || k > n - throw(ArgumentError("Invalid parameters: n and k must be non-negative. Also, 1 < k < n / 2 and n < 500 in order to obtain a valid code and to remain tractable")) + throw(ArgumentError("Invalid parameters: n and k must be non-negative. Also, 2 ≤ k ≤ n and n < 500 in order to obtain a valid code and to remain tractable")) end new(n, k) end @@ -47,7 +47,6 @@ function generator_polynomial(rs::ReedSolomon) return gx end -# Reed-Solomon Codes and Binary Transmission with soft decisions """ This function applies Reed-Solomon (RS) codes with soft decision decoding for binary transmission channels. @@ -80,14 +79,14 @@ Augmented Extended RS Codes: Field Parity-Check Matrix (`HField`) Properties: ``` -(α₀)ʲ (α₁)ʲ (α₂)ʲ ... (αₓ₋₂)ʲ 1 0 -(α₀)ʲ ⁺ ¹ (α₁)ʲ ⁺ ¹ (α₂)ʲ ⁺ ¹ ... (αₓ₋₂)ʲ ⁺ ¹ 0 0 -(α₀)ʲ ⁺ ² (α₁)ʲ ⁺ ² (α₂)ʲ ⁺ ² ... (αₓ₋₂)ʲ ⁺ ² 0 0 - . . . ... . . . - . . . ... . . . - . . . ... . . . -(α₀)ʲ ⁺ ˣ ⁻ ᵏ ⁻ ¹ (α₁)ʲ ⁺ ˣ ⁻ ᵏ ⁻ ¹ (α₂)ʲ ⁺ ˣ ⁻ ᵏ ⁻ ¹ ... (αₓ₋₂)ʲ ⁺ ˣ ⁻ ᵏ ⁻ ¹ 0 0 -(α₀)ʲ ⁺ ˣ ⁻ ᵏ (α₁)ʲ ⁺ ˣ ⁻ ᵏ (α₂)ʲ ⁺ ˣ ⁻ ᵏ ... (αₓ₋₂)ʲ ⁺ ˣ ⁻ ᵏ 0 1 +(α₀)ʲ (α₁)ʲ (α₂)ʲ ... (αₓ₋₂)ʲ 1 0 +(α₀)ʲ ⁺ ¹ (α₁)ʲ ⁺ ¹ (α₂)ʲ ⁺ ¹ ... (αₓ₋₂)ʲ ⁺ ¹ 0 0 +(α₀)ʲ ⁺ ² (α₁)ʲ ⁺ ² (α₂)ʲ ⁺ ² ... (αₓ₋₂)ʲ ⁺ ² 0 0 +. . . . +. . . . +. . . . +(α₀)ʲ ⁺ ˣ ⁻ ᵏ ⁻ ¹ (α₁)ʲ ⁺ ˣ ⁻ ᵏ ⁻ ¹ (α₂)ʲ ⁺ ˣ ⁻ ᵏ ⁻ ¹ ... (αₓ₋₂)ʲ ⁺ ˣ ⁻ ᵏ ⁻ ¹ 0 0 +(α₀)ʲ ⁺ ˣ ⁻ ᵏ (α₁)ʲ ⁺ ˣ ⁻ ᵏ (α₂)ʲ ⁺ ˣ ⁻ ᵏ ... (αₓ₋₂)ʲ ⁺ ˣ ⁻ ᵏ 0 1 ``` - The matrix has x - k + 1 rows corresponding to the code's parity symbols. @@ -106,7 +105,8 @@ Cyclic Code Construction: - Using the first x - 1 columns of the field parity-check matrix (HField), using j = 0, and setting α₀, α₁, α₂, ..., αₓ ₋ ₁ to α⁰, α¹, α², ..., αˣ ⁻ ¹ in the parity-check matrix are set equal to the powers of a primitive element α of the Galois Field GF(q), a cyclic code can be constructed for efficient encoding and decoding. The resulting matrix is represented by `HSeed`. -- `HSeed` Matrix element expansion: +`HSeed` Matrix element expansion: + 1. Row expansion: Each row of in the `HField` matrix is replaced with an `m`-by-`m` Field matrix defined over the base field GF (2ᵐ). This expansion is represented by `HFieldExpanded`. 2. Column expansion: The elements in each column of `HFieldExpanded` matrix are converted to binary representations by substituting powers of a primitive element (`α`) in the Galois Field GF(2ᵐ) with their corresponding m-tuples over the Boolean/Binary Field GF(2). """ diff --git a/test/test_ecc_reedsolomon.jl b/test/test_ecc_reedsolomon.jl index cbffaae61..49c606537 100644 --- a/test/test_ecc_reedsolomon.jl +++ b/test/test_ecc_reedsolomon.jl @@ -24,6 +24,27 @@ function designed_distance(matrix, k, n, r) return false end +function generate_examplepage175() + GF2ʳ, a = finite_field(2, 5, "a") + q = 30 + k = 15 + HField = Matrix{FqFieldElem}(undef, q - k + 1, q) + for j in 1: q + HField[1, j] = a ^ 0 + end + HTemp2 = Matrix{FqFieldElem}(undef, 5, q) + for i in 1: q - k + 1 + HField[i, 1] = a ^ 0 + end + for i in 2:q - k + 1 + for j in 2: q + HField[i, j] = (a ^ (j - 1)) ^ (i - 2) + end + end + HSeed = vcat(HField[1:1, :], HField[3:end, :]) + return HSeed +end + @testset "Testing Shortened and Expanded Maximum Distance Separable (MDS) Reed Solomon codes's binary parity check matrices" begin n_cases = [31, 63, 127, 255] for n in n_cases @@ -46,7 +67,29 @@ end P, x = GF2ʳ[:x] @test generator_polynomial(ReedSolomon(7, 2)) == x ^ 4 + (a ^ 2 + 1) * x ^ 3 + (a ^ 2 + 1) * x ^ 2 + (a + 1) * x + a - #example taken from page 175 of [tomlinson2017error](@cite). + #example taken from page 173 of [tomlinson2017error](@cite). + GF2ʳ, a = finite_field(2, 5, "a") + HF = Matrix{FqFieldElem}(undef, 15, 30) + HF = generate_examplepage175() + @test reshape(HF[1,:], 1, 30) == [1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1] + @test reshape(HF[:,1], 1, 15) == [ 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1] + @test HF[2,2] == a + @test HF[2,3] == a ^ 2 + @test HF[2,30] == a ^ 3 + 1 == a ^ 29 + @test HF[3,2] == a ^ 2 + @test HF[3,3] == a ^ 4 + @test HF[3,30] == a ^ 3 + a + 1 == a ^ 27 + @test HF[4,2] == a ^ 3 + @test HF[4,3] == a ^ 3 + a == a ^ 6 + @test HF[4,30] == a ^ 4 + a ^ 3 + 1 == a ^ 25 + @test HF[14,2] == a ^ 4 + a ^ 3 + a ^ 2 == a ^ 13 + @test HF[14,3] == a ^ 4 + a ^ 2 + a + 1 == a ^ 26 + @test HF[14,30] == a ^ 2 + 1 == a ^ 5 + @test HF[15,2] == a ^ 4 + a ^ 3 + a ^ 2 + 1 == a ^ 14 + @test HF[15,3] == a ^ 4 + a ^ 2 + a == a ^ 28 + @test HF[15,30] == a ^ 3 + + #example taken from page 175 of [tomlinson2017error](@cite) @test size(parity_checks(ReedSolomon(31, 15))) == (75, 150) @test parity_checks(ReedSolomon(31, 15)) == [1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0; 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0; From 0799c54ce01fed4fdfdb729b1e4a0b4b936d33cf Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Sat, 4 May 2024 02:13:06 +0500 Subject: [PATCH 28/70] stylistic changes in docstring --- src/ecc/codes/classical/reedsolomon.jl | 14 ++++++------ test/test_ecc_reedsolomon.jl | 30 +++++++++++++------------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/ecc/codes/classical/reedsolomon.jl b/src/ecc/codes/classical/reedsolomon.jl index 44d3127c8..835d94a98 100644 --- a/src/ecc/codes/classical/reedsolomon.jl +++ b/src/ecc/codes/classical/reedsolomon.jl @@ -9,10 +9,10 @@ They are not binary codes but frequently are used with x = 2ᵐ, and so there is (α⁰)ʲ ⁺ ¹ (α¹)ʲ ⁺ ¹ (α²)ʲ ⁺ ¹ ... (αˣ ⁻ ¹)ʲ ⁺ ¹ (α⁰)ʲ ⁺ ² (α¹)ʲ ⁺ ² (α²)ʲ ⁺ ² ... (αˣ ⁻ ¹)ʲ ⁺ ² (α⁰)ʲ ⁺ ˣ ⁻ ᵏ ⁻ ¹ (α¹)ʲ ⁺ ˣ ⁻ ᵏ ⁻ ¹ (α²)ʲ ⁺ ˣ ⁻ ᵏ ⁻ ¹ ... (αˣ ⁻ ¹)ʲ ⁺ ˣ ⁻ ᵏ ⁻ ¹ - . . . . - . . . . - . . . . -(α⁰)ʲ ⁺ ˣ ⁻ ᵏ (α¹)ʲ ⁺ ˣ ⁻ ᵏ (α²)ʲ ⁺ ˣ ⁻ ᵏ ... (αˣ ⁻ ¹)ʲ ⁺ ˣ ⁻ ᵏ + . . . ... . + . . . ... . + . . . ... . +(α⁰)ʲ ⁺ ˣ ⁻ ᵏ (α¹)ʲ ⁺ ˣ ⁻ ᵏ (α²)ʲ ⁺ ˣ ⁻ ᵏ ... (αˣ ⁻ ¹)ʲ ⁺ ˣ ⁻ ᵏ ``` You might be interested in consulting [geisel1990tutorial](@cite), [wicker1999reed](@cite), [sklar2001reed](@cite), [berlekamp1978readable](@cite), [tomlinson2017error](@cite), [macwilliams1977theory](@cite) and [https://youtu.be/K26Ssr8H3ec?si=QOeohq_6I0Oyd8qu] as well. @@ -82,10 +82,10 @@ Field Parity-Check Matrix (`HField`) Properties: (α₀)ʲ (α₁)ʲ (α₂)ʲ ... (αₓ₋₂)ʲ 1 0 (α₀)ʲ ⁺ ¹ (α₁)ʲ ⁺ ¹ (α₂)ʲ ⁺ ¹ ... (αₓ₋₂)ʲ ⁺ ¹ 0 0 (α₀)ʲ ⁺ ² (α₁)ʲ ⁺ ² (α₂)ʲ ⁺ ² ... (αₓ₋₂)ʲ ⁺ ² 0 0 -. . . . -. . . . -. . . . (α₀)ʲ ⁺ ˣ ⁻ ᵏ ⁻ ¹ (α₁)ʲ ⁺ ˣ ⁻ ᵏ ⁻ ¹ (α₂)ʲ ⁺ ˣ ⁻ ᵏ ⁻ ¹ ... (αₓ₋₂)ʲ ⁺ ˣ ⁻ ᵏ ⁻ ¹ 0 0 + . . . ... . . . + . . . ... . . . + . . . ... . . . (α₀)ʲ ⁺ ˣ ⁻ ᵏ (α₁)ʲ ⁺ ˣ ⁻ ᵏ (α₂)ʲ ⁺ ˣ ⁻ ᵏ ... (αₓ₋₂)ʲ ⁺ ˣ ⁻ ᵏ 0 1 ``` diff --git a/test/test_ecc_reedsolomon.jl b/test/test_ecc_reedsolomon.jl index 49c606537..c02d51d1d 100644 --- a/test/test_ecc_reedsolomon.jl +++ b/test/test_ecc_reedsolomon.jl @@ -73,21 +73,21 @@ end HF = generate_examplepage175() @test reshape(HF[1,:], 1, 30) == [1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1] @test reshape(HF[:,1], 1, 15) == [ 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1] - @test HF[2,2] == a - @test HF[2,3] == a ^ 2 - @test HF[2,30] == a ^ 3 + 1 == a ^ 29 - @test HF[3,2] == a ^ 2 - @test HF[3,3] == a ^ 4 - @test HF[3,30] == a ^ 3 + a + 1 == a ^ 27 - @test HF[4,2] == a ^ 3 - @test HF[4,3] == a ^ 3 + a == a ^ 6 - @test HF[4,30] == a ^ 4 + a ^ 3 + 1 == a ^ 25 - @test HF[14,2] == a ^ 4 + a ^ 3 + a ^ 2 == a ^ 13 - @test HF[14,3] == a ^ 4 + a ^ 2 + a + 1 == a ^ 26 - @test HF[14,30] == a ^ 2 + 1 == a ^ 5 - @test HF[15,2] == a ^ 4 + a ^ 3 + a ^ 2 + 1 == a ^ 14 - @test HF[15,3] == a ^ 4 + a ^ 2 + a == a ^ 28 - @test HF[15,30] == a ^ 3 + @test HF[2, 2] == a + @test HF[2, 3] == a ^ 2 + @test HF[2, 30] == a ^ 3 + 1 == a ^ 29 + @test HF[3, 2] == a ^ 2 + @test HF[3, 3] == a ^ 4 + @test HF[3, 30] == a ^ 3 + a + 1 == a ^ 27 + @test HF[4, 2] == a ^ 3 + @test HF[4, 3] == a ^ 3 + a == a ^ 6 + @test HF[4, 30] == a ^ 4 + a ^ 3 + 1 == a ^ 25 + @test HF[14, 2] == a ^ 4 + a ^ 3 + a ^ 2 == a ^ 13 + @test HF[14, 3] == a ^ 4 + a ^ 2 + a + 1 == a ^ 26 + @test HF[14, 30] == a ^ 2 + 1 == a ^ 5 + @test HF[15, 2] == a ^ 4 + a ^ 3 + a ^ 2 + 1 == a ^ 14 + @test HF[15, 3] == a ^ 4 + a ^ 2 + a == a ^ 28 + @test HF[15, 30] == a ^ 3 #example taken from page 175 of [tomlinson2017error](@cite) @test size(parity_checks(ReedSolomon(31, 15))) == (75, 150) From 50fc5a445cce894e1b20b3018e48d72c0755404b Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Sat, 4 May 2024 02:23:27 +0500 Subject: [PATCH 29/70] matrices unicode docstring --- src/ecc/codes/classical/reedsolomon.jl | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/ecc/codes/classical/reedsolomon.jl b/src/ecc/codes/classical/reedsolomon.jl index 835d94a98..1fca1fe1e 100644 --- a/src/ecc/codes/classical/reedsolomon.jl +++ b/src/ecc/codes/classical/reedsolomon.jl @@ -5,14 +5,14 @@ Reed Solomon codes are maximum distance separable (MDS) codes and have the highe They are not binary codes but frequently are used with x = 2ᵐ, and so there is a mapping of residue classes of a primitive polynomial with binary coefficients and each element of GF(2ᵐ) is represented as a binary m-tuple. Denoting the x field elements as 0, α⁰, α¹, α²,... αˣ ⁻ ¹, the shortened Field parity-check matrix (`HSeed`) is given by ``` -(α⁰)ʲ (α¹)ʲ (α²)ʲ ... (αˣ ⁻ ¹)ʲ -(α⁰)ʲ ⁺ ¹ (α¹)ʲ ⁺ ¹ (α²)ʲ ⁺ ¹ ... (αˣ ⁻ ¹)ʲ ⁺ ¹ -(α⁰)ʲ ⁺ ² (α¹)ʲ ⁺ ² (α²)ʲ ⁺ ² ... (αˣ ⁻ ¹)ʲ ⁺ ² -(α⁰)ʲ ⁺ ˣ ⁻ ᵏ ⁻ ¹ (α¹)ʲ ⁺ ˣ ⁻ ᵏ ⁻ ¹ (α²)ʲ ⁺ ˣ ⁻ ᵏ ⁻ ¹ ... (αˣ ⁻ ¹)ʲ ⁺ ˣ ⁻ ᵏ ⁻ ¹ - . . . ... . - . . . ... . - . . . ... . -(α⁰)ʲ ⁺ ˣ ⁻ ᵏ (α¹)ʲ ⁺ ˣ ⁻ ᵏ (α²)ʲ ⁺ ˣ ⁻ ᵏ ... (αˣ ⁻ ¹)ʲ ⁺ ˣ ⁻ ᵏ +(α⁰)ʲ (α¹)ʲ (α²)ʲ ... (αˣ ⁻ ¹)ʲ +(α⁰)ʲ ⁺ ¹ (α¹)ʲ ⁺ ¹ (α²)ʲ ⁺ ¹ ... (αˣ ⁻ ¹)ʲ ⁺ ¹ +(α⁰)ʲ ⁺ ² (α¹)ʲ ⁺ ² (α²)ʲ ⁺ ² ... (αˣ ⁻ ¹)ʲ ⁺ ² +(α⁰)ʲ ⁺ ˣ ⁻ ᵏ ⁻ ¹ (α¹)ʲ ⁺ ˣ ⁻ ᵏ ⁻ ¹ (α²)ʲ ⁺ ˣ ⁻ ᵏ ⁻ ¹ ... (αˣ ⁻ ¹)ʲ ⁺ ˣ ⁻ ᵏ ⁻ ¹ + . . . ... . + . . . ... . + . . . ... . +(α⁰)ʲ ⁺ ˣ ⁻ ᵏ (α¹)ʲ ⁺ ˣ ⁻ ᵏ (α²)ʲ ⁺ ˣ ⁻ ᵏ ... (αˣ ⁻ ¹)ʲ ⁺ ˣ ⁻ ᵏ ``` You might be interested in consulting [geisel1990tutorial](@cite), [wicker1999reed](@cite), [sklar2001reed](@cite), [berlekamp1978readable](@cite), [tomlinson2017error](@cite), [macwilliams1977theory](@cite) and [https://youtu.be/K26Ssr8H3ec?si=QOeohq_6I0Oyd8qu] as well. From 6c64a6d4d337809bf5c39268da9d97664ce0cfd5 Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Sat, 4 May 2024 16:32:41 +0500 Subject: [PATCH 30/70] adding more tests to Reed-Solomon and setting it up for code review --- src/ecc/codes/classical/reedsolomon.jl | 14 +-- test/test_ecc_reedsolomon.jl | 148 +++++++++++-------------- 2 files changed, 71 insertions(+), 91 deletions(-) diff --git a/src/ecc/codes/classical/reedsolomon.jl b/src/ecc/codes/classical/reedsolomon.jl index 1fca1fe1e..d38334ca6 100644 --- a/src/ecc/codes/classical/reedsolomon.jl +++ b/src/ecc/codes/classical/reedsolomon.jl @@ -5,14 +5,14 @@ Reed Solomon codes are maximum distance separable (MDS) codes and have the highe They are not binary codes but frequently are used with x = 2ᵐ, and so there is a mapping of residue classes of a primitive polynomial with binary coefficients and each element of GF(2ᵐ) is represented as a binary m-tuple. Denoting the x field elements as 0, α⁰, α¹, α²,... αˣ ⁻ ¹, the shortened Field parity-check matrix (`HSeed`) is given by ``` -(α⁰)ʲ (α¹)ʲ (α²)ʲ ... (αˣ ⁻ ¹)ʲ -(α⁰)ʲ ⁺ ¹ (α¹)ʲ ⁺ ¹ (α²)ʲ ⁺ ¹ ... (αˣ ⁻ ¹)ʲ ⁺ ¹ -(α⁰)ʲ ⁺ ² (α¹)ʲ ⁺ ² (α²)ʲ ⁺ ² ... (αˣ ⁻ ¹)ʲ ⁺ ² +(α⁰)ʲ (α¹)ʲ (α²)ʲ ... (αˣ ⁻ ¹)ʲ +(α⁰)ʲ ⁺ ¹ (α¹)ʲ ⁺ ¹ (α²)ʲ ⁺ ¹ ... (αˣ ⁻ ¹)ʲ ⁺ ¹ +(α⁰)ʲ ⁺ ² (α¹)ʲ ⁺ ² (α²)ʲ ⁺ ² ... (αˣ ⁻ ¹)ʲ ⁺ ² (α⁰)ʲ ⁺ ˣ ⁻ ᵏ ⁻ ¹ (α¹)ʲ ⁺ ˣ ⁻ ᵏ ⁻ ¹ (α²)ʲ ⁺ ˣ ⁻ ᵏ ⁻ ¹ ... (αˣ ⁻ ¹)ʲ ⁺ ˣ ⁻ ᵏ ⁻ ¹ . . . ... . . . . ... . . . . ... . -(α⁰)ʲ ⁺ ˣ ⁻ ᵏ (α¹)ʲ ⁺ ˣ ⁻ ᵏ (α²)ʲ ⁺ ˣ ⁻ ᵏ ... (αˣ ⁻ ¹)ʲ ⁺ ˣ ⁻ ᵏ +(α⁰)ʲ ⁺ ˣ ⁻ ᵏ (α¹)ʲ ⁺ ˣ ⁻ ᵏ (α²)ʲ ⁺ ˣ ⁻ ᵏ ... (αˣ ⁻ ¹)ʲ ⁺ ˣ ⁻ ᵏ ``` You might be interested in consulting [geisel1990tutorial](@cite), [wicker1999reed](@cite), [sklar2001reed](@cite), [berlekamp1978readable](@cite), [tomlinson2017error](@cite), [macwilliams1977theory](@cite) and [https://youtu.be/K26Ssr8H3ec?si=QOeohq_6I0Oyd8qu] as well. @@ -79,9 +79,9 @@ Augmented Extended RS Codes: Field Parity-Check Matrix (`HField`) Properties: ``` -(α₀)ʲ (α₁)ʲ (α₂)ʲ ... (αₓ₋₂)ʲ 1 0 +(α₀)ʲ (α₁)ʲ (α₂)ʲ ... (αₓ₋₂)ʲ 1 0 (α₀)ʲ ⁺ ¹ (α₁)ʲ ⁺ ¹ (α₂)ʲ ⁺ ¹ ... (αₓ₋₂)ʲ ⁺ ¹ 0 0 -(α₀)ʲ ⁺ ² (α₁)ʲ ⁺ ² (α₂)ʲ ⁺ ² ... (αₓ₋₂)ʲ ⁺ ² 0 0 +(α₀)ʲ ⁺ ² (α₁)ʲ ⁺ ² (α₂)ʲ ⁺ ² ... (αₓ₋₂)ʲ ⁺ ² 0 0 (α₀)ʲ ⁺ ˣ ⁻ ᵏ ⁻ ¹ (α₁)ʲ ⁺ ˣ ⁻ ᵏ ⁻ ¹ (α₂)ʲ ⁺ ˣ ⁻ ᵏ ⁻ ¹ ... (αₓ₋₂)ʲ ⁺ ˣ ⁻ ᵏ ⁻ ¹ 0 0 . . . ... . . . . . . ... . . . @@ -155,5 +155,5 @@ function parity_checks(rs::ReedSolomon) H[i, col_start:col_end] .= vec(t_tuple) end end - return H + return H end diff --git a/test/test_ecc_reedsolomon.jl b/test/test_ecc_reedsolomon.jl index c02d51d1d..335596b95 100644 --- a/test/test_ecc_reedsolomon.jl +++ b/test/test_ecc_reedsolomon.jl @@ -75,95 +75,75 @@ end @test reshape(HF[:,1], 1, 15) == [ 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1] @test HF[2, 2] == a @test HF[2, 3] == a ^ 2 - @test HF[2, 30] == a ^ 3 + 1 == a ^ 29 + @test HF[2, 30] == a ^ 3 + 1 == a ^ 29 @test HF[3, 2] == a ^ 2 @test HF[3, 3] == a ^ 4 - @test HF[3, 30] == a ^ 3 + a + 1 == a ^ 27 + @test HF[3, 30] == a ^ 3 + a + 1 == a ^ 27 @test HF[4, 2] == a ^ 3 - @test HF[4, 3] == a ^ 3 + a == a ^ 6 - @test HF[4, 30] == a ^ 4 + a ^ 3 + 1 == a ^ 25 - @test HF[14, 2] == a ^ 4 + a ^ 3 + a ^ 2 == a ^ 13 - @test HF[14, 3] == a ^ 4 + a ^ 2 + a + 1 == a ^ 26 - @test HF[14, 30] == a ^ 2 + 1 == a ^ 5 - @test HF[15, 2] == a ^ 4 + a ^ 3 + a ^ 2 + 1 == a ^ 14 - @test HF[15, 3] == a ^ 4 + a ^ 2 + a == a ^ 28 + @test HF[4, 3] == a ^ 3 + a == a ^ 6 + @test HF[4, 30] == a ^ 4 + a ^ 3 + 1 == a ^ 25 + @test HF[14, 2] == a ^ 4 + a ^ 3 + a ^ 2 == a ^ 13 + @test HF[14, 3] == a ^ 4 + a ^ 2 + a + 1 == a ^ 26 + @test HF[14, 30] == a ^ 2 + 1 ==a ^ 5 + @test HF[15, 2] == a ^ 4 + a ^ 3 + a ^ 2 + 1 == a ^ 14 + @test HF[15, 3] == a ^ 4 + a ^ 2 + a == a ^ 28 @test HF[15, 30] == a ^ 3 #example taken from page 175 of [tomlinson2017error](@cite) @test size(parity_checks(ReedSolomon(31, 15))) == (75, 150) - @test parity_checks(ReedSolomon(31, 15)) == [1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0; - 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0; - 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0; - 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0; - 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1; - 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 1 0 1 0 0 0 1 0 1 0 0 0 1 0 1 1 0 1 1 0 0 1 0 1 1 1 0 0 0 1 1 1 1 0 0 0 1 1 1 0 0 0 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 0 0 1 1 1 0 0 0 0 1 1 0 0 0 0 1 1 0 0 0 0 1 1 1 0 1 0 1 1 1 1 1 0 0 1 1 1 1 1 0 0 1 1 1 1 1 0 1 1 1 0 1 0 0 1 1 0 1 1 0 0 1 0; - 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 1 0 1 0 0 0 1 0 1 0 0 0 1 0 1 1 0 1 1 0 0 1 0 1 1 1 0 0 0 1 1 1 1 0 0 0 1 1 1 0 0 0 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 0 0 1 1 1 0 0 0 0 1 1 0 0 0 0 1 1 0 0 0 0 1 1 1 0 1 0 1 1 1 1 1 0 0 1 1 1 1 1 0 0 1 1 1 1 1 0 1 1 1 0 1 0 0 1 1 0 1 1 0 0 1 0 0 1 0 0 1; - 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 1 0 1 0 0 0 1 0 1 0 0 0 1 0 1 1 0 1 1 0 0 1 0 1 1 1 0 0 0 1 1 1 1 0 0 0 1 1 1 0 0 0 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 0 0 1 1 1 0 0 0 0 1 1 0 0 0 0 1 1 0 0 0 0 1 1 1 0 1 0 1 1 1 1 1 0 0 1 1 1 1 1 0 0 1 1 1 1 1 0 1 1 1 0 1 0 0 1 1 0 1 1 0 0 1 0 0 1 0 0 1 1 0 0 0 0; - 0 0 0 1 0 0 0 0 0 1 1 0 1 0 0 0 1 0 1 0 0 0 1 0 1 1 0 1 1 0 0 1 0 1 1 1 0 0 0 1 1 1 1 0 0 0 1 1 1 0 0 0 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 0 0 1 1 1 0 0 0 0 1 1 0 0 0 0 1 1 0 0 0 0 1 1 1 0 1 0 1 1 1 1 1 0 0 1 1 1 1 1 0 0 1 1 1 1 1 0 1 1 1 0 1 0 0 1 1 0 1 1 0 0 1 0 0 1 0 0 1 1 0 0 0 0 0 1 0 0 0; - 0 0 0 0 1 1 0 1 0 0 0 1 0 1 0 0 0 1 0 1 1 0 1 1 0 0 1 0 1 1 1 0 0 0 1 1 1 1 0 0 0 1 1 1 0 0 0 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 0 0 1 1 1 0 0 0 0 1 1 0 0 0 0 1 1 0 0 0 0 1 1 1 0 1 0 1 1 1 1 1 0 0 1 1 1 1 1 0 0 1 1 1 1 1 0 1 1 1 0 1 0 0 1 1 0 1 1 0 0 1 0 0 1 0 0 1 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0; - 1 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 1 0 1 0 1 0 1 1 0 1 0 0 0 1 0 1 1 1 0 1 0 1 1 1 1 1 0 1 1 1 1 0 0 0 0 0 1 1 0 1 0 1 0 1 0 1 1 1 1 1 1 1 0 1 0 1 1 0 1 0 1 0 0 1 0 1 0 0 0 0 0 0 1 0 1 0 1 0 0 0 0 1 0 1 0 1 0 1 1 1 1 1 0 0 0 0 1 1 1 1 1 1 1 1 1 1 0 0 1 0 1 1 0 0 0 0 0 1 1 1 1 1 1 0 1 0 0 1 1 1 1 0 1 0; - 0 1 0 0 0 0 0 0 1 0 1 0 1 0 0 0 0 1 0 1 0 1 0 1 1 1 1 1 0 0 0 0 1 1 1 1 1 1 1 1 1 1 0 0 1 0 1 1 0 0 0 0 0 1 1 1 1 1 1 0 1 0 0 1 1 1 1 0 1 0 1 0 0 1 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 1 0 1 0 1 0 1 1 0 1 0 0 0 1 0 1 1 1 0 1 0 1 1 1 1 1 0 1 1 1 1 0 0 0 0 0 1 1 0 1 0 1 0 1 0 1 1 1 1 1 1 1 0 1 0 1 1 0 1; - 0 0 1 0 0 0 0 0 0 1 0 1 0 1 0 1 0 1 1 0 1 0 0 0 1 0 1 1 1 0 1 0 1 1 1 1 1 0 1 1 1 1 0 0 0 0 0 1 1 0 1 0 1 0 1 0 1 1 1 1 1 1 1 0 1 0 1 1 0 1 0 1 0 0 1 0 1 0 0 0 0 0 0 1 0 1 0 1 0 0 0 0 1 0 1 0 1 0 1 1 1 1 1 0 0 0 0 1 1 1 1 1 1 1 1 1 1 0 0 1 0 1 1 0 0 0 0 0 1 1 1 1 1 1 0 1 0 0 1 1 1 1 0 1 0 1 0 0 1 0; - 0 0 0 1 0 1 0 1 0 0 0 0 1 0 1 0 1 0 1 1 1 1 1 0 0 0 0 1 1 1 1 1 1 1 1 1 1 0 0 1 0 1 1 0 0 0 0 0 1 1 1 1 1 1 0 1 0 0 1 1 1 1 0 1 0 1 0 0 1 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 1 0 1 0 1 0 1 1 0 1 0 0 0 1 0 1 1 1 0 1 0 1 1 1 1 1 0 1 1 1 1 0 0 0 0 0 1 1 0 1 0 1 0 1 0 1 1 1 1 1 1 1 0 1 0 1 1 0 1 0 1 0 0 1; - 0 0 0 0 1 0 1 0 1 0 1 0 1 1 0 1 0 0 0 1 0 1 1 1 0 1 0 1 1 1 1 1 0 1 1 1 1 0 0 0 0 0 1 1 0 1 0 1 0 1 0 1 1 1 1 1 1 1 0 1 0 1 1 0 1 0 1 0 0 1 0 1 0 0 0 0 0 0 1 0 1 0 1 0 0 0 0 1 0 1 0 1 0 1 1 1 1 1 0 0 0 0 1 1 1 1 1 1 1 1 1 1 0 0 1 0 1 1 0 0 0 0 0 1 1 1 1 1 1 0 1 0 0 1 1 1 1 0 1 0 1 0 0 1 0 1 0 0 0 0; - 1 0 0 0 0 0 0 0 1 0 0 1 0 1 0 0 1 0 1 1 0 1 1 1 0 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 0 1 1 1 1 1 1 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 1 0 0 1 0 1 1 0 1 1 1 0 0 1 0 1 1 1 1 1 0 0 1 0 0 1 1 0 1 1 1 1 0 1 1 1 0 1 1 0 0 1 0 0 1 0 0 0 0 0 0 0 1 0 0 1 0 1 1 0 0 0 1 0 0 1 1 1 1 1 0 1 1 0 1 1 0 0 1 0 1 0 1 1 0 0 1 1; - 0 1 0 0 0 0 0 0 0 1 0 0 1 0 1 1 0 0 0 1 0 0 1 1 1 1 1 0 1 1 0 1 1 0 0 1 0 1 0 1 1 0 0 1 1 0 1 1 0 1 1 0 0 0 0 0 0 0 1 0 0 1 0 1 0 0 1 0 1 1 0 1 1 1 0 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 0 1 1 1 1 1 1 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 1 0 0 1 0 1 1 0 1 1 1 0 0 1 0 1 1 1 1 1 0 0 1 0 0 1 1 0 1 1 1 1 0 1 1 1 0 1; - 0 0 1 0 0 1 0 1 0 0 1 0 1 1 0 1 1 1 0 0 1 0 1 1 1 1 1 0 0 1 0 0 1 1 0 1 1 1 1 0 1 1 1 0 1 1 0 0 1 0 0 1 0 0 0 0 0 0 0 1 0 0 1 0 1 1 0 0 0 1 0 0 1 1 1 1 1 0 1 1 0 1 1 0 0 1 0 1 0 1 1 0 0 1 1 0 1 1 0 1 1 0 0 0 0 0 0 0 1 0 0 1 0 1 0 0 1 0 1 1 0 1 1 1 0 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 0 1 1 1 1 1 1 0 1 0; - 0 0 0 1 0 0 1 0 1 0 0 1 0 1 1 0 1 1 1 0 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 0 1 1 1 1 1 1 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 1 0 0 1 0 1 1 0 1 1 1 0 0 1 0 1 1 1 1 1 0 0 1 0 0 1 1 0 1 1 1 1 0 1 1 1 0 1 1 0 0 1 0 0 1 0 0 0 0 0 0 0 1 0 0 1 0 1 1 0 0 0 1 0 0 1 1 1 1 1 0 1 1 0 1 1 0 0 1 0 1 0 1 1 0 0 1 1 0 1 1 0 1; - 0 0 0 0 1 0 0 1 0 1 1 0 0 0 1 0 0 1 1 1 1 1 0 1 1 0 1 1 0 0 1 0 1 0 1 1 0 0 1 1 0 1 1 0 1 1 0 0 0 0 0 0 0 1 0 0 1 0 1 0 0 1 0 1 1 0 1 1 1 0 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 0 1 1 1 1 1 1 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 1 0 0 1 0 1 1 0 1 1 1 0 0 1 0 1 1 1 1 1 0 0 1 0 0 1 1 0 1 1 1 1 0 1 1 1 0 1 1 0 0 1 0; - 1 0 0 0 0 0 0 0 0 1 1 0 1 1 0 0 1 1 1 0 1 1 0 1 1 0 0 1 1 0 0 1 1 1 1 0 1 1 0 1 0 1 0 0 0 1 0 1 0 0 0 1 0 1 1 0 0 1 1 1 1 1 0 0 1 0 0 0 1 1 1 0 0 1 1 1 0 0 1 0 0 0 1 0 0 0 1 0 1 0 1 0 0 0 1 1 0 1 1 1 1 1 0 0 0 1 0 1 0 1 1 1 1 0 1 0 1 0 0 1 0 0 0 1 0 0 0 1 0 1 1 1 1 0 0 1 1 1 1 1 0 1 1 0 0 1 1 1 1 0; - 0 1 0 0 0 1 0 1 0 0 0 1 0 1 1 0 0 1 1 1 1 1 0 0 1 0 0 0 1 1 1 0 0 1 1 1 0 0 1 0 0 0 1 0 0 0 1 0 1 0 1 0 0 0 1 1 0 1 1 1 1 1 0 0 0 1 0 1 0 1 1 1 1 0 1 0 1 0 0 1 0 0 0 1 0 0 0 1 0 1 1 1 1 0 0 1 1 1 1 1 0 1 1 0 0 1 1 1 1 0 1 1 0 1 0 1 0 0 0 0 0 0 0 0 1 1 0 1 1 0 0 1 1 1 0 1 1 0 1 1 0 0 1 1 0 0 1 1 1 1; - 0 0 1 0 0 0 1 0 1 0 1 0 0 0 1 1 0 1 1 1 1 1 0 0 0 1 0 1 0 1 1 1 1 0 1 0 1 0 0 1 0 0 0 1 0 0 0 1 0 1 1 1 1 0 0 1 1 1 1 1 0 1 1 0 0 1 1 1 1 0 1 1 0 1 0 1 0 0 0 0 0 0 0 0 1 1 0 1 1 0 0 1 1 1 0 1 1 0 1 1 0 0 1 1 0 0 1 1 1 1 0 1 1 0 1 0 1 0 0 0 1 0 1 0 0 0 1 0 1 1 0 0 1 1 1 1 1 0 0 1 0 0 0 1 1 1 0 0 1 1; - 0 0 0 1 0 0 0 1 0 1 1 1 1 0 0 1 1 1 1 1 0 1 1 0 0 1 1 1 1 0 1 1 0 1 0 1 0 0 0 0 0 0 0 0 1 1 0 1 1 0 0 1 1 1 0 1 1 0 1 1 0 0 1 1 0 0 1 1 1 1 0 1 1 0 1 0 1 0 0 0 1 0 1 0 0 0 1 0 1 1 0 0 1 1 1 1 1 0 0 1 0 0 0 1 1 1 0 0 1 1 1 0 0 1 0 0 0 1 0 0 0 1 0 1 0 1 0 0 0 1 1 0 1 1 1 1 1 0 0 0 1 0 1 0 1 1 1 1 0 1; - 0 0 0 0 1 1 0 1 1 0 0 1 1 1 0 1 1 0 1 1 0 0 1 1 0 0 1 1 1 1 0 1 1 0 1 0 1 0 0 0 1 0 1 0 0 0 1 0 1 1 0 0 1 1 1 1 1 0 0 1 0 0 0 1 1 1 0 0 1 1 1 0 0 1 0 0 0 1 0 0 0 1 0 1 0 1 0 0 0 1 1 0 1 1 1 1 1 0 0 0 1 0 1 0 1 1 1 1 0 1 0 1 0 0 1 0 0 0 1 0 0 0 1 0 1 1 1 1 0 0 1 1 1 1 1 0 1 1 0 0 1 1 1 1 0 1 1 0 1 0; - 1 0 0 0 0 1 0 1 0 0 1 0 0 0 1 1 1 1 1 1 0 0 1 1 0 1 0 0 1 1 0 1 0 0 1 0 0 0 0 1 0 1 0 1 1 1 0 1 1 1 0 1 1 0 0 0 1 1 1 1 1 0 0 1 0 0 0 0 1 0 1 0 1 1 0 0 0 1 1 1 1 1 0 0 0 1 1 1 1 0 0 1 1 0 1 0 0 1 0 0 0 0 1 0 1 0 1 1 1 0 1 1 0 0 1 1 0 1 0 1 1 1 0 1 0 0 1 0 0 0 0 1 0 1 0 1 1 1 0 0 1 1 0 1 1 0 0 0 1 1; - 0 1 0 0 0 0 1 0 1 0 1 1 1 0 0 1 1 0 1 1 0 0 0 1 1 1 1 1 0 1 1 0 0 0 0 1 0 1 0 0 1 0 0 0 1 1 1 1 1 1 0 0 1 1 0 1 0 0 1 1 0 1 0 0 1 0 0 0 0 1 0 1 0 1 1 1 0 1 1 1 0 1 1 0 0 0 1 1 1 1 1 0 0 1 0 0 0 0 1 0 1 0 1 1 0 0 0 1 1 1 1 1 0 0 0 1 1 1 1 0 0 1 1 0 1 0 0 1 0 0 0 0 1 0 1 0 1 1 1 0 1 1 0 0 1 1 0 1 0 1; - 0 0 1 0 0 0 0 1 0 1 0 1 1 1 0 1 1 0 0 1 1 0 1 0 1 1 1 0 1 0 0 1 0 0 0 0 1 0 1 0 1 1 1 0 0 1 1 0 1 1 0 0 0 1 1 1 1 1 0 1 1 0 0 0 0 1 0 1 0 0 1 0 0 0 1 1 1 1 1 1 0 0 1 1 0 1 0 0 1 1 0 1 0 0 1 0 0 0 0 1 0 1 0 1 1 1 0 1 1 1 0 1 1 0 0 0 1 1 1 1 1 0 0 1 0 0 0 0 1 0 1 0 1 1 0 0 0 1 1 1 1 1 0 0 0 1 1 1 1 0; - 0 0 0 1 0 1 0 1 1 0 0 0 1 1 1 1 1 0 0 0 1 1 1 1 0 0 1 1 0 1 0 0 1 0 0 0 0 1 0 1 0 1 1 1 0 1 1 0 0 1 1 0 1 0 1 1 1 0 1 0 0 1 0 0 0 0 1 0 1 0 1 1 1 0 0 1 1 0 1 1 0 0 0 1 1 1 1 1 0 1 1 0 0 0 0 1 0 1 0 0 1 0 0 0 1 1 1 1 1 1 0 0 1 1 0 1 0 0 1 1 0 1 0 0 1 0 0 0 0 1 0 1 0 1 1 1 0 1 1 1 0 1 1 0 0 0 1 1 1 1; - 0 0 0 0 1 0 1 0 1 1 1 0 1 1 1 0 1 1 0 0 0 1 1 1 1 1 0 0 1 0 0 0 0 1 0 1 0 1 1 0 0 0 1 1 1 1 1 0 0 0 1 1 1 1 0 0 1 1 0 1 0 0 1 0 0 0 0 1 0 1 0 1 1 1 0 1 1 0 0 1 1 0 1 0 1 1 1 0 1 0 0 1 0 0 0 0 1 0 1 0 1 1 1 0 0 1 1 0 1 1 0 0 0 1 1 1 1 1 0 1 1 0 0 0 0 1 0 1 0 0 1 0 0 0 1 1 1 1 1 1 0 0 1 1 0 1 0 0 1 1; - 1 0 0 0 0 0 1 0 1 0 0 1 1 1 0 1 1 0 0 0 0 1 1 1 1 0 1 0 0 1 1 0 1 0 0 1 1 1 0 0 1 1 0 0 1 1 1 1 1 0 1 0 0 1 0 0 0 0 0 1 1 0 0 0 1 1 1 0 1 1 1 0 1 0 1 0 1 1 0 1 0 0 0 1 0 0 1 0 1 1 1 1 1 1 1 0 0 0 1 1 1 1 0 1 0 0 0 1 0 0 1 0 1 1 0 1 0 1 1 1 0 0 1 1 0 1 1 1 0 1 0 1 0 0 0 0 0 1 0 1 0 0 1 1 1 0 1 1 0 0; - 0 1 0 0 0 0 0 1 0 1 0 0 1 1 1 0 1 1 0 0 1 0 0 1 1 1 0 0 0 0 0 1 0 1 0 0 1 1 1 0 1 1 0 0 0 0 1 1 1 1 0 1 0 0 1 1 0 1 0 0 1 1 1 0 0 1 1 0 0 1 1 1 1 1 0 1 0 0 1 0 0 0 0 0 1 1 0 0 0 1 1 1 0 1 1 1 0 1 0 1 0 1 1 0 1 0 0 0 1 0 0 1 0 1 1 1 1 1 1 1 0 0 0 1 1 1 1 0 1 0 0 0 1 0 0 1 0 1 1 0 1 0 1 1 1 0 0 1 1 0; - 0 0 1 0 0 1 0 1 1 0 1 0 1 1 1 0 0 1 1 0 1 1 1 0 1 0 1 0 0 0 0 0 1 0 1 0 0 1 1 1 0 1 1 0 0 1 0 0 1 1 1 0 0 0 0 0 1 0 1 0 0 1 1 1 0 1 1 0 0 0 0 1 1 1 1 0 1 0 0 1 1 0 1 0 0 1 1 1 0 0 1 1 0 0 1 1 1 1 1 0 1 0 0 1 0 0 0 0 0 1 1 0 0 0 1 1 1 0 1 1 1 0 1 0 1 0 1 1 0 1 0 0 0 1 0 0 1 0 1 1 1 1 1 1 1 0 0 0 1 1; - 0 0 0 1 0 0 1 0 1 1 1 1 1 1 1 0 0 0 1 1 1 1 0 1 0 0 0 1 0 0 1 0 1 1 0 1 0 1 1 1 0 0 1 1 0 1 1 1 0 1 0 1 0 0 0 0 0 1 0 1 0 0 1 1 1 0 1 1 0 0 1 0 0 1 1 1 0 0 0 0 0 1 0 1 0 0 1 1 1 0 1 1 0 0 0 0 1 1 1 1 0 1 0 0 1 1 0 1 0 0 1 1 1 0 0 1 1 0 0 1 1 1 1 1 0 1 0 0 1 0 0 0 0 0 1 1 0 0 0 1 1 1 0 1 1 1 0 1 0 1; - 0 0 0 0 1 1 0 0 0 1 1 1 0 1 1 1 0 1 0 1 0 1 1 0 1 0 0 0 1 0 0 1 0 1 1 1 1 1 1 1 0 0 0 1 1 1 1 0 1 0 0 0 1 0 0 1 0 1 1 0 1 0 1 1 1 0 0 1 1 0 1 1 1 0 1 0 1 0 0 0 0 0 1 0 1 0 0 1 1 1 0 1 1 0 0 1 0 0 1 1 1 0 0 0 0 0 1 0 1 0 0 1 1 1 0 1 1 0 0 0 0 1 1 1 1 0 1 0 0 1 1 0 1 0 0 1 1 1 0 0 1 1 0 0 1 1 1 1 1 0; - 1 0 0 0 0 0 0 1 0 1 1 0 1 1 1 0 0 0 1 1 0 1 1 0 1 0 0 0 0 1 1 1 1 0 0 1 1 0 0 0 1 0 0 1 1 0 1 0 0 0 1 0 1 1 0 1 1 1 1 1 1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0 1 1 1 0 0 1 1 0 0 1 1 1 0 1 0 0 1 0 0 0 1 0 1 1 1 1 0 1 1 1 1 1 1 0 0 1 0 0 1 0 1 0 1 0 0 0 1 1 1 0 0 1 1 0 1 1 0 1 0 0 0 0 1 0 1 0 0 0 1 1 1 0 0 1; - 0 1 0 0 0 1 0 1 1 0 1 1 1 1 1 1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0 1 1 1 0 0 1 1 0 0 1 1 1 0 1 0 0 1 0 0 0 1 0 1 1 1 1 0 1 1 1 1 1 1 0 0 1 0 0 1 0 1 0 1 0 0 0 1 1 1 0 0 1 1 0 1 1 0 1 0 0 0 0 1 0 1 0 0 0 1 1 1 0 0 1 0 1 1 1 1 1 0 0 0 0 0 0 1 0 1 1 0 1 1 1 0 0 0 1 1 0 1 1 0 1 0 0 0 0 1 1 1 1 0 0 1 1 0 0 0; - 0 0 1 0 0 0 1 0 1 1 1 1 0 1 1 1 1 1 1 0 0 1 0 0 1 0 1 0 1 0 0 0 1 1 1 0 0 1 1 0 1 1 0 1 0 0 0 0 1 0 1 0 0 0 1 1 1 0 0 1 0 1 1 1 1 1 0 0 0 0 0 0 1 0 1 1 0 1 1 1 0 0 0 1 1 0 1 1 0 1 0 0 0 0 1 1 1 1 0 0 1 1 0 0 0 1 0 0 1 1 0 1 0 0 0 1 0 1 1 0 1 1 1 1 1 1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0 1 1 1 0 0 1 1 0 0; - 0 0 0 1 0 1 0 0 0 1 1 1 0 0 1 0 1 1 1 1 1 0 0 0 0 0 0 1 0 1 1 0 1 1 1 0 0 0 1 1 0 1 1 0 1 0 0 0 0 1 1 1 1 0 0 1 1 0 0 0 1 0 0 1 1 0 1 0 0 0 1 0 1 1 0 1 1 1 1 1 1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0 1 1 1 0 0 1 1 0 0 1 1 1 0 1 0 0 1 0 0 0 1 0 1 1 1 1 0 1 1 1 1 1 1 0 0 1 0 0 1 0 1 0 1 0 0 0 1 1 1 0 0 1 1 0; - 0 0 0 0 1 1 1 1 0 0 1 1 0 0 0 1 0 0 1 1 0 1 0 0 0 1 0 1 1 0 1 1 1 1 1 1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0 1 1 1 0 0 1 1 0 0 1 1 1 0 1 0 0 1 0 0 0 1 0 1 1 1 1 0 1 1 1 1 1 1 0 0 1 0 0 1 0 1 0 1 0 0 0 1 1 1 0 0 1 1 0 1 1 0 1 0 0 0 0 1 0 1 0 0 0 1 1 1 0 0 1 0 1 1 1 1 1 0 0 0 0 0 0 1 0 1 1 0 1 1 1 0 0 0 1 1; - 1 0 0 0 0 1 0 1 1 0 1 1 0 1 1 0 1 1 1 1 0 1 0 0 0 0 1 0 1 1 1 1 0 0 1 1 0 0 1 1 0 0 1 0 0 1 0 0 0 1 1 1 0 0 0 1 1 1 0 1 0 0 0 1 0 1 1 1 0 0 0 1 1 0 0 1 1 0 1 0 0 0 0 0 1 0 1 1 1 0 0 0 1 1 0 0 1 1 0 1 1 0 1 0 0 0 0 1 1 1 0 0 0 1 1 1 0 0 1 0 0 1 0 1 0 1 0 1 1 1 1 0 1 0 1 0 1 0 0 1 0 0 1 0 1 1 1 1 1 1; - 0 1 0 0 0 0 1 0 1 1 1 1 0 0 1 1 0 0 1 1 0 0 1 0 0 1 0 0 0 1 1 1 0 0 0 1 1 1 0 1 0 0 0 1 0 1 1 1 0 0 0 1 1 0 0 1 1 0 1 0 0 0 0 0 1 0 1 1 1 0 0 0 1 1 0 0 1 1 0 1 1 0 1 0 0 0 0 1 1 1 0 0 0 1 1 1 0 0 1 0 0 1 0 1 0 1 0 1 1 1 1 0 1 0 1 0 1 0 0 1 0 0 1 0 1 1 1 1 1 1 1 1 1 1 0 1 0 0 0 0 1 0 1 1 0 1 1 0 1 1; - 0 0 1 0 0 1 0 0 0 1 1 1 0 0 0 1 1 1 0 1 0 0 0 1 0 1 1 1 0 0 0 1 1 0 0 1 1 0 1 0 0 0 0 0 1 0 1 1 1 0 0 0 1 1 0 0 1 1 0 1 1 0 1 0 0 0 0 1 1 1 0 0 0 1 1 1 0 0 1 0 0 1 0 1 0 1 0 1 1 1 1 0 1 0 1 0 1 0 0 1 0 0 1 0 1 1 1 1 1 1 1 1 1 1 0 1 0 0 0 0 1 0 1 1 0 1 1 0 1 1 0 1 1 1 1 0 1 0 0 0 0 1 0 1 1 1 1 0 0 1; - 0 0 0 1 0 1 1 1 0 0 0 1 1 0 0 1 1 0 1 0 0 0 0 0 1 0 1 1 1 0 0 0 1 1 0 0 1 1 0 1 1 0 1 0 0 0 0 1 1 1 0 0 0 1 1 1 0 0 1 0 0 1 0 1 0 1 0 1 1 1 1 0 1 0 1 0 1 0 0 1 0 0 1 0 1 1 1 1 1 1 1 1 1 1 0 1 0 0 0 0 1 0 1 1 0 1 1 0 1 1 0 1 1 1 1 0 1 0 0 0 0 1 0 1 1 1 1 0 0 1 1 0 0 1 1 0 0 1 0 0 1 0 0 0 1 1 1 0 0 0; - 0 0 0 0 1 0 1 1 1 0 0 0 1 1 0 0 1 1 0 1 1 0 1 0 0 0 0 1 1 1 0 0 0 1 1 1 0 0 1 0 0 1 0 1 0 1 0 1 1 1 1 0 1 0 1 0 1 0 0 1 0 0 1 0 1 1 1 1 1 1 1 1 1 1 0 1 0 0 0 0 1 0 1 1 0 1 1 0 1 1 0 1 1 1 1 0 1 0 0 0 0 1 0 1 1 1 1 0 0 1 1 0 0 1 1 0 0 1 0 0 1 0 0 0 1 1 1 0 0 0 1 1 1 0 1 0 0 0 1 0 1 1 1 0 0 0 1 1 0 0; - 1 0 0 0 0 0 1 0 1 1 1 1 0 0 0 1 1 0 1 0 1 0 1 0 0 1 0 1 1 1 1 1 1 1 0 0 1 0 0 0 1 0 0 0 1 0 1 1 0 0 0 1 1 0 1 0 1 0 1 0 1 1 1 1 1 0 1 1 1 1 0 0 1 0 0 1 1 1 0 0 0 0 1 1 0 1 0 0 1 0 0 0 1 0 1 1 1 0 1 1 1 0 0 1 1 0 0 0 1 0 0 1 1 1 0 0 0 0 1 1 0 1 0 0 1 1 0 1 1 0 1 1 0 0 1 1 1 1 0 1 0 0 0 0 1 0 0 1 1 1; - 0 1 0 0 0 1 0 0 0 1 0 1 1 0 0 0 1 1 0 1 0 1 0 1 0 1 1 1 1 1 0 1 1 1 1 0 0 1 0 0 1 1 1 0 0 0 0 1 1 0 1 0 0 1 0 0 0 1 0 1 1 1 0 1 1 1 0 0 1 1 0 0 0 1 0 0 1 1 1 0 0 0 0 1 1 0 1 0 0 1 1 0 1 1 0 1 1 0 0 1 1 1 1 0 1 0 0 0 0 1 0 0 1 1 1 1 0 1 0 1 1 0 0 0 0 0 1 0 1 1 1 1 0 0 0 1 1 0 1 0 1 0 1 0 0 1 0 1 1 1; - 0 0 1 0 0 1 1 1 0 0 0 0 1 1 0 1 0 0 1 0 0 0 1 0 1 1 1 0 1 1 1 0 0 1 1 0 0 0 1 0 0 1 1 1 0 0 0 0 1 1 0 1 0 0 1 1 0 1 1 0 1 1 0 0 1 1 1 1 0 1 0 0 0 0 1 0 0 1 1 1 1 0 1 0 1 1 0 0 0 0 0 1 0 1 1 1 1 0 0 0 1 1 0 1 0 1 0 1 0 0 1 0 1 1 1 1 1 1 1 0 0 1 0 0 0 1 0 0 0 1 0 1 1 0 0 0 1 1 0 1 0 1 0 1 0 1 1 1 1 1; - 0 0 0 1 0 0 1 1 1 0 0 0 0 1 1 0 1 0 0 1 1 0 1 1 0 1 1 0 0 1 1 1 1 0 1 0 0 0 0 1 0 0 1 1 1 1 0 1 0 1 1 0 0 0 0 0 1 0 1 1 1 1 0 0 0 1 1 0 1 0 1 0 1 0 0 1 0 1 1 1 1 1 1 1 0 0 1 0 0 0 1 0 0 0 1 0 1 1 0 0 0 1 1 0 1 0 1 0 1 0 1 1 1 1 1 0 1 1 1 1 0 0 1 0 0 1 1 1 0 0 0 0 1 1 0 1 0 0 1 0 0 0 1 0 1 1 1 0 1 1; - 0 0 0 0 1 0 0 1 1 1 1 0 1 0 1 1 0 0 0 0 0 1 0 1 1 1 1 0 0 0 1 1 0 1 0 1 0 1 0 0 1 0 1 1 1 1 1 1 1 0 0 1 0 0 0 1 0 0 0 1 0 1 1 0 0 0 1 1 0 1 0 1 0 1 0 1 1 1 1 1 0 1 1 1 1 0 0 1 0 0 1 1 1 0 0 0 0 1 1 0 1 0 0 1 0 0 0 1 0 1 1 1 0 1 1 1 0 0 1 1 0 0 0 1 0 0 1 1 1 0 0 0 0 1 1 0 1 0 0 1 1 0 1 1 0 1 1 0 0 1; - 1 0 0 0 0 1 0 0 0 1 0 0 1 1 0 0 1 0 0 1 0 1 0 1 1 0 1 1 0 0 1 0 0 1 0 1 0 1 1 0 1 1 0 0 0 0 1 1 0 1 0 0 1 0 1 1 1 0 0 1 1 1 0 1 0 0 1 0 1 0 1 1 0 1 1 1 1 1 0 1 1 0 1 0 0 1 1 1 1 1 1 0 0 1 1 0 0 0 0 1 1 0 1 1 1 0 1 1 1 1 0 0 0 1 0 0 0 1 1 1 1 1 1 1 0 0 0 1 0 0 0 1 1 1 0 1 0 1 0 1 0 1 0 0 0 1 1 1 0 0; - 0 1 0 0 0 1 1 1 0 0 0 0 0 1 1 1 0 0 0 0 1 0 0 0 1 0 0 1 1 0 0 1 0 0 1 0 1 0 1 1 0 1 1 0 0 1 0 0 1 0 1 0 1 1 0 1 1 0 0 0 0 1 1 0 1 0 0 1 0 1 1 1 0 0 1 1 1 0 1 0 0 1 0 1 0 1 1 0 1 1 1 1 1 0 1 1 0 1 0 0 1 1 1 1 1 1 0 0 1 1 0 0 0 0 1 1 0 1 1 1 0 1 1 1 1 0 0 0 1 0 0 0 1 1 1 1 1 1 1 0 0 0 1 0 0 0 1 1 1 0; - 0 0 1 0 0 0 1 1 1 0 1 0 1 0 1 0 1 0 0 0 1 1 1 0 0 0 0 0 1 1 1 0 0 0 0 1 0 0 0 1 0 0 1 1 0 0 1 0 0 1 0 1 0 1 1 0 1 1 0 0 1 0 0 1 0 1 0 1 1 0 1 1 0 0 0 0 1 1 0 1 0 0 1 0 1 1 1 0 0 1 1 1 0 1 0 0 1 0 1 0 1 1 0 1 1 1 1 1 0 1 1 0 1 0 0 1 1 1 1 1 1 0 0 1 1 0 0 0 0 1 1 0 1 1 1 0 1 1 1 1 0 0 0 1 0 0 0 1 1 1; - 0 0 0 1 0 0 0 1 1 1 1 1 1 1 0 0 0 1 0 0 0 1 1 1 0 1 0 1 0 1 0 1 0 0 0 1 1 1 0 0 0 0 0 1 1 1 0 0 0 0 1 0 0 0 1 0 0 1 1 0 0 1 0 0 1 0 1 0 1 1 0 1 1 0 0 1 0 0 1 0 1 0 1 1 0 1 1 0 0 0 0 1 1 0 1 0 0 1 0 1 1 1 0 0 1 1 1 0 1 0 0 1 0 1 0 1 1 0 1 1 1 1 1 0 1 1 0 1 0 0 1 1 1 1 1 1 0 0 1 1 0 0 0 0 1 1 0 1 1 1; - 0 0 0 0 1 1 0 1 1 1 0 1 1 1 1 0 0 0 1 0 0 0 1 1 1 1 1 1 1 0 0 0 1 0 0 0 1 1 1 0 1 0 1 0 1 0 1 0 0 0 1 1 1 0 0 0 0 0 1 1 1 0 0 0 0 1 0 0 0 1 0 0 1 1 0 0 1 0 0 1 0 1 0 1 1 0 1 1 0 0 1 0 0 1 0 1 0 1 1 0 1 1 0 0 0 0 1 1 0 1 0 0 1 0 1 1 1 0 0 1 1 1 0 1 0 0 1 0 1 0 1 1 0 1 1 1 1 1 0 1 1 0 1 0 0 1 1 1 1 1; - 1 0 0 0 0 1 1 1 0 0 1 0 1 0 1 0 0 1 0 0 0 0 1 1 1 0 1 1 1 1 0 0 0 0 1 1 1 1 1 1 1 1 1 0 1 0 1 0 1 0 1 1 0 0 1 0 1 1 0 1 1 0 1 1 0 0 1 1 0 0 0 1 0 0 1 1 0 0 0 1 0 0 0 1 1 0 1 0 0 0 0 1 1 1 0 1 1 1 1 0 0 0 0 1 0 1 0 1 1 1 1 0 0 1 1 1 0 1 0 0 1 1 0 1 1 1 1 0 1 0 0 0 1 0 1 1 1 0 0 0 1 0 0 1 0 0 1 0 1 1; - 0 1 0 0 0 0 1 1 1 0 1 1 1 1 0 0 0 0 1 0 1 0 1 1 1 1 0 0 1 1 1 0 1 0 0 1 1 0 1 1 1 1 0 1 0 0 0 1 0 1 1 1 0 0 0 1 0 0 1 0 0 1 0 1 1 0 0 1 1 0 1 0 0 0 0 1 1 1 0 0 1 0 1 0 1 0 0 1 0 0 0 0 1 1 1 0 1 1 1 1 0 0 0 0 1 1 1 1 1 1 1 1 1 0 1 0 1 0 1 0 1 1 0 0 1 0 1 1 0 1 1 0 1 1 0 0 1 1 0 0 0 1 0 0 1 1 0 0 0 1; - 0 0 1 0 0 0 0 1 1 1 0 1 1 1 1 0 0 0 0 1 1 1 1 1 1 1 1 1 0 1 0 1 0 1 0 1 1 0 0 1 0 1 1 0 1 1 0 1 1 0 0 1 1 0 0 0 1 0 0 1 1 0 0 0 1 0 0 0 1 1 0 1 0 0 0 0 1 1 1 0 1 1 1 1 0 0 0 0 1 0 1 0 1 1 1 1 0 0 1 1 1 0 1 0 0 1 1 0 1 1 1 1 0 1 0 0 0 1 0 1 1 1 0 0 0 1 0 0 1 0 0 1 0 1 1 0 0 1 1 0 1 0 0 0 0 1 1 1 0 0; - 0 0 0 1 0 1 0 1 1 1 1 0 0 1 1 1 0 1 0 0 1 1 0 1 1 1 1 0 1 0 0 0 1 0 1 1 1 0 0 0 1 0 0 1 0 0 1 0 1 1 0 0 1 1 0 1 0 0 0 0 1 1 1 0 0 1 0 1 0 1 0 0 1 0 0 0 0 1 1 1 0 1 1 1 1 0 0 0 0 1 1 1 1 1 1 1 1 1 0 1 0 1 0 1 0 1 1 0 0 1 0 1 1 0 1 1 0 1 1 0 0 1 1 0 0 0 1 0 0 1 1 0 0 0 1 0 0 0 1 1 0 1 0 0 0 0 1 1 1 0; - 0 0 0 0 1 1 1 1 1 1 1 1 1 0 1 0 1 0 1 0 1 1 0 0 1 0 1 1 0 1 1 0 1 1 0 0 1 1 0 0 0 1 0 0 1 1 0 0 0 1 0 0 0 1 1 0 1 0 0 0 0 1 1 1 0 1 1 1 1 0 0 0 0 1 0 1 0 1 1 1 1 0 0 1 1 1 0 1 0 0 1 1 0 1 1 1 1 0 1 0 0 0 1 0 1 1 1 0 0 0 1 0 0 1 0 0 1 0 1 1 0 0 1 1 0 1 0 0 0 0 1 1 1 0 0 1 0 1 0 1 0 0 1 0 0 0 0 1 1 1; - 1 0 0 0 0 0 1 1 1 0 0 1 1 1 1 1 0 1 0 0 1 1 0 0 1 1 0 0 1 0 1 0 0 0 1 1 0 1 0 1 0 0 0 1 0 1 1 1 1 1 1 1 0 1 0 1 0 1 1 0 0 0 1 1 0 0 1 0 0 0 0 0 1 1 1 1 0 0 1 1 0 1 0 1 0 1 1 0 0 0 0 1 0 0 1 1 1 1 0 0 1 1 1 1 0 0 0 0 0 1 1 1 0 1 1 0 1 1 0 1 0 1 0 1 1 0 0 0 1 1 0 0 1 0 0 1 0 1 1 1 1 1 1 0 1 0 0 1 0 1; - 0 1 0 0 0 0 0 1 1 1 1 0 0 1 1 0 1 0 1 0 1 1 0 0 0 0 1 0 0 1 1 1 1 0 0 1 1 1 1 0 0 0 0 0 1 1 1 0 1 1 0 1 1 0 1 0 1 0 1 1 0 0 0 1 1 0 0 1 0 0 1 0 1 1 1 1 1 1 0 1 0 0 1 0 1 0 1 1 0 0 1 0 0 0 0 0 1 1 1 0 0 1 1 1 1 1 0 1 0 0 1 1 0 0 1 1 0 0 1 0 1 0 0 0 1 1 0 1 0 1 0 0 0 1 0 1 1 1 1 1 1 1 0 1 0 1 0 1 1 0; - 0 0 1 0 0 1 0 1 1 1 1 1 1 0 1 0 0 1 0 1 0 1 1 0 0 1 0 0 0 0 0 1 1 1 0 0 1 1 1 1 1 0 1 0 0 1 1 0 0 1 1 0 0 1 0 1 0 0 0 1 1 0 1 0 1 0 0 0 1 0 1 1 1 1 1 1 1 0 1 0 1 0 1 1 0 0 0 1 1 0 0 1 0 0 0 0 0 1 1 1 1 0 0 1 1 0 1 0 1 0 1 1 0 0 0 0 1 0 0 1 1 1 1 0 0 1 1 1 1 0 0 0 0 0 1 1 1 0 1 1 0 1 1 0 1 0 1 0 1 1; - 0 0 0 1 0 1 1 1 1 1 1 1 0 1 0 1 0 1 1 0 0 0 1 1 0 0 1 0 0 0 0 0 1 1 1 1 0 0 1 1 0 1 0 1 0 1 1 0 0 0 0 1 0 0 1 1 1 1 0 0 1 1 1 1 0 0 0 0 0 1 1 1 0 1 1 0 1 1 0 1 0 1 0 1 1 0 0 0 1 1 0 0 1 0 0 1 0 1 1 1 1 1 1 0 1 0 0 1 0 1 0 1 1 0 0 1 0 0 0 0 0 1 1 1 0 0 1 1 1 1 1 0 1 0 0 1 1 0 0 1 1 0 0 1 0 1 0 0 0 1; - 0 0 0 0 1 1 1 0 1 1 0 1 1 0 1 0 1 0 1 1 0 0 0 1 1 0 0 1 0 0 1 0 1 1 1 1 1 1 0 1 0 0 1 0 1 0 1 1 0 0 1 0 0 0 0 0 1 1 1 0 0 1 1 1 1 1 0 1 0 0 1 1 0 0 1 1 0 0 1 0 1 0 0 0 1 1 0 1 0 1 0 0 0 1 0 1 1 1 1 1 1 1 0 1 0 1 0 1 1 0 0 0 1 1 0 0 1 0 0 0 0 0 1 1 1 1 0 0 1 1 0 1 0 1 0 1 1 0 0 0 0 1 0 0 1 1 1 1 0 0; - 1 0 0 0 0 0 0 1 1 1 1 1 1 0 1 1 0 1 1 0 0 0 0 1 1 0 0 0 1 0 1 1 0 1 1 1 0 0 1 0 1 1 1 0 0 0 1 1 1 1 0 1 0 1 0 0 1 1 0 0 0 1 0 0 0 1 0 1 1 1 1 1 0 1 0 0 1 0 1 1 1 0 1 0 1 0 0 0 0 1 1 1 0 0 1 0 1 0 0 1 0 1 1 1 0 1 0 0 1 1 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 1 1 1 1 1 0 1 1 0 1 1 0 0 0 1 1 1 1 1 0 1 0 1 0 0; - 0 1 0 0 0 1 0 1 1 1 1 1 0 1 0 0 1 0 1 1 1 0 1 0 1 0 0 0 0 1 1 1 0 0 1 0 1 0 0 1 0 1 1 1 0 1 0 0 1 1 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 1 1 1 1 1 0 1 1 0 1 1 0 0 0 1 1 1 1 1 0 1 0 1 0 0 1 1 0 0 0 1 0 0 0 0 0 0 1 1 1 1 1 1 0 1 1 0 1 1 0 0 0 0 1 1 0 0 0 1 0 1 1 0 1 1 1 0 0 1 0 1 1 1 0 0 0 1 1 1 1 0 1 0 1 0; - 0 0 1 0 0 1 1 1 1 1 0 1 1 0 1 1 0 0 0 1 1 1 1 1 0 1 0 1 0 0 1 1 0 0 0 1 0 0 0 0 0 0 1 1 1 1 1 1 0 1 1 0 1 1 0 0 0 0 1 1 0 0 0 1 0 1 1 0 1 1 1 0 0 1 0 1 1 1 0 0 0 1 1 1 1 0 1 0 1 0 0 1 1 0 0 0 1 0 0 0 1 0 1 1 1 1 1 0 1 0 0 1 0 1 1 1 0 1 0 1 0 0 0 0 1 1 1 0 0 1 0 1 0 0 1 0 1 1 1 0 1 0 0 1 1 0 0 1 0 1; - 0 0 0 1 0 1 1 0 1 1 1 0 0 1 0 1 1 1 0 0 0 1 1 1 1 0 1 0 1 0 0 1 1 0 0 0 1 0 0 0 1 0 1 1 1 1 1 0 1 0 0 1 0 1 1 1 0 1 0 1 0 0 0 0 1 1 1 0 0 1 0 1 0 0 1 0 1 1 1 0 1 0 0 1 1 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 1 1 1 1 1 0 1 1 0 1 1 0 0 0 1 1 1 1 1 0 1 0 1 0 0 1 1 0 0 0 1 0 0 0 0 0 0 1 1 1 1 1 1 0 1 1 0 1 1 0; - 0 0 0 0 1 1 1 0 0 1 0 1 0 0 1 0 1 1 1 0 1 0 0 1 1 0 0 1 0 1 0 0 1 1 0 0 0 1 0 0 1 1 1 1 1 0 1 1 0 1 1 0 0 0 1 1 1 1 1 0 1 0 1 0 0 1 1 0 0 0 1 0 0 0 0 0 0 1 1 1 1 1 1 0 1 1 0 1 1 0 0 0 0 1 1 0 0 0 1 0 1 1 0 1 1 1 0 0 1 0 1 1 1 0 0 0 1 1 1 1 0 1 0 1 0 0 1 1 0 0 0 1 0 0 0 1 0 1 1 1 1 1 0 1 0 0 1 0 1 1; - 1 0 0 0 0 1 0 1 1 1 0 1 1 0 1 1 1 1 0 0 1 0 0 1 1 1 0 1 1 0 1 0 1 0 1 1 0 1 0 0 0 1 1 0 0 0 0 1 0 0 1 1 0 1 1 0 1 0 0 1 0 0 1 1 1 1 1 0 1 0 1 0 0 0 1 0 1 1 1 1 0 0 1 0 1 0 0 0 1 1 0 0 0 0 1 1 1 0 0 0 0 1 0 0 0 1 1 1 1 1 1 0 0 1 0 0 1 1 1 0 1 1 1 0 1 0 1 0 1 1 1 1 1 1 0 0 1 0 1 0 0 0 1 1 0 0 0 0 1 0; - 0 1 0 0 0 1 1 1 1 1 1 0 0 1 0 0 1 1 1 0 1 1 1 0 1 0 1 0 1 1 1 1 1 1 0 0 1 0 1 0 0 0 1 1 0 0 0 0 1 0 1 1 0 0 1 1 0 0 0 0 1 0 1 1 1 0 1 1 0 1 1 1 1 0 0 1 0 0 1 1 1 0 1 1 0 1 0 1 0 1 1 0 1 0 0 0 1 1 0 0 0 0 1 0 0 1 1 0 1 1 0 1 0 0 1 0 0 1 1 1 1 1 0 1 0 1 0 0 0 1 0 1 1 1 1 0 0 1 0 1 0 0 0 1 1 0 0 0 0 1; - 0 0 1 0 0 1 1 0 1 1 0 1 0 0 1 0 0 1 1 1 1 1 0 1 0 1 0 0 0 1 0 1 1 1 1 0 0 1 0 1 0 0 0 1 1 0 0 0 0 1 1 1 0 0 0 0 1 0 0 0 1 1 1 1 1 1 0 0 1 0 0 1 1 1 0 1 1 1 0 1 0 1 0 1 1 1 1 1 1 0 0 1 0 1 0 0 0 1 1 0 0 0 0 1 0 1 1 0 0 1 1 0 0 0 0 1 0 1 1 1 0 1 1 0 1 1 1 1 0 0 1 0 0 1 1 1 0 1 1 0 1 0 1 0 1 1 0 1 0 0; - 0 0 0 1 0 1 1 0 0 1 1 0 0 0 0 1 0 1 1 1 0 1 1 0 1 1 1 1 0 0 1 0 0 1 1 1 0 1 1 0 1 0 1 0 1 1 0 1 0 0 0 1 1 0 0 0 0 1 0 0 1 1 0 1 1 0 1 0 0 1 0 0 1 1 1 1 1 0 1 0 1 0 0 0 1 0 1 1 1 1 0 0 1 0 1 0 0 0 1 1 0 0 0 0 1 1 1 0 0 0 0 1 0 0 0 1 1 1 1 1 1 0 0 1 0 0 1 1 1 0 1 1 1 0 1 0 1 0 1 1 1 1 1 1 0 0 1 0 1 0; - 0 0 0 0 1 1 1 0 0 0 0 1 0 0 0 1 1 1 1 1 1 0 0 1 0 0 1 1 1 0 1 1 1 0 1 0 1 0 1 1 1 1 1 1 0 0 1 0 1 0 0 0 1 1 0 0 0 0 1 0 1 1 0 0 1 1 0 0 0 0 1 0 1 1 1 0 1 1 0 1 1 1 1 0 0 1 0 0 1 1 1 0 1 1 0 1 0 1 0 1 1 0 1 0 0 0 1 1 0 0 0 0 1 0 0 1 1 0 1 1 0 1 0 0 1 0 0 1 1 1 1 1 0 1 0 1 0 0 0 1 0 1 1 1 1 0 0 1 0 1] + H = Matrix{Bool}(undef, 75, 150) + H = parity_checks(ReedSolomon(31, 15)) + @test H[1:20, 1:15] == [1 0 0 0 0 1 0 0 0 0 1 0 0 0 0; + 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0; + 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0; + 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0; + 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1; + 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0; + 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0; + 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1; + 0 0 0 1 0 0 0 0 0 1 1 0 1 0 0; + 0 0 0 0 1 1 0 1 0 0 0 1 0 1 0; + 1 0 0 0 0 0 0 1 0 0 0 0 0 0 1; + 0 1 0 0 0 0 0 0 1 0 1 0 1 0 0; + 0 0 1 0 0 0 0 0 0 1 0 1 0 1 0; + 0 0 0 1 0 1 0 1 0 0 0 0 1 0 1; + 0 0 0 0 1 0 1 0 1 0 1 0 1 1 0; + 1 0 0 0 0 0 0 0 1 0 0 1 0 1 0; + 0 1 0 0 0 0 0 0 0 1 0 0 1 0 1; + 0 0 1 0 0 1 0 1 0 0 1 0 1 1 0; + 0 0 0 1 0 0 1 0 1 0 0 1 0 1 1; + 0 0 0 0 1 0 0 1 0 1 1 0 0 0 1] + + @test H[71:75, 1:15] == [1 0 0 0 0 1 0 1 1 1 0 1 1 0 1; + 0 1 0 0 0 1 1 1 1 1 1 0 0 1 0; + 0 0 1 0 0 1 1 0 1 1 0 1 0 0 1; + 0 0 0 1 0 1 1 0 0 1 1 0 0 0 0; + 0 0 0 0 1 1 1 0 0 0 0 1 0 0 0] + + @test H[1:20, 146:150] == [1 0 0 0 0; + 0 1 0 0 0; + 0 0 1 0 0; + 0 0 0 1 0; + 0 0 0 0 1; + 1 0 0 1 0; + 0 1 0 0 1; + 1 0 0 0 0; + 0 1 0 0 0; + 0 0 1 0 0; + 1 1 0 1 0; + 0 1 1 0 1; + 1 0 0 1 0; + 0 1 0 0 1; + 1 0 0 0 0; + 1 0 0 1 1; + 1 1 1 0 1; + 1 1 0 1 0; + 0 1 1 0 1; + 1 0 0 1 0] + + @test H[71:75, 146:150] == [0 0 0 1 0; + 0 0 0 0 1; + 1 0 1 0 0; + 0 1 0 1 0; + 0 0 1 0 1] end From 452ceb6be5cb2c20c5f0ecbc1e765bd3e0dd31d7 Mon Sep 17 00:00:00 2001 From: Feroz <93876775+Fe-r-oz@users.noreply.github.com> Date: Sun, 5 May 2024 09:05:01 +0500 Subject: [PATCH 31/70] improving indentation in test file --- test/test_ecc_reedsolomon.jl | 115 ++++++++++++++++++----------------- 1 file changed, 58 insertions(+), 57 deletions(-) diff --git a/test/test_ecc_reedsolomon.jl b/test/test_ecc_reedsolomon.jl index 335596b95..044ad4a0b 100644 --- a/test/test_ecc_reedsolomon.jl +++ b/test/test_ecc_reedsolomon.jl @@ -24,6 +24,7 @@ function designed_distance(matrix, k, n, r) return false end +#Example taken from page 173 of [tomlinson2017error](@cite). function generate_examplepage175() GF2ʳ, a = finite_field(2, 5, "a") q = 30 @@ -67,7 +68,7 @@ end P, x = GF2ʳ[:x] @test generator_polynomial(ReedSolomon(7, 2)) == x ^ 4 + (a ^ 2 + 1) * x ^ 3 + (a ^ 2 + 1) * x ^ 2 + (a + 1) * x + a - #example taken from page 173 of [tomlinson2017error](@cite). + #Example taken from page 173 of [tomlinson2017error](@cite). GF2ʳ, a = finite_field(2, 5, "a") HF = Matrix{FqFieldElem}(undef, 15, 30) HF = generate_examplepage175() @@ -75,75 +76,75 @@ end @test reshape(HF[:,1], 1, 15) == [ 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1] @test HF[2, 2] == a @test HF[2, 3] == a ^ 2 - @test HF[2, 30] == a ^ 3 + 1 == a ^ 29 + @test HF[2, 30] == a ^ 3 + 1 == a ^ 29 @test HF[3, 2] == a ^ 2 @test HF[3, 3] == a ^ 4 - @test HF[3, 30] == a ^ 3 + a + 1 == a ^ 27 + @test HF[3, 30] == a ^ 3 + a + 1 == a ^ 27 @test HF[4, 2] == a ^ 3 - @test HF[4, 3] == a ^ 3 + a == a ^ 6 - @test HF[4, 30] == a ^ 4 + a ^ 3 + 1 == a ^ 25 - @test HF[14, 2] == a ^ 4 + a ^ 3 + a ^ 2 == a ^ 13 - @test HF[14, 3] == a ^ 4 + a ^ 2 + a + 1 == a ^ 26 - @test HF[14, 30] == a ^ 2 + 1 ==a ^ 5 - @test HF[15, 2] == a ^ 4 + a ^ 3 + a ^ 2 + 1 == a ^ 14 - @test HF[15, 3] == a ^ 4 + a ^ 2 + a == a ^ 28 + @test HF[4, 3] == a ^ 3 + a == a ^ 6 + @test HF[4, 30] == a ^ 4 + a ^ 3 + 1 == a ^ 25 + @test HF[14, 2] == a ^ 4 + a ^ 3 + a ^ 2 == a ^ 13 + @test HF[14, 3] == a ^ 4 + a ^ 2 + a + 1 == a ^ 26 + @test HF[14, 30] == a ^ 2 + 1 == a ^ 5 + @test HF[15, 2] == a ^ 4 + a ^ 3 + a ^ 2 + 1 == a ^ 14 + @test HF[15, 3] == a ^ 4 + a ^ 2 + a == a ^ 28 @test HF[15, 30] == a ^ 3 - #example taken from page 175 of [tomlinson2017error](@cite) + #Example taken from page 175 of [tomlinson2017error](@cite). @test size(parity_checks(ReedSolomon(31, 15))) == (75, 150) H = Matrix{Bool}(undef, 75, 150) H = parity_checks(ReedSolomon(31, 15)) @test H[1:20, 1:15] == [1 0 0 0 0 1 0 0 0 0 1 0 0 0 0; - 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0; - 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0; - 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0; - 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1; - 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0; - 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0; - 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1; - 0 0 0 1 0 0 0 0 0 1 1 0 1 0 0; - 0 0 0 0 1 1 0 1 0 0 0 1 0 1 0; - 1 0 0 0 0 0 0 1 0 0 0 0 0 0 1; - 0 1 0 0 0 0 0 0 1 0 1 0 1 0 0; - 0 0 1 0 0 0 0 0 0 1 0 1 0 1 0; - 0 0 0 1 0 1 0 1 0 0 0 0 1 0 1; - 0 0 0 0 1 0 1 0 1 0 1 0 1 1 0; - 1 0 0 0 0 0 0 0 1 0 0 1 0 1 0; - 0 1 0 0 0 0 0 0 0 1 0 0 1 0 1; - 0 0 1 0 0 1 0 1 0 0 1 0 1 1 0; - 0 0 0 1 0 0 1 0 1 0 0 1 0 1 1; - 0 0 0 0 1 0 0 1 0 1 1 0 0 0 1] + 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0; + 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0; + 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0; + 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1; + 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0; + 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0; + 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1; + 0 0 0 1 0 0 0 0 0 1 1 0 1 0 0; + 0 0 0 0 1 1 0 1 0 0 0 1 0 1 0; + 1 0 0 0 0 0 0 1 0 0 0 0 0 0 1; + 0 1 0 0 0 0 0 0 1 0 1 0 1 0 0; + 0 0 1 0 0 0 0 0 0 1 0 1 0 1 0; + 0 0 0 1 0 1 0 1 0 0 0 0 1 0 1; + 0 0 0 0 1 0 1 0 1 0 1 0 1 1 0; + 1 0 0 0 0 0 0 0 1 0 0 1 0 1 0; + 0 1 0 0 0 0 0 0 0 1 0 0 1 0 1; + 0 0 1 0 0 1 0 1 0 0 1 0 1 1 0; + 0 0 0 1 0 0 1 0 1 0 0 1 0 1 1; + 0 0 0 0 1 0 0 1 0 1 1 0 0 0 1] @test H[71:75, 1:15] == [1 0 0 0 0 1 0 1 1 1 0 1 1 0 1; - 0 1 0 0 0 1 1 1 1 1 1 0 0 1 0; - 0 0 1 0 0 1 1 0 1 1 0 1 0 0 1; - 0 0 0 1 0 1 1 0 0 1 1 0 0 0 0; - 0 0 0 0 1 1 1 0 0 0 0 1 0 0 0] + 0 1 0 0 0 1 1 1 1 1 1 0 0 1 0; + 0 0 1 0 0 1 1 0 1 1 0 1 0 0 1; + 0 0 0 1 0 1 1 0 0 1 1 0 0 0 0; + 0 0 0 0 1 1 1 0 0 0 0 1 0 0 0] @test H[1:20, 146:150] == [1 0 0 0 0; - 0 1 0 0 0; - 0 0 1 0 0; - 0 0 0 1 0; - 0 0 0 0 1; - 1 0 0 1 0; - 0 1 0 0 1; - 1 0 0 0 0; - 0 1 0 0 0; - 0 0 1 0 0; - 1 1 0 1 0; - 0 1 1 0 1; - 1 0 0 1 0; - 0 1 0 0 1; - 1 0 0 0 0; - 1 0 0 1 1; - 1 1 1 0 1; - 1 1 0 1 0; - 0 1 1 0 1; - 1 0 0 1 0] + 0 1 0 0 0; + 0 0 1 0 0; + 0 0 0 1 0; + 0 0 0 0 1; + 1 0 0 1 0; + 0 1 0 0 1; + 1 0 0 0 0; + 0 1 0 0 0; + 0 0 1 0 0; + 1 1 0 1 0; + 0 1 1 0 1; + 1 0 0 1 0; + 0 1 0 0 1; + 1 0 0 0 0; + 1 0 0 1 1; + 1 1 1 0 1; + 1 1 0 1 0; + 0 1 1 0 1; + 1 0 0 1 0] @test H[71:75, 146:150] == [0 0 0 1 0; - 0 0 0 0 1; - 1 0 1 0 0; - 0 1 0 1 0; - 0 0 1 0 1] + 0 0 0 0 1; + 1 0 1 0 0; + 0 1 0 1 0; + 0 0 1 0 1] end From d926bd9b67a41d7a3faa119e5e4926abdfbf23b4 Mon Sep 17 00:00:00 2001 From: Feroz <93876775+Fe-r-oz@users.noreply.github.com> Date: Sun, 5 May 2024 09:05:54 +0500 Subject: [PATCH 32/70] improving indentation in src file --- src/ecc/codes/classical/reedsolomon.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ecc/codes/classical/reedsolomon.jl b/src/ecc/codes/classical/reedsolomon.jl index d38334ca6..8ed6d7f2f 100644 --- a/src/ecc/codes/classical/reedsolomon.jl +++ b/src/ecc/codes/classical/reedsolomon.jl @@ -60,7 +60,7 @@ Improved Binary Codes through Concatenation: - This method enhances RS codes for binary channels through code concatenation. - It adds a single overall binary parity check to each m-tuple representing a symbol. -- This approach transforms the original RS code [[n, k, n - k - 1]] into a new binary code with parameters [[n[m + 1], k*m, 2[n - k -1]]]. +- This approach transforms the original RS code [[n, k, n - k - 1]] into a new binary code with parameters [[n[m + 1], k * m, 2[n - k -1]]]. - The resulting binary code boasts a minimum symbol weight of 2, effectively doubling the minimum Hamming distance compared to the original RS code. Key Points: @@ -86,7 +86,7 @@ Field Parity-Check Matrix (`HField`) Properties: . . . ... . . . . . . ... . . . . . . ... . . . -(α₀)ʲ ⁺ ˣ ⁻ ᵏ (α₁)ʲ ⁺ ˣ ⁻ ᵏ (α₂)ʲ ⁺ ˣ ⁻ ᵏ ... (αₓ₋₂)ʲ ⁺ ˣ ⁻ ᵏ 0 1 +(α₀)ʲ ⁺ ˣ ⁻ ᵏ (α₁)ʲ ⁺ ˣ ⁻ ᵏ (α₂)ʲ ⁺ ˣ ⁻ ᵏ ... (αₓ₋₂)ʲ ⁺ ˣ ⁻ ᵏ 0 1 ``` - The matrix has x - k + 1 rows corresponding to the code's parity symbols. From 6fa1dbf3a01dc28f321c1365ae0fbcf34e1e064e Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Sun, 5 May 2024 13:53:04 +0500 Subject: [PATCH 33/70] adding code review suggestions: m, t in place of derived n, k. Adding more comprehensive tests --- docs/src/references.bib | 7 ++ docs/src/references.md | 1 + src/ecc/codes/classical/reedsolomon.jl | 109 ++++++++++++++++--------- test/test_ecc_reedsolomon.jl | 41 ++++++---- test/test_ecc_throws.jl | 6 +- 5 files changed, 109 insertions(+), 55 deletions(-) diff --git a/docs/src/references.bib b/docs/src/references.bib index 7e16c8321..839c36ea2 100644 --- a/docs/src/references.bib +++ b/docs/src/references.bib @@ -402,3 +402,10 @@ @book{macwilliams1977theory year={1977}, publisher={Elsevier} } + +@book{peterson1972error, + title={Error-correcting codes}, + author={Peterson, William Wesley and Weldon, Edward J}, + year={1972}, + publisher={MIT press} +} diff --git a/docs/src/references.md b/docs/src/references.md index 71b1c33af..865bfa13a 100644 --- a/docs/src/references.md +++ b/docs/src/references.md @@ -50,6 +50,7 @@ For classical code construction routines: - [sklar2001reed](@cite) - [tomlinson2017error](@cite) - [macwilliams1977theory](@cite) +- [peterson1972error](@cite) # References diff --git a/src/ecc/codes/classical/reedsolomon.jl b/src/ecc/codes/classical/reedsolomon.jl index 8ed6d7f2f..a12b0e954 100644 --- a/src/ecc/codes/classical/reedsolomon.jl +++ b/src/ecc/codes/classical/reedsolomon.jl @@ -15,7 +15,7 @@ They are not binary codes but frequently are used with x = 2ᵐ, and so there is (α⁰)ʲ ⁺ ˣ ⁻ ᵏ (α¹)ʲ ⁺ ˣ ⁻ ᵏ (α²)ʲ ⁺ ˣ ⁻ ᵏ ... (αˣ ⁻ ¹)ʲ ⁺ ˣ ⁻ ᵏ ``` -You might be interested in consulting [geisel1990tutorial](@cite), [wicker1999reed](@cite), [sklar2001reed](@cite), [berlekamp1978readable](@cite), [tomlinson2017error](@cite), [macwilliams1977theory](@cite) and [https://youtu.be/K26Ssr8H3ec?si=QOeohq_6I0Oyd8qu] as well. +You might be interested in consulting [geisel1990tutorial](@cite), [wicker1999reed](@cite), [sklar2001reed](@cite), [berlekamp1978readable](@cite), [tomlinson2017error](@cite), [macwilliams1977theory](@cite), [https://youtu.be/K26Ssr8H3ec?si=QOeohq_6I0Oyd8qu] and [peterson1972error](@cite) as well. The ECC Zoo has an [entry for this family](https://errorcorrectionzoo.org/c/reed_solomon) """ @@ -23,26 +23,61 @@ The ECC Zoo has an [entry for this family](https://errorcorrectionzoo.org/c/reed abstract type AbstractPolynomialCode <: ClassicalCode end struct ReedSolomon <: AbstractPolynomialCode - n::Int - k::Int + m::Int + t::Int - function ReedSolomon(n, k) - if n < 0 || k < 2 || n > 500 || k > n - throw(ArgumentError("Invalid parameters: n and k must be non-negative. Also, 2 ≤ k ≤ n and n < 500 in order to obtain a valid code and to remain tractable")) + function ReedSolomon(m, t) + if m < 3 || t < 0 || t >= 2 ^ (m - 1) + throw(ArgumentError("Invalid parameters: m and t must be non-negative. Also, m > 3 and t < 2 ^ (m - 1) in order to obtain a valid code and to remain tractable.")) end - new(n, k) + new(m, t) end end +""" +generator_polynomial(ReedSolomon(m, t)): +- `m` (Integer): The positive integer defining the degree of the finite (Galois) field, GF(2ᵐ). +- `t` (Integer): The positive integer specifying the number of correctable errors (`t`). + +The generator polynomial for an RS code takes the following form: + +``` +g(X) = g₀ + g₁X¹ + g₂X² + ... + g₂ₜ₋₁X²ᵗ⁻¹ + X²ᵗ +``` + +where: +- `X` is the indeterminate variable. +- `gᵢ` are the coefficients of the polynomial. +- `t` is the number of correctable symbol errors. + +We describe the generator polynomial in terms of its 2 * `t` = `n` - `k` roots, as follows: + +``` +g(X) = (X - α¹)(X - α²)(X - α³) ... (X - α²ᵗ) +``` + +Degree and Parity Symbols: + +- The degree of the generator polynomial is equal to 2 * `t`, which is also the number of parity symbols added to the original data (`k` symbols) to create a codeword of length `n` (`n` = `k` + 2 * `t`). + +Roots of the Generator Polynomial: + +- The generator polynomial has 2 * `t` distinct roots, designated as `α¹, α², ... , α²ᵗ`. These roots are chosen from a Finite Galois Field. +- Any power of α can be used as the starting root, not necessarily `α¹` itself. + +Notes: + +- Only in this construction scheme for defining the fixed generator polynomial, `g(x)`, RS codes are a subset of the Bose, Chaudhuri, and Hocquenghem (BCH) codes; hence, this relationship between the degree of the generator polynomial and the number of parity symbols holds, just as for BCH codes where degree of BCH generator polynomial, `degree(g(x)) == n - k`. This is proved via RS test suite as well. + +- Prior to 1963, RS codes employed a variable generator polynomial for encoding. This approach [peterson1972error](@cite) differed from the prevalent BCH scheme (used here), which utilizes a fixed generator polynomial. Consequently, these original RS codes weren't strictly categorized as BCH codes. Furthermore, depending on the chosen evaluation points, they might not even qualify as cyclic codes. + +""" function generator_polynomial(rs::ReedSolomon) - m = ilog2(rs.n + 1) - t = div(rs.n - rs.k, 2) - GF2ʳ, a = finite_field(2, m, "a") + GF2ʳ, a = finite_field(2, rs.m, "a") P, x = GF2ʳ[:x] - pzeros = 2*t - gx = x - a^pzeros - for i in 1:(2*t - 1) - gx *= (x - a ^ (pzeros + i)) + gx = x - a ^ 1 + for i in 2:2*rs.t + gx *= (x - a ^ i) end return gx end @@ -111,45 +146,45 @@ Cyclic Code Construction: 2. Column expansion: The elements in each column of `HFieldExpanded` matrix are converted to binary representations by substituting powers of a primitive element (`α`) in the Galois Field GF(2ᵐ) with their corresponding m-tuples over the Boolean/Binary Field GF(2). """ function parity_checks(rs::ReedSolomon) - m = ilog2(rs.n + 1) - GF2ʳ, a = finite_field(2, m, "a") - # 3-level quantization, q is same as x. - q = 2 ^ m + 1 - 3 - HField = Matrix{FqFieldElem}(undef, q - rs.k + 1, q) - for j in 1: q + GF2ʳ, a = finite_field(2, rs.m, "a") + s_symbols = 3 # 3-level quantization. + x = 2 ^ rs.m + 1 - s_symbols + k = 2 ^ rs.m - 1 - 2 * rs.t + HField = Matrix{FqFieldElem}(undef, x - k + 1, x) + for j in 1:x HField[1, j] = a ^ 0 end - HTemp2 = Matrix{FqFieldElem}(undef, m, q) - for i in 1: q - rs.k + 1 + HTemp2 = Matrix{FqFieldElem}(undef, rs.m, x) + for i in 1: x - k + 1 HField[i, 1] = a ^ 0 end - for i in 2:q - rs.k + 1 - for j in 2: q + for i in 2:x - k + 1 + for j in 2:x HField[i, j] = (a ^ (j - 1)) ^ (i - 2) end end HSeed = vcat(HField[1:1, :], HField[3:end, :]) - HFieldExpanded = Matrix{FqFieldElem}(undef, m * rs.k, q) + HFieldExpanded = Matrix{FqFieldElem}(undef, rs.m * k, x) g = 1 - while g <= m * rs.k - for i in 1:q - rs.k - for p in 1:m + while g <= rs.m * k + for i in 1:x - k + for p in 1:rs.m HTemp2[p:p, :] = reshape(HSeed[i, :].*a ^ (p - 1) , 1, :) end - if g > m * rs.k + if g > rs.m * k break end - HFieldExpanded[g:g + m - 1, :] .= HTemp2 - g = g + m + HFieldExpanded[g:g + rs.m - 1, :] .= HTemp2 + g = g + rs.m end end - H = Matrix{Bool}(undef, m * rs.k, m * q) - for i in 1:m * rs.k - for j in 1:q - col_start = (j - 1) * m + 1 - col_end = col_start + m - 1 + H = Matrix{Bool}(undef, rs.m * k, rs.m * x) + for i in 1:rs.m * k + for j in 1:x + col_start = (j - 1) * rs.m + 1 + col_end = col_start + rs.m - 1 t_tuple = Bool[] - for k in 0:m - 1 + for k in 0:rs.m - 1 push!(t_tuple, !is_zero(coeff(HFieldExpanded[i, j], k))) end H[i, col_start:col_end] .= vec(t_tuple) diff --git a/test/test_ecc_reedsolomon.jl b/test/test_ecc_reedsolomon.jl index 044ad4a0b..9a65d450e 100644 --- a/test/test_ecc_reedsolomon.jl +++ b/test/test_ecc_reedsolomon.jl @@ -14,10 +14,11 @@ Shortened Maximum Distance Separable (MDS) codes have the following parameters - The designed distance for binary expanded parity check matrix remains same as symbol based parity check matrix. According to [macwilliams1977theory](@cite), changing the basis `j` can increase the designed distance `(dmin)` of the resulting binary code. """ -function designed_distance(matrix, k, n, r) +function designed_distance(matrix, m, t) + k = 2 ^ m - 1 - 2 * t for row in eachrow(matrix) count = sum(row) - if count >= 2 ^ (r + 1) - 3 - k + if count >= 2 ^ (m + 1) - 3 - k return true end end @@ -47,26 +48,36 @@ function generate_examplepage175() end @testset "Testing Shortened and Expanded Maximum Distance Separable (MDS) Reed Solomon codes's binary parity check matrices" begin - n_cases = [31, 63, 127, 255] - for n in n_cases - r = ilog2(n + 1) - for k in 2:15 - mat = matrix(GF(2), parity_checks(ReedSolomon(n, k))) - computed_rank = rank(mat) - @test computed_rank == r * k - @test designed_distance(parity_checks(ReedSolomon(n, k)), k, n, r) == true + m_cases = [3, 4, 5, 6, 7, 8] + for m in m_cases + for t in 1:m - 1 + mat = matrix(GF(2), parity_checks(ReedSolomon(m, t))) + computed_rank = rank(mat) + k = (2 ^ m - 1 - 2 * t) * m + n = (2 ^ m + 1 - 3) * m + @test computed_rank == n - k + end + end + + m_cases = [5, 6, 7, 8, 9] + for m in m_cases + for t in m:2*m + @test designed_distance(parity_checks(ReedSolomon(m, t)), m, t) == true end end # RS(7, 3), RS(15, 9), RS(255, 223), RS(160, 128), RS(255, 251), (255, 239) and (255, 249) codes. test_cases = [(7, 3), (15, 9), (225, 223), (160, 128), (255, 251), (255, 239), (255, 249)] for (n, k) in test_cases - @test degree(generator_polynomial(ReedSolomon(n, k))) == n - k + m = ilog2(n + 1) + t = div(n - k, 2) + # Using fixed generator polynomial construction scheme for defining generator polynomial, `g(x)`, of RS codes, `degree(g(x))` == 2 * t == n - k. + @test degree(generator_polynomial(ReedSolomon(m, t))) == 2 * t == n - k end - #examples taken from [https://www.youtube.com/watch?v=K26Ssr8H3ec]. + #Examples taken from [http://hscc.cs.nthu.edu.tw/~sheujp/lecture_note/rs.pdf]. GF2ʳ, a = finite_field(2, 3, "a") P, x = GF2ʳ[:x] - @test generator_polynomial(ReedSolomon(7, 2)) == x ^ 4 + (a ^ 2 + 1) * x ^ 3 + (a ^ 2 + 1) * x ^ 2 + (a + 1) * x + a + @test generator_polynomial(ReedSolomon(3, 2)) == x^4 + (a + 1)*x^3 + x^2 + a*x + a + 1 #Example taken from page 173 of [tomlinson2017error](@cite). GF2ʳ, a = finite_field(2, 5, "a") @@ -91,9 +102,9 @@ end @test HF[15, 30] == a ^ 3 #Example taken from page 175 of [tomlinson2017error](@cite). - @test size(parity_checks(ReedSolomon(31, 15))) == (75, 150) + @test size(parity_checks(ReedSolomon(5, 8))) == (75, 150) H = Matrix{Bool}(undef, 75, 150) - H = parity_checks(ReedSolomon(31, 15)) + H = parity_checks(ReedSolomon(5, 8)) @test H[1:20, 1:15] == [1 0 0 0 0 1 0 0 0 0 1 0 0 0 0; 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0; 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0; diff --git a/test/test_ecc_throws.jl b/test/test_ecc_throws.jl index e0785fd92..002dc712f 100644 --- a/test/test_ecc_throws.jl +++ b/test/test_ecc_throws.jl @@ -6,6 +6,6 @@ using QuantumClifford.ECC: ReedMuller, ReedSolomon @test_throws ArgumentError ReedMuller(-1, 3) @test_throws ArgumentError ReedMuller(1, 0) -@test_throws ArgumentError ReedSolomon(31, 1) -@test_throws ArgumentError ReedSolomon(31, 35) -@test_throws ArgumentError ReedSolomon(-1, 1) +@test_throws ArgumentError ReedSolomon(2, 1) +@test_throws ArgumentError ReedSolomon(3, 10) +@test_throws ArgumentError ReedSolomon(-2, 1) From dea157ebb62b63547af6a6871df5b0300fc1f2b8 Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Sun, 5 May 2024 14:57:11 +0500 Subject: [PATCH 34/70] Polishing up: setting up for code review --- src/ecc/codes/classical/reedsolomon.jl | 26 +++++++++++++++----------- test/test_ecc_reedsolomon.jl | 11 ++++++----- 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/src/ecc/codes/classical/reedsolomon.jl b/src/ecc/codes/classical/reedsolomon.jl index a12b0e954..b9a106ada 100644 --- a/src/ecc/codes/classical/reedsolomon.jl +++ b/src/ecc/codes/classical/reedsolomon.jl @@ -1,8 +1,8 @@ """The family of Reed-Solomon codes, as discovered by Reed and Solomon in their 1960 paper [reed1960polynomial](@cite). -Reed Solomon codes are maximum distance separable (MDS) codes and have the highest possible minimum Hamming distance. The codes have symbols from F_q with parameters [[x - 1, k, x - k]]. +Reed Solomon codes are maximum distance separable (MDS) codes and have the highest possible minimum Hamming distance. The codes have symbols from F_q with parameters `[[x - 1, k, x - k]]`. -They are not binary codes but frequently are used with x = 2ᵐ, and so there is a mapping of residue classes of a primitive polynomial with binary coefficients and each element of GF(2ᵐ) is represented as a binary m-tuple. Denoting the x field elements as 0, α⁰, α¹, α²,... αˣ ⁻ ¹, the shortened Field parity-check matrix (`HSeed`) is given by +They are not binary codes but frequently are used with `x = 2ᵐ`, and so there is a mapping of residue classes of a primitive polynomial with binary coefficients and each element of `GF(2ᵐ)` is represented as a binary `m`-tuple. Denoting the `x` field elements as `0, α⁰, α¹, α²,... αˣ ⁻ ¹`, the shortened field parity-check matrix (`HSeed`) is given as follows: ``` (α⁰)ʲ (α¹)ʲ (α²)ʲ ... (αˣ ⁻ ¹)ʲ @@ -17,7 +17,7 @@ They are not binary codes but frequently are used with x = 2ᵐ, and so there is You might be interested in consulting [geisel1990tutorial](@cite), [wicker1999reed](@cite), [sklar2001reed](@cite), [berlekamp1978readable](@cite), [tomlinson2017error](@cite), [macwilliams1977theory](@cite), [https://youtu.be/K26Ssr8H3ec?si=QOeohq_6I0Oyd8qu] and [peterson1972error](@cite) as well. -The ECC Zoo has an [entry for this family](https://errorcorrectionzoo.org/c/reed_solomon) +The ECC Zoo has an [entry for this family](https://errorcorrectionzoo.org/c/reed_solomon). """ abstract type AbstractPolynomialCode <: ClassicalCode end @@ -36,8 +36,8 @@ end """ generator_polynomial(ReedSolomon(m, t)): -- `m` (Integer): The positive integer defining the degree of the finite (Galois) field, GF(2ᵐ). -- `t` (Integer): The positive integer specifying the number of correctable errors (`t`). +- `m` (Integer): The positive integer defining the degree of the finite (Galois) field, `GF(2ᵐ)`. +- `t` (Integer): The positive integer specifying the number of correctable errors `(t)`. The generator polynomial for an RS code takes the following form: @@ -50,7 +50,7 @@ where: - `gᵢ` are the coefficients of the polynomial. - `t` is the number of correctable symbol errors. -We describe the generator polynomial in terms of its 2 * `t` = `n` - `k` roots, as follows: +We describe the generator polynomial in terms of its `2 * t = n - k` roots, as follows: ``` g(X) = (X - α¹)(X - α²)(X - α³) ... (X - α²ᵗ) @@ -58,16 +58,16 @@ g(X) = (X - α¹)(X - α²)(X - α³) ... (X - α²ᵗ) Degree and Parity Symbols: -- The degree of the generator polynomial is equal to 2 * `t`, which is also the number of parity symbols added to the original data (`k` symbols) to create a codeword of length `n` (`n` = `k` + 2 * `t`). +- The degree of the generator polynomial is equal to 2 * `t`, which is also the number of parity symbols added to the original data (`k` symbols) to create a codeword of length `n` `(n = k + 2 * t)`. Roots of the Generator Polynomial: -- The generator polynomial has 2 * `t` distinct roots, designated as `α¹, α², ... , α²ᵗ`. These roots are chosen from a Finite Galois Field. +- The generator polynomial has `2 * t` distinct roots, designated as `α¹, α², ... , α²ᵗ`. These roots are chosen from a Finite Galois Field. - Any power of α can be used as the starting root, not necessarily `α¹` itself. -Notes: +Fixed generator polynomial scheme vs variable generator polynomial scheme: -- Only in this construction scheme for defining the fixed generator polynomial, `g(x)`, RS codes are a subset of the Bose, Chaudhuri, and Hocquenghem (BCH) codes; hence, this relationship between the degree of the generator polynomial and the number of parity symbols holds, just as for BCH codes where degree of BCH generator polynomial, `degree(g(x)) == n - k`. This is proved via RS test suite as well. +- Only in this construction scheme using fixed generator polynomial `g(x)`, RS codes are a subset of the Bose, Chaudhuri, and Hocquenghem (BCH) codes; hence, this relationship between the degree of the generator polynomial and the number of parity symbols holds, just as for BCH codes where degree of BCH generator polynomial, `degree(g(x)) == n - k`. This is proved via RS test suite as well. - Prior to 1963, RS codes employed a variable generator polynomial for encoding. This approach [peterson1972error](@cite) differed from the prevalent BCH scheme (used here), which utilizes a fixed generator polynomial. Consequently, these original RS codes weren't strictly categorized as BCH codes. Furthermore, depending on the chosen evaluation points, they might not even qualify as cyclic codes. @@ -83,6 +83,10 @@ function generator_polynomial(rs::ReedSolomon) end """ +parity_checks(ReedSolomon(m, t)): +- `m` (Integer): The positive integer defining the degree of the finite (Galois) field, `GF(2ᵐ)`. +- `t` (Integer): The positive integer specifying the number of correctable errors `(t)`. + This function applies Reed-Solomon (RS) codes with soft decision decoding for binary transmission channels. Challenges of Standard RS Codes: @@ -134,7 +138,7 @@ Shortened MDS Codes: - Corresponding columns of the field parity-check matrix `HField` can be deleted to form a shortened [[2ᵐ + 1 - s, k, 2ᵐ ⁺ ¹ - s - k]] MDS code. - This is an important property of MDS codes, particularly for their practical realisation in the form of augmented, extended RS codes because it enables efficient implementation in applications such as incremental redundancy systems, and network coding. -- 3 - level quantization of the received channel bits meaning 3 symbols deleted +- 3 - level quantization of the received channel bits meaning 3 symbols deleted. Cyclic Code Construction: diff --git a/test/test_ecc_reedsolomon.jl b/test/test_ecc_reedsolomon.jl index 9a65d450e..527170587 100644 --- a/test/test_ecc_reedsolomon.jl +++ b/test/test_ecc_reedsolomon.jl @@ -48,25 +48,26 @@ function generate_examplepage175() end @testset "Testing Shortened and Expanded Maximum Distance Separable (MDS) Reed Solomon codes's binary parity check matrices" begin - m_cases = [3, 4, 5, 6, 7, 8] + m_cases = [3, 4, 5, 6, 7, 8, 9, 10] for m in m_cases for t in 1:m - 1 mat = matrix(GF(2), parity_checks(ReedSolomon(m, t))) computed_rank = rank(mat) + s_symbols = 3 k = (2 ^ m - 1 - 2 * t) * m - n = (2 ^ m + 1 - 3) * m + n = (2 ^ m + 1 - s_symbols) * m @test computed_rank == n - k end end - m_cases = [5, 6, 7, 8, 9] + m_cases = [5, 6, 7, 8, 9, 10] for m in m_cases - for t in m:2*m + for t in m:2 * m @test designed_distance(parity_checks(ReedSolomon(m, t)), m, t) == true end end - # RS(7, 3), RS(15, 9), RS(255, 223), RS(160, 128), RS(255, 251), (255, 239) and (255, 249) codes. + # RS(7, 3), RS(15, 9), RS(255, 223), RS(160, 128), RS(255, 251), (255, 239) and (255, 249) codes. Examples taken from [https://en.wikipedia.org/wiki/Reed%E2%80%93Solomon_error_correction], [https://www.cs.cmu.edu/~guyb/realworld/reedsolomon/reed_solomon_codes.html], [http://www.chencode.cn/lecture/Information_Theory_and_Coding/Information%20Theory%20and%20Coding-CH7.pdf], [https://citeseerx.ist.psu.edu/document?repid=rep1&type=pdf&doi=91e1d6d27311780b0a8c34a41793fa85f3947af1]. test_cases = [(7, 3), (15, 9), (225, 223), (160, 128), (255, 251), (255, 239), (255, 249)] for (n, k) in test_cases m = ilog2(n + 1) From 62c1e54e1044afd4dda1d299944b0884b215aebf Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Sun, 5 May 2024 15:16:48 +0500 Subject: [PATCH 35/70] use feasible values for small test time because of large matrices --- test/test_ecc_reedsolomon.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test_ecc_reedsolomon.jl b/test/test_ecc_reedsolomon.jl index 527170587..50076a358 100644 --- a/test/test_ecc_reedsolomon.jl +++ b/test/test_ecc_reedsolomon.jl @@ -48,7 +48,7 @@ function generate_examplepage175() end @testset "Testing Shortened and Expanded Maximum Distance Separable (MDS) Reed Solomon codes's binary parity check matrices" begin - m_cases = [3, 4, 5, 6, 7, 8, 9, 10] + m_cases = [3, 4, 5, 6, 7, 8] for m in m_cases for t in 1:m - 1 mat = matrix(GF(2), parity_checks(ReedSolomon(m, t))) @@ -60,7 +60,7 @@ end end end - m_cases = [5, 6, 7, 8, 9, 10] + m_cases = [5, 6, 7, 8, 9] for m in m_cases for t in m:2 * m @test designed_distance(parity_checks(ReedSolomon(m, t)), m, t) == true From 81514972f681213d672772bd8e5ed0fe02a741cf Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Wed, 8 May 2024 00:00:12 +0500 Subject: [PATCH 36/70] Matrices Alignment in docstrings --- src/ecc/codes/classical/reedsolomon.jl | 2 +- test/test_ecc_reedsolomon.jl | 112 ++++++++++++------------- 2 files changed, 57 insertions(+), 57 deletions(-) diff --git a/src/ecc/codes/classical/reedsolomon.jl b/src/ecc/codes/classical/reedsolomon.jl index b9a106ada..b87d81da3 100644 --- a/src/ecc/codes/classical/reedsolomon.jl +++ b/src/ecc/codes/classical/reedsolomon.jl @@ -125,7 +125,7 @@ Field Parity-Check Matrix (`HField`) Properties: . . . ... . . . . . . ... . . . . . . ... . . . -(α₀)ʲ ⁺ ˣ ⁻ ᵏ (α₁)ʲ ⁺ ˣ ⁻ ᵏ (α₂)ʲ ⁺ ˣ ⁻ ᵏ ... (αₓ₋₂)ʲ ⁺ ˣ ⁻ ᵏ 0 1 +(α₀)ʲ ⁺ ˣ ⁻ ᵏ (α₁)ʲ ⁺ ˣ ⁻ ᵏ (α₂)ʲ ⁺ ˣ ⁻ ᵏ ... (αₓ₋₂)ʲ ⁺ ˣ ⁻ ᵏ 0 1 ``` - The matrix has x - k + 1 rows corresponding to the code's parity symbols. diff --git a/test/test_ecc_reedsolomon.jl b/test/test_ecc_reedsolomon.jl index 50076a358..26fa47b40 100644 --- a/test/test_ecc_reedsolomon.jl +++ b/test/test_ecc_reedsolomon.jl @@ -88,18 +88,18 @@ end @test reshape(HF[:,1], 1, 15) == [ 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1] @test HF[2, 2] == a @test HF[2, 3] == a ^ 2 - @test HF[2, 30] == a ^ 3 + 1 == a ^ 29 + @test HF[2, 30] == a ^ 3 + 1 == a ^ 29 @test HF[3, 2] == a ^ 2 @test HF[3, 3] == a ^ 4 - @test HF[3, 30] == a ^ 3 + a + 1 == a ^ 27 + @test HF[3, 30] == a ^ 3 + a + 1 == a ^ 27 @test HF[4, 2] == a ^ 3 - @test HF[4, 3] == a ^ 3 + a == a ^ 6 - @test HF[4, 30] == a ^ 4 + a ^ 3 + 1 == a ^ 25 - @test HF[14, 2] == a ^ 4 + a ^ 3 + a ^ 2 == a ^ 13 - @test HF[14, 3] == a ^ 4 + a ^ 2 + a + 1 == a ^ 26 - @test HF[14, 30] == a ^ 2 + 1 == a ^ 5 - @test HF[15, 2] == a ^ 4 + a ^ 3 + a ^ 2 + 1 == a ^ 14 - @test HF[15, 3] == a ^ 4 + a ^ 2 + a == a ^ 28 + @test HF[4, 3] == a ^ 3 + a == a ^ 6 + @test HF[4, 30] == a ^ 4 + a ^ 3 + 1 == a ^ 25 + @test HF[14, 2] == a ^ 4 + a ^ 3 + a ^ 2 == a ^ 13 + @test HF[14, 3] == a ^ 4 + a ^ 2 + a + 1 == a ^ 26 + @test HF[14, 30] == a ^ 2 + 1 == a ^ 5 + @test HF[15, 2] == a ^ 4 + a ^ 3 + a ^ 2 + 1 == a ^ 14 + @test HF[15, 3] == a ^ 4 + a ^ 2 + a == a ^ 28 @test HF[15, 30] == a ^ 3 #Example taken from page 175 of [tomlinson2017error](@cite). @@ -107,56 +107,56 @@ end H = Matrix{Bool}(undef, 75, 150) H = parity_checks(ReedSolomon(5, 8)) @test H[1:20, 1:15] == [1 0 0 0 0 1 0 0 0 0 1 0 0 0 0; - 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0; - 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0; - 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0; - 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1; - 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0; - 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0; - 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1; - 0 0 0 1 0 0 0 0 0 1 1 0 1 0 0; - 0 0 0 0 1 1 0 1 0 0 0 1 0 1 0; - 1 0 0 0 0 0 0 1 0 0 0 0 0 0 1; - 0 1 0 0 0 0 0 0 1 0 1 0 1 0 0; - 0 0 1 0 0 0 0 0 0 1 0 1 0 1 0; - 0 0 0 1 0 1 0 1 0 0 0 0 1 0 1; - 0 0 0 0 1 0 1 0 1 0 1 0 1 1 0; - 1 0 0 0 0 0 0 0 1 0 0 1 0 1 0; - 0 1 0 0 0 0 0 0 0 1 0 0 1 0 1; - 0 0 1 0 0 1 0 1 0 0 1 0 1 1 0; - 0 0 0 1 0 0 1 0 1 0 0 1 0 1 1; - 0 0 0 0 1 0 0 1 0 1 1 0 0 0 1] + 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0; + 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0; + 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0; + 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1; + 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0; + 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0; + 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1; + 0 0 0 1 0 0 0 0 0 1 1 0 1 0 0; + 0 0 0 0 1 1 0 1 0 0 0 1 0 1 0; + 1 0 0 0 0 0 0 1 0 0 0 0 0 0 1; + 0 1 0 0 0 0 0 0 1 0 1 0 1 0 0; + 0 0 1 0 0 0 0 0 0 1 0 1 0 1 0; + 0 0 0 1 0 1 0 1 0 0 0 0 1 0 1; + 0 0 0 0 1 0 1 0 1 0 1 0 1 1 0; + 1 0 0 0 0 0 0 0 1 0 0 1 0 1 0; + 0 1 0 0 0 0 0 0 0 1 0 0 1 0 1; + 0 0 1 0 0 1 0 1 0 0 1 0 1 1 0; + 0 0 0 1 0 0 1 0 1 0 0 1 0 1 1; + 0 0 0 0 1 0 0 1 0 1 1 0 0 0 1] @test H[71:75, 1:15] == [1 0 0 0 0 1 0 1 1 1 0 1 1 0 1; - 0 1 0 0 0 1 1 1 1 1 1 0 0 1 0; - 0 0 1 0 0 1 1 0 1 1 0 1 0 0 1; - 0 0 0 1 0 1 1 0 0 1 1 0 0 0 0; - 0 0 0 0 1 1 1 0 0 0 0 1 0 0 0] + 0 1 0 0 0 1 1 1 1 1 1 0 0 1 0; + 0 0 1 0 0 1 1 0 1 1 0 1 0 0 1; + 0 0 0 1 0 1 1 0 0 1 1 0 0 0 0; + 0 0 0 0 1 1 1 0 0 0 0 1 0 0 0] @test H[1:20, 146:150] == [1 0 0 0 0; - 0 1 0 0 0; - 0 0 1 0 0; - 0 0 0 1 0; - 0 0 0 0 1; - 1 0 0 1 0; - 0 1 0 0 1; - 1 0 0 0 0; - 0 1 0 0 0; - 0 0 1 0 0; - 1 1 0 1 0; - 0 1 1 0 1; - 1 0 0 1 0; - 0 1 0 0 1; - 1 0 0 0 0; - 1 0 0 1 1; - 1 1 1 0 1; - 1 1 0 1 0; - 0 1 1 0 1; - 1 0 0 1 0] + 0 1 0 0 0; + 0 0 1 0 0; + 0 0 0 1 0; + 0 0 0 0 1; + 1 0 0 1 0; + 0 1 0 0 1; + 1 0 0 0 0; + 0 1 0 0 0; + 0 0 1 0 0; + 1 1 0 1 0; + 0 1 1 0 1; + 1 0 0 1 0; + 0 1 0 0 1; + 1 0 0 0 0; + 1 0 0 1 1; + 1 1 1 0 1; + 1 1 0 1 0; + 0 1 1 0 1; + 1 0 0 1 0] - @test H[71:75, 146:150] == [0 0 0 1 0; - 0 0 0 0 1; - 1 0 1 0 0; - 0 1 0 1 0; - 0 0 1 0 1] + @test H[71:75, 146:150] == [0 0 0 1 0; + 0 0 0 0 1; + 1 0 1 0 0; + 0 1 0 1 0; + 0 0 1 0 1] end From 83050851c8b71aa05742b5398701c708b8fabff5 Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Sun, 12 May 2024 15:54:45 +0500 Subject: [PATCH 37/70] minor cleanup --- test/test_ecc_reedsolomon.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_ecc_reedsolomon.jl b/test/test_ecc_reedsolomon.jl index 26fa47b40..23f5c2d8a 100644 --- a/test/test_ecc_reedsolomon.jl +++ b/test/test_ecc_reedsolomon.jl @@ -5,7 +5,7 @@ using Combinatorics using Nemo: finite_field, GF, FqFieldElem, FqPolyRingElem, coeff, is_zero, degree, matrix using QuantumClifford using QuantumClifford.ECC -using QuantumClifford.ECC: AbstractECC, ReedSolomon +using QuantumClifford.ECC: AbstractECC, ReedSolomon, generator_polynomial """ Employing `3-level` quantization of the channel bits and erasing entire symbols if any of their constituent bits are erased can improve the performance of RS codes. From 6f960e20c65147b33f8302b776a0a4901fa07552 Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Sun, 12 May 2024 15:58:55 +0500 Subject: [PATCH 38/70] minor cleanups --- test/test_ecc_reedsolomon.jl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/test_ecc_reedsolomon.jl b/test/test_ecc_reedsolomon.jl index 23f5c2d8a..39dab3cae 100644 --- a/test/test_ecc_reedsolomon.jl +++ b/test/test_ecc_reedsolomon.jl @@ -48,9 +48,9 @@ function generate_examplepage175() end @testset "Testing Shortened and Expanded Maximum Distance Separable (MDS) Reed Solomon codes's binary parity check matrices" begin - m_cases = [3, 4, 5, 6, 7, 8] + m_cases = [3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 14, 15] for m in m_cases - for t in 1:m - 1 + for t in rand(1:m - 1, 2) mat = matrix(GF(2), parity_checks(ReedSolomon(m, t))) computed_rank = rank(mat) s_symbols = 3 @@ -60,9 +60,9 @@ end end end - m_cases = [5, 6, 7, 8, 9] + m_cases = [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] for m in m_cases - for t in m:2 * m + for t in rand(m:2 * m, 2) @test designed_distance(parity_checks(ReedSolomon(m, t)), m, t) == true end end @@ -78,7 +78,7 @@ end #Examples taken from [http://hscc.cs.nthu.edu.tw/~sheujp/lecture_note/rs.pdf]. GF2ʳ, a = finite_field(2, 3, "a") P, x = GF2ʳ[:x] - @test generator_polynomial(ReedSolomon(3, 2)) == x^4 + (a + 1)*x^3 + x^2 + a*x + a + 1 + @test generator_polynomial(ReedSolomon(3, 2)) == x ^ 4 + (a + 1) * x ^ 3 + x ^ 2 + a * x + a + 1 #Example taken from page 173 of [tomlinson2017error](@cite). GF2ʳ, a = finite_field(2, 5, "a") From a0e712e4192541c57bb483f05e7cf5ab879cce19 Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Sun, 12 May 2024 16:20:54 +0500 Subject: [PATCH 39/70] polishing up docstring --- src/ecc/codes/classical/reedsolomon.jl | 74 ++++++-------------------- test/test_ecc_reedsolomon.jl | 13 ++--- 2 files changed, 21 insertions(+), 66 deletions(-) diff --git a/src/ecc/codes/classical/reedsolomon.jl b/src/ecc/codes/classical/reedsolomon.jl index b87d81da3..a1cb258f6 100644 --- a/src/ecc/codes/classical/reedsolomon.jl +++ b/src/ecc/codes/classical/reedsolomon.jl @@ -15,7 +15,7 @@ They are not binary codes but frequently are used with `x = 2ᵐ`, and so there (α⁰)ʲ ⁺ ˣ ⁻ ᵏ (α¹)ʲ ⁺ ˣ ⁻ ᵏ (α²)ʲ ⁺ ˣ ⁻ ᵏ ... (αˣ ⁻ ¹)ʲ ⁺ ˣ ⁻ ᵏ ``` -You might be interested in consulting [geisel1990tutorial](@cite), [wicker1999reed](@cite), [sklar2001reed](@cite), [berlekamp1978readable](@cite), [tomlinson2017error](@cite), [macwilliams1977theory](@cite), [https://youtu.be/K26Ssr8H3ec?si=QOeohq_6I0Oyd8qu] and [peterson1972error](@cite) as well. +You might be interested in consulting [geisel1990tutorial](@cite), [wicker1999reed](@cite), [sklar2001reed](@cite), [berlekamp1978readable](@cite), [tomlinson2017error](@cite), [macwilliams1977theory](@cite), https://youtu.be/K26Ssr8H3ec?si=QOeohq_6I0Oyd8qu and [peterson1972error](@cite) as well. The ECC Zoo has an [entry for this family](https://errorcorrectionzoo.org/c/reed_solomon). """ @@ -36,8 +36,8 @@ end """ generator_polynomial(ReedSolomon(m, t)): -- `m` (Integer): The positive integer defining the degree of the finite (Galois) field, `GF(2ᵐ)`. -- `t` (Integer): The positive integer specifying the number of correctable errors `(t)`. +- `m`: The positive integer defining the degree of the finite (Galois) field, `GF(2ᵐ)`. +- `t`: The positive integer specifying the number of correctable errors `(t)`. The generator polynomial for an RS code takes the following form: @@ -45,10 +45,7 @@ The generator polynomial for an RS code takes the following form: g(X) = g₀ + g₁X¹ + g₂X² + ... + g₂ₜ₋₁X²ᵗ⁻¹ + X²ᵗ ``` -where: -- `X` is the indeterminate variable. -- `gᵢ` are the coefficients of the polynomial. -- `t` is the number of correctable symbol errors. +where `X` is the indeterminate variable, `gᵢ` are the coefficients of the polynomial and `t` is the number of correctable symbol errors. We describe the generator polynomial in terms of its `2 * t = n - k` roots, as follows: @@ -56,20 +53,11 @@ We describe the generator polynomial in terms of its `2 * t = n - k` roots, as g(X) = (X - α¹)(X - α²)(X - α³) ... (X - α²ᵗ) ``` -Degree and Parity Symbols: +Degree and Parity Symbols: The degree of the generator polynomial is equal to 2 * `t`, which is also the number of parity symbols added to the original data (`k` symbols) to create a codeword of length `n` `(n = k + 2 * t)`. -- The degree of the generator polynomial is equal to 2 * `t`, which is also the number of parity symbols added to the original data (`k` symbols) to create a codeword of length `n` `(n = k + 2 * t)`. +Roots of the Generator Polynomial: The generator polynomial has `2 * t` distinct roots, designated as `α¹, α², ... , α²ᵗ`. These roots are chosen from a Finite Galois Field. Any power of α can be used as the starting root, not necessarily `α¹` itself. -Roots of the Generator Polynomial: - -- The generator polynomial has `2 * t` distinct roots, designated as `α¹, α², ... , α²ᵗ`. These roots are chosen from a Finite Galois Field. -- Any power of α can be used as the starting root, not necessarily `α¹` itself. - -Fixed generator polynomial scheme vs variable generator polynomial scheme: - -- Only in this construction scheme using fixed generator polynomial `g(x)`, RS codes are a subset of the Bose, Chaudhuri, and Hocquenghem (BCH) codes; hence, this relationship between the degree of the generator polynomial and the number of parity symbols holds, just as for BCH codes where degree of BCH generator polynomial, `degree(g(x)) == n - k`. This is proved via RS test suite as well. - -- Prior to 1963, RS codes employed a variable generator polynomial for encoding. This approach [peterson1972error](@cite) differed from the prevalent BCH scheme (used here), which utilizes a fixed generator polynomial. Consequently, these original RS codes weren't strictly categorized as BCH codes. Furthermore, depending on the chosen evaluation points, they might not even qualify as cyclic codes. +Fixed generator polynomial scheme vs variable generator polynomial scheme: Only in this construction scheme using fixed generator polynomial `g(x)`, RS codes are a subset of the Bose, Chaudhuri, and Hocquenghem (BCH) codes; hence, this relationship between the degree of the generator polynomial and the number of parity symbols holds, just as for BCH codes where degree of BCH generator polynomial, `degree(g(x)) == n - k`. This is proved via RS test suite as well. Prior to 1963, RS codes employed a variable generator polynomial for encoding. This approach [peterson1972error](@cite) differed from the prevalent BCH scheme (used here), which utilizes a fixed generator polynomial. Consequently, these original RS codes weren't strictly categorized as BCH codes. Furthermore, depending on the chosen evaluation points, they might not even qualify as cyclic codes. """ function generator_polynomial(rs::ReedSolomon) @@ -84,36 +72,16 @@ end """ parity_checks(ReedSolomon(m, t)): -- `m` (Integer): The positive integer defining the degree of the finite (Galois) field, `GF(2ᵐ)`. -- `t` (Integer): The positive integer specifying the number of correctable errors `(t)`. - -This function applies Reed-Solomon (RS) codes with soft decision decoding for binary transmission channels. - -Challenges of Standard RS Codes: +- `m`: The positive integer defining the degree of the finite (Galois) field, `GF(2ᵐ)`. +- `t`: The positive integer specifying the number of correctable errors `(t)`. -- While efficient as MDS codes, standard RS codes are not ideal for binary channels. -- As demonstrated in the results (see section 7.2)[tomlinson2017error](@cite), their performance suffers due to a mismatch between the code structure (symbol-based) and the channel (binary). -- A single bit error can lead to a symbol error, negating the code's benefits. +This function applies Reed-Solomon (RS) codes for binary transmission using soft decisions (see section 7.3)[tomlinson2017error](@cite). Code length limitations: For significant coding gain, code length is typically restricted to less than 200 bits. Modified Dorsch decoder is recommended for near maximum likelihood decoding. -Improved Binary Codes through Concatenation: +Challenges of Standard RS Codes: While efficient as MDS codes, standard RS codes are not ideal for binary channels. As demonstrated in the results (see section 7.2)[tomlinson2017error](@cite), their performance suffers due to a mismatch between the code structure (symbol-based) and the channel (binary). A single bit error can lead to a symbol error, negating the code's benefits. -- This method enhances RS codes for binary channels through code concatenation. -- It adds a single overall binary parity check to each m-tuple representing a symbol. -- This approach transforms the original RS code [[n, k, n - k - 1]] into a new binary code with parameters [[n[m + 1], k * m, 2[n - k -1]]]. -- The resulting binary code boasts a minimum symbol weight of 2, effectively doubling the minimum Hamming distance compared to the original RS code. +Improved Binary Codes through Concatenation: This method enhances RS codes for binary channels through code concatenation. It adds a single overall binary parity check to each m-tuple representing a symbol. This approach transforms the original RS code [[n, k, n - k - 1]] into a new binary code with parameters [[n[m + 1], k * m, 2[n - k -1]]]. The resulting binary code boasts a minimum symbol weight of 2, effectively doubling the minimum Hamming distance compared to the original RS code. -Key Points: - -- Uses unquantized soft decision decoding for improved performance. -- Modified Dorsch decoder is recommended for near maximum likelihood decoding. -- Code length limitations: For significant coding gain, code length is typically restricted to less than 200 bits. - -Augmented Extended RS Codes: - -- Constructed from Galois Field GF(2ᵐ). -- Length: 2ᵐ + 1 (Maximum Distance Separable (MDS) codes). -- Parameters: [[2ᵐ + 1, k, 2ᵐ ⁺ ¹ - k]]. -- Generalization: Applicable to any Galois Field GF(q) with parameters [[x + 1, k, x + 2 - k]]. +Augmented Extended RS Codes: Constructed from Galois Field GF(2ᵐ). Length: 2ᵐ + 1 (Maximum Distance Separable (MDS) codes). Parameters: [[2ᵐ + 1, k, 2ᵐ ⁺ ¹ - k]]. Generalization: Applicable to any Galois Field GF(q) with parameters [[x + 1, k, x + 2 - k]]. Field Parity-Check Matrix (`HField`) Properties: @@ -128,21 +96,11 @@ Field Parity-Check Matrix (`HField`) Properties: (α₀)ʲ ⁺ ˣ ⁻ ᵏ (α₁)ʲ ⁺ ˣ ⁻ ᵏ (α₂)ʲ ⁺ ˣ ⁻ ᵏ ... (αₓ₋₂)ʲ ⁺ ˣ ⁻ ᵏ 0 1 ``` -- The matrix has x - k + 1 rows corresponding to the code's parity symbols. -- Any x - k + 1 columns form a Vandermonde matrix (non-singular). -- This ensures correction of up to x - k + 1 symbol erasures in a codeword. -- Permutation: We can re-arrange the columns of the `HField` matrix in any desired order. -- Parity symbols (s) deletion: Any set of `s` symbols within a codeword can be designated as parity symbols and permanently removed. This important property leads to construction of Shortened MDS codes. - -Shortened MDS Codes: - -- Corresponding columns of the field parity-check matrix `HField` can be deleted to form a shortened [[2ᵐ + 1 - s, k, 2ᵐ ⁺ ¹ - s - k]] MDS code. -- This is an important property of MDS codes, particularly for their practical realisation in the form of augmented, extended RS codes because it enables efficient implementation in applications such as incremental redundancy systems, and network coding. -- 3 - level quantization of the received channel bits meaning 3 symbols deleted. +The matrix has x - k + 1 rows corresponding to the code's parity symbols. Any x - k + 1 columns form a Vandermonde matrix (non-singular). This ensures correction of up to x - k + 1 symbol erasures in a codeword. Permutation: We can re-arrange the columns of the `HField` matrix in any desired order. Parity symbols (s) deletion: Any set of `s` symbols within a codeword can be designated as parity symbols and permanently removed. This important property leads to construction of Shortened MDS codes. -Cyclic Code Construction: +Shortened MDS Codes: Corresponding columns of the field parity-check matrix `HField` can be deleted to form a shortened [[2ᵐ + 1 - s, k, 2ᵐ ⁺ ¹ - s - k]] MDS code. This is an important property of MDS codes, particularly for their practical realisation in the form of augmented, extended RS codes because it enables efficient implementation in applications such as incremental redundancy systems, and network coding. 3 - level quantization of the received channel bits meaning 3 symbols deleted. -- Using the first x - 1 columns of the field parity-check matrix (HField), using j = 0, and setting α₀, α₁, α₂, ..., αₓ ₋ ₁ to α⁰, α¹, α², ..., αˣ ⁻ ¹ in the parity-check matrix are set equal to the powers of a primitive element α of the Galois Field GF(q), a cyclic code can be constructed for efficient encoding and decoding. The resulting matrix is represented by `HSeed`. +Cyclic Code Construction: Using the first x - 1 columns of the field parity-check matrix (HField), using j = 0, and setting α₀, α₁, α₂, ..., αₓ ₋ ₁ to α⁰, α¹, α², ..., αˣ ⁻ ¹ in the parity-check matrix are set equal to the powers of a primitive element α of the Galois Field GF(q), a cyclic code can be constructed for efficient encoding and decoding. The resulting matrix is represented by `HSeed`. `HSeed` Matrix element expansion: diff --git a/test/test_ecc_reedsolomon.jl b/test/test_ecc_reedsolomon.jl index 39dab3cae..8173002b9 100644 --- a/test/test_ecc_reedsolomon.jl +++ b/test/test_ecc_reedsolomon.jl @@ -8,11 +8,8 @@ using QuantumClifford.ECC using QuantumClifford.ECC: AbstractECC, ReedSolomon, generator_polynomial """ -Employing `3-level` quantization of the channel bits and erasing entire symbols if any of their constituent bits are erased can improve the performance of RS codes. - -Shortened Maximum Distance Separable (MDS) codes have the following parameters - code length `(n)`, codesize `(k)` and minimum Hamming distance `(d)` represented by [[n, k, d]] as follows: [[2 ^ (m) + 1 - s, k, 2 ^ (m + 1) - s - k]]. Thus, the designed minimum distance `d` is 2 ^ (m + 1) - s - k. Refer to chapter: 07, section: 03, pages: 172 to 175 [tomlinson2017error](@cite). - -The designed distance for binary expanded parity check matrix remains same as symbol based parity check matrix. According to [macwilliams1977theory](@cite), changing the basis `j` can increase the designed distance `(dmin)` of the resulting binary code. +- Employing `3-level` quantization of the channel bits and erasing entire symbols if any of their constituent bits are erased can improve the performance of RS codes. Shortened Maximum Distance Separable (MDS) codes have the following parameters - code length `(n)`, codesize `(k)` and minimum Hamming distance `(d)` represented by [[n, k, d]] as follows: [[2 ^ (m) + 1 - s, k, 2 ^ (m + 1) - s - k]]. Thus, the designed minimum distance `d` is 2 ^ (m + 1) - s - k. Refer to chapter: 07, section: 03, pages: 172 to 175 [tomlinson2017error](@cite). +- The designed distance for binary expanded parity check matrix remains same as symbol based parity check matrix. According to [macwilliams1977theory](@cite), changing the basis `j` can increase the designed distance `(dmin)` of the resulting binary code. """ function designed_distance(matrix, m, t) k = 2 ^ m - 1 - 2 * t @@ -48,7 +45,7 @@ function generate_examplepage175() end @testset "Testing Shortened and Expanded Maximum Distance Separable (MDS) Reed Solomon codes's binary parity check matrices" begin - m_cases = [3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 14, 15] + m_cases = [3, 4, 5, 6, 7, 8] for m in m_cases for t in rand(1:m - 1, 2) mat = matrix(GF(2), parity_checks(ReedSolomon(m, t))) @@ -60,14 +57,14 @@ end end end - m_cases = [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] + m_cases = [5, 6, 7, 8, 9] for m in m_cases for t in rand(m:2 * m, 2) @test designed_distance(parity_checks(ReedSolomon(m, t)), m, t) == true end end - # RS(7, 3), RS(15, 9), RS(255, 223), RS(160, 128), RS(255, 251), (255, 239) and (255, 249) codes. Examples taken from [https://en.wikipedia.org/wiki/Reed%E2%80%93Solomon_error_correction], [https://www.cs.cmu.edu/~guyb/realworld/reedsolomon/reed_solomon_codes.html], [http://www.chencode.cn/lecture/Information_Theory_and_Coding/Information%20Theory%20and%20Coding-CH7.pdf], [https://citeseerx.ist.psu.edu/document?repid=rep1&type=pdf&doi=91e1d6d27311780b0a8c34a41793fa85f3947af1]. + # RS(7, 3), RS(15, 9), RS(255, 223), RS(160, 128), RS(255, 251), (255, 239) and (255, 249) codes. Examples taken from https://en.wikipedia.org/wiki/Reed%E2%80%93Solomon_error_correction, https://www.cs.cmu.edu/~guyb/realworld/reedsolomon/reed_solomon_codes.html, http://www.chencode.cn/lecture/Information_Theory_and_Coding/Information%20Theory%20and%20Coding-CH7.pdf, https://citeseerx.ist.psu.edu/document?repid=rep1&type=pdf&doi=91e1d6d27311780b0a8c34a41793fa85f3947af1. test_cases = [(7, 3), (15, 9), (225, 223), (160, 128), (255, 251), (255, 239), (255, 249)] for (n, k) in test_cases m = ilog2(n + 1) From cb896ba54c157c30dc02b7eb540f0ddb6a4c643d Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Sun, 12 May 2024 19:50:40 +0500 Subject: [PATCH 40/70] tightening docstring and minor cleanups --- src/ecc/codes/classical/reedsolomon.jl | 17 ++--- test/test_ecc_reedsolomon.jl | 86 +++++++++++++------------- 2 files changed, 51 insertions(+), 52 deletions(-) diff --git a/src/ecc/codes/classical/reedsolomon.jl b/src/ecc/codes/classical/reedsolomon.jl index a1cb258f6..fbe1fecf3 100644 --- a/src/ecc/codes/classical/reedsolomon.jl +++ b/src/ecc/codes/classical/reedsolomon.jl @@ -1,6 +1,6 @@ """The family of Reed-Solomon codes, as discovered by Reed and Solomon in their 1960 paper [reed1960polynomial](@cite). -Reed Solomon codes are maximum distance separable (MDS) codes and have the highest possible minimum Hamming distance. The codes have symbols from F_q with parameters `[[x - 1, k, x - k]]`. +Reed Solomon codes are maximum distance separable (MDS) codes and have the highest possible minimum Hamming distance. The codes have symbols from finite Galois fields `GF(pᵐ)` of degree `m`, where `p` is a prime number, with parameters `[[x - 1, k, x - k]]`. They are not binary codes but frequently are used with `x = 2ᵐ`, and so there is a mapping of residue classes of a primitive polynomial with binary coefficients and each element of `GF(2ᵐ)` is represented as a binary `m`-tuple. Denoting the `x` field elements as `0, α⁰, α¹, α²,... αˣ ⁻ ¹`, the shortened field parity-check matrix (`HSeed`) is given as follows: @@ -12,7 +12,7 @@ They are not binary codes but frequently are used with `x = 2ᵐ`, and so there . . . ... . . . . ... . . . . ... . -(α⁰)ʲ ⁺ ˣ ⁻ ᵏ (α¹)ʲ ⁺ ˣ ⁻ ᵏ (α²)ʲ ⁺ ˣ ⁻ ᵏ ... (αˣ ⁻ ¹)ʲ ⁺ ˣ ⁻ ᵏ +(α⁰)ʲ ⁺ ˣ ⁻ ᵏ (α¹)ʲ ⁺ ˣ ⁻ ᵏ (α²)ʲ ⁺ ˣ ⁻ ᵏ ... (αˣ ⁻ ¹)ʲ ⁺ ˣ ⁻ ᵏ ``` You might be interested in consulting [geisel1990tutorial](@cite), [wicker1999reed](@cite), [sklar2001reed](@cite), [berlekamp1978readable](@cite), [tomlinson2017error](@cite), [macwilliams1977theory](@cite), https://youtu.be/K26Ssr8H3ec?si=QOeohq_6I0Oyd8qu and [peterson1972error](@cite) as well. @@ -75,7 +75,9 @@ parity_checks(ReedSolomon(m, t)): - `m`: The positive integer defining the degree of the finite (Galois) field, `GF(2ᵐ)`. - `t`: The positive integer specifying the number of correctable errors `(t)`. -This function applies Reed-Solomon (RS) codes for binary transmission using soft decisions (see section 7.3)[tomlinson2017error](@cite). Code length limitations: For significant coding gain, code length is typically restricted to less than 200 bits. Modified Dorsch decoder is recommended for near maximum likelihood decoding. +This function applies Reed-Solomon (RS) codes for binary transmission using soft decisions (see section 7.3)[tomlinson2017error](@cite). For significant coding gain, code length is typically restricted to less than 200 bits. Modified Dorsch decoder is recommended for near maximum likelihood decoding. + +Soft Decision Decoding: In some communication systems, the received signal might not be a simple 0 or 1 but have a certain level of "softness" indicating the likelihood of being a 0 or 1. The 3-level quantization is used to represent these likelihoods (e.g., highly likely 0, likely 0, likely 1, highly likely 1) before feeding them into a Reed-Solomon decoder for error correction. Challenges of Standard RS Codes: While efficient as MDS codes, standard RS codes are not ideal for binary channels. As demonstrated in the results (see section 7.2)[tomlinson2017error](@cite), their performance suffers due to a mismatch between the code structure (symbol-based) and the channel (binary). A single bit error can lead to a symbol error, negating the code's benefits. @@ -96,16 +98,15 @@ Field Parity-Check Matrix (`HField`) Properties: (α₀)ʲ ⁺ ˣ ⁻ ᵏ (α₁)ʲ ⁺ ˣ ⁻ ᵏ (α₂)ʲ ⁺ ˣ ⁻ ᵏ ... (αₓ₋₂)ʲ ⁺ ˣ ⁻ ᵏ 0 1 ``` -The matrix has x - k + 1 rows corresponding to the code's parity symbols. Any x - k + 1 columns form a Vandermonde matrix (non-singular). This ensures correction of up to x - k + 1 symbol erasures in a codeword. Permutation: We can re-arrange the columns of the `HField` matrix in any desired order. Parity symbols (s) deletion: Any set of `s` symbols within a codeword can be designated as parity symbols and permanently removed. This important property leads to construction of Shortened MDS codes. +The matrix has x - k + 1 rows corresponding to the code's parity symbols. Any x - k + 1 columns form a Vandermonde matrix (non-singular). This ensures correction of up to x - k + 1 symbol erasures in a codeword. We can re-arrange the columns of the `HField` matrix in any desired order. Any set of `s` symbols within a codeword can be designated as parity symbols and permanently removed. This important property leads to construction of Shortened MDS codes. -Shortened MDS Codes: Corresponding columns of the field parity-check matrix `HField` can be deleted to form a shortened [[2ᵐ + 1 - s, k, 2ᵐ ⁺ ¹ - s - k]] MDS code. This is an important property of MDS codes, particularly for their practical realisation in the form of augmented, extended RS codes because it enables efficient implementation in applications such as incremental redundancy systems, and network coding. 3 - level quantization of the received channel bits meaning 3 symbols deleted. +Shortened MDS Codes: Corresponding columns of the field parity-check matrix `HField` can be deleted to form a shortened [[2ᵐ + 1 - s, k, 2ᵐ ⁺ ¹ - s - k]] MDS code. This is an important property of MDS codes, particularly for their practical realisation in the form of augmented, extended RS codes because it enables efficient implementation in applications such as incremental redundancy systems, and network coding. The 3 - level quantization of the received channel bits is utilized meaning 3 symbols are deleted. Cyclic Code Construction: Using the first x - 1 columns of the field parity-check matrix (HField), using j = 0, and setting α₀, α₁, α₂, ..., αₓ ₋ ₁ to α⁰, α¹, α², ..., αˣ ⁻ ¹ in the parity-check matrix are set equal to the powers of a primitive element α of the Galois Field GF(q), a cyclic code can be constructed for efficient encoding and decoding. The resulting matrix is represented by `HSeed`. `HSeed` Matrix element expansion: - - 1. Row expansion: Each row of in the `HField` matrix is replaced with an `m`-by-`m` Field matrix defined over the base field GF (2ᵐ). This expansion is represented by `HFieldExpanded`. - 2. Column expansion: The elements in each column of `HFieldExpanded` matrix are converted to binary representations by substituting powers of a primitive element (`α`) in the Galois Field GF(2ᵐ) with their corresponding m-tuples over the Boolean/Binary Field GF(2). + 1. Row expansion: Each row of in the `HField` matrix is replaced with an `m`-by-`m` Field matrix defined over the base field GF(2ᵐ). This expansion is represented by `HFieldExpanded`. + 2. Column expansion: The elements in each column of `HFieldExpanded` matrix are converted to binary representations by substituting powers of a primitive element (`α`) in the Galois Field GF(2ᵐ) with their corresponding m-tuples over the Boolean Field GF(2). """ function parity_checks(rs::ReedSolomon) GF2ʳ, a = finite_field(2, rs.m, "a") diff --git a/test/test_ecc_reedsolomon.jl b/test/test_ecc_reedsolomon.jl index 8173002b9..c2de82300 100644 --- a/test/test_ecc_reedsolomon.jl +++ b/test/test_ecc_reedsolomon.jl @@ -11,37 +11,20 @@ using QuantumClifford.ECC: AbstractECC, ReedSolomon, generator_polynomial - Employing `3-level` quantization of the channel bits and erasing entire symbols if any of their constituent bits are erased can improve the performance of RS codes. Shortened Maximum Distance Separable (MDS) codes have the following parameters - code length `(n)`, codesize `(k)` and minimum Hamming distance `(d)` represented by [[n, k, d]] as follows: [[2 ^ (m) + 1 - s, k, 2 ^ (m + 1) - s - k]]. Thus, the designed minimum distance `d` is 2 ^ (m + 1) - s - k. Refer to chapter: 07, section: 03, pages: 172 to 175 [tomlinson2017error](@cite). - The designed distance for binary expanded parity check matrix remains same as symbol based parity check matrix. According to [macwilliams1977theory](@cite), changing the basis `j` can increase the designed distance `(dmin)` of the resulting binary code. """ -function designed_distance(matrix, m, t) +function check_designed_distance(matrix, m, t) k = 2 ^ m - 1 - 2 * t - for row in eachrow(matrix) - count = sum(row) - if count >= 2 ^ (m + 1) - 3 - k - return true + s_symbols = 3 + n_cols = size(matrix, 2) + for num_cols in 1:2 ^ (m + 1) - s_symbols - k + for i in 1:n_cols - num_cols + 1 + combo = matrix[:, i:(i + num_cols - 1)] + sum_cols = sum(combo, dims = 2) + if all(sum_cols .== 0) + return false # Minimum distance is not greater than `2 ^ (m + 1) - s_symbols - k`. + end end end - return false -end - -#Example taken from page 173 of [tomlinson2017error](@cite). -function generate_examplepage175() - GF2ʳ, a = finite_field(2, 5, "a") - q = 30 - k = 15 - HField = Matrix{FqFieldElem}(undef, q - k + 1, q) - for j in 1: q - HField[1, j] = a ^ 0 - end - HTemp2 = Matrix{FqFieldElem}(undef, 5, q) - for i in 1: q - k + 1 - HField[i, 1] = a ^ 0 - end - for i in 2:q - k + 1 - for j in 2: q - HField[i, j] = (a ^ (j - 1)) ^ (i - 2) - end - end - HSeed = vcat(HField[1:1, :], HField[3:end, :]) - return HSeed + return true # Minimum distance is at least `2 ^ (m + 1) - s_symbols - k`. end @testset "Testing Shortened and Expanded Maximum Distance Separable (MDS) Reed Solomon codes's binary parity check matrices" begin @@ -54,13 +37,7 @@ end k = (2 ^ m - 1 - 2 * t) * m n = (2 ^ m + 1 - s_symbols) * m @test computed_rank == n - k - end - end - - m_cases = [5, 6, 7, 8, 9] - for m in m_cases - for t in rand(m:2 * m, 2) - @test designed_distance(parity_checks(ReedSolomon(m, t)), m, t) == true + @test check_designed_distance(parity_checks(ReedSolomon(m, t)), m, t) == true end end @@ -78,6 +55,27 @@ end @test generator_polynomial(ReedSolomon(3, 2)) == x ^ 4 + (a + 1) * x ^ 3 + x ^ 2 + a * x + a + 1 #Example taken from page 173 of [tomlinson2017error](@cite). + function generate_examplepage175() + GF2ʳ, a = finite_field(2, 5, "a") + q = 30 + k = 15 + HField = Matrix{FqFieldElem}(undef, q - k + 1, q) + for j in 1: q + HField[1, j] = a ^ 0 + end + HTemp2 = Matrix{FqFieldElem}(undef, 5, q) + for i in 1: q - k + 1 + HField[i, 1] = a ^ 0 + end + for i in 2:q - k + 1 + for j in 2: q + HField[i, j] = (a ^ (j - 1)) ^ (i - 2) + end + end + HSeed = vcat(HField[1:1, :], HField[3:end, :]) + return HSeed + end + GF2ʳ, a = finite_field(2, 5, "a") HF = Matrix{FqFieldElem}(undef, 15, 30) HF = generate_examplepage175() @@ -85,18 +83,18 @@ end @test reshape(HF[:,1], 1, 15) == [ 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1] @test HF[2, 2] == a @test HF[2, 3] == a ^ 2 - @test HF[2, 30] == a ^ 3 + 1 == a ^ 29 + @test HF[2, 30] == a ^ 29 @test HF[3, 2] == a ^ 2 @test HF[3, 3] == a ^ 4 - @test HF[3, 30] == a ^ 3 + a + 1 == a ^ 27 + @test HF[3, 30] == a ^ 27 @test HF[4, 2] == a ^ 3 - @test HF[4, 3] == a ^ 3 + a == a ^ 6 - @test HF[4, 30] == a ^ 4 + a ^ 3 + 1 == a ^ 25 - @test HF[14, 2] == a ^ 4 + a ^ 3 + a ^ 2 == a ^ 13 - @test HF[14, 3] == a ^ 4 + a ^ 2 + a + 1 == a ^ 26 - @test HF[14, 30] == a ^ 2 + 1 == a ^ 5 - @test HF[15, 2] == a ^ 4 + a ^ 3 + a ^ 2 + 1 == a ^ 14 - @test HF[15, 3] == a ^ 4 + a ^ 2 + a == a ^ 28 + @test HF[4, 3] == a ^ 6 + @test HF[4, 30] == a ^ 25 + @test HF[14, 2] == a ^ 13 + @test HF[14, 3] == a ^ 26 + @test HF[14, 30] == a ^ 5 + @test HF[15, 2] == a ^ 14 + @test HF[15, 3] == a ^ 28 @test HF[15, 30] == a ^ 3 #Example taken from page 175 of [tomlinson2017error](@cite). From 9de59a6c184b37c2044af7d84c0fa400477c088f Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Sun, 12 May 2024 20:13:43 +0500 Subject: [PATCH 41/70] Setting up for review --- src/ecc/codes/classical/reedsolomon.jl | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/ecc/codes/classical/reedsolomon.jl b/src/ecc/codes/classical/reedsolomon.jl index fbe1fecf3..af97903bc 100644 --- a/src/ecc/codes/classical/reedsolomon.jl +++ b/src/ecc/codes/classical/reedsolomon.jl @@ -53,7 +53,7 @@ We describe the generator polynomial in terms of its `2 * t = n - k` roots, as g(X) = (X - α¹)(X - α²)(X - α³) ... (X - α²ᵗ) ``` -Degree and Parity Symbols: The degree of the generator polynomial is equal to 2 * `t`, which is also the number of parity symbols added to the original data (`k` symbols) to create a codeword of length `n` `(n = k + 2 * t)`. +Degree and Parity Symbols: The degree of the generator polynomial is equal to `2 * t`, which is also the number of parity symbols added to the original data (`k` symbols) to create a codeword of length `n` `(n = k + 2 * t)`. Roots of the Generator Polynomial: The generator polynomial has `2 * t` distinct roots, designated as `α¹, α², ... , α²ᵗ`. These roots are chosen from a Finite Galois Field. Any power of α can be used as the starting root, not necessarily `α¹` itself. @@ -75,15 +75,15 @@ parity_checks(ReedSolomon(m, t)): - `m`: The positive integer defining the degree of the finite (Galois) field, `GF(2ᵐ)`. - `t`: The positive integer specifying the number of correctable errors `(t)`. -This function applies Reed-Solomon (RS) codes for binary transmission using soft decisions (see section 7.3)[tomlinson2017error](@cite). For significant coding gain, code length is typically restricted to less than 200 bits. Modified Dorsch decoder is recommended for near maximum likelihood decoding. +This function applies Reed-Solomon codes for binary transmission using soft decisions (see section 7.3)[tomlinson2017error](@cite). For significant coding gain, code length is typically restricted to less than 200 bits. Modified Dorsch decoder is recommended for near maximum likelihood decoding. -Soft Decision Decoding: In some communication systems, the received signal might not be a simple 0 or 1 but have a certain level of "softness" indicating the likelihood of being a 0 or 1. The 3-level quantization is used to represent these likelihoods (e.g., highly likely 0, likely 0, likely 1, highly likely 1) before feeding them into a Reed-Solomon decoder for error correction. +Soft Decision Decoding: In some communication systems, the received signal might not be a simple 0 or 1 but have a certain level of "softness" indicating the likelihood of being a 0 or 1. The benefit of using 3-level quantization with Reed-Solomon coding lies in exploiting the "soft information" present in the received signal. In traditional channels, bits are received as either 0 or 1 (hard decision). However, due to noise or other factors, the received signal might not be perfectly clear. The 3-level quantization captures this "softness" by assigning levels that represent the likelihood of a bit being 0 or 1 (e.g., highly likely 0, likely 0, likely 1, highly likely 1). Reed-Solomon decoding algorithms utilize this additional information to make better decisions about correcting errors, leading to a higher success rate compared to using just hard decisions. Challenges of Standard RS Codes: While efficient as MDS codes, standard RS codes are not ideal for binary channels. As demonstrated in the results (see section 7.2)[tomlinson2017error](@cite), their performance suffers due to a mismatch between the code structure (symbol-based) and the channel (binary). A single bit error can lead to a symbol error, negating the code's benefits. -Improved Binary Codes through Concatenation: This method enhances RS codes for binary channels through code concatenation. It adds a single overall binary parity check to each m-tuple representing a symbol. This approach transforms the original RS code [[n, k, n - k - 1]] into a new binary code with parameters [[n[m + 1], k * m, 2[n - k -1]]]. The resulting binary code boasts a minimum symbol weight of 2, effectively doubling the minimum Hamming distance compared to the original RS code. +Improved Binary Codes through Concatenation: This method enhances RS codes for binary channels through code concatenation. It adds a single overall binary parity check to each `m`-tuple representing a symbol. This approach transforms the original RS code `[[n, k, n - k - 1]]` into a new binary code with parameters `[[n[m + 1], k * m, 2[n - k -1]]]`. The resulting binary code boasts a minimum symbol weight of 2, effectively doubling the minimum Hamming distance compared to the original RS code. -Augmented Extended RS Codes: Constructed from Galois Field GF(2ᵐ). Length: 2ᵐ + 1 (Maximum Distance Separable (MDS) codes). Parameters: [[2ᵐ + 1, k, 2ᵐ ⁺ ¹ - k]]. Generalization: Applicable to any Galois Field GF(q) with parameters [[x + 1, k, x + 2 - k]]. +Augmented Extended RS Codes: Constructed from Galois Field `GF(2ᵐ)`. Length: `2ᵐ + 1` (Maximum Distance Separable (MDS) codes). Parameters: `[[2ᵐ + 1, k, 2ᵐ ⁺ ¹ - k]]`. Generalization: Applicable to any Galois Field `GF(x)` with parameters `[[x + 1, k, x + 2 - k]]`. Field Parity-Check Matrix (`HField`) Properties: @@ -98,15 +98,15 @@ Field Parity-Check Matrix (`HField`) Properties: (α₀)ʲ ⁺ ˣ ⁻ ᵏ (α₁)ʲ ⁺ ˣ ⁻ ᵏ (α₂)ʲ ⁺ ˣ ⁻ ᵏ ... (αₓ₋₂)ʲ ⁺ ˣ ⁻ ᵏ 0 1 ``` -The matrix has x - k + 1 rows corresponding to the code's parity symbols. Any x - k + 1 columns form a Vandermonde matrix (non-singular). This ensures correction of up to x - k + 1 symbol erasures in a codeword. We can re-arrange the columns of the `HField` matrix in any desired order. Any set of `s` symbols within a codeword can be designated as parity symbols and permanently removed. This important property leads to construction of Shortened MDS codes. +The matrix has `x - k + 1` rows corresponding to the code's parity symbols. Any `x - k + 1` columns form a Vandermonde matrix (non-singular). This ensures correction of up to `x - k + 1` symbol erasures in a codeword. We can re-arrange the columns of the `HField` matrix in any desired order. Any set of `s` symbols within a codeword can be designated as parity symbols and permanently removed. This important property leads to construction of Shortened MDS codes. -Shortened MDS Codes: Corresponding columns of the field parity-check matrix `HField` can be deleted to form a shortened [[2ᵐ + 1 - s, k, 2ᵐ ⁺ ¹ - s - k]] MDS code. This is an important property of MDS codes, particularly for their practical realisation in the form of augmented, extended RS codes because it enables efficient implementation in applications such as incremental redundancy systems, and network coding. The 3 - level quantization of the received channel bits is utilized meaning 3 symbols are deleted. +Shortened MDS Codes: Corresponding columns of the field parity-check matrix `HField` can be deleted to form a shortened `[[2ᵐ + 1 - s, k, 2ᵐ ⁺ ¹ - s - k]]` MDS code. This is an important property of MDS codes, particularly for their practical realisation in the form of augmented, extended RS codes because it enables efficient implementation in applications such as incremental redundancy systems, and network coding. The 3-level quantization of the received channel bits is utilized meaning 3 symbols are deleted. The Fig. 7.2 [tomlinson2017error](@cite) shows that with 3-level quantization, there is an improvement over the binary-transmission with hard decisions for Reed-Solomon coding. -Cyclic Code Construction: Using the first x - 1 columns of the field parity-check matrix (HField), using j = 0, and setting α₀, α₁, α₂, ..., αₓ ₋ ₁ to α⁰, α¹, α², ..., αˣ ⁻ ¹ in the parity-check matrix are set equal to the powers of a primitive element α of the Galois Field GF(q), a cyclic code can be constructed for efficient encoding and decoding. The resulting matrix is represented by `HSeed`. +Cyclic Code Construction: Using the first `x - 1` columns of the field parity-check matrix (HField), using `j = 0`, and setting `α₀, α₁, α₂, ..., αₓ ₋ ₁` to `α⁰, α¹, α², ..., αˣ ⁻ ¹` in the parity-check matrix are set equal to the powers of a primitive element α of the Galois Field `GF(x)`, a cyclic code can be constructed for efficient encoding and decoding. The resulting matrix is represented by `HSeed`. `HSeed` Matrix element expansion: - 1. Row expansion: Each row of in the `HField` matrix is replaced with an `m`-by-`m` Field matrix defined over the base field GF(2ᵐ). This expansion is represented by `HFieldExpanded`. - 2. Column expansion: The elements in each column of `HFieldExpanded` matrix are converted to binary representations by substituting powers of a primitive element (`α`) in the Galois Field GF(2ᵐ) with their corresponding m-tuples over the Boolean Field GF(2). + 1. Row expansion: Each row of in the `HField` matrix is replaced with an `m`-by-`m` Field matrix defined over the base field `GF(2ᵐ)`. This expansion is represented by `HFieldExpanded`. + 2. Column expansion: The elements in each column of `HFieldExpanded` matrix are converted to binary representations by substituting powers of a primitive element (`α`) in the Galois Field `GF(2ᵐ)` with their corresponding `m`-tuples over the Boolean Field `GF(2)`. """ function parity_checks(rs::ReedSolomon) GF2ʳ, a = finite_field(2, rs.m, "a") From 327f854ff11c241a33b8a47b483a0dc03cb070b6 Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Sun, 12 May 2024 23:11:14 +0500 Subject: [PATCH 42/70] Testing that Reed-Solomon codes exactly meet the Singleton Bound, adding some more sample examples as well --- src/ecc/codes/classical/reedsolomon.jl | 2 +- test/test_ecc_reedsolomon.jl | 17 +++++++++++++---- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/ecc/codes/classical/reedsolomon.jl b/src/ecc/codes/classical/reedsolomon.jl index af97903bc..0d7ff36f3 100644 --- a/src/ecc/codes/classical/reedsolomon.jl +++ b/src/ecc/codes/classical/reedsolomon.jl @@ -64,7 +64,7 @@ function generator_polynomial(rs::ReedSolomon) GF2ʳ, a = finite_field(2, rs.m, "a") P, x = GF2ʳ[:x] gx = x - a ^ 1 - for i in 2:2*rs.t + for i in 2:2 * rs.t gx *= (x - a ^ i) end return gx diff --git a/test/test_ecc_reedsolomon.jl b/test/test_ecc_reedsolomon.jl index c2de82300..0569ce94b 100644 --- a/test/test_ecc_reedsolomon.jl +++ b/test/test_ecc_reedsolomon.jl @@ -33,11 +33,14 @@ end for t in rand(1:m - 1, 2) mat = matrix(GF(2), parity_checks(ReedSolomon(m, t))) computed_rank = rank(mat) - s_symbols = 3 + s_symbols = 3 k = (2 ^ m - 1 - 2 * t) * m n = (2 ^ m + 1 - s_symbols) * m + d = 2 ^ (m + 1) - s_symbols - k @test computed_rank == n - k @test check_designed_distance(parity_checks(ReedSolomon(m, t)), m, t) == true + # Reed-Solomon codes exactly meet the [Singleton Bound](https://en.wikipedia.org/wiki/Singleton_bound). + @test d <= n - k + 1 end end @@ -49,12 +52,18 @@ end # Using fixed generator polynomial construction scheme for defining generator polynomial, `g(x)`, of RS codes, `degree(g(x))` == 2 * t == n - k. @test degree(generator_polynomial(ReedSolomon(m, t))) == 2 * t == n - k end - #Examples taken from [http://hscc.cs.nthu.edu.tw/~sheujp/lecture_note/rs.pdf]. + + # Examples taken from [http://hscc.cs.nthu.edu.tw/~sheujp/lecture_note/rs.pdf]. GF2ʳ, a = finite_field(2, 3, "a") P, x = GF2ʳ[:x] @test generator_polynomial(ReedSolomon(3, 2)) == x ^ 4 + (a + 1) * x ^ 3 + x ^ 2 + a * x + a + 1 - #Example taken from page 173 of [tomlinson2017error](@cite). + # Example taken from https://www.youtube.com/watch?v=dpxD8gwgbOc + GF2ʳ, a = finite_field(2, 4, "a") + P, x = GF2ʳ[:x] + @test generator_polynomial(ReedSolomon(4, 2)) == x ^ 4 + a ^ 13 * x ^ 3 + a ^ 6 * x ^ 2 + a ^ 3 * x + a ^ 10 + + # Example taken from page 173 of [tomlinson2017error](@cite). function generate_examplepage175() GF2ʳ, a = finite_field(2, 5, "a") q = 30 @@ -97,7 +106,7 @@ end @test HF[15, 3] == a ^ 28 @test HF[15, 30] == a ^ 3 - #Example taken from page 175 of [tomlinson2017error](@cite). + # Example taken from page 175 of [tomlinson2017error](@cite). @test size(parity_checks(ReedSolomon(5, 8))) == (75, 150) H = Matrix{Bool}(undef, 75, 150) H = parity_checks(ReedSolomon(5, 8)) From a0962a1181bdf691740dd78332799dd413ea7ed3 Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Mon, 13 May 2024 15:34:55 +0500 Subject: [PATCH 43/70] Adding Test that Reed-Solomon codes are cyclic --- test/test_ecc_reedsolomon.jl | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/test/test_ecc_reedsolomon.jl b/test/test_ecc_reedsolomon.jl index 0569ce94b..869efe2c8 100644 --- a/test/test_ecc_reedsolomon.jl +++ b/test/test_ecc_reedsolomon.jl @@ -27,10 +27,10 @@ function check_designed_distance(matrix, m, t) return true # Minimum distance is at least `2 ^ (m + 1) - s_symbols - k`. end -@testset "Testing Shortened and Expanded Maximum Distance Separable (MDS) Reed Solomon codes's binary parity check matrices" begin +@testset "Testing Shortened and Expanded Maximum Distance Separable (MDS) Reed Solomon codes's properties" begin m_cases = [3, 4, 5, 6, 7, 8] for m in m_cases - for t in rand(1:m - 1, 2) + for t in rand(1:m, 2) mat = matrix(GF(2), parity_checks(ReedSolomon(m, t))) computed_rank = rank(mat) s_symbols = 3 @@ -41,18 +41,23 @@ end @test check_designed_distance(parity_checks(ReedSolomon(m, t)), m, t) == true # Reed-Solomon codes exactly meet the [Singleton Bound](https://en.wikipedia.org/wiki/Singleton_bound). @test d <= n - k + 1 + # Reed-Solomon code is cyclic as its generator polynomial, `g(x)` divides `xⁿ - 1`, so `mod (xⁿ - 1, g(x))` = 0. + n_gx = 2 ^ m - 1 + GF2ʳ, a = finite_field(2, m, "a") + GF2x, x = GF2ʳ[:x] + mod(x ^ n_gx - 1, generator_polynomial(ReedSolomon(m, t))) == 0 end end # RS(7, 3), RS(15, 9), RS(255, 223), RS(160, 128), RS(255, 251), (255, 239) and (255, 249) codes. Examples taken from https://en.wikipedia.org/wiki/Reed%E2%80%93Solomon_error_correction, https://www.cs.cmu.edu/~guyb/realworld/reedsolomon/reed_solomon_codes.html, http://www.chencode.cn/lecture/Information_Theory_and_Coding/Information%20Theory%20and%20Coding-CH7.pdf, https://citeseerx.ist.psu.edu/document?repid=rep1&type=pdf&doi=91e1d6d27311780b0a8c34a41793fa85f3947af1. - test_cases = [(7, 3), (15, 9), (225, 223), (160, 128), (255, 251), (255, 239), (255, 249)] + test_cases = [(7, 1), (7, 3), (15, 9), (225, 223), (160, 128), (255, 251), (255, 239), (255, 249)] for (n, k) in test_cases m = ilog2(n + 1) t = div(n - k, 2) # Using fixed generator polynomial construction scheme for defining generator polynomial, `g(x)`, of RS codes, `degree(g(x))` == 2 * t == n - k. @test degree(generator_polynomial(ReedSolomon(m, t))) == 2 * t == n - k end - + # Examples taken from [http://hscc.cs.nthu.edu.tw/~sheujp/lecture_note/rs.pdf]. GF2ʳ, a = finite_field(2, 3, "a") P, x = GF2ʳ[:x] From e3582a798aa43e6993e60a98099db703fef94ad3 Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Mon, 13 May 2024 15:48:10 +0500 Subject: [PATCH 44/70] Minor Cleanup --- test/test_ecc_reedsolomon.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test_ecc_reedsolomon.jl b/test/test_ecc_reedsolomon.jl index 869efe2c8..33d5d9d9b 100644 --- a/test/test_ecc_reedsolomon.jl +++ b/test/test_ecc_reedsolomon.jl @@ -30,7 +30,7 @@ end @testset "Testing Shortened and Expanded Maximum Distance Separable (MDS) Reed Solomon codes's properties" begin m_cases = [3, 4, 5, 6, 7, 8] for m in m_cases - for t in rand(1:m, 2) + for t in rand(1:m - 1, 2) mat = matrix(GF(2), parity_checks(ReedSolomon(m, t))) computed_rank = rank(mat) s_symbols = 3 @@ -50,7 +50,7 @@ end end # RS(7, 3), RS(15, 9), RS(255, 223), RS(160, 128), RS(255, 251), (255, 239) and (255, 249) codes. Examples taken from https://en.wikipedia.org/wiki/Reed%E2%80%93Solomon_error_correction, https://www.cs.cmu.edu/~guyb/realworld/reedsolomon/reed_solomon_codes.html, http://www.chencode.cn/lecture/Information_Theory_and_Coding/Information%20Theory%20and%20Coding-CH7.pdf, https://citeseerx.ist.psu.edu/document?repid=rep1&type=pdf&doi=91e1d6d27311780b0a8c34a41793fa85f3947af1. - test_cases = [(7, 1), (7, 3), (15, 9), (225, 223), (160, 128), (255, 251), (255, 239), (255, 249)] + test_cases = [(7, 3), (15, 9), (225, 223), (160, 128), (255, 251), (255, 239), (255, 249)] for (n, k) in test_cases m = ilog2(n + 1) t = div(n - k, 2) From 768000a053cb31facfa1a697244f494edb5a71ea Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Wed, 15 May 2024 09:37:14 +0500 Subject: [PATCH 45/70] Removing Redundancy: Cleaning Up --- src/ecc/codes/classical/reedsolomon.jl | 2 +- test/test_ecc_reedsolomon.jl | 153 +++++++++---------------- 2 files changed, 57 insertions(+), 98 deletions(-) diff --git a/src/ecc/codes/classical/reedsolomon.jl b/src/ecc/codes/classical/reedsolomon.jl index 0d7ff36f3..6aac54ecf 100644 --- a/src/ecc/codes/classical/reedsolomon.jl +++ b/src/ecc/codes/classical/reedsolomon.jl @@ -117,7 +117,6 @@ function parity_checks(rs::ReedSolomon) for j in 1:x HField[1, j] = a ^ 0 end - HTemp2 = Matrix{FqFieldElem}(undef, rs.m, x) for i in 1: x - k + 1 HField[i, 1] = a ^ 0 end @@ -127,6 +126,7 @@ function parity_checks(rs::ReedSolomon) end end HSeed = vcat(HField[1:1, :], HField[3:end, :]) + HTemp2 = Matrix{FqFieldElem}(undef, rs.m, x) HFieldExpanded = Matrix{FqFieldElem}(undef, rs.m * k, x) g = 1 while g <= rs.m * k diff --git a/test/test_ecc_reedsolomon.jl b/test/test_ecc_reedsolomon.jl index 33d5d9d9b..479b4af2c 100644 --- a/test/test_ecc_reedsolomon.jl +++ b/test/test_ecc_reedsolomon.jl @@ -27,7 +27,7 @@ function check_designed_distance(matrix, m, t) return true # Minimum distance is at least `2 ^ (m + 1) - s_symbols - k`. end -@testset "Testing Shortened and Expanded Maximum Distance Separable (MDS) Reed Solomon codes's properties" begin +@testset "Testing Shortened and Maximum Distance Separable (MDS) Reed Solomon codes's properties" begin m_cases = [3, 4, 5, 6, 7, 8] for m in m_cases for t in rand(1:m - 1, 2) @@ -67,105 +67,64 @@ end GF2ʳ, a = finite_field(2, 4, "a") P, x = GF2ʳ[:x] @test generator_polynomial(ReedSolomon(4, 2)) == x ^ 4 + a ^ 13 * x ^ 3 + a ^ 6 * x ^ 2 + a ^ 3 * x + a ^ 10 - - # Example taken from page 173 of [tomlinson2017error](@cite). - function generate_examplepage175() - GF2ʳ, a = finite_field(2, 5, "a") - q = 30 - k = 15 - HField = Matrix{FqFieldElem}(undef, q - k + 1, q) - for j in 1: q - HField[1, j] = a ^ 0 - end - HTemp2 = Matrix{FqFieldElem}(undef, 5, q) - for i in 1: q - k + 1 - HField[i, 1] = a ^ 0 - end - for i in 2:q - k + 1 - for j in 2: q - HField[i, j] = (a ^ (j - 1)) ^ (i - 2) - end - end - HSeed = vcat(HField[1:1, :], HField[3:end, :]) - return HSeed - end - GF2ʳ, a = finite_field(2, 5, "a") - HF = Matrix{FqFieldElem}(undef, 15, 30) - HF = generate_examplepage175() - @test reshape(HF[1,:], 1, 30) == [1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1] - @test reshape(HF[:,1], 1, 15) == [ 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1] - @test HF[2, 2] == a - @test HF[2, 3] == a ^ 2 - @test HF[2, 30] == a ^ 29 - @test HF[3, 2] == a ^ 2 - @test HF[3, 3] == a ^ 4 - @test HF[3, 30] == a ^ 27 - @test HF[4, 2] == a ^ 3 - @test HF[4, 3] == a ^ 6 - @test HF[4, 30] == a ^ 25 - @test HF[14, 2] == a ^ 13 - @test HF[14, 3] == a ^ 26 - @test HF[14, 30] == a ^ 5 - @test HF[15, 2] == a ^ 14 - @test HF[15, 3] == a ^ 28 - @test HF[15, 30] == a ^ 3 - - # Example taken from page 175 of [tomlinson2017error](@cite). + # Example `(H₁₅₀₋₇₅`) taken from Eq. 7.9 of pg. 175 of [tomlinson2017error](@cite). @test size(parity_checks(ReedSolomon(5, 8))) == (75, 150) H = Matrix{Bool}(undef, 75, 150) H = parity_checks(ReedSolomon(5, 8)) - @test H[1:20, 1:15] == [1 0 0 0 0 1 0 0 0 0 1 0 0 0 0; - 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0; - 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0; - 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0; - 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1; - 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0; - 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0; - 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1; - 0 0 0 1 0 0 0 0 0 1 1 0 1 0 0; - 0 0 0 0 1 1 0 1 0 0 0 1 0 1 0; - 1 0 0 0 0 0 0 1 0 0 0 0 0 0 1; - 0 1 0 0 0 0 0 0 1 0 1 0 1 0 0; - 0 0 1 0 0 0 0 0 0 1 0 1 0 1 0; - 0 0 0 1 0 1 0 1 0 0 0 0 1 0 1; - 0 0 0 0 1 0 1 0 1 0 1 0 1 1 0; - 1 0 0 0 0 0 0 0 1 0 0 1 0 1 0; - 0 1 0 0 0 0 0 0 0 1 0 0 1 0 1; - 0 0 1 0 0 1 0 1 0 0 1 0 1 1 0; - 0 0 0 1 0 0 1 0 1 0 0 1 0 1 1; - 0 0 0 0 1 0 0 1 0 1 1 0 0 0 1] - - @test H[71:75, 1:15] == [1 0 0 0 0 1 0 1 1 1 0 1 1 0 1; - 0 1 0 0 0 1 1 1 1 1 1 0 0 1 0; - 0 0 1 0 0 1 1 0 1 1 0 1 0 0 1; - 0 0 0 1 0 1 1 0 0 1 1 0 0 0 0; - 0 0 0 0 1 1 1 0 0 0 0 1 0 0 0] - - @test H[1:20, 146:150] == [1 0 0 0 0; - 0 1 0 0 0; - 0 0 1 0 0; - 0 0 0 1 0; - 0 0 0 0 1; - 1 0 0 1 0; - 0 1 0 0 1; - 1 0 0 0 0; - 0 1 0 0 0; - 0 0 1 0 0; - 1 1 0 1 0; - 0 1 1 0 1; - 1 0 0 1 0; - 0 1 0 0 1; - 1 0 0 0 0; - 1 0 0 1 1; - 1 1 1 0 1; - 1 1 0 1 0; - 0 1 1 0 1; - 1 0 0 1 0] + example₁₋₁ = [1 0 0 0 0 1 0 0 0 0 1 0 0 0 0; + 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0; + 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0; + 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0; + 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1; + 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0; + 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0; + 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1; + 0 0 0 1 0 0 0 0 0 1 1 0 1 0 0; + 0 0 0 0 1 1 0 1 0 0 0 1 0 1 0; + 1 0 0 0 0 0 0 1 0 0 0 0 0 0 1; + 0 1 0 0 0 0 0 0 1 0 1 0 1 0 0; + 0 0 1 0 0 0 0 0 0 1 0 1 0 1 0; + 0 0 0 1 0 1 0 1 0 0 0 0 1 0 1; + 0 0 0 0 1 0 1 0 1 0 1 0 1 1 0; + 1 0 0 0 0 0 0 0 1 0 0 1 0 1 0; + 0 1 0 0 0 0 0 0 0 1 0 0 1 0 1; + 0 0 1 0 0 1 0 1 0 0 1 0 1 1 0; + 0 0 0 1 0 0 1 0 1 0 0 1 0 1 1; + 0 0 0 0 1 0 0 1 0 1 1 0 0 0 1] + example₁₋₂ = [1 0 0 0 0 1 0 1 1 1 0 1 1 0 1; + 0 1 0 0 0 1 1 1 1 1 1 0 0 1 0; + 0 0 1 0 0 1 1 0 1 1 0 1 0 0 1; + 0 0 0 1 0 1 1 0 0 1 1 0 0 0 0; + 0 0 0 0 1 1 1 0 0 0 0 1 0 0 0] + example₁₋₃ = [1 0 0 0 0; + 0 1 0 0 0; + 0 0 1 0 0; + 0 0 0 1 0; + 0 0 0 0 1; + 1 0 0 1 0; + 0 1 0 0 1; + 1 0 0 0 0; + 0 1 0 0 0; + 0 0 1 0 0; + 1 1 0 1 0; + 0 1 1 0 1; + 1 0 0 1 0; + 0 1 0 0 1; + 1 0 0 0 0; + 1 0 0 1 1; + 1 1 1 0 1; + 1 1 0 1 0; + 0 1 1 0 1; + 1 0 0 1 0] + example₁₋₄ = [0 0 0 1 0; + 0 0 0 0 1; + 1 0 1 0 0; + 0 1 0 1 0; + 0 0 1 0 1] - @test H[71:75, 146:150] == [0 0 0 1 0; - 0 0 0 0 1; - 1 0 1 0 0; - 0 1 0 1 0; - 0 0 1 0 1] + @test H[1:20, 1:15] == example₁₋₁ + @test H[71:75, 1:15] == example₁₋₂ + @test H[1:20, 146:150] == example₁₋₃ + @test H[71:75, 146:150] == example₁₋₄ end From 65bb3fa3ee3c30a772ad6883a14e2dac058942d8 Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Fri, 17 May 2024 09:52:44 +0500 Subject: [PATCH 46/70] fixing minor typo --- test/test_ecc_reedsolomon.jl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/test_ecc_reedsolomon.jl b/test/test_ecc_reedsolomon.jl index 479b4af2c..3a4bb6362 100644 --- a/test/test_ecc_reedsolomon.jl +++ b/test/test_ecc_reedsolomon.jl @@ -45,7 +45,7 @@ end n_gx = 2 ^ m - 1 GF2ʳ, a = finite_field(2, m, "a") GF2x, x = GF2ʳ[:x] - mod(x ^ n_gx - 1, generator_polynomial(ReedSolomon(m, t))) == 0 + @test mod(x ^ n_gx - 1, generator_polynomial(ReedSolomon(m, t))) == 0 end end @@ -72,7 +72,7 @@ end @test size(parity_checks(ReedSolomon(5, 8))) == (75, 150) H = Matrix{Bool}(undef, 75, 150) H = parity_checks(ReedSolomon(5, 8)) - example₁₋₁ = [1 0 0 0 0 1 0 0 0 0 1 0 0 0 0; + example₁₋₁ = [1 0 0 0 0 1 0 0 0 0 1 0 0 0 0; 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0; 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0; 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0; @@ -92,12 +92,12 @@ end 0 0 1 0 0 1 0 1 0 0 1 0 1 1 0; 0 0 0 1 0 0 1 0 1 0 0 1 0 1 1; 0 0 0 0 1 0 0 1 0 1 1 0 0 0 1] - example₁₋₂ = [1 0 0 0 0 1 0 1 1 1 0 1 1 0 1; + example₁₋₂ = [1 0 0 0 0 1 0 1 1 1 0 1 1 0 1; 0 1 0 0 0 1 1 1 1 1 1 0 0 1 0; 0 0 1 0 0 1 1 0 1 1 0 1 0 0 1; 0 0 0 1 0 1 1 0 0 1 1 0 0 0 0; 0 0 0 0 1 1 1 0 0 0 0 1 0 0 0] - example₁₋₃ = [1 0 0 0 0; + example₁₋₃ = [1 0 0 0 0; 0 1 0 0 0; 0 0 1 0 0; 0 0 0 1 0; @@ -117,7 +117,7 @@ end 1 1 0 1 0; 0 1 1 0 1; 1 0 0 1 0] - example₁₋₄ = [0 0 0 1 0; + example₁₋₄ = [0 0 0 1 0; 0 0 0 0 1; 1 0 1 0 0; 0 1 0 1 0; From 249bd41d510f9bdc3b26926cf92607c1ae55a93d Mon Sep 17 00:00:00 2001 From: Feroz <93876775+Fe-r-oz@users.noreply.github.com> Date: Mon, 20 May 2024 11:44:48 +0500 Subject: [PATCH 47/70] Update src/ecc/codes/classical/reedsolomon.jl Co-authored-by: Stefan Krastanov --- src/ecc/codes/classical/reedsolomon.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ecc/codes/classical/reedsolomon.jl b/src/ecc/codes/classical/reedsolomon.jl index 6aac54ecf..8880dfe88 100644 --- a/src/ecc/codes/classical/reedsolomon.jl +++ b/src/ecc/codes/classical/reedsolomon.jl @@ -28,7 +28,7 @@ struct ReedSolomon <: AbstractPolynomialCode function ReedSolomon(m, t) if m < 3 || t < 0 || t >= 2 ^ (m - 1) - throw(ArgumentError("Invalid parameters: m and t must be non-negative. Also, m > 3 and t < 2 ^ (m - 1) in order to obtain a valid code and to remain tractable.")) + throw(ArgumentError("Invalid parameters: m and t must be non-negative. Also, m > 3 and t < 2 ^ (m - 1) in order to obtain a valid code.")) end new(m, t) end From 503abcfe583a1dbbcfbcc2bd9f24b59ac667c4ae Mon Sep 17 00:00:00 2001 From: Feroz <93876775+Fe-r-oz@users.noreply.github.com> Date: Mon, 20 May 2024 11:45:02 +0500 Subject: [PATCH 48/70] Update src/ecc/codes/classical/reedsolomon.jl Co-authored-by: Stefan Krastanov --- src/ecc/codes/classical/reedsolomon.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ecc/codes/classical/reedsolomon.jl b/src/ecc/codes/classical/reedsolomon.jl index 8880dfe88..f2d33cdb8 100644 --- a/src/ecc/codes/classical/reedsolomon.jl +++ b/src/ecc/codes/classical/reedsolomon.jl @@ -35,7 +35,8 @@ struct ReedSolomon <: AbstractPolynomialCode end """ -generator_polynomial(ReedSolomon(m, t)): +`generator_polynomial(ReedSolomon(m, t))` + - `m`: The positive integer defining the degree of the finite (Galois) field, `GF(2ᵐ)`. - `t`: The positive integer specifying the number of correctable errors `(t)`. From e64adaee1ec494ca903acc2351f3dd0eeacf7151 Mon Sep 17 00:00:00 2001 From: Feroz <93876775+Fe-r-oz@users.noreply.github.com> Date: Mon, 20 May 2024 11:45:15 +0500 Subject: [PATCH 49/70] Update src/ecc/codes/classical/reedsolomon.jl Co-authored-by: Stefan Krastanov --- src/ecc/codes/classical/reedsolomon.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ecc/codes/classical/reedsolomon.jl b/src/ecc/codes/classical/reedsolomon.jl index f2d33cdb8..cc179618c 100644 --- a/src/ecc/codes/classical/reedsolomon.jl +++ b/src/ecc/codes/classical/reedsolomon.jl @@ -38,7 +38,7 @@ end `generator_polynomial(ReedSolomon(m, t))` - `m`: The positive integer defining the degree of the finite (Galois) field, `GF(2ᵐ)`. -- `t`: The positive integer specifying the number of correctable errors `(t)`. +- `t`: The positive integer specifying the number of correctable errors. The generator polynomial for an RS code takes the following form: From 6307c3dfcef3668490198d34e36546b0fe4db293 Mon Sep 17 00:00:00 2001 From: Feroz <93876775+Fe-r-oz@users.noreply.github.com> Date: Mon, 20 May 2024 11:45:30 +0500 Subject: [PATCH 50/70] Update src/ecc/codes/classical/reedsolomon.jl Co-authored-by: Stefan Krastanov --- src/ecc/codes/classical/reedsolomon.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ecc/codes/classical/reedsolomon.jl b/src/ecc/codes/classical/reedsolomon.jl index cc179618c..23c61cfb5 100644 --- a/src/ecc/codes/classical/reedsolomon.jl +++ b/src/ecc/codes/classical/reedsolomon.jl @@ -72,7 +72,7 @@ function generator_polynomial(rs::ReedSolomon) end """ -parity_checks(ReedSolomon(m, t)): +`parity_checks(ReedSolomon(m, t))` - `m`: The positive integer defining the degree of the finite (Galois) field, `GF(2ᵐ)`. - `t`: The positive integer specifying the number of correctable errors `(t)`. From d06a2746c0600fb878fbd83e9d05208084b1893f Mon Sep 17 00:00:00 2001 From: Feroz <93876775+Fe-r-oz@users.noreply.github.com> Date: Mon, 20 May 2024 11:45:43 +0500 Subject: [PATCH 51/70] Update src/ecc/codes/classical/reedsolomon.jl Co-authored-by: Stefan Krastanov --- src/ecc/codes/classical/reedsolomon.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ecc/codes/classical/reedsolomon.jl b/src/ecc/codes/classical/reedsolomon.jl index 23c61cfb5..b55751c29 100644 --- a/src/ecc/codes/classical/reedsolomon.jl +++ b/src/ecc/codes/classical/reedsolomon.jl @@ -74,7 +74,7 @@ end """ `parity_checks(ReedSolomon(m, t))` - `m`: The positive integer defining the degree of the finite (Galois) field, `GF(2ᵐ)`. -- `t`: The positive integer specifying the number of correctable errors `(t)`. +- `t`: The positive integer specifying the number of correctable errors. This function applies Reed-Solomon codes for binary transmission using soft decisions (see section 7.3)[tomlinson2017error](@cite). For significant coding gain, code length is typically restricted to less than 200 bits. Modified Dorsch decoder is recommended for near maximum likelihood decoding. From 6245ce6eb7ed4d4be6b43685a996bc0e376f9896 Mon Sep 17 00:00:00 2001 From: Feroz <93876775+Fe-r-oz@users.noreply.github.com> Date: Mon, 20 May 2024 11:46:12 +0500 Subject: [PATCH 52/70] Update src/ecc/codes/classical/reedsolomon.jl Co-authored-by: Stefan Krastanov --- src/ecc/codes/classical/reedsolomon.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ecc/codes/classical/reedsolomon.jl b/src/ecc/codes/classical/reedsolomon.jl index b55751c29..bebe4ccd3 100644 --- a/src/ecc/codes/classical/reedsolomon.jl +++ b/src/ecc/codes/classical/reedsolomon.jl @@ -58,7 +58,7 @@ Degree and Parity Symbols: The degree of the generator polynomial is equal to `2 Roots of the Generator Polynomial: The generator polynomial has `2 * t` distinct roots, designated as `α¹, α², ... , α²ᵗ`. These roots are chosen from a Finite Galois Field. Any power of α can be used as the starting root, not necessarily `α¹` itself. -Fixed generator polynomial scheme vs variable generator polynomial scheme: Only in this construction scheme using fixed generator polynomial `g(x)`, RS codes are a subset of the Bose, Chaudhuri, and Hocquenghem (BCH) codes; hence, this relationship between the degree of the generator polynomial and the number of parity symbols holds, just as for BCH codes where degree of BCH generator polynomial, `degree(g(x)) == n - k`. This is proved via RS test suite as well. Prior to 1963, RS codes employed a variable generator polynomial for encoding. This approach [peterson1972error](@cite) differed from the prevalent BCH scheme (used here), which utilizes a fixed generator polynomial. Consequently, these original RS codes weren't strictly categorized as BCH codes. Furthermore, depending on the chosen evaluation points, they might not even qualify as cyclic codes. +Fixed generator polynomial scheme vs variable generator polynomial scheme: Only in this construction scheme using fixed generator polynomial `g(x)`, RS codes are a subset of the Bose, Chaudhuri, and Hocquenghem (BCH) codes; hence, this relationship between the degree of the generator polynomial and the number of parity symbols holds, just as for BCH codes where degree of BCH generator polynomial, `degree(g(x)) == n - k`. Prior to 1963, RS codes employed a variable generator polynomial for encoding. This approach [peterson1972error](@cite) differed from the prevalent BCH scheme (used here), which utilizes a fixed generator polynomial. Consequently, these original RS codes weren't strictly categorized as BCH codes. Furthermore, depending on the chosen evaluation points, they might not even qualify as cyclic codes. """ function generator_polynomial(rs::ReedSolomon) From d9338b6f6f3db854e118fabde414be9be8cba9a8 Mon Sep 17 00:00:00 2001 From: Feroz <93876775+Fe-r-oz@users.noreply.github.com> Date: Mon, 20 May 2024 11:47:13 +0500 Subject: [PATCH 53/70] Update src/ecc/codes/classical/reedsolomon.jl Co-authored-by: Stefan Krastanov --- src/ecc/codes/classical/reedsolomon.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ecc/codes/classical/reedsolomon.jl b/src/ecc/codes/classical/reedsolomon.jl index bebe4ccd3..a5730f331 100644 --- a/src/ecc/codes/classical/reedsolomon.jl +++ b/src/ecc/codes/classical/reedsolomon.jl @@ -103,7 +103,7 @@ The matrix has `x - k + 1` rows corresponding to the code's parity symbols. Any Shortened MDS Codes: Corresponding columns of the field parity-check matrix `HField` can be deleted to form a shortened `[[2ᵐ + 1 - s, k, 2ᵐ ⁺ ¹ - s - k]]` MDS code. This is an important property of MDS codes, particularly for their practical realisation in the form of augmented, extended RS codes because it enables efficient implementation in applications such as incremental redundancy systems, and network coding. The 3-level quantization of the received channel bits is utilized meaning 3 symbols are deleted. The Fig. 7.2 [tomlinson2017error](@cite) shows that with 3-level quantization, there is an improvement over the binary-transmission with hard decisions for Reed-Solomon coding. -Cyclic Code Construction: Using the first `x - 1` columns of the field parity-check matrix (HField), using `j = 0`, and setting `α₀, α₁, α₂, ..., αₓ ₋ ₁` to `α⁰, α¹, α², ..., αˣ ⁻ ¹` in the parity-check matrix are set equal to the powers of a primitive element α of the Galois Field `GF(x)`, a cyclic code can be constructed for efficient encoding and decoding. The resulting matrix is represented by `HSeed`. +Cyclic Code Construction: Using the first `x - 1` columns of the field parity-check matrix `HField`, using `j = 0`, and setting `α₀, α₁, α₂, ..., αₓ ₋ ₁` to `α⁰, α¹, α², ..., αˣ ⁻ ¹` in the parity-check matrix are set equal to the powers of a primitive element α of the Galois Field `GF(x)`, a cyclic code can be constructed for efficient encoding and decoding. `HSeed` Matrix element expansion: 1. Row expansion: Each row of in the `HField` matrix is replaced with an `m`-by-`m` Field matrix defined over the base field `GF(2ᵐ)`. This expansion is represented by `HFieldExpanded`. From 5914d9adf682e90dfa0d5bd5bd8295787812bccb Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Mon, 20 May 2024 11:57:14 +0500 Subject: [PATCH 54/70] code suggestions --- src/ecc/codes/classical/reedsolomon.jl | 3 +++ test/test_ecc_reedsolomon.jl | 4 +--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/ecc/codes/classical/reedsolomon.jl b/src/ecc/codes/classical/reedsolomon.jl index 6aac54ecf..c445cd32b 100644 --- a/src/ecc/codes/classical/reedsolomon.jl +++ b/src/ecc/codes/classical/reedsolomon.jl @@ -155,3 +155,6 @@ function parity_checks(rs::ReedSolomon) end return H end + +code_n(rs::ReedSolomon) = (2 ^ rs.m + 1 - 3) * rs.m +code_k(rs::ReedSolomon) = (2 ^ rs.m - 1 - 2 * rs.t) * rs.m diff --git a/test/test_ecc_reedsolomon.jl b/test/test_ecc_reedsolomon.jl index 3a4bb6362..00bd2a5e1 100644 --- a/test/test_ecc_reedsolomon.jl +++ b/test/test_ecc_reedsolomon.jl @@ -30,7 +30,7 @@ end @testset "Testing Shortened and Maximum Distance Separable (MDS) Reed Solomon codes's properties" begin m_cases = [3, 4, 5, 6, 7, 8] for m in m_cases - for t in rand(1:m - 1, 2) + for t in rand(2:m - 1, 2) mat = matrix(GF(2), parity_checks(ReedSolomon(m, t))) computed_rank = rank(mat) s_symbols = 3 @@ -39,8 +39,6 @@ end d = 2 ^ (m + 1) - s_symbols - k @test computed_rank == n - k @test check_designed_distance(parity_checks(ReedSolomon(m, t)), m, t) == true - # Reed-Solomon codes exactly meet the [Singleton Bound](https://en.wikipedia.org/wiki/Singleton_bound). - @test d <= n - k + 1 # Reed-Solomon code is cyclic as its generator polynomial, `g(x)` divides `xⁿ - 1`, so `mod (xⁿ - 1, g(x))` = 0. n_gx = 2 ^ m - 1 GF2ʳ, a = finite_field(2, m, "a") From 58288b3e30c01527ac4dd24d2ce660f26154a361 Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Mon, 20 May 2024 15:10:09 +0500 Subject: [PATCH 55/70] code review suggestions --- docs/src/references.bib | 13 ++++++++- docs/src/references.md | 1 + src/ecc/codes/classical/reedsolomon.jl | 22 +++++++-------- test/test_ecc_bch.jl | 24 ++++++++-------- test/test_ecc_reedsolomon.jl | 39 ++++++++++++-------------- test/utils_test_ecc.jl | 14 +++++++++ 6 files changed, 66 insertions(+), 47 deletions(-) create mode 100644 test/utils_test_ecc.jl diff --git a/docs/src/references.bib b/docs/src/references.bib index 29ddc8197..297bc9374 100644 --- a/docs/src/references.bib +++ b/docs/src/references.bib @@ -421,7 +421,7 @@ @book{wicker1999reed @article{sklar2001reed, title={Reed-solomon codes}, author={Sklar, Bernard}, - journal={Downloaded from URL http://www. informit. com/content/images/art. sub.--sklar7. sub.--reed-solomo-n/elementLinks/art. sub.--sklar7. sub.--reed-solomon. pdf}, + journal={Downloaded from URL https://ptgmedia.pearsoncmg.com/images/art_sklar7_reed-solomon/elementlinks/art_sklar7_reed-solomon.pdf}, pages={1--33}, year={2001} } @@ -447,3 +447,14 @@ @book{peterson1972error year={1972}, publisher={MIT press} } + +@article{dorsch1974decoding, + title={A decoding algorithm for binary block codes and J-ary output channels (corresp.)}, + author={Dorsch, B}, + journal={IEEE Transactions on Information Theory}, + volume={20}, + number={3}, + pages={391--394}, + year={1974}, + publisher={IEEE} +} diff --git a/docs/src/references.md b/docs/src/references.md index c69f18d86..60dac0915 100644 --- a/docs/src/references.md +++ b/docs/src/references.md @@ -55,6 +55,7 @@ For classical code construction routines: - [tomlinson2017error](@cite) - [macwilliams1977theory](@cite) - [peterson1972error](@cite) +- [dorsch1974decoding](@cite) # References diff --git a/src/ecc/codes/classical/reedsolomon.jl b/src/ecc/codes/classical/reedsolomon.jl index 9ad7fa911..7d78968e6 100644 --- a/src/ecc/codes/classical/reedsolomon.jl +++ b/src/ecc/codes/classical/reedsolomon.jl @@ -2,7 +2,7 @@ Reed Solomon codes are maximum distance separable (MDS) codes and have the highest possible minimum Hamming distance. The codes have symbols from finite Galois fields `GF(pᵐ)` of degree `m`, where `p` is a prime number, with parameters `[[x - 1, k, x - k]]`. -They are not binary codes but frequently are used with `x = 2ᵐ`, and so there is a mapping of residue classes of a primitive polynomial with binary coefficients and each element of `GF(2ᵐ)` is represented as a binary `m`-tuple. Denoting the `x` field elements as `0, α⁰, α¹, α²,... αˣ ⁻ ¹`, the shortened field parity-check matrix (`HSeed`) is given as follows: +They are not binary codes but frequently are used with `x = 2ᵐ`, and so there is a mapping of residue classes of a primitive polynomial with binary coefficients and each element of `GF(2ᵐ)` is represented as a binary `m`-tuple. Denoting the `x` field elements as `0, α⁰, α¹, α²,... αˣ ⁻ ¹`, the shortened field parity-check matrix (`HF`) is given as follows: ``` (α⁰)ʲ (α¹)ʲ (α²)ʲ ... (αˣ ⁻ ¹)ʲ @@ -15,7 +15,7 @@ They are not binary codes but frequently are used with `x = 2ᵐ`, and so there (α⁰)ʲ ⁺ ˣ ⁻ ᵏ (α¹)ʲ ⁺ ˣ ⁻ ᵏ (α²)ʲ ⁺ ˣ ⁻ ᵏ ... (αˣ ⁻ ¹)ʲ ⁺ ˣ ⁻ ᵏ ``` -You might be interested in consulting [geisel1990tutorial](@cite), [wicker1999reed](@cite), [sklar2001reed](@cite), [berlekamp1978readable](@cite), [tomlinson2017error](@cite), [macwilliams1977theory](@cite), https://youtu.be/K26Ssr8H3ec?si=QOeohq_6I0Oyd8qu and [peterson1972error](@cite) as well. +You might be interested in consulting [geisel1990tutorial](@cite), [wicker1999reed](@cite), [sklar2001reed](@cite), [berlekamp1978readable](@cite), [tomlinson2017error](@cite), [macwilliams1977theory](@cite), and [peterson1972error](@cite) as well. The ECC Zoo has an [entry for this family](https://errorcorrectionzoo.org/c/reed_solomon). """ @@ -76,9 +76,7 @@ end - `m`: The positive integer defining the degree of the finite (Galois) field, `GF(2ᵐ)`. - `t`: The positive integer specifying the number of correctable errors. -This function applies Reed-Solomon codes for binary transmission using soft decisions (see section 7.3)[tomlinson2017error](@cite). For significant coding gain, code length is typically restricted to less than 200 bits. Modified Dorsch decoder is recommended for near maximum likelihood decoding. - -Soft Decision Decoding: In some communication systems, the received signal might not be a simple 0 or 1 but have a certain level of "softness" indicating the likelihood of being a 0 or 1. The benefit of using 3-level quantization with Reed-Solomon coding lies in exploiting the "soft information" present in the received signal. In traditional channels, bits are received as either 0 or 1 (hard decision). However, due to noise or other factors, the received signal might not be perfectly clear. The 3-level quantization captures this "softness" by assigning levels that represent the likelihood of a bit being 0 or 1 (e.g., highly likely 0, likely 0, likely 1, highly likely 1). Reed-Solomon decoding algorithms utilize this additional information to make better decisions about correcting errors, leading to a higher success rate compared to using just hard decisions. +This function applies Reed-Solomon codes for binary transmission using soft decisions (see section 7.3)[tomlinson2017error](@cite). For significant coding gain, code length is typically restricted to less than 200 bits. Modified Dorsch decoder [dorsch1974decoding](@cite) is recommended for near maximum likelihood decoding. Challenges of Standard RS Codes: While efficient as MDS codes, standard RS codes are not ideal for binary channels. As demonstrated in the results (see section 7.2)[tomlinson2017error](@cite), their performance suffers due to a mismatch between the code structure (symbol-based) and the channel (binary). A single bit error can lead to a symbol error, negating the code's benefits. @@ -86,7 +84,7 @@ Improved Binary Codes through Concatenation: This method enhances RS codes for b Augmented Extended RS Codes: Constructed from Galois Field `GF(2ᵐ)`. Length: `2ᵐ + 1` (Maximum Distance Separable (MDS) codes). Parameters: `[[2ᵐ + 1, k, 2ᵐ ⁺ ¹ - k]]`. Generalization: Applicable to any Galois Field `GF(x)` with parameters `[[x + 1, k, x + 2 - k]]`. -Field Parity-Check Matrix (`HField`) Properties: +Field Parity-Check Matrix Properties: ``` (α₀)ʲ (α₁)ʲ (α₂)ʲ ... (αₓ₋₂)ʲ 1 0 @@ -99,15 +97,15 @@ Field Parity-Check Matrix (`HField`) Properties: (α₀)ʲ ⁺ ˣ ⁻ ᵏ (α₁)ʲ ⁺ ˣ ⁻ ᵏ (α₂)ʲ ⁺ ˣ ⁻ ᵏ ... (αₓ₋₂)ʲ ⁺ ˣ ⁻ ᵏ 0 1 ``` -The matrix has `x - k + 1` rows corresponding to the code's parity symbols. Any `x - k + 1` columns form a Vandermonde matrix (non-singular). This ensures correction of up to `x - k + 1` symbol erasures in a codeword. We can re-arrange the columns of the `HField` matrix in any desired order. Any set of `s` symbols within a codeword can be designated as parity symbols and permanently removed. This important property leads to construction of Shortened MDS codes. +The matrix has `x - k + 1` rows corresponding to the code's parity symbols. Any `x - k + 1` columns form a Vandermonde matrix (non-singular). This ensures correction of up to `x - k + 1` symbol erasures in a codeword. We can re-arrange the columns of this matrix in any desired order. Any set of `s` symbols within a codeword can be designated as parity symbols and permanently removed. This important property leads to construction of Shortened MDS codes. -Shortened MDS Codes: Corresponding columns of the field parity-check matrix `HField` can be deleted to form a shortened `[[2ᵐ + 1 - s, k, 2ᵐ ⁺ ¹ - s - k]]` MDS code. This is an important property of MDS codes, particularly for their practical realisation in the form of augmented, extended RS codes because it enables efficient implementation in applications such as incremental redundancy systems, and network coding. The 3-level quantization of the received channel bits is utilized meaning 3 symbols are deleted. The Fig. 7.2 [tomlinson2017error](@cite) shows that with 3-level quantization, there is an improvement over the binary-transmission with hard decisions for Reed-Solomon coding. +Shortened MDS Codes: Corresponding columns of the field parity-check matrix can be deleted to form a shortened `[[2ᵐ + 1 - s, k, 2ᵐ ⁺ ¹ - s - k]]` MDS code. This is an important property of MDS codes, particularly for their practical realisation in the form of augmented, extended RS codes because it enables efficient implementation in applications such as incremental redundancy systems, and network coding. The 3-level quantization of the received channel bits is utilized meaning 3 symbols are deleted. The Fig. 7.2 [tomlinson2017error](@cite) shows that with 3-level quantization, there is an improvement over the binary-transmission with hard decisions for Reed-Solomon coding. The designed distance for binary expanded parity check matrix remains same as symbol based parity check matrix. According to [macwilliams1977theory](@cite), changing the basis `j` can increase the designed distance `(dmin)` of the resulting binary code. -Cyclic Code Construction: Using the first `x - 1` columns of the field parity-check matrix `HField`, using `j = 0`, and setting `α₀, α₁, α₂, ..., αₓ ₋ ₁` to `α⁰, α¹, α², ..., αˣ ⁻ ¹` in the parity-check matrix are set equal to the powers of a primitive element α of the Galois Field `GF(x)`, a cyclic code can be constructed for efficient encoding and decoding. +Cyclic Code Construction: Using the first `x - 1` columns of the field parity-check matrix, using `j = 0`, and setting `α₀, α₁, α₂, ..., αₓ ₋ ₁` to `α⁰, α¹, α², ..., αˣ ⁻ ¹` in the parity-check matrix are set equal to the powers of a primitive element α of the Galois Field `GF(x)`, a cyclic code can be constructed for efficient encoding and decoding. -`HSeed` Matrix element expansion: - 1. Row expansion: Each row of in the `HField` matrix is replaced with an `m`-by-`m` Field matrix defined over the base field `GF(2ᵐ)`. This expansion is represented by `HFieldExpanded`. - 2. Column expansion: The elements in each column of `HFieldExpanded` matrix are converted to binary representations by substituting powers of a primitive element (`α`) in the Galois Field `GF(2ᵐ)` with their corresponding `m`-tuples over the Boolean Field `GF(2)`. +Shortened MDS (`HF`) Matrix element expansion: + 1. Row expansion: Each row of in the field parity-check matrix is replaced with an `m`-by-`m` field matrix defined over the base field `GF(2ᵐ)`. + 2. Column expansion: Consequently, the elements in each column of expanded field parity-check matrix are converted to binary representations by substituting powers of a primitive element (`α`) in the Galois Field `GF(2ᵐ)` with their corresponding `m`-tuples over the Boolean Field `GF(2)`. """ function parity_checks(rs::ReedSolomon) GF2ʳ, a = finite_field(2, rs.m, "a") diff --git a/test/test_ecc_bch.jl b/test/test_ecc_bch.jl index 2885cd2ae..f42a1d90c 100644 --- a/test/test_ecc_bch.jl +++ b/test/test_ecc_bch.jl @@ -4,32 +4,29 @@ using QuantumClifford using QuantumClifford.ECC using QuantumClifford.ECC: AbstractECC, BCH, generator_polynomial using Nemo: ZZ, residue_ring, matrix, finite_field, GF, minpoly, coeff, lcm, FqPolyRingElem, FqFieldElem, is_zero, degree, defining_polynomial, is_irreducible +include("utils_test_ecc.jl") """ - To prove that `t`-bit error correcting BCH code indeed has minimum distance of at least `2 * t + 1`, it is shown that no `2 * t` or fewer columns of its binary parity check matrix `H` sum to zero. A formal mathematical proof can be found on pages 168 and 169 of Ch6 of Error Control Coding by Lin, Shu and Costello, Daniel. - The parameter `2 * t + 1` is usually called the designed distance of the `t`-bit error correcting BCH code. """ -function check_designed_distance(matrix, t) - n_cols = size(matrix, 2) - for num_cols in 1:2 * t - for i in 1:n_cols - num_cols + 1 - combo = matrix[:, i:(i + num_cols - 1)] - sum_cols = sum(combo, dims = 2) - if all(sum_cols .== 0) - return false # Minimum distance is not greater than `2 * t`. - end + +@testset "Testing designed distance of BCH codes" begin + m_cases = [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] + for m in m_cases + for t in rand(1:m, 2) + d = 2 * t + @test check_designed_distance(parity_checks(BCH(m, t)), m, t, d, 0, 0) == true end end - return true # Minimum distance is at least `2 * t + 1`. end - + @testset "Testing properties of BCH codes" begin m_cases = [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] for m in m_cases n = 2 ^ m - 1 for t in rand(1:m, 2) H = parity_checks(BCH(m, t)) - @test check_designed_distance(H, t) == true # n - k == degree of generator polynomial, `g(x)` == rank of binary parity check matrix, `H`. mat = matrix(GF(2), parity_checks(BCH(m, t))) computed_rank = rank(mat) @@ -79,7 +76,8 @@ end results = [57 51 45 39 36 30 24 18 16 10 7] for (result, (m, t)) in zip(results, test_cases) + d = 2 * t @test code_k(BCH(m, t)) == result - @test check_designed_distance(parity_checks(BCH(m, t)), t) == true + @test check_designed_distance(parity_checks(BCH(m, t)), m, t, d, 0, 0) == true end end diff --git a/test/test_ecc_reedsolomon.jl b/test/test_ecc_reedsolomon.jl index 00bd2a5e1..681e81bb0 100644 --- a/test/test_ecc_reedsolomon.jl +++ b/test/test_ecc_reedsolomon.jl @@ -2,47 +2,44 @@ using Test using ILog2 using LinearAlgebra using Combinatorics -using Nemo: finite_field, GF, FqFieldElem, FqPolyRingElem, coeff, is_zero, degree, matrix using QuantumClifford using QuantumClifford.ECC using QuantumClifford.ECC: AbstractECC, ReedSolomon, generator_polynomial +using Nemo: finite_field, GF, FqFieldElem, FqPolyRingElem, coeff, is_zero, degree, matrix +include("utils_test_ecc.jl") """ - Employing `3-level` quantization of the channel bits and erasing entire symbols if any of their constituent bits are erased can improve the performance of RS codes. Shortened Maximum Distance Separable (MDS) codes have the following parameters - code length `(n)`, codesize `(k)` and minimum Hamming distance `(d)` represented by [[n, k, d]] as follows: [[2 ^ (m) + 1 - s, k, 2 ^ (m + 1) - s - k]]. Thus, the designed minimum distance `d` is 2 ^ (m + 1) - s - k. Refer to chapter: 07, section: 03, pages: 172 to 175 [tomlinson2017error](@cite). - The designed distance for binary expanded parity check matrix remains same as symbol based parity check matrix. According to [macwilliams1977theory](@cite), changing the basis `j` can increase the designed distance `(dmin)` of the resulting binary code. """ -function check_designed_distance(matrix, m, t) - k = 2 ^ m - 1 - 2 * t - s_symbols = 3 - n_cols = size(matrix, 2) - for num_cols in 1:2 ^ (m + 1) - s_symbols - k - for i in 1:n_cols - num_cols + 1 - combo = matrix[:, i:(i + num_cols - 1)] - sum_cols = sum(combo, dims = 2) - if all(sum_cols .== 0) - return false # Minimum distance is not greater than `2 ^ (m + 1) - s_symbols - k`. - end + +@testset "Testing designed distance of Shortened and Maximum Distance Separable (MDS) Reed-Solomon codes" begin + m_cases = [3, 4, 5, 6, 7, 8] + for m in m_cases + for t in rand(1:m - 1, 2) + # The variable s_symbols is set to 3 because the last three columns of the field parity check matrix `HF`​ are erased. By using the first `x − 1` columns of `HF`​, assigning `j = 0` and setting `α₀, α₁, α₂, ..., αₓ ₋ ₁` to `α⁰, α¹, α², ..., αˣ ⁻ ¹`, where `α` is a primitive element of `GF(x)`. This approach allows for the construction of a cyclic code, which offers advantages in the implementation of encoding and decoding. + s_symbols = 3 + k = (2 ^ m - 1 - 2 * t) * m + d = 2 ^ (m + 1) - s_symbols - k + @test check_designed_distance(parity_checks(ReedSolomon(m, t)), m, t, d, 0, 0) == true end end - return true # Minimum distance is at least `2 ^ (m + 1) - s_symbols - k`. end @testset "Testing Shortened and Maximum Distance Separable (MDS) Reed Solomon codes's properties" begin m_cases = [3, 4, 5, 6, 7, 8] for m in m_cases - for t in rand(2:m - 1, 2) + for t in rand(1:m - 1, 2) mat = matrix(GF(2), parity_checks(ReedSolomon(m, t))) - computed_rank = rank(mat) + computed_rank = rank(mat) s_symbols = 3 k = (2 ^ m - 1 - 2 * t) * m n = (2 ^ m + 1 - s_symbols) * m - d = 2 ^ (m + 1) - s_symbols - k - @test computed_rank == n - k - @test check_designed_distance(parity_checks(ReedSolomon(m, t)), m, t) == true - # Reed-Solomon code is cyclic as its generator polynomial, `g(x)` divides `xⁿ - 1`, so `mod (xⁿ - 1, g(x))` = 0. + @test computed_rank == n - k n_gx = 2 ^ m - 1 GF2ʳ, a = finite_field(2, m, "a") GF2x, x = GF2ʳ[:x] + # Reed-Solomon code is cyclic as its generator polynomial, `g(x)` divides `xⁿ - 1`, so `mod (xⁿ - 1, g(x))` = 0. @test mod(x ^ n_gx - 1, generator_polynomial(ReedSolomon(m, t))) == 0 end end @@ -56,12 +53,12 @@ end @test degree(generator_polynomial(ReedSolomon(m, t))) == 2 * t == n - k end - # Examples taken from [http://hscc.cs.nthu.edu.tw/~sheujp/lecture_note/rs.pdf]. + # Examples taken from pg. 18 of http://hscc.cs.nthu.edu.tw/~sheujp/lecture_note/rs.pdf. GF2ʳ, a = finite_field(2, 3, "a") P, x = GF2ʳ[:x] @test generator_polynomial(ReedSolomon(3, 2)) == x ^ 4 + (a + 1) * x ^ 3 + x ^ 2 + a * x + a + 1 - # Example taken from https://www.youtube.com/watch?v=dpxD8gwgbOc + # Example taken from https://www.youtube.com/watch?v=dpxD8gwgbOc. GF2ʳ, a = finite_field(2, 4, "a") P, x = GF2ʳ[:x] @test generator_polynomial(ReedSolomon(4, 2)) == x ^ 4 + a ^ 13 * x ^ 3 + a ^ 6 * x ^ 2 + a ^ 3 * x + a ^ 10 diff --git a/test/utils_test_ecc.jl b/test/utils_test_ecc.jl new file mode 100644 index 000000000..16cbcbad2 --- /dev/null +++ b/test/utils_test_ecc.jl @@ -0,0 +1,14 @@ +"""The designed distance of a classical linear code with paramters `[[n, k, d]]`, where `n` represents the code length, `k` denotes the code dimension, and `d` signifies the minimum Hamming distance. For polynomial codes, `t` indicates the degree of the generator polynomial, and `m` represents the extension degree for the finite Galois field `GF(2ᵐ)`.""" +function check_designed_distance(matrix, m, t, d, n, k) + n_cols = size(matrix, 2) + for num_cols in 1:d + for i in 1:n_cols - num_cols + 1 + combo = matrix[:, i:(i + num_cols - 1)] + sum_cols = sum(combo, dims = 2) + if all(sum_cols .== 0) + return false + end + end + end + return true +end From 1fbffd21f9b782d5555474560195493116ac0861 Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Mon, 20 May 2024 15:19:43 +0500 Subject: [PATCH 56/70] adding doctest --- src/ecc/codes/classical/reedsolomon.jl | 12 ++++++++++++ test/utils_test_ecc.jl | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/ecc/codes/classical/reedsolomon.jl b/src/ecc/codes/classical/reedsolomon.jl index 7d78968e6..bd5b3c6e9 100644 --- a/src/ecc/codes/classical/reedsolomon.jl +++ b/src/ecc/codes/classical/reedsolomon.jl @@ -61,6 +61,18 @@ Roots of the Generator Polynomial: The generator polynomial has `2 * t` distinct Fixed generator polynomial scheme vs variable generator polynomial scheme: Only in this construction scheme using fixed generator polynomial `g(x)`, RS codes are a subset of the Bose, Chaudhuri, and Hocquenghem (BCH) codes; hence, this relationship between the degree of the generator polynomial and the number of parity symbols holds, just as for BCH codes where degree of BCH generator polynomial, `degree(g(x)) == n - k`. Prior to 1963, RS codes employed a variable generator polynomial for encoding. This approach [peterson1972error](@cite) differed from the prevalent BCH scheme (used here), which utilizes a fixed generator polynomial. Consequently, these original RS codes weren't strictly categorized as BCH codes. Furthermore, depending on the chosen evaluation points, they might not even qualify as cyclic codes. """ + +```jldoctest +julia> test_cases = [(7, 3), (15, 9), (225, 223), (160, 128), (255, 251), (255, 239), (255, 249)]; + +julia> for (n, k) in test_cases + m = ilog2(n + 1) + t = div(n - k, 2) + # Using fixed generator polynomial construction scheme for defining generator polynomial, `g(x)`, of RS codes, `degree(g(x))` == 2 * t == n - k. + degree(generator_polynomial(ReedSolomon(m, t))) == 2 * t == n - k + end +``` + function generator_polynomial(rs::ReedSolomon) GF2ʳ, a = finite_field(2, rs.m, "a") P, x = GF2ʳ[:x] diff --git a/test/utils_test_ecc.jl b/test/utils_test_ecc.jl index 16cbcbad2..143f8da75 100644 --- a/test/utils_test_ecc.jl +++ b/test/utils_test_ecc.jl @@ -1,4 +1,4 @@ -"""The designed distance of a classical linear code with paramters `[[n, k, d]]`, where `n` represents the code length, `k` denotes the code dimension, and `d` signifies the minimum Hamming distance. For polynomial codes, `t` indicates the degree of the generator polynomial, and `m` represents the extension degree for the finite Galois field `GF(2ᵐ)`.""" +"""The designed distance of a classical linear code with parameters `[[n, k, d]]`, where `n` represents the code length, `k` denotes the code dimension, and `d` signifies the minimum Hamming distance. For polynomial codes, `t` indicates the degree of the generator polynomial, and `m` represents the extension degree for the finite Galois field `GF(2ᵐ)`.""" function check_designed_distance(matrix, m, t, d, n, k) n_cols = size(matrix, 2) for num_cols in 1:d From b05dfdc4d72436e67087c30f07688b933090f1c2 Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Mon, 20 May 2024 15:24:17 +0500 Subject: [PATCH 57/70] Adding code suggestions --- src/ecc/codes/classical/reedsolomon.jl | 11 ++++++++++- test/test_ecc_reedsolomon.jl | 9 --------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/ecc/codes/classical/reedsolomon.jl b/src/ecc/codes/classical/reedsolomon.jl index bd5b3c6e9..eb3bc3e07 100644 --- a/src/ecc/codes/classical/reedsolomon.jl +++ b/src/ecc/codes/classical/reedsolomon.jl @@ -61,9 +61,18 @@ Roots of the Generator Polynomial: The generator polynomial has `2 * t` distinct Fixed generator polynomial scheme vs variable generator polynomial scheme: Only in this construction scheme using fixed generator polynomial `g(x)`, RS codes are a subset of the Bose, Chaudhuri, and Hocquenghem (BCH) codes; hence, this relationship between the degree of the generator polynomial and the number of parity symbols holds, just as for BCH codes where degree of BCH generator polynomial, `degree(g(x)) == n - k`. Prior to 1963, RS codes employed a variable generator polynomial for encoding. This approach [peterson1972error](@cite) differed from the prevalent BCH scheme (used here), which utilizes a fixed generator polynomial. Consequently, these original RS codes weren't strictly categorized as BCH codes. Furthermore, depending on the chosen evaluation points, they might not even qualify as cyclic codes. """ +# RS(7, 3), RS(15, 9), RS(255, 223), RS(160, 128), RS(255, 251), (255, 239) and (255, 249) codes. Examples taken from https://en.wikipedia.org/wiki/Reed%E2%80%93Solomon_error_correction, https://www.cs.cmu.edu/~guyb/realworld/reedsolomon/reed_solomon_codes.html, http://www.chencode.cn/lecture/Information_Theory_and_Coding/Information%20Theory%20and%20Coding-CH7.pdf, https://citeseerx.ist.psu.edu/document?repid=rep1&type=pdf&doi=91e1d6d27311780b0a8c34a41793fa85f3947af1. ```jldoctest -julia> test_cases = [(7, 3), (15, 9), (225, 223), (160, 128), (255, 251), (255, 239), (255, 249)]; +julia> test_cases = [(7, 3), (15, 9), (225, 223), (160, 128), (255, 251), (255, 239), (255, 249)] +7-element Vector{Tuple{Int64, Int64}}: + (7, 3) + (15, 9) + (225, 223) + (160, 128) + (255, 251) + (255, 239) + (255, 249) julia> for (n, k) in test_cases m = ilog2(n + 1) diff --git a/test/test_ecc_reedsolomon.jl b/test/test_ecc_reedsolomon.jl index 681e81bb0..03ebf2415 100644 --- a/test/test_ecc_reedsolomon.jl +++ b/test/test_ecc_reedsolomon.jl @@ -44,15 +44,6 @@ end end end - # RS(7, 3), RS(15, 9), RS(255, 223), RS(160, 128), RS(255, 251), (255, 239) and (255, 249) codes. Examples taken from https://en.wikipedia.org/wiki/Reed%E2%80%93Solomon_error_correction, https://www.cs.cmu.edu/~guyb/realworld/reedsolomon/reed_solomon_codes.html, http://www.chencode.cn/lecture/Information_Theory_and_Coding/Information%20Theory%20and%20Coding-CH7.pdf, https://citeseerx.ist.psu.edu/document?repid=rep1&type=pdf&doi=91e1d6d27311780b0a8c34a41793fa85f3947af1. - test_cases = [(7, 3), (15, 9), (225, 223), (160, 128), (255, 251), (255, 239), (255, 249)] - for (n, k) in test_cases - m = ilog2(n + 1) - t = div(n - k, 2) - # Using fixed generator polynomial construction scheme for defining generator polynomial, `g(x)`, of RS codes, `degree(g(x))` == 2 * t == n - k. - @test degree(generator_polynomial(ReedSolomon(m, t))) == 2 * t == n - k - end - # Examples taken from pg. 18 of http://hscc.cs.nthu.edu.tw/~sheujp/lecture_note/rs.pdf. GF2ʳ, a = finite_field(2, 3, "a") P, x = GF2ʳ[:x] From 2ea910e42b01d90bc5bc411b9e4b38ea2f411d7d Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Mon, 20 May 2024 15:36:11 +0500 Subject: [PATCH 58/70] improving doctest --- src/ecc/codes/classical/reedsolomon.jl | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/src/ecc/codes/classical/reedsolomon.jl b/src/ecc/codes/classical/reedsolomon.jl index eb3bc3e07..655fe2bfd 100644 --- a/src/ecc/codes/classical/reedsolomon.jl +++ b/src/ecc/codes/classical/reedsolomon.jl @@ -64,20 +64,10 @@ Fixed generator polynomial scheme vs variable generator polynomial scheme: Only # RS(7, 3), RS(15, 9), RS(255, 223), RS(160, 128), RS(255, 251), (255, 239) and (255, 249) codes. Examples taken from https://en.wikipedia.org/wiki/Reed%E2%80%93Solomon_error_correction, https://www.cs.cmu.edu/~guyb/realworld/reedsolomon/reed_solomon_codes.html, http://www.chencode.cn/lecture/Information_Theory_and_Coding/Information%20Theory%20and%20Coding-CH7.pdf, https://citeseerx.ist.psu.edu/document?repid=rep1&type=pdf&doi=91e1d6d27311780b0a8c34a41793fa85f3947af1. ```jldoctest -julia> test_cases = [(7, 3), (15, 9), (225, 223), (160, 128), (255, 251), (255, 239), (255, 249)] -7-element Vector{Tuple{Int64, Int64}}: - (7, 3) - (15, 9) - (225, 223) - (160, 128) - (255, 251) - (255, 239) - (255, 249) - +julia> test_cases = [(7, 3), (15, 9), (225, 223), (160, 128), (255, 251), (255, 239), (255, 249)]; julia> for (n, k) in test_cases m = ilog2(n + 1) t = div(n - k, 2) - # Using fixed generator polynomial construction scheme for defining generator polynomial, `g(x)`, of RS codes, `degree(g(x))` == 2 * t == n - k. degree(generator_polynomial(ReedSolomon(m, t))) == 2 * t == n - k end ``` From 82a18f0f619e8087a686a9905284d06fdc4fcb55 Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Mon, 20 May 2024 15:43:35 +0500 Subject: [PATCH 59/70] setting up; working on doctest --- src/ecc/codes/classical/reedsolomon.jl | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/ecc/codes/classical/reedsolomon.jl b/src/ecc/codes/classical/reedsolomon.jl index 655fe2bfd..7d78968e6 100644 --- a/src/ecc/codes/classical/reedsolomon.jl +++ b/src/ecc/codes/classical/reedsolomon.jl @@ -61,17 +61,6 @@ Roots of the Generator Polynomial: The generator polynomial has `2 * t` distinct Fixed generator polynomial scheme vs variable generator polynomial scheme: Only in this construction scheme using fixed generator polynomial `g(x)`, RS codes are a subset of the Bose, Chaudhuri, and Hocquenghem (BCH) codes; hence, this relationship between the degree of the generator polynomial and the number of parity symbols holds, just as for BCH codes where degree of BCH generator polynomial, `degree(g(x)) == n - k`. Prior to 1963, RS codes employed a variable generator polynomial for encoding. This approach [peterson1972error](@cite) differed from the prevalent BCH scheme (used here), which utilizes a fixed generator polynomial. Consequently, these original RS codes weren't strictly categorized as BCH codes. Furthermore, depending on the chosen evaluation points, they might not even qualify as cyclic codes. """ -# RS(7, 3), RS(15, 9), RS(255, 223), RS(160, 128), RS(255, 251), (255, 239) and (255, 249) codes. Examples taken from https://en.wikipedia.org/wiki/Reed%E2%80%93Solomon_error_correction, https://www.cs.cmu.edu/~guyb/realworld/reedsolomon/reed_solomon_codes.html, http://www.chencode.cn/lecture/Information_Theory_and_Coding/Information%20Theory%20and%20Coding-CH7.pdf, https://citeseerx.ist.psu.edu/document?repid=rep1&type=pdf&doi=91e1d6d27311780b0a8c34a41793fa85f3947af1. - -```jldoctest -julia> test_cases = [(7, 3), (15, 9), (225, 223), (160, 128), (255, 251), (255, 239), (255, 249)]; -julia> for (n, k) in test_cases - m = ilog2(n + 1) - t = div(n - k, 2) - degree(generator_polynomial(ReedSolomon(m, t))) == 2 * t == n - k - end -``` - function generator_polynomial(rs::ReedSolomon) GF2ʳ, a = finite_field(2, rs.m, "a") P, x = GF2ʳ[:x] From cb4852947a8e25e10293d355fa65c63a490d3b2e Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Mon, 20 May 2024 20:11:07 +0500 Subject: [PATCH 60/70] Adding CodeReview suggestions --- src/ecc/codes/classical/reedsolomon.jl | 3 +-- test/test_ecc_reedsolomon.jl | 5 ++--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/ecc/codes/classical/reedsolomon.jl b/src/ecc/codes/classical/reedsolomon.jl index 7d78968e6..b7736fac4 100644 --- a/src/ecc/codes/classical/reedsolomon.jl +++ b/src/ecc/codes/classical/reedsolomon.jl @@ -12,7 +12,7 @@ They are not binary codes but frequently are used with `x = 2ᵐ`, and so there . . . ... . . . . ... . . . . ... . -(α⁰)ʲ ⁺ ˣ ⁻ ᵏ (α¹)ʲ ⁺ ˣ ⁻ ᵏ (α²)ʲ ⁺ ˣ ⁻ ᵏ ... (αˣ ⁻ ¹)ʲ ⁺ ˣ ⁻ ᵏ +(α⁰)ʲ ⁺ ˣ ⁻ ᵏ (α¹)ʲ ⁺ ˣ ⁻ ᵏ (α²)ʲ ⁺ ˣ ⁻ ᵏ ... (αˣ ⁻ ¹)ʲ ⁺ ˣ ⁻ ᵏ ``` You might be interested in consulting [geisel1990tutorial](@cite), [wicker1999reed](@cite), [sklar2001reed](@cite), [berlekamp1978readable](@cite), [tomlinson2017error](@cite), [macwilliams1977theory](@cite), and [peterson1972error](@cite) as well. @@ -59,7 +59,6 @@ Degree and Parity Symbols: The degree of the generator polynomial is equal to `2 Roots of the Generator Polynomial: The generator polynomial has `2 * t` distinct roots, designated as `α¹, α², ... , α²ᵗ`. These roots are chosen from a Finite Galois Field. Any power of α can be used as the starting root, not necessarily `α¹` itself. Fixed generator polynomial scheme vs variable generator polynomial scheme: Only in this construction scheme using fixed generator polynomial `g(x)`, RS codes are a subset of the Bose, Chaudhuri, and Hocquenghem (BCH) codes; hence, this relationship between the degree of the generator polynomial and the number of parity symbols holds, just as for BCH codes where degree of BCH generator polynomial, `degree(g(x)) == n - k`. Prior to 1963, RS codes employed a variable generator polynomial for encoding. This approach [peterson1972error](@cite) differed from the prevalent BCH scheme (used here), which utilizes a fixed generator polynomial. Consequently, these original RS codes weren't strictly categorized as BCH codes. Furthermore, depending on the chosen evaluation points, they might not even qualify as cyclic codes. - """ function generator_polynomial(rs::ReedSolomon) GF2ʳ, a = finite_field(2, rs.m, "a") diff --git a/test/test_ecc_reedsolomon.jl b/test/test_ecc_reedsolomon.jl index 03ebf2415..4da8df9d8 100644 --- a/test/test_ecc_reedsolomon.jl +++ b/test/test_ecc_reedsolomon.jl @@ -17,8 +17,7 @@ include("utils_test_ecc.jl") m_cases = [3, 4, 5, 6, 7, 8] for m in m_cases for t in rand(1:m - 1, 2) - # The variable s_symbols is set to 3 because the last three columns of the field parity check matrix `HF`​ are erased. By using the first `x − 1` columns of `HF`​, assigning `j = 0` and setting `α₀, α₁, α₂, ..., αₓ ₋ ₁` to `α⁰, α¹, α², ..., αˣ ⁻ ¹`, where `α` is a primitive element of `GF(x)`. This approach allows for the construction of a cyclic code, which offers advantages in the implementation of encoding and decoding. - s_symbols = 3 + s_symbols = 3 # Refer to chapter: 07, section: 03, pages: 172 to 175 [tomlinson2017error](@cite). k = (2 ^ m - 1 - 2 * t) * m d = 2 ^ (m + 1) - s_symbols - k @test check_designed_distance(parity_checks(ReedSolomon(m, t)), m, t, d, 0, 0) == true @@ -32,7 +31,7 @@ end for t in rand(1:m - 1, 2) mat = matrix(GF(2), parity_checks(ReedSolomon(m, t))) computed_rank = rank(mat) - s_symbols = 3 + s_symbols = 3 # Refer to chapter: 07, section: 03, pages: 172 to 175 [tomlinson2017error](@cite). k = (2 ^ m - 1 - 2 * t) * m n = (2 ^ m + 1 - s_symbols) * m @test computed_rank == n - k From 00035bbabba48f03530b8cbcf479a22f8fe41f9c Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Mon, 20 May 2024 23:28:54 +0500 Subject: [PATCH 61/70] Introducing Signigicant changes: ExtendedReedSolomonMDS codes --- docs/src/references.bib | 57 +++++++---------- docs/src/references.md | 2 + src/ecc/ECC.jl | 2 +- ...edsolomon.jl => extendedreedsolomonmds.jl} | 62 ++++--------------- test/runtests.jl | 2 +- ....jl => test_ecc_extendedreedsolomonmds.jl} | 29 +++------ test/test_ecc_throws.jl | 6 +- 7 files changed, 48 insertions(+), 112 deletions(-) rename src/ecc/codes/classical/{reedsolomon.jl => extendedreedsolomonmds.jl} (62%) rename test/{test_ecc_reedsolomon.jl => test_ecc_extendedreedsolomonmds.jl} (73%) diff --git a/docs/src/references.bib b/docs/src/references.bib index 297bc9374..ac2e37ea7 100644 --- a/docs/src/references.bib +++ b/docs/src/references.bib @@ -391,41 +391,6 @@ @article{reed1960polynomial publisher={SIAM} } -@book{geisel1990tutorial, - title={Tutorial on Reed-Solomon Error Correction Coding}, - author={Geisel, W.A. and United States. National Aeronautics and Space Administration and Lyndon B. Johnson Space Center}, - series={NASA technical memorandum}, - url={https://books.google.com.pk/books?id=Uys2AQAAMAAJ}, - year={1990}, - publisher={National Aeronautics and Space Administration, Lyndon B. Johnson Space Center} -} - -@article{berlekamp1978readable, - title={Readable erasures improve the performance of Reed-Solomon codes (Corresp.)}, - author={Berlekamp, E and Ramsey, J}, - journal={IEEE Transactions on Information Theory}, - volume={24}, - number={5}, - pages={632--633}, - year={1978}, - publisher={IEEE} -} - -@book{wicker1999reed, - title={Reed-Solomon codes and their applications}, - author={Wicker, Stephen B and Bhargava, Vijay K}, - year={1999}, - publisher={John Wiley \& Sons} -} - -@article{sklar2001reed, - title={Reed-solomon codes}, - author={Sklar, Bernard}, - journal={Downloaded from URL https://ptgmedia.pearsoncmg.com/images/art_sklar7_reed-solomon/elementlinks/art_sklar7_reed-solomon.pdf}, - pages={1--33}, - year={2001} -} - @book{tomlinson2017error, title={Error-correction coding and decoding: bounds, codes, decoders, analysis and applications}, author={Tomlinson, Martin and Tjhai, Cen Jung and Ambroze, Marcel A and Ahmed, Mohammed and Jibril, Mubarak}, @@ -458,3 +423,25 @@ @article{dorsch1974decoding year={1974}, publisher={IEEE} } + +@article{seroussi1986mds, + title={On MDS extensions of generalized Reed-Solomon codes}, + author={Seroussi, Gadiel and Roth, Ron M}, + journal={IEEE Transactions on Information Theory}, + volume={32}, + number={3}, + pages={349--354}, + year={1986}, + publisher={IEEE} +} + +@article{dur1987automorphism, + title={The automorphism groups of Reed-Solomon codes}, + author={D{\"u}r, Arne}, + journal={Journal of Combinatorial Theory, Series A}, + volume={44}, + number={1}, + pages={69--82}, + year={1987}, + publisher={Elsevier} +} diff --git a/docs/src/references.md b/docs/src/references.md index 60dac0915..f2c91cffe 100644 --- a/docs/src/references.md +++ b/docs/src/references.md @@ -56,6 +56,8 @@ For classical code construction routines: - [macwilliams1977theory](@cite) - [peterson1972error](@cite) - [dorsch1974decoding](@cite) +- [seroussi1986mds](@cite) +- [dur1987automorphism](@cite) # References diff --git a/src/ecc/ECC.jl b/src/ecc/ECC.jl index aba3ebd41..608ba02b0 100644 --- a/src/ecc/ECC.jl +++ b/src/ecc/ECC.jl @@ -356,5 +356,5 @@ include("codes/gottesman.jl") include("codes/surface.jl") include("codes/classical/reedmuller.jl") include("codes/classical/bch.jl") -include("codes/classical/reedsolomon.jl") +include("codes/classical/extendedreedsolomonmds.jl") end #module diff --git a/src/ecc/codes/classical/reedsolomon.jl b/src/ecc/codes/classical/extendedreedsolomonmds.jl similarity index 62% rename from src/ecc/codes/classical/reedsolomon.jl rename to src/ecc/codes/classical/extendedreedsolomonmds.jl index b7736fac4..1912e9bd4 100644 --- a/src/ecc/codes/classical/reedsolomon.jl +++ b/src/ecc/codes/classical/extendedreedsolomonmds.jl @@ -1,8 +1,6 @@ -"""The family of Reed-Solomon codes, as discovered by Reed and Solomon in their 1960 paper [reed1960polynomial](@cite). +"""Extended Reed-Solomon Maximum Distance Separable `(ExtendedReedSolomonMDS)` codes are constructed from the Galois Field `GF(2ᵐ)`. These codes are extensions of the family of Reed-Solomon codes, as discovered by Reed and Solomon in their 1960 paper [reed1960polynomial](@cite). -Reed Solomon codes are maximum distance separable (MDS) codes and have the highest possible minimum Hamming distance. The codes have symbols from finite Galois fields `GF(pᵐ)` of degree `m`, where `p` is a prime number, with parameters `[[x - 1, k, x - k]]`. - -They are not binary codes but frequently are used with `x = 2ᵐ`, and so there is a mapping of residue classes of a primitive polynomial with binary coefficients and each element of `GF(2ᵐ)` is represented as a binary `m`-tuple. Denoting the `x` field elements as `0, α⁰, α¹, α²,... αˣ ⁻ ¹`, the shortened field parity-check matrix (`HF`) is given as follows: +These codes possess a code length `(n)` of `2ᵐ + 1` and are Maximum Distance Separable `(MDS)` codes with parameters `[[2ᵐ + 1, k, 2ᵐ⁺¹ − k]]`. These ExtendedReedSolomonMDS codes are not binary codes but frequently are used with `x = 2ᵐ`, and so there is a mapping of residue classes of a primitive polynomial with binary coefficients and each element of `GF(2ᵐ)` is represented as a binary `m`-tuple. Denoting the `x` field elements as `0, α⁰, α¹, α²,... αˣ ⁻ ¹`, the shortened field parity-check matrix (`HF`) is given as follows: ``` (α⁰)ʲ (α¹)ʲ (α²)ʲ ... (αˣ ⁻ ¹)ʲ @@ -12,21 +10,21 @@ They are not binary codes but frequently are used with `x = 2ᵐ`, and so there . . . ... . . . . ... . . . . ... . -(α⁰)ʲ ⁺ ˣ ⁻ ᵏ (α¹)ʲ ⁺ ˣ ⁻ ᵏ (α²)ʲ ⁺ ˣ ⁻ ᵏ ... (αˣ ⁻ ¹)ʲ ⁺ ˣ ⁻ ᵏ +(α⁰)ʲ ⁺ ˣ ⁻ ᵏ (α¹)ʲ ⁺ ˣ ⁻ ᵏ (α²)ʲ ⁺ ˣ ⁻ ᵏ ... (αˣ ⁻ ¹)ʲ ⁺ ˣ ⁻ ᵏ ``` -You might be interested in consulting [geisel1990tutorial](@cite), [wicker1999reed](@cite), [sklar2001reed](@cite), [berlekamp1978readable](@cite), [tomlinson2017error](@cite), [macwilliams1977theory](@cite), and [peterson1972error](@cite) as well. +You might be interested in consulting [tomlinson2017error](@cite), [macwilliams1977theory](@cite), [peterson1972error](@cite), [seroussi1986mds](@cite), [dur1987automorphism](@cite) and [Extending MDS Codes](https://www.unb.ca/faculty-staff/directory/_resources/pdf/sase/alderson/mds-codes.pdf) as well. -The ECC Zoo has an [entry for this family](https://errorcorrectionzoo.org/c/reed_solomon). +Extended RS codes may be constructed using any Galois Field `GF(x)`, resulting in parameters [[x + 1, k, x + 2 − k]] [macwilliams1977theory](@cite). The ECC Zoo has an [entry for Extended Generalized Reed-Solomon codes](https://errorcorrectionzoo.org/c/extended_reed_solomon). """ abstract type AbstractPolynomialCode <: ClassicalCode end -struct ReedSolomon <: AbstractPolynomialCode +struct ExtendedReedSolomonMDS <: AbstractPolynomialCode m::Int t::Int - function ReedSolomon(m, t) + function ExtendedReedSolomonMDS(m, t) if m < 3 || t < 0 || t >= 2 ^ (m - 1) throw(ArgumentError("Invalid parameters: m and t must be non-negative. Also, m > 3 and t < 2 ^ (m - 1) in order to obtain a valid code.")) end @@ -35,47 +33,11 @@ struct ReedSolomon <: AbstractPolynomialCode end """ -`generator_polynomial(ReedSolomon(m, t))` - -- `m`: The positive integer defining the degree of the finite (Galois) field, `GF(2ᵐ)`. -- `t`: The positive integer specifying the number of correctable errors. - -The generator polynomial for an RS code takes the following form: - -``` -g(X) = g₀ + g₁X¹ + g₂X² + ... + g₂ₜ₋₁X²ᵗ⁻¹ + X²ᵗ -``` - -where `X` is the indeterminate variable, `gᵢ` are the coefficients of the polynomial and `t` is the number of correctable symbol errors. - -We describe the generator polynomial in terms of its `2 * t = n - k` roots, as follows: - -``` -g(X) = (X - α¹)(X - α²)(X - α³) ... (X - α²ᵗ) -``` - -Degree and Parity Symbols: The degree of the generator polynomial is equal to `2 * t`, which is also the number of parity symbols added to the original data (`k` symbols) to create a codeword of length `n` `(n = k + 2 * t)`. - -Roots of the Generator Polynomial: The generator polynomial has `2 * t` distinct roots, designated as `α¹, α², ... , α²ᵗ`. These roots are chosen from a Finite Galois Field. Any power of α can be used as the starting root, not necessarily `α¹` itself. - -Fixed generator polynomial scheme vs variable generator polynomial scheme: Only in this construction scheme using fixed generator polynomial `g(x)`, RS codes are a subset of the Bose, Chaudhuri, and Hocquenghem (BCH) codes; hence, this relationship between the degree of the generator polynomial and the number of parity symbols holds, just as for BCH codes where degree of BCH generator polynomial, `degree(g(x)) == n - k`. Prior to 1963, RS codes employed a variable generator polynomial for encoding. This approach [peterson1972error](@cite) differed from the prevalent BCH scheme (used here), which utilizes a fixed generator polynomial. Consequently, these original RS codes weren't strictly categorized as BCH codes. Furthermore, depending on the chosen evaluation points, they might not even qualify as cyclic codes. -""" -function generator_polynomial(rs::ReedSolomon) - GF2ʳ, a = finite_field(2, rs.m, "a") - P, x = GF2ʳ[:x] - gx = x - a ^ 1 - for i in 2:2 * rs.t - gx *= (x - a ^ i) - end - return gx -end - -""" -`parity_checks(ReedSolomon(m, t))` +`parity_checks(ExtendedReedSolomonMDS(m, t))` - `m`: The positive integer defining the degree of the finite (Galois) field, `GF(2ᵐ)`. - `t`: The positive integer specifying the number of correctable errors. -This function applies Reed-Solomon codes for binary transmission using soft decisions (see section 7.3)[tomlinson2017error](@cite). For significant coding gain, code length is typically restricted to less than 200 bits. Modified Dorsch decoder [dorsch1974decoding](@cite) is recommended for near maximum likelihood decoding. +This function applies Extended Reed-Solomon Maximum Distance Separable `(ExtendedReedSolomonMDS)` codes for binary transmission using soft decisions (see section 7.3)[tomlinson2017error](@cite). For significant coding gain, code length is typically restricted to less than 200 bits. Modified Dorsch decoder [dorsch1974decoding](@cite) is recommended for near maximum likelihood decoding. Challenges of Standard RS Codes: While efficient as MDS codes, standard RS codes are not ideal for binary channels. As demonstrated in the results (see section 7.2)[tomlinson2017error](@cite), their performance suffers due to a mismatch between the code structure (symbol-based) and the channel (binary). A single bit error can lead to a symbol error, negating the code's benefits. @@ -106,7 +68,7 @@ Shortened MDS (`HF`) Matrix element expansion: 1. Row expansion: Each row of in the field parity-check matrix is replaced with an `m`-by-`m` field matrix defined over the base field `GF(2ᵐ)`. 2. Column expansion: Consequently, the elements in each column of expanded field parity-check matrix are converted to binary representations by substituting powers of a primitive element (`α`) in the Galois Field `GF(2ᵐ)` with their corresponding `m`-tuples over the Boolean Field `GF(2)`. """ -function parity_checks(rs::ReedSolomon) +function parity_checks(rs::ExtendedReedSolomonMDS) GF2ʳ, a = finite_field(2, rs.m, "a") s_symbols = 3 # 3-level quantization. x = 2 ^ rs.m + 1 - s_symbols @@ -154,5 +116,5 @@ function parity_checks(rs::ReedSolomon) return H end -code_n(rs::ReedSolomon) = (2 ^ rs.m + 1 - 3) * rs.m -code_k(rs::ReedSolomon) = (2 ^ rs.m - 1 - 2 * rs.t) * rs.m +code_n(rs::ExtendedReedSolomonMDS) = (2 ^ rs.m + 1 - 3) * rs.m +code_k(rs::ExtendedReedSolomonMDS) = (2 ^ rs.m - 1 - 2 * rs.t) * rs.m diff --git a/test/runtests.jl b/test/runtests.jl index 8ac01ff54..539019306 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -65,7 +65,7 @@ end @doset "ecc_gottesman" @doset "ecc_reedmuller" @doset "ecc_bch" -@doset "ecc_reedsolomon" +@doset "ecc_extendedreedsolomonmds" @doset "ecc_syndromes" @doset "ecc_throws" @doset "precompile" diff --git a/test/test_ecc_reedsolomon.jl b/test/test_ecc_extendedreedsolomonmds.jl similarity index 73% rename from test/test_ecc_reedsolomon.jl rename to test/test_ecc_extendedreedsolomonmds.jl index 4da8df9d8..18cc8bfa3 100644 --- a/test/test_ecc_reedsolomon.jl +++ b/test/test_ecc_extendedreedsolomonmds.jl @@ -4,7 +4,7 @@ using LinearAlgebra using Combinatorics using QuantumClifford using QuantumClifford.ECC -using QuantumClifford.ECC: AbstractECC, ReedSolomon, generator_polynomial +using QuantumClifford.ECC: AbstractECC, ExtendedReedSolomonMDS, generator_polynomial using Nemo: finite_field, GF, FqFieldElem, FqPolyRingElem, coeff, is_zero, degree, matrix include("utils_test_ecc.jl") @@ -13,50 +13,35 @@ include("utils_test_ecc.jl") - The designed distance for binary expanded parity check matrix remains same as symbol based parity check matrix. According to [macwilliams1977theory](@cite), changing the basis `j` can increase the designed distance `(dmin)` of the resulting binary code. """ -@testset "Testing designed distance of Shortened and Maximum Distance Separable (MDS) Reed-Solomon codes" begin +@testset "Testing designed distance of ExtendedReedSolomonMDS codes" begin m_cases = [3, 4, 5, 6, 7, 8] for m in m_cases for t in rand(1:m - 1, 2) s_symbols = 3 # Refer to chapter: 07, section: 03, pages: 172 to 175 [tomlinson2017error](@cite). k = (2 ^ m - 1 - 2 * t) * m d = 2 ^ (m + 1) - s_symbols - k - @test check_designed_distance(parity_checks(ReedSolomon(m, t)), m, t, d, 0, 0) == true + @test check_designed_distance(parity_checks(ExtendedReedSolomonMDS(m, t)), m, t, d, 0, 0) == true end end end -@testset "Testing Shortened and Maximum Distance Separable (MDS) Reed Solomon codes's properties" begin +@testset "Testing ExtendedReedSolomonMDS codes's properties" begin m_cases = [3, 4, 5, 6, 7, 8] for m in m_cases for t in rand(1:m - 1, 2) - mat = matrix(GF(2), parity_checks(ReedSolomon(m, t))) + mat = matrix(GF(2), parity_checks(ExtendedReedSolomonMDS(m, t))) computed_rank = rank(mat) s_symbols = 3 # Refer to chapter: 07, section: 03, pages: 172 to 175 [tomlinson2017error](@cite). k = (2 ^ m - 1 - 2 * t) * m n = (2 ^ m + 1 - s_symbols) * m @test computed_rank == n - k - n_gx = 2 ^ m - 1 - GF2ʳ, a = finite_field(2, m, "a") - GF2x, x = GF2ʳ[:x] - # Reed-Solomon code is cyclic as its generator polynomial, `g(x)` divides `xⁿ - 1`, so `mod (xⁿ - 1, g(x))` = 0. - @test mod(x ^ n_gx - 1, generator_polynomial(ReedSolomon(m, t))) == 0 end end - # Examples taken from pg. 18 of http://hscc.cs.nthu.edu.tw/~sheujp/lecture_note/rs.pdf. - GF2ʳ, a = finite_field(2, 3, "a") - P, x = GF2ʳ[:x] - @test generator_polynomial(ReedSolomon(3, 2)) == x ^ 4 + (a + 1) * x ^ 3 + x ^ 2 + a * x + a + 1 - - # Example taken from https://www.youtube.com/watch?v=dpxD8gwgbOc. - GF2ʳ, a = finite_field(2, 4, "a") - P, x = GF2ʳ[:x] - @test generator_polynomial(ReedSolomon(4, 2)) == x ^ 4 + a ^ 13 * x ^ 3 + a ^ 6 * x ^ 2 + a ^ 3 * x + a ^ 10 - # Example `(H₁₅₀₋₇₅`) taken from Eq. 7.9 of pg. 175 of [tomlinson2017error](@cite). - @test size(parity_checks(ReedSolomon(5, 8))) == (75, 150) + @test size(parity_checks(ExtendedReedSolomonMDS(5, 8))) == (75, 150) H = Matrix{Bool}(undef, 75, 150) - H = parity_checks(ReedSolomon(5, 8)) + H = parity_checks(ExtendedReedSolomonMDS(5, 8)) example₁₋₁ = [1 0 0 0 0 1 0 0 0 0 1 0 0 0 0; 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0; 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0; diff --git a/test/test_ecc_throws.jl b/test/test_ecc_throws.jl index ac5ba74a6..8e0473edc 100644 --- a/test/test_ecc_throws.jl +++ b/test/test_ecc_throws.jl @@ -8,6 +8,6 @@ using QuantumClifford.ECC: ReedMuller, BCH, ReedSolomon @test_throws ArgumentError BCH(2, 2) @test_throws ArgumentError BCH(3, 4) -@test_throws ArgumentError ReedSolomon(2, 1) -@test_throws ArgumentError ReedSolomon(3, 10) -@test_throws ArgumentError ReedSolomon(-2, 1) +@test_throws ArgumentError ExtendedReedSolomonMDS(2, 1) +@test_throws ArgumentError ExtendedReedSolomonMDS(3, 10) +@test_throws ArgumentError ExtendedReedSolomonMDS(-2, 1) From b1995d81dd7cbddb08f9dfe456d03a8d76717ffb Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Mon, 20 May 2024 23:32:40 +0500 Subject: [PATCH 62/70] setting up for review --- docs/src/references.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/docs/src/references.md b/docs/src/references.md index f2c91cffe..ffd2badb2 100644 --- a/docs/src/references.md +++ b/docs/src/references.md @@ -48,10 +48,6 @@ For classical code construction routines: - [bose1960further](@cite) - [error2024lin](@cite) - [reed1960polynomial](@cite) -- [geisel1990tutorial](@cite) -- [berlekamp1978readable](@cite) -- [wicker1999reed](@cite) -- [sklar2001reed](@cite) - [tomlinson2017error](@cite) - [macwilliams1977theory](@cite) - [peterson1972error](@cite) From 48b78c592aec1933ee9a4d00779df855a0eafd29 Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Mon, 20 May 2024 23:34:59 +0500 Subject: [PATCH 63/70] minor cleanup --- test/test_ecc_throws.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_ecc_throws.jl b/test/test_ecc_throws.jl index 8e0473edc..68cd16ee6 100644 --- a/test/test_ecc_throws.jl +++ b/test/test_ecc_throws.jl @@ -1,6 +1,6 @@ using Test using QuantumClifford -using QuantumClifford.ECC: ReedMuller, BCH, ReedSolomon +using QuantumClifford.ECC: ReedMuller, BCH, ExtendedReedSolomonMDS @test_throws ArgumentError ReedMuller(-1, 3) @test_throws ArgumentError ReedMuller(1, 0) From 95f0e7fd44ee4b535de321febd0015afb37ad26f Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Mon, 20 May 2024 23:41:00 +0500 Subject: [PATCH 64/70] skip changelog --- CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 94217f0a0..0232077d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,6 @@ - Gate errors are now conveniently supported by the various ECC benchmark setups in the `ECC` module. - Remove printing of spurious debug info from the PyBP decoder. - Significant improvements to the low-level circuit compiler (the sumtype compactifier), leading to faster Pauli frame simulation of noisy circuits. -- Adding classical Reed-Solomon code to the ECC module. ## v0.9.3 - 2024-04-10 From 05c1b21b52d077446a6dcae12b7a1f6585d25485 Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Tue, 21 May 2024 19:25:33 +0500 Subject: [PATCH 65/70] Significantly Improving Docstring --- docs/src/references.bib | 29 ++++++------------- docs/src/references.md | 3 +- .../codes/classical/extendedreedsolomonmds.jl | 8 ++--- 3 files changed, 14 insertions(+), 26 deletions(-) diff --git a/docs/src/references.bib b/docs/src/references.bib index ac2e37ea7..7df8cea8c 100644 --- a/docs/src/references.bib +++ b/docs/src/references.bib @@ -380,15 +380,15 @@ @book{error2024lin publisher={Pearson} } -@article{reed1960polynomial, - title={Polynomial codes over certain finite fields}, - author={Reed, Irving S and Solomon, Gustave}, - journal={Journal of the society for industrial and applied mathematics}, - volume={8}, - number={2}, - pages={300--304}, - year={1960}, - publisher={SIAM} +@article{dur1987automorphism, + title={The automorphism groups of Reed-Solomon codes}, + author={D{\"u}r, Arne}, + journal={Journal of Combinatorial Theory, Series A}, + volume={44}, + number={1}, + pages={69--82}, + year={1987}, + publisher={Elsevier} } @book{tomlinson2017error, @@ -434,14 +434,3 @@ @article{seroussi1986mds year={1986}, publisher={IEEE} } - -@article{dur1987automorphism, - title={The automorphism groups of Reed-Solomon codes}, - author={D{\"u}r, Arne}, - journal={Journal of Combinatorial Theory, Series A}, - volume={44}, - number={1}, - pages={69--82}, - year={1987}, - publisher={Elsevier} -} diff --git a/docs/src/references.md b/docs/src/references.md index ffd2badb2..3b9e8414a 100644 --- a/docs/src/references.md +++ b/docs/src/references.md @@ -47,13 +47,12 @@ For classical code construction routines: - [bose1960class](@cite) - [bose1960further](@cite) - [error2024lin](@cite) -- [reed1960polynomial](@cite) +- [dur1987automorphism](@cite) - [tomlinson2017error](@cite) - [macwilliams1977theory](@cite) - [peterson1972error](@cite) - [dorsch1974decoding](@cite) - [seroussi1986mds](@cite) -- [dur1987automorphism](@cite) # References diff --git a/src/ecc/codes/classical/extendedreedsolomonmds.jl b/src/ecc/codes/classical/extendedreedsolomonmds.jl index 1912e9bd4..50a6c1c09 100644 --- a/src/ecc/codes/classical/extendedreedsolomonmds.jl +++ b/src/ecc/codes/classical/extendedreedsolomonmds.jl @@ -1,6 +1,6 @@ -"""Extended Reed-Solomon Maximum Distance Separable `(ExtendedReedSolomonMDS)` codes are constructed from the Galois Field `GF(2ᵐ)`. These codes are extensions of the family of Reed-Solomon codes, as discovered by Reed and Solomon in their 1960 paper [reed1960polynomial](@cite). +"""The family of `[[2ᵐ + 1, k, 2ᵐ⁺¹ − k]]` augmented, extended Reed-Solomon Maximum Distance Separable `(ExtendedReedSolomonMDS)` codes are constructed from the Galois Field `GF(2ᵐ)`. Extended Reed-Solomon codes were first described by Arne Dür in his 1987 paper [dur1987automorphism](@cite). -These codes possess a code length `(n)` of `2ᵐ + 1` and are Maximum Distance Separable `(MDS)` codes with parameters `[[2ᵐ + 1, k, 2ᵐ⁺¹ − k]]`. These ExtendedReedSolomonMDS codes are not binary codes but frequently are used with `x = 2ᵐ`, and so there is a mapping of residue classes of a primitive polynomial with binary coefficients and each element of `GF(2ᵐ)` is represented as a binary `m`-tuple. Denoting the `x` field elements as `0, α⁰, α¹, α²,... αˣ ⁻ ¹`, the shortened field parity-check matrix (`HF`) is given as follows: +The `ExtendedReedSolomonMDS` codes possess a code length `(n)` of `2ᵐ + 1` and are Maximum Distance Separable `(MDS)` codes. Moreover, the general case is that augmented, extended RS codes may be constructed using any Galois Field `GF(x)` with parameters `[[x + 1, k, x + 2 − k ]]` [macwilliams1977theory](@cite). These codes are not binary codes but frequently are used with `x = 2ᵐ`, and so there is a mapping of residue classes of a primitive polynomial with binary coefficients and each element of `GF(2ᵐ)` is represented as a binary `m`-tuple. Denoting the `x` field elements as `0, α⁰, α¹, α²,... αˣ ⁻ ¹`, the shortened field parity-check matrix (`HF`) is given as follows: ``` (α⁰)ʲ (α¹)ʲ (α²)ʲ ... (αˣ ⁻ ¹)ʲ @@ -10,12 +10,12 @@ These codes possess a code length `(n)` of `2ᵐ + 1` and are Maximum Distance S . . . ... . . . . ... . . . . ... . -(α⁰)ʲ ⁺ ˣ ⁻ ᵏ (α¹)ʲ ⁺ ˣ ⁻ ᵏ (α²)ʲ ⁺ ˣ ⁻ ᵏ ... (αˣ ⁻ ¹)ʲ ⁺ ˣ ⁻ ᵏ +(α⁰)ʲ ⁺ ˣ ⁻ ᵏ (α¹)ʲ ⁺ ˣ ⁻ ᵏ (α²)ʲ ⁺ ˣ ⁻ ᵏ ... (αˣ ⁻ ¹)ʲ ⁺ ˣ ⁻ ᵏ ``` You might be interested in consulting [tomlinson2017error](@cite), [macwilliams1977theory](@cite), [peterson1972error](@cite), [seroussi1986mds](@cite), [dur1987automorphism](@cite) and [Extending MDS Codes](https://www.unb.ca/faculty-staff/directory/_resources/pdf/sase/alderson/mds-codes.pdf) as well. -Extended RS codes may be constructed using any Galois Field `GF(x)`, resulting in parameters [[x + 1, k, x + 2 − k]] [macwilliams1977theory](@cite). The ECC Zoo has an [entry for Extended Generalized Reed-Solomon codes](https://errorcorrectionzoo.org/c/extended_reed_solomon). +The ECC Zoo has an [entry for Extended Generalized Reed-Solomon codes](https://errorcorrectionzoo.org/c/extended_reed_solomon). """ abstract type AbstractPolynomialCode <: ClassicalCode end From 1a25aa57faa84b69b723bc450bfeb800077da90d Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Thu, 6 Jun 2024 12:54:25 +0500 Subject: [PATCH 66/70] [Feature]: classical ShortenedMDS codes to the ECC Module --- src/ecc/ECC.jl | 2 +- ...endedreedsolomonmds.jl => shortenedmds.jl} | 22 ++++++++----------- test/runtests.jl | 2 +- ...solomonmds.jl => test_ecc_shortenedmds.jl} | 14 ++++++------ test/test_ecc_throws.jl | 8 +++---- 5 files changed, 22 insertions(+), 26 deletions(-) rename src/ecc/codes/classical/{extendedreedsolomonmds.jl => shortenedmds.jl} (74%) rename test/{test_ecc_extendedreedsolomonmds.jl => test_ecc_shortenedmds.jl} (87%) diff --git a/src/ecc/ECC.jl b/src/ecc/ECC.jl index 608ba02b0..4dff0e878 100644 --- a/src/ecc/ECC.jl +++ b/src/ecc/ECC.jl @@ -356,5 +356,5 @@ include("codes/gottesman.jl") include("codes/surface.jl") include("codes/classical/reedmuller.jl") include("codes/classical/bch.jl") -include("codes/classical/extendedreedsolomonmds.jl") +include("codes/classical/shortenedmds.jl") end #module diff --git a/src/ecc/codes/classical/extendedreedsolomonmds.jl b/src/ecc/codes/classical/shortenedmds.jl similarity index 74% rename from src/ecc/codes/classical/extendedreedsolomonmds.jl rename to src/ecc/codes/classical/shortenedmds.jl index 50a6c1c09..6867d9a5a 100644 --- a/src/ecc/codes/classical/extendedreedsolomonmds.jl +++ b/src/ecc/codes/classical/shortenedmds.jl @@ -1,6 +1,6 @@ -"""The family of `[[2ᵐ + 1, k, 2ᵐ⁺¹ − k]]` augmented, extended Reed-Solomon Maximum Distance Separable `(ExtendedReedSolomonMDS)` codes are constructed from the Galois Field `GF(2ᵐ)`. Extended Reed-Solomon codes were first described by Arne Dür in his 1987 paper [dur1987automorphism](@cite). +"""The family of `[[2ᵐ + 1 - s, k, 2ᵐ ⁺ ¹ - s - k]]` Shortened Maximum Distance Separable `(ShortenedMDS)` codes are constructed from the `[[2ᵐ + 1, k, 2ᵐ ⁺ ¹ - k]]` Extended, Augmented Reed-Solomon codes from the corresponding first `x - 1` columns of latter's parity-check matrix, using `j = 0`, and setting `α₀, α₁, α₂, ..., αₓ ₋ ₁` to `α⁰, α¹, α², ..., αˣ ⁻ ¹` in the parity-check matrix. -The `ExtendedReedSolomonMDS` codes possess a code length `(n)` of `2ᵐ + 1` and are Maximum Distance Separable `(MDS)` codes. Moreover, the general case is that augmented, extended RS codes may be constructed using any Galois Field `GF(x)` with parameters `[[x + 1, k, x + 2 − k ]]` [macwilliams1977theory](@cite). These codes are not binary codes but frequently are used with `x = 2ᵐ`, and so there is a mapping of residue classes of a primitive polynomial with binary coefficients and each element of `GF(2ᵐ)` is represented as a binary `m`-tuple. Denoting the `x` field elements as `0, α⁰, α¹, α²,... αˣ ⁻ ¹`, the shortened field parity-check matrix (`HF`) is given as follows: +Denoting the `x` field elements as `0, α⁰, α¹, α²,... αˣ ⁻ ¹`, the shortened field parity-check matrix (`HF`) is given as follows: ``` (α⁰)ʲ (α¹)ʲ (α²)ʲ ... (αˣ ⁻ ¹)ʲ @@ -14,17 +14,15 @@ The `ExtendedReedSolomonMDS` codes possess a code length `(n)` of `2ᵐ + 1` and ``` You might be interested in consulting [tomlinson2017error](@cite), [macwilliams1977theory](@cite), [peterson1972error](@cite), [seroussi1986mds](@cite), [dur1987automorphism](@cite) and [Extending MDS Codes](https://www.unb.ca/faculty-staff/directory/_resources/pdf/sase/alderson/mds-codes.pdf) as well. - -The ECC Zoo has an [entry for Extended Generalized Reed-Solomon codes](https://errorcorrectionzoo.org/c/extended_reed_solomon). """ abstract type AbstractPolynomialCode <: ClassicalCode end -struct ExtendedReedSolomonMDS <: AbstractPolynomialCode +struct ShortenedMDS <: AbstractPolynomialCode m::Int t::Int - function ExtendedReedSolomonMDS(m, t) + function ShortenedMDS(m, t) if m < 3 || t < 0 || t >= 2 ^ (m - 1) throw(ArgumentError("Invalid parameters: m and t must be non-negative. Also, m > 3 and t < 2 ^ (m - 1) in order to obtain a valid code.")) end @@ -33,11 +31,11 @@ struct ExtendedReedSolomonMDS <: AbstractPolynomialCode end """ -`parity_checks(ExtendedReedSolomonMDS(m, t))` +`parity_checks(ShortenedMDS(m, t))` - `m`: The positive integer defining the degree of the finite (Galois) field, `GF(2ᵐ)`. - `t`: The positive integer specifying the number of correctable errors. -This function applies Extended Reed-Solomon Maximum Distance Separable `(ExtendedReedSolomonMDS)` codes for binary transmission using soft decisions (see section 7.3)[tomlinson2017error](@cite). For significant coding gain, code length is typically restricted to less than 200 bits. Modified Dorsch decoder [dorsch1974decoding](@cite) is recommended for near maximum likelihood decoding. +This function applies Extended Reed-Solomon Maximum Distance Separable `(ShortenedMDS)` codes for binary transmission using soft decisions (see section 7.3)[tomlinson2017error](@cite). For significant coding gain, code length is typically restricted to less than 200 bits. Modified Dorsch decoder [dorsch1974decoding](@cite) is recommended for near maximum likelihood decoding. Challenges of Standard RS Codes: While efficient as MDS codes, standard RS codes are not ideal for binary channels. As demonstrated in the results (see section 7.2)[tomlinson2017error](@cite), their performance suffers due to a mismatch between the code structure (symbol-based) and the channel (binary). A single bit error can lead to a symbol error, negating the code's benefits. @@ -62,13 +60,11 @@ The matrix has `x - k + 1` rows corresponding to the code's parity symbols. Any Shortened MDS Codes: Corresponding columns of the field parity-check matrix can be deleted to form a shortened `[[2ᵐ + 1 - s, k, 2ᵐ ⁺ ¹ - s - k]]` MDS code. This is an important property of MDS codes, particularly for their practical realisation in the form of augmented, extended RS codes because it enables efficient implementation in applications such as incremental redundancy systems, and network coding. The 3-level quantization of the received channel bits is utilized meaning 3 symbols are deleted. The Fig. 7.2 [tomlinson2017error](@cite) shows that with 3-level quantization, there is an improvement over the binary-transmission with hard decisions for Reed-Solomon coding. The designed distance for binary expanded parity check matrix remains same as symbol based parity check matrix. According to [macwilliams1977theory](@cite), changing the basis `j` can increase the designed distance `(dmin)` of the resulting binary code. -Cyclic Code Construction: Using the first `x - 1` columns of the field parity-check matrix, using `j = 0`, and setting `α₀, α₁, α₂, ..., αₓ ₋ ₁` to `α⁰, α¹, α², ..., αˣ ⁻ ¹` in the parity-check matrix are set equal to the powers of a primitive element α of the Galois Field `GF(x)`, a cyclic code can be constructed for efficient encoding and decoding. - Shortened MDS (`HF`) Matrix element expansion: 1. Row expansion: Each row of in the field parity-check matrix is replaced with an `m`-by-`m` field matrix defined over the base field `GF(2ᵐ)`. 2. Column expansion: Consequently, the elements in each column of expanded field parity-check matrix are converted to binary representations by substituting powers of a primitive element (`α`) in the Galois Field `GF(2ᵐ)` with their corresponding `m`-tuples over the Boolean Field `GF(2)`. """ -function parity_checks(rs::ExtendedReedSolomonMDS) +function parity_checks(rs::ShortenedMDS) GF2ʳ, a = finite_field(2, rs.m, "a") s_symbols = 3 # 3-level quantization. x = 2 ^ rs.m + 1 - s_symbols @@ -116,5 +112,5 @@ function parity_checks(rs::ExtendedReedSolomonMDS) return H end -code_n(rs::ExtendedReedSolomonMDS) = (2 ^ rs.m + 1 - 3) * rs.m -code_k(rs::ExtendedReedSolomonMDS) = (2 ^ rs.m - 1 - 2 * rs.t) * rs.m +code_n(rs::ShortenedMDS) = (2 ^ rs.m + 1 - 3) * rs.m +code_k(rs::ShortenedMDS) = (2 ^ rs.m - 1 - 2 * rs.t) * rs.m diff --git a/test/runtests.jl b/test/runtests.jl index 539019306..8981827d9 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -65,7 +65,7 @@ end @doset "ecc_gottesman" @doset "ecc_reedmuller" @doset "ecc_bch" -@doset "ecc_extendedreedsolomonmds" +@doset "ecc_shortenedmds" @doset "ecc_syndromes" @doset "ecc_throws" @doset "precompile" diff --git a/test/test_ecc_extendedreedsolomonmds.jl b/test/test_ecc_shortenedmds.jl similarity index 87% rename from test/test_ecc_extendedreedsolomonmds.jl rename to test/test_ecc_shortenedmds.jl index 18cc8bfa3..35a402dd6 100644 --- a/test/test_ecc_extendedreedsolomonmds.jl +++ b/test/test_ecc_shortenedmds.jl @@ -4,7 +4,7 @@ using LinearAlgebra using Combinatorics using QuantumClifford using QuantumClifford.ECC -using QuantumClifford.ECC: AbstractECC, ExtendedReedSolomonMDS, generator_polynomial +using QuantumClifford.ECC: AbstractECC, ShortenedMDS, generator_polynomial using Nemo: finite_field, GF, FqFieldElem, FqPolyRingElem, coeff, is_zero, degree, matrix include("utils_test_ecc.jl") @@ -13,23 +13,23 @@ include("utils_test_ecc.jl") - The designed distance for binary expanded parity check matrix remains same as symbol based parity check matrix. According to [macwilliams1977theory](@cite), changing the basis `j` can increase the designed distance `(dmin)` of the resulting binary code. """ -@testset "Testing designed distance of ExtendedReedSolomonMDS codes" begin +@testset "Testing designed distance of ShortenedMDS codes" begin m_cases = [3, 4, 5, 6, 7, 8] for m in m_cases for t in rand(1:m - 1, 2) s_symbols = 3 # Refer to chapter: 07, section: 03, pages: 172 to 175 [tomlinson2017error](@cite). k = (2 ^ m - 1 - 2 * t) * m d = 2 ^ (m + 1) - s_symbols - k - @test check_designed_distance(parity_checks(ExtendedReedSolomonMDS(m, t)), m, t, d, 0, 0) == true + @test check_designed_distance(parity_checks(ShortenedMDS(m, t)), m, t, d, 0, 0) == true end end end -@testset "Testing ExtendedReedSolomonMDS codes's properties" begin +@testset "Testing ShortenedMDS codes's properties" begin m_cases = [3, 4, 5, 6, 7, 8] for m in m_cases for t in rand(1:m - 1, 2) - mat = matrix(GF(2), parity_checks(ExtendedReedSolomonMDS(m, t))) + mat = matrix(GF(2), parity_checks(ShortenedMDS(m, t))) computed_rank = rank(mat) s_symbols = 3 # Refer to chapter: 07, section: 03, pages: 172 to 175 [tomlinson2017error](@cite). k = (2 ^ m - 1 - 2 * t) * m @@ -39,9 +39,9 @@ end end # Example `(H₁₅₀₋₇₅`) taken from Eq. 7.9 of pg. 175 of [tomlinson2017error](@cite). - @test size(parity_checks(ExtendedReedSolomonMDS(5, 8))) == (75, 150) + @test size(parity_checks(ShortenedMDS(5, 8))) == (75, 150) H = Matrix{Bool}(undef, 75, 150) - H = parity_checks(ExtendedReedSolomonMDS(5, 8)) + H = parity_checks(ShortenedMDS(5, 8)) example₁₋₁ = [1 0 0 0 0 1 0 0 0 0 1 0 0 0 0; 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0; 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0; diff --git a/test/test_ecc_throws.jl b/test/test_ecc_throws.jl index 68cd16ee6..7f7dcff7d 100644 --- a/test/test_ecc_throws.jl +++ b/test/test_ecc_throws.jl @@ -1,6 +1,6 @@ using Test using QuantumClifford -using QuantumClifford.ECC: ReedMuller, BCH, ExtendedReedSolomonMDS +using QuantumClifford.ECC: ReedMuller, BCH, ShortenedMDS @test_throws ArgumentError ReedMuller(-1, 3) @test_throws ArgumentError ReedMuller(1, 0) @@ -8,6 +8,6 @@ using QuantumClifford.ECC: ReedMuller, BCH, ExtendedReedSolomonMDS @test_throws ArgumentError BCH(2, 2) @test_throws ArgumentError BCH(3, 4) -@test_throws ArgumentError ExtendedReedSolomonMDS(2, 1) -@test_throws ArgumentError ExtendedReedSolomonMDS(3, 10) -@test_throws ArgumentError ExtendedReedSolomonMDS(-2, 1) +@test_throws ArgumentError ShortenedMDS(2, 1) +@test_throws ArgumentError ShortenedMDS(3, 10) +@test_throws ArgumentError ShortenedMDS(-2, 1) From 77548ab6cee54500947066e83babf9c878393f90 Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Sat, 29 Jun 2024 07:27:45 +0500 Subject: [PATCH 67/70] code review suggestions --- src/ecc/ECC.jl | 3 +- src/ecc/codes/classical/shortenedmds.jl | 40 +++++-------------------- test/test_ecc_bch.jl | 2 +- test/test_ecc_shortenedmds.jl | 3 +- 4 files changed, 11 insertions(+), 37 deletions(-) diff --git a/src/ecc/ECC.jl b/src/ecc/ECC.jl index 4dff0e878..159b8e390 100644 --- a/src/ecc/ECC.jl +++ b/src/ecc/ECC.jl @@ -8,8 +8,7 @@ using DocStringExtensions using Combinatorics: combinations using SparseArrays: sparse using Statistics: std -using Nemo: ZZ, residue_ring, matrix, finite_field, GF, minpoly, coeff, lcm, FqPolyRingElem, FqFieldElem, is_zero, degree, defining_polynomial, is_irreducible -using ILog2 +using Nemo: ZZ, residue_ring, matrix, finite_field, GF, minpoly, coeff, lcm, FqPolyRingElem, FqFieldElem, is_zero, degree, defining_polynomial, is_irreducible abstract type AbstractECC end diff --git a/src/ecc/codes/classical/shortenedmds.jl b/src/ecc/codes/classical/shortenedmds.jl index 6867d9a5a..844a32c74 100644 --- a/src/ecc/codes/classical/shortenedmds.jl +++ b/src/ecc/codes/classical/shortenedmds.jl @@ -1,4 +1,4 @@ -"""The family of `[[2ᵐ + 1 - s, k, 2ᵐ ⁺ ¹ - s - k]]` Shortened Maximum Distance Separable `(ShortenedMDS)` codes are constructed from the `[[2ᵐ + 1, k, 2ᵐ ⁺ ¹ - k]]` Extended, Augmented Reed-Solomon codes from the corresponding first `x - 1` columns of latter's parity-check matrix, using `j = 0`, and setting `α₀, α₁, α₂, ..., αₓ ₋ ₁` to `α⁰, α¹, α², ..., αˣ ⁻ ¹` in the parity-check matrix. +"""The family of `[2ᵐ + 1 - s, k, 2ᵐ ⁺ ¹ - s - k]` Shortened Maximum Distance Separable `(ShortenedMDS)` codes are constructed from the `[2ᵐ + 1, k, 2ᵐ ⁺ ¹ - k]` Extended, Augmented Reed-Solomon codes from the corresponding first `x - 1` columns of latter's parity-check matrix, using `j = 0`, and setting `α₀, α₁, α₂, ..., αₓ ₋ ₁` to `α⁰, α¹, α², ..., αˣ ⁻ ¹` in the parity-check matrix. Denoting the `x` field elements as `0, α⁰, α¹, α²,... αˣ ⁻ ¹`, the shortened field parity-check matrix (`HF`) is given as follows: @@ -10,12 +10,17 @@ Denoting the `x` field elements as `0, α⁰, α¹, α²,... αˣ ⁻ ¹`, the s . . . ... . . . . ... . . . . ... . -(α⁰)ʲ ⁺ ˣ ⁻ ᵏ (α¹)ʲ ⁺ ˣ ⁻ ᵏ (α²)ʲ ⁺ ˣ ⁻ ᵏ ... (αˣ ⁻ ¹)ʲ ⁺ ˣ ⁻ ᵏ +(α⁰)ʲ ⁺ ˣ ⁻ ᵏ (α¹)ʲ ⁺ ˣ ⁻ ᵏ (α²)ʲ ⁺ ˣ ⁻ ᵏ ... (αˣ ⁻ ¹)ʲ ⁺ ˣ ⁻ ᵏ ``` +For significant coding gain, code length is typically restricted to less than 200 bits. Modified Dorsch decoder [dorsch1974decoding](@cite) is recommended for near maximum likelihood decoding. + +Shortened MDS (`HF`) Matrix element expansion: + 1. Row expansion: Each row of in the field parity-check matrix is replaced with an `m`-by-`m` field matrix defined over the base field `GF(2ᵐ)`. + 2. Column expansion: Consequently, the elements in each column of expanded field parity-check matrix are converted to binary representations by substituting powers of a primitive element (`α`) in the Galois Field `GF(2ᵐ)` with their corresponding `m`-tuples over the Boolean Field `GF(2)`. + You might be interested in consulting [tomlinson2017error](@cite), [macwilliams1977theory](@cite), [peterson1972error](@cite), [seroussi1986mds](@cite), [dur1987automorphism](@cite) and [Extending MDS Codes](https://www.unb.ca/faculty-staff/directory/_resources/pdf/sase/alderson/mds-codes.pdf) as well. """ - abstract type AbstractPolynomialCode <: ClassicalCode end struct ShortenedMDS <: AbstractPolynomialCode @@ -34,35 +39,6 @@ end `parity_checks(ShortenedMDS(m, t))` - `m`: The positive integer defining the degree of the finite (Galois) field, `GF(2ᵐ)`. - `t`: The positive integer specifying the number of correctable errors. - -This function applies Extended Reed-Solomon Maximum Distance Separable `(ShortenedMDS)` codes for binary transmission using soft decisions (see section 7.3)[tomlinson2017error](@cite). For significant coding gain, code length is typically restricted to less than 200 bits. Modified Dorsch decoder [dorsch1974decoding](@cite) is recommended for near maximum likelihood decoding. - -Challenges of Standard RS Codes: While efficient as MDS codes, standard RS codes are not ideal for binary channels. As demonstrated in the results (see section 7.2)[tomlinson2017error](@cite), their performance suffers due to a mismatch between the code structure (symbol-based) and the channel (binary). A single bit error can lead to a symbol error, negating the code's benefits. - -Improved Binary Codes through Concatenation: This method enhances RS codes for binary channels through code concatenation. It adds a single overall binary parity check to each `m`-tuple representing a symbol. This approach transforms the original RS code `[[n, k, n - k - 1]]` into a new binary code with parameters `[[n[m + 1], k * m, 2[n - k -1]]]`. The resulting binary code boasts a minimum symbol weight of 2, effectively doubling the minimum Hamming distance compared to the original RS code. - -Augmented Extended RS Codes: Constructed from Galois Field `GF(2ᵐ)`. Length: `2ᵐ + 1` (Maximum Distance Separable (MDS) codes). Parameters: `[[2ᵐ + 1, k, 2ᵐ ⁺ ¹ - k]]`. Generalization: Applicable to any Galois Field `GF(x)` with parameters `[[x + 1, k, x + 2 - k]]`. - -Field Parity-Check Matrix Properties: - -``` -(α₀)ʲ (α₁)ʲ (α₂)ʲ ... (αₓ₋₂)ʲ 1 0 -(α₀)ʲ ⁺ ¹ (α₁)ʲ ⁺ ¹ (α₂)ʲ ⁺ ¹ ... (αₓ₋₂)ʲ ⁺ ¹ 0 0 -(α₀)ʲ ⁺ ² (α₁)ʲ ⁺ ² (α₂)ʲ ⁺ ² ... (αₓ₋₂)ʲ ⁺ ² 0 0 -(α₀)ʲ ⁺ ˣ ⁻ ᵏ ⁻ ¹ (α₁)ʲ ⁺ ˣ ⁻ ᵏ ⁻ ¹ (α₂)ʲ ⁺ ˣ ⁻ ᵏ ⁻ ¹ ... (αₓ₋₂)ʲ ⁺ ˣ ⁻ ᵏ ⁻ ¹ 0 0 - . . . ... . . . - . . . ... . . . - . . . ... . . . -(α₀)ʲ ⁺ ˣ ⁻ ᵏ (α₁)ʲ ⁺ ˣ ⁻ ᵏ (α₂)ʲ ⁺ ˣ ⁻ ᵏ ... (αₓ₋₂)ʲ ⁺ ˣ ⁻ ᵏ 0 1 -``` - -The matrix has `x - k + 1` rows corresponding to the code's parity symbols. Any `x - k + 1` columns form a Vandermonde matrix (non-singular). This ensures correction of up to `x - k + 1` symbol erasures in a codeword. We can re-arrange the columns of this matrix in any desired order. Any set of `s` symbols within a codeword can be designated as parity symbols and permanently removed. This important property leads to construction of Shortened MDS codes. - -Shortened MDS Codes: Corresponding columns of the field parity-check matrix can be deleted to form a shortened `[[2ᵐ + 1 - s, k, 2ᵐ ⁺ ¹ - s - k]]` MDS code. This is an important property of MDS codes, particularly for their practical realisation in the form of augmented, extended RS codes because it enables efficient implementation in applications such as incremental redundancy systems, and network coding. The 3-level quantization of the received channel bits is utilized meaning 3 symbols are deleted. The Fig. 7.2 [tomlinson2017error](@cite) shows that with 3-level quantization, there is an improvement over the binary-transmission with hard decisions for Reed-Solomon coding. The designed distance for binary expanded parity check matrix remains same as symbol based parity check matrix. According to [macwilliams1977theory](@cite), changing the basis `j` can increase the designed distance `(dmin)` of the resulting binary code. - -Shortened MDS (`HF`) Matrix element expansion: - 1. Row expansion: Each row of in the field parity-check matrix is replaced with an `m`-by-`m` field matrix defined over the base field `GF(2ᵐ)`. - 2. Column expansion: Consequently, the elements in each column of expanded field parity-check matrix are converted to binary representations by substituting powers of a primitive element (`α`) in the Galois Field `GF(2ᵐ)` with their corresponding `m`-tuples over the Boolean Field `GF(2)`. """ function parity_checks(rs::ShortenedMDS) GF2ʳ, a = finite_field(2, rs.m, "a") diff --git a/test/test_ecc_bch.jl b/test/test_ecc_bch.jl index f42a1d90c..b73ac7eec 100644 --- a/test/test_ecc_bch.jl +++ b/test/test_ecc_bch.jl @@ -20,7 +20,7 @@ include("utils_test_ecc.jl") end end end - + @testset "Testing properties of BCH codes" begin m_cases = [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] for m in m_cases diff --git a/test/test_ecc_shortenedmds.jl b/test/test_ecc_shortenedmds.jl index 35a402dd6..3a5c6481e 100644 --- a/test/test_ecc_shortenedmds.jl +++ b/test/test_ecc_shortenedmds.jl @@ -1,5 +1,4 @@ using Test -using ILog2 using LinearAlgebra using Combinatorics using QuantumClifford @@ -9,7 +8,7 @@ using Nemo: finite_field, GF, FqFieldElem, FqPolyRingElem, coeff, is_zero, degre include("utils_test_ecc.jl") """ -- Employing `3-level` quantization of the channel bits and erasing entire symbols if any of their constituent bits are erased can improve the performance of RS codes. Shortened Maximum Distance Separable (MDS) codes have the following parameters - code length `(n)`, codesize `(k)` and minimum Hamming distance `(d)` represented by [[n, k, d]] as follows: [[2 ^ (m) + 1 - s, k, 2 ^ (m + 1) - s - k]]. Thus, the designed minimum distance `d` is 2 ^ (m + 1) - s - k. Refer to chapter: 07, section: 03, pages: 172 to 175 [tomlinson2017error](@cite). +- Employing `3-level` quantization of the channel bits and erasing entire symbols if any of their constituent bits are erased can improve the performance of RS codes. Shortened Maximum Distance Separable (MDS) codes have the following parameters - code length `(n)`, codesize `(k)` and minimum Hamming distance `(d)` represented by [n, k, d] as follows: [2 ^ (m) + 1 - s, k, 2 ^ (m + 1) - s - k]. Thus, the designed minimum distance `d` is 2 ^ (m + 1) - s - k. Refer to chapter: 07, section: 03, pages: 172 to 175 [tomlinson2017error](@cite). - The designed distance for binary expanded parity check matrix remains same as symbol based parity check matrix. According to [macwilliams1977theory](@cite), changing the basis `j` can increase the designed distance `(dmin)` of the resulting binary code. """ From 228590e748689ee20ecbaefea457f143dfdc616a Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Sat, 29 Jun 2024 07:31:00 +0500 Subject: [PATCH 68/70] fix docs formatting --- docs/src/references.bib | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/src/references.bib b/docs/src/references.bib index 355dfa67f..e8309718e 100644 --- a/docs/src/references.bib +++ b/docs/src/references.bib @@ -385,7 +385,6 @@ @article{knill1996concatenated author={Knill, Emanuel and Laflamme, Raymond}, journal={arXiv preprint quant-ph/9608012}, year={1996} - } @article{dur1987automorphism, From b593646463e14ec3e03c070fd6b4b28ec35fdb55 Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Sat, 29 Jun 2024 07:33:43 +0500 Subject: [PATCH 69/70] fix rendering --- src/ecc/codes/classical/shortenedmds.jl | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/ecc/codes/classical/shortenedmds.jl b/src/ecc/codes/classical/shortenedmds.jl index 844a32c74..4fc5fa244 100644 --- a/src/ecc/codes/classical/shortenedmds.jl +++ b/src/ecc/codes/classical/shortenedmds.jl @@ -3,14 +3,14 @@ Denoting the `x` field elements as `0, α⁰, α¹, α²,... αˣ ⁻ ¹`, the shortened field parity-check matrix (`HF`) is given as follows: ``` -(α⁰)ʲ (α¹)ʲ (α²)ʲ ... (αˣ ⁻ ¹)ʲ -(α⁰)ʲ ⁺ ¹ (α¹)ʲ ⁺ ¹ (α²)ʲ ⁺ ¹ ... (αˣ ⁻ ¹)ʲ ⁺ ¹ -(α⁰)ʲ ⁺ ² (α¹)ʲ ⁺ ² (α²)ʲ ⁺ ² ... (αˣ ⁻ ¹)ʲ ⁺ ² -(α⁰)ʲ ⁺ ˣ ⁻ ᵏ ⁻ ¹ (α¹)ʲ ⁺ ˣ ⁻ ᵏ ⁻ ¹ (α²)ʲ ⁺ ˣ ⁻ ᵏ ⁻ ¹ ... (αˣ ⁻ ¹)ʲ ⁺ ˣ ⁻ ᵏ ⁻ ¹ - . . . ... . - . . . ... . - . . . ... . -(α⁰)ʲ ⁺ ˣ ⁻ ᵏ (α¹)ʲ ⁺ ˣ ⁻ ᵏ (α²)ʲ ⁺ ˣ ⁻ ᵏ ... (αˣ ⁻ ¹)ʲ ⁺ ˣ ⁻ ᵏ +(α⁰)ʲ (α¹)ʲ (α²)ʲ ... (αˣ ⁻ ¹)ʲ +(α⁰)ʲ ⁺ ¹ (α¹)ʲ ⁺ ¹ (α²)ʲ ⁺ ¹ ... (αˣ ⁻ ¹)ʲ ⁺ ¹ +(α⁰)ʲ ⁺ ² (α¹)ʲ ⁺ ² (α²)ʲ ⁺ ² ... (αˣ ⁻ ¹)ʲ ⁺ ² +(α⁰)ʲ ⁺ ˣ ⁻ ᵏ ⁻ ¹ (α¹)ʲ ⁺ ˣ ⁻ ᵏ ⁻ ¹ (α²)ʲ ⁺ ˣ ⁻ ᵏ ⁻ ¹ ... (αˣ ⁻ ¹)ʲ ⁺ ˣ ⁻ ᵏ ⁻ ¹ + . . . ... . + . . . ... . + . . . ... . +(α⁰)ʲ ⁺ ˣ ⁻ ᵏ (α¹)ʲ ⁺ ˣ ⁻ ᵏ (α²)ʲ ⁺ ˣ ⁻ ᵏ . ... (αˣ ⁻ ¹)ʲ ⁺ ˣ ⁻ ᵏ ``` For significant coding gain, code length is typically restricted to less than 200 bits. Modified Dorsch decoder [dorsch1974decoding](@cite) is recommended for near maximum likelihood decoding. From fe26c08ddb98e22a50cc0764fe21e0624b6d7d60 Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Sat, 29 Jun 2024 11:24:47 +0500 Subject: [PATCH 70/70] Cleanup --- src/ecc/codes/classical/shortenedmds.jl | 3 +- test/test_ecc_shortenedmds.jl | 114 ++++++++++++------------ test/utils_test_ecc.jl | 2 +- 3 files changed, 62 insertions(+), 57 deletions(-) diff --git a/src/ecc/codes/classical/shortenedmds.jl b/src/ecc/codes/classical/shortenedmds.jl index 4fc5fa244..238893db8 100644 --- a/src/ecc/codes/classical/shortenedmds.jl +++ b/src/ecc/codes/classical/shortenedmds.jl @@ -1,4 +1,4 @@ -"""The family of `[2ᵐ + 1 - s, k, 2ᵐ ⁺ ¹ - s - k]` Shortened Maximum Distance Separable `(ShortenedMDS)` codes are constructed from the `[2ᵐ + 1, k, 2ᵐ ⁺ ¹ - k]` Extended, Augmented Reed-Solomon codes from the corresponding first `x - 1` columns of latter's parity-check matrix, using `j = 0`, and setting `α₀, α₁, α₂, ..., αₓ ₋ ₁` to `α⁰, α¹, α², ..., αˣ ⁻ ¹` in the parity-check matrix. +"""The family of `[2ᵐ + 1 - 3, k, 2ᵐ ⁺ ¹ - 3 - k]` Shortened Maximum Distance Separable `(ShortenedMDS)` codes are constructed from the `[2ᵐ + 1, k, 2ᵐ ⁺ ¹ - k]` Extended, Augmented Reed-Solomon codes from the corresponding first `x - 1` columns of latter's parity-check matrix, using `j = 0`, and setting `α₀, α₁, α₂, ..., αₓ ₋ ₁` to `α⁰, α¹, α², ..., αˣ ⁻ ¹` in the parity-check matrix. Denoting the `x` field elements as `0, α⁰, α¹, α²,... αˣ ⁻ ¹`, the shortened field parity-check matrix (`HF`) is given as follows: @@ -89,4 +89,5 @@ function parity_checks(rs::ShortenedMDS) end code_n(rs::ShortenedMDS) = (2 ^ rs.m + 1 - 3) * rs.m + code_k(rs::ShortenedMDS) = (2 ^ rs.m - 1 - 2 * rs.t) * rs.m diff --git a/test/test_ecc_shortenedmds.jl b/test/test_ecc_shortenedmds.jl index 3a5c6481e..b53297a9b 100644 --- a/test/test_ecc_shortenedmds.jl +++ b/test/test_ecc_shortenedmds.jl @@ -7,8 +7,10 @@ using QuantumClifford.ECC: AbstractECC, ShortenedMDS, generator_polynomial using Nemo: finite_field, GF, FqFieldElem, FqPolyRingElem, coeff, is_zero, degree, matrix include("utils_test_ecc.jl") +@testset "Testing ShortenedMDS code" begin + """ -- Employing `3-level` quantization of the channel bits and erasing entire symbols if any of their constituent bits are erased can improve the performance of RS codes. Shortened Maximum Distance Separable (MDS) codes have the following parameters - code length `(n)`, codesize `(k)` and minimum Hamming distance `(d)` represented by [n, k, d] as follows: [2 ^ (m) + 1 - s, k, 2 ^ (m + 1) - s - k]. Thus, the designed minimum distance `d` is 2 ^ (m + 1) - s - k. Refer to chapter: 07, section: 03, pages: 172 to 175 [tomlinson2017error](@cite). +- Employing `3-level` quantization of the channel bits and erasing entire symbols if any of their constituent bits are erased can improve the performance of RS codes. Shortened Maximum Distance Separable (MDS) codes have the following parameters - code length `(n)`, codesize `(k)` and minimum Hamming distance `(d)` represented by [n, k, d] as follows: [2 ^ (m) + 1 - 3, k, 2 ^ (m + 1) - 3 - k]. Thus, the designed minimum distance `d` is 2 ^ (m + 1) - s - k. Refer to chapter: 07, section: 03, pages: 172 to 175 [tomlinson2017error](@cite). - The designed distance for binary expanded parity check matrix remains same as symbol based parity check matrix. According to [macwilliams1977theory](@cite), changing the basis `j` can increase the designed distance `(dmin)` of the resulting binary code. """ @@ -41,59 +43,61 @@ end @test size(parity_checks(ShortenedMDS(5, 8))) == (75, 150) H = Matrix{Bool}(undef, 75, 150) H = parity_checks(ShortenedMDS(5, 8)) - example₁₋₁ = [1 0 0 0 0 1 0 0 0 0 1 0 0 0 0; - 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0; - 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0; - 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0; - 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1; - 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0; - 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0; - 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1; - 0 0 0 1 0 0 0 0 0 1 1 0 1 0 0; - 0 0 0 0 1 1 0 1 0 0 0 1 0 1 0; - 1 0 0 0 0 0 0 1 0 0 0 0 0 0 1; - 0 1 0 0 0 0 0 0 1 0 1 0 1 0 0; - 0 0 1 0 0 0 0 0 0 1 0 1 0 1 0; - 0 0 0 1 0 1 0 1 0 0 0 0 1 0 1; - 0 0 0 0 1 0 1 0 1 0 1 0 1 1 0; - 1 0 0 0 0 0 0 0 1 0 0 1 0 1 0; - 0 1 0 0 0 0 0 0 0 1 0 0 1 0 1; - 0 0 1 0 0 1 0 1 0 0 1 0 1 1 0; - 0 0 0 1 0 0 1 0 1 0 0 1 0 1 1; - 0 0 0 0 1 0 0 1 0 1 1 0 0 0 1] - example₁₋₂ = [1 0 0 0 0 1 0 1 1 1 0 1 1 0 1; - 0 1 0 0 0 1 1 1 1 1 1 0 0 1 0; - 0 0 1 0 0 1 1 0 1 1 0 1 0 0 1; - 0 0 0 1 0 1 1 0 0 1 1 0 0 0 0; - 0 0 0 0 1 1 1 0 0 0 0 1 0 0 0] - example₁₋₃ = [1 0 0 0 0; - 0 1 0 0 0; - 0 0 1 0 0; - 0 0 0 1 0; - 0 0 0 0 1; - 1 0 0 1 0; - 0 1 0 0 1; - 1 0 0 0 0; - 0 1 0 0 0; - 0 0 1 0 0; - 1 1 0 1 0; - 0 1 1 0 1; - 1 0 0 1 0; - 0 1 0 0 1; - 1 0 0 0 0; - 1 0 0 1 1; - 1 1 1 0 1; - 1 1 0 1 0; - 0 1 1 0 1; - 1 0 0 1 0] - example₁₋₄ = [0 0 0 1 0; - 0 0 0 0 1; - 1 0 1 0 0; - 0 1 0 1 0; - 0 0 1 0 1] + H₁₋₁ = [1 0 0 0 0 1 0 0 0 0 1 0 0 0 0; + 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0; + 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0; + 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0; + 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1; + 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0; + 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0; + 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1; + 0 0 0 1 0 0 0 0 0 1 1 0 1 0 0; + 0 0 0 0 1 1 0 1 0 0 0 1 0 1 0; + 1 0 0 0 0 0 0 1 0 0 0 0 0 0 1; + 0 1 0 0 0 0 0 0 1 0 1 0 1 0 0; + 0 0 1 0 0 0 0 0 0 1 0 1 0 1 0; + 0 0 0 1 0 1 0 1 0 0 0 0 1 0 1; + 0 0 0 0 1 0 1 0 1 0 1 0 1 1 0; + 1 0 0 0 0 0 0 0 1 0 0 1 0 1 0; + 0 1 0 0 0 0 0 0 0 1 0 0 1 0 1; + 0 0 1 0 0 1 0 1 0 0 1 0 1 1 0; + 0 0 0 1 0 0 1 0 1 0 0 1 0 1 1; + 0 0 0 0 1 0 0 1 0 1 1 0 0 0 1] + H₁₋₂ = [1 0 0 0 0 1 0 1 1 1 0 1 1 0 1; + 0 1 0 0 0 1 1 1 1 1 1 0 0 1 0; + 0 0 1 0 0 1 1 0 1 1 0 1 0 0 1; + 0 0 0 1 0 1 1 0 0 1 1 0 0 0 0; + 0 0 0 0 1 1 1 0 0 0 0 1 0 0 0] + H₁₋₃ = [1 0 0 0 0; + 0 1 0 0 0; + 0 0 1 0 0; + 0 0 0 1 0; + 0 0 0 0 1; + 1 0 0 1 0; + 0 1 0 0 1; + 1 0 0 0 0; + 0 1 0 0 0; + 0 0 1 0 0; + 1 1 0 1 0; + 0 1 1 0 1; + 1 0 0 1 0; + 0 1 0 0 1; + 1 0 0 0 0; + 1 0 0 1 1; + 1 1 1 0 1; + 1 1 0 1 0; + 0 1 1 0 1; + 1 0 0 1 0] + H₁₋₄ = [0 0 0 1 0; + 0 0 0 0 1; + 1 0 1 0 0; + 0 1 0 1 0; + 0 0 1 0 1] - @test H[1:20, 1:15] == example₁₋₁ - @test H[71:75, 1:15] == example₁₋₂ - @test H[1:20, 146:150] == example₁₋₃ - @test H[71:75, 146:150] == example₁₋₄ + @test H[1:20, 1:15] == H₁₋₁ + @test H[71:75, 1:15] == H₁₋₂ + @test H[1:20, 146:150] == H₁₋₃ + @test H[71:75, 146:150] == H₁₋₄ end + +end \ No newline at end of file diff --git a/test/utils_test_ecc.jl b/test/utils_test_ecc.jl index 143f8da75..676e4cfb4 100644 --- a/test/utils_test_ecc.jl +++ b/test/utils_test_ecc.jl @@ -1,4 +1,4 @@ -"""The designed distance of a classical linear code with parameters `[[n, k, d]]`, where `n` represents the code length, `k` denotes the code dimension, and `d` signifies the minimum Hamming distance. For polynomial codes, `t` indicates the degree of the generator polynomial, and `m` represents the extension degree for the finite Galois field `GF(2ᵐ)`.""" +"""The designed distance of a classical linear code with parameters `[n, k, d]`, where `n` represents the code length, `k` denotes the code dimension, and `d` signifies the minimum Hamming distance. For polynomial codes, `t` indicates the degree of the generator polynomial, and `m` represents the extension degree for the finite Galois field `GF(2ᵐ)`.""" function check_designed_distance(matrix, m, t, d, n, k) n_cols = size(matrix, 2) for num_cols in 1:d