|
| 1 | +# Copyright (c) 2022 - 2024 Eric Sabo |
| 2 | +# All rights reserved. |
| 3 | +# |
| 4 | +# This source code is licensed under the BSD-style license found in the |
| 5 | +# LICENSE file in the root directory of this source tree. |
| 6 | + |
| 7 | +############################# |
| 8 | + # constructors |
| 9 | +############################# |
| 10 | + |
| 11 | +""" |
| 12 | + GeneralizedReedSolomonCode(k::Int, v::Vector{FqFieldElem}, γ::Vector{FqFieldElem}) |
| 13 | +
|
| 14 | +Return the dimension `k` Generalized Reed-Solomon code with scalars `v` and |
| 15 | +evaluation points `γ`. |
| 16 | +
|
| 17 | +# Notes |
| 18 | +* The vectors `v` and `γ` must have the same length and every element must be over the same field. |
| 19 | +* The elements of `v` need not be distinct but must be nonzero. |
| 20 | +* The elements of `γ` must be distinct. |
| 21 | +""" |
| 22 | +function GeneralizedReedSolomonCode(k::Int, v::Vector{FqFieldElem}, γ::Vector{FqFieldElem}) |
| 23 | + n = length(v) |
| 24 | + 1 <= k <= n || throw(DomainError("The dimension of the code must be between `1` and `n`.")) |
| 25 | + n == length(γ) || throw(DomainError("Lengths of scalars and evaluation points must be equal.")) |
| 26 | + F = parent(v[1]) |
| 27 | + 1 <= n <= Int(order(F)) || throw(DomainError("The length of the code must be between `1` and the order of the field.")) |
| 28 | + for (i, x) in enumerate(v) |
| 29 | + iszero(x) && throw(ArgumentError("The elements of `v` must be nonzero.")) |
| 30 | + parent(x) == F || throw(ArgumentError("The elements of `v` must be over the same field.")) |
| 31 | + parent(γ[i]) == F || throw(ArgumentError("The elements of `γ` must be over the same field as `v`.")) |
| 32 | + end |
| 33 | + length(unique(γ)) == n || throw(ArgumentError("The elements of `γ` must be distinct.")) |
| 34 | + |
| 35 | + G = zero_matrix(F, k, n) |
| 36 | + for c in 1:n |
| 37 | + for r in 1:k |
| 38 | + G[r, c] = v[c] * γ[c]^(r - 1) |
| 39 | + end |
| 40 | + end |
| 41 | + |
| 42 | + # evaluation points are the same for the parity check, but scalars are now |
| 43 | + # w_i = (v_i * \prod(γ_j - γ_i))^-1 |
| 44 | + # which follows from Lagrange interpolation |
| 45 | + w = [F(0) for _ in 1:n] |
| 46 | + for i in 1:n |
| 47 | + w[i] = (v[i] * prod(γ[j] - γ[i] for j in 1:n if j ≠ i))^-1 |
| 48 | + end |
| 49 | + |
| 50 | + H = zero_matrix(F, n - k, n) |
| 51 | + for c in 1:n |
| 52 | + for r in 1:n - k |
| 53 | + H[r, c] = w[c] * γ[c]^(r - 1) |
| 54 | + end |
| 55 | + end |
| 56 | + |
| 57 | + iszero(G * transpose(H)) || error("Calculation of dual scalars failed in constructor.") |
| 58 | + G_stand, H_stand, P, rnk = _standard_form(G) |
| 59 | + rnk == k || error("Computed rank not equal to desired input rank") |
| 60 | + d = n - k + 1 |
| 61 | + return GeneralizedReedSolomonCode(F, n, k, d, d, d, v, w, γ, G, H, |
| 62 | + G_stand, H_stand, P, missing) |
| 63 | +end |
| 64 | + |
| 65 | +# using notation of MacWilliams & Sloane, p. 340 |
| 66 | +""" |
| 67 | + GeneralizedReedSolomonCode(C::AbstractGoppaCode) |
| 68 | +
|
| 69 | +Return the generalized Reed-Solomon code associated with the Goppa code `C`. |
| 70 | +""" |
| 71 | +GeneralizedReedSolomonCode(C::AbstractGoppaCode) = GeneralizedReedSolomonCode(C.n - degree(C.g), [C.g(C.L[i]) * prod(C.L[j] - C.L[i] for j in 1:C.n if i ≠ j)^(-1) for i in 1:C.n], C.L) |
| 72 | + |
| 73 | +# doesn't have it's own struct |
| 74 | +""" |
| 75 | + AlternateCode(F::CTFieldTypes, k::Int, v::Vector{FqFieldElem}, γ::Vector{FqFieldElem}) |
| 76 | +
|
| 77 | +Return the alternate code as a subfield subcode of `GRS_k(v, γ)^⟂` over `F`. |
| 78 | +""" |
| 79 | +function AlternateCode(F::CTFieldTypes, k::Int, v::Vector{FqFieldElem}, |
| 80 | + γ::Vector{FqFieldElem}) |
| 81 | + |
| 82 | + E = parent(v[1]) |
| 83 | + flag, _ = is_subfield(F, E) |
| 84 | + flag || throw(ArgumentError("Given field is not a subfield of the base ring of the vectors")) |
| 85 | + |
| 86 | + # let this do the rest of the type checking |
| 87 | + GRS = GeneralizedReedSolomonCode(k, v, γ) |
| 88 | + GRS = dual(GRS) |
| 89 | + basis, _ = primitive_basis(E, F) |
| 90 | + C = subfield_subcode(GRS, F, basis) |
| 91 | + return AlternateCode(F, E, C.n, C.k, C.d, C.l_bound, C.u_bound, v, γ, C.G, C.H, C.G_stand, |
| 92 | + C.H_stand, C.P_stand, C.weight_enum) |
| 93 | +end |
| 94 | + |
| 95 | +""" |
| 96 | + AlternateCode(F::CTFieldTypes, C::GeneralizedReedSolomonCode) |
| 97 | +
|
| 98 | +Return the subfield subcode of `C` over `F`. |
| 99 | +""" |
| 100 | +function AlternateCode(F::CTFieldTypes, C::GeneralizedReedSolomonCode) |
| 101 | + flag, _ = is_subfield(F, C.F) |
| 102 | + flag || throw(ArgumentError("Given field is not a subfield of the base ring of the code")) |
| 103 | + |
| 104 | + basis, _ = primitive_basis(C.F, F) |
| 105 | + return subfield_subcode(C, F, basis) |
| 106 | +end |
| 107 | + |
| 108 | +""" |
| 109 | + GeneralizedReedSolomonCode(C::AbstractAlternateCode) |
| 110 | +
|
| 111 | +Return the generalized Reed-Solomon code associated with the alternate code `C`. |
| 112 | +""" |
| 113 | +GeneralizedReedSolomonCode(C::AbstractAlternateCode) = dual(GeneralizedReedSolomonCode(C.k, C.scalars, C.eval_pts)) |
| 114 | + |
| 115 | +""" |
| 116 | + GeneralizedSrivastavaCode(F::CTFieldTypes, a::Vector{T}, w::Vector{T}, z::Vector{T}, t::Int) where T <: CTFieldElem |
| 117 | +
|
| 118 | +Return the generalized Srivastava code over `F` given `a`, `w`, `z`, and `t`. |
| 119 | +
|
| 120 | +# Notes |
| 121 | +- These inputs are defined on page 357 of MacWilliams & Sloane |
| 122 | +""" |
| 123 | +function GeneralizedSrivastavaCode(F::CTFieldTypes, a::Vector{T}, w::Vector{T}, z::Vector{T}, |
| 124 | + t::Int) where T <: CTFieldElem |
| 125 | + |
| 126 | + is_empty(a) && throw(ArgumentError("The input vector `a` cannot be empty.")) |
| 127 | + is_empty(w) && throw(ArgumentError("The input vector `w` cannot be empty.")) |
| 128 | + is_empty(z) && throw(ArgumentError("The input vector `z` cannot be empty.")) |
| 129 | + is_positive(t) || throw(DomainError(t, "The parameter `t` must be positive")) |
| 130 | + n = length(a) |
| 131 | + n == length(z) || throw(ArgumentError("Vectors `a` and `z` must be the same length")) |
| 132 | + s = length(w) |
| 133 | + length(unique([a; w])) == n + s || throw(ArgumentError("Elements of `a` and `w` must be distinct")) |
| 134 | + any(iszero, z) && throw(DomainError(z, "Elements of `z` must be nonzero")) |
| 135 | + E = parent(a[1]) |
| 136 | + all(parent(pt) == E for pt in a) || throw(ArgumentError("All elements of the input vector `a` must be over the same base ring.")) |
| 137 | + all(parent(pt) == E for pt in w) || throw(ArgumentError("All elements of the input vector `w` must be over the same base ring as `a`.")) |
| 138 | + all(parent(pt) == E for pt in z) || throw(ArgumentError("All elements of the input vector `z` must be over the same base ring as `a`.")) |
| 139 | + flag, _ = is_subfield(F, E) |
| 140 | + flag || throw(ArgumentError("Input field is not a subfield of the base ring of the input veectors")) |
| 141 | + |
| 142 | + H = zero_matrix(E, s * t, n) |
| 143 | + for l in 1:s |
| 144 | + count = 1 |
| 145 | + for r in (l - 1) * s + 1:(l - 1) * s + t |
| 146 | + for c in 1:n |
| 147 | + H[r, c] = z[c] * (a[c] - w[l])^(-count) |
| 148 | + end |
| 149 | + count += 1 |
| 150 | + end |
| 151 | + end |
| 152 | + |
| 153 | + basis, _ = primitive_basis(E, F) |
| 154 | + if typeof(E) === typeof(F) |
| 155 | + H_exp = transpose(expand_matrix(transpose(H), F, basis)) |
| 156 | + else |
| 157 | + H_exp = change_base_ring(F, transpose(expand_matrix(transpose(H), GF(Int(order(F))), basis))) |
| 158 | + end |
| 159 | + C = LinearCode(H_exp, true) |
| 160 | + C2 = GeneralizedSrivastavaCode(F, E, C.n, C.k, C.d, C.l_bound, C.u_bound, a, w, z, t, C.G, C.H, |
| 161 | + C.G_stand, C.H_stand, C.P_stand, C.weight_enum) |
| 162 | + ismissing(C2.d) && set_distance_lower_bound!(C2, s * t + 1) |
| 163 | + |
| 164 | + return C2 |
| 165 | +end |
| 166 | + |
| 167 | +""" |
| 168 | + SrivastavaCode(F::CTFieldTypes, a::Vector{T}, w::Vector{T}, z::Vector{T}, t::Int) where T <: CTFieldElem |
| 169 | +
|
| 170 | +Return the Srivastava code over `F` given `a`, `w`, and `z`. |
| 171 | +
|
| 172 | +# Notes |
| 173 | +- These inputs are defined on page 357 of MacWilliams & Sloane |
| 174 | +""" |
| 175 | +SrivastavaCode(F::CTFieldTypes, a::Vector{T}, w::Vector{T}, z::Vector{T}) where T <: CTFieldElem = |
| 176 | + GeneralizedSrivastavaCode(F, a, w, z, 1) |
| 177 | + |
| 178 | +############################# |
| 179 | + # getter functions |
| 180 | +############################# |
| 181 | + |
| 182 | +""" |
| 183 | + scalars(C::GeneralizedReedSolomonCode) |
| 184 | +
|
| 185 | +Return the scalars `v` of the Generalized Reed-Solomon code `C`. |
| 186 | +""" |
| 187 | +scalars(C::GeneralizedReedSolomonCode) = C.scalars |
| 188 | + |
| 189 | +""" |
| 190 | + dual_scalars(C::GeneralizedReedSolomonCode) |
| 191 | +
|
| 192 | +Return the scalars of the dual of the Generalized Reed-Solomon code `C`. |
| 193 | +""" |
| 194 | +dual_scalars(C::GeneralizedReedSolomonCode) = C.dual_scalars |
| 195 | + |
| 196 | +""" |
| 197 | + evaluation_points(C::GeneralizedReedSolomonCode) |
| 198 | +
|
| 199 | +Return the evaluation points `γ` of the Generalized Reed-Solomon code `C`. |
| 200 | +""" |
| 201 | +evaluation_points(C::GeneralizedReedSolomonCode) = C.eval_pts |
| 202 | + |
| 203 | +############################# |
| 204 | + # setter functions |
| 205 | +############################# |
| 206 | + |
| 207 | +############################# |
| 208 | + # general functions |
| 209 | +############################# |
| 210 | + |
| 211 | +""" |
| 212 | + is_primitive(C::AbstractGeneralizedSrivastavaCode) |
| 213 | +
|
| 214 | +Return `true` if `C` is primitive |
| 215 | +""" |
| 216 | +is_primitive(C::AbstractGeneralizedSrivastavaCode) = C.n == Int(order(C.E)) - length(C.w) |
| 217 | + |
| 218 | +# TODO |
| 219 | +# write conversion function from Reed-Solomon code to GRS |
| 220 | +# generalized BCH codes |
0 commit comments