Skip to content

Commit 4339de2

Browse files
authored
Merge branch 'dev' into doctests
2 parents f9a7d6c + ed3e65d commit 4339de2

28 files changed

+2436
-496
lines changed

docs/src/references.bib

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,3 +222,22 @@ @article{ostrev2024classical
222222
year={2024},
223223
publisher={Verein zur F{\"o}rderung des Open Access Publizierens in den Quantenwissenschaften}
224224
}
225+
226+
@book{kreher1999combinatorial,
227+
title={Combinatorial algorithms: generation, enumeration, and search},
228+
author={Kreher, Donald L and Stinson, Douglas R},
229+
publisher={CRC Press},
230+
pages={329},
231+
year={1999},
232+
}
233+
234+
@article{bitner1976efficient,
235+
title={Efficient generation of the binary reflected Gray code and its applications},
236+
author={Bitner, James R and Ehrlich, Gideon and Reingold, Edward M},
237+
journal={Communications of the ACM},
238+
volume={19},
239+
number={9},
240+
pages={517--521},
241+
year={1976},
242+
publisher={ACM New York, NY, USA}
243+
}

src/Classical/GRS_alternate.jl

Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
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

src/Classical/Gabidulin.jl

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
# Copyright (c) 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+
# TODO currently untested and have no unit tests
12+
13+
"""
14+
GeneralizedGabidulinCode(F::CTFieldTypes, eval_pts::Vector{CTFieldElem}, k::Int, s::Int; parity::Bool = false)
15+
16+
Return the vector representation of the dimension `k` generalized Gabidulin code given the
17+
evaluation points `eval_pts` with respect to the subfield `F` of the base ring of `eval_pts`.
18+
19+
# Notes
20+
- Distances are reported with respect to the Hamming metric.
21+
"""
22+
function GeneralizedGabidulinCode(F::CTFieldTypes, eval_pts::Vector{CTFieldElem}, k::Int, s::Int; parity::Bool = false)
23+
24+
is_empty(eval_pts) && throw(ArgumentError("The input vector `eval_pts` cannot be empty."))
25+
is_positive(s) || throw(DomainError(s, "The parameter `s` must be positive."))
26+
E = parent(eval_pts[1])
27+
all(parent(pt) == E for pt in eval_pts) || throw(ArgumentError("All evaluation points must be over the same base ring."))
28+
flag, m = is_extension_field(E, F)
29+
flag || throw(ArgumentError("The input field is not a subfield of the base ring of the evaluation points."))
30+
n = length(eval_pts)
31+
n m || throw(ArgumentError("The number of evaluation points must be less than or equal to the degree of the field extension."))
32+
0 < k n || throw(DomainError(k, "The code dimenion must be `0 < k ≤ n`."))
33+
q = Int(order(F))
34+
35+
B = zero_matrix(E, n, n)
36+
for r in 1:n
37+
for c in 1:n
38+
B[r, c] = eval_pts[c]^(q^(n - 1))
39+
end
40+
end
41+
iszero(det(B)) || throw(ArgumentError("The evaluation points must be linearly independent."))
42+
43+
G = zero_matrix(E, k, n)
44+
for r in 1:k
45+
for c in 1:n
46+
G[r, c] = eval_pts[c]^(q^(s * (r - 1)))
47+
end
48+
end
49+
50+
return LinearCode(G, parity)
51+
# reaches Singleton bound for the rank metric: d_R = n - k + 1
52+
end
53+
54+
"""
55+
GabidulinCode(F::CTFieldTypes, eval_pts::Vector{CTFieldElem}, k::Int; parity::Bool = false)
56+
57+
Return the vector representation of the dimension `k` Gabidulin code given the evaluation points
58+
`eval_pts` with respect to the subfield `F` of the base ring of `eval_pts`.
59+
60+
# Notes
61+
- Distances are reported with respect to the Hamming metric.
62+
"""
63+
GabidulinCode(F::CTFieldTypes, eval_pts::Vector{CTFieldElem}, k::Int; parity::Bool = false) =
64+
GeneralizedGabidulinCode(F, eval_pts, k, 1, parity = parity)
65+
66+
# TODO the dual is also a Gabidulin code, need to figure out those eval points based on these
67+
# but that would require making a type for this named code
68+
# TODO are these MDS or just in rank metric?

0 commit comments

Comments
 (0)