Reed-Solomon encoding and decoding, and the two computational engines the decoders are built on: univariate root finding and computable linear algebra.
This page owns the decoding stack. It spans four subtrees that are easy to miss because none of them is named after coding theory:
CompPoly/Univariate/ReedSolomon/ encoding, and unique decoding (Gao)
CompPoly/Bivariate/GuruswamiSudan/ list decoding
CompPoly/Univariate/Roots/ univariate root finding
CompPoly/LinearAlgebra/ dense and polynomial matrices
The last two are general-purpose and useful on their own; they live outside
ReedSolomon/ and GuruswamiSudan/ for that reason. See
../../CompPoly/LinearAlgebra/README.md
for the matrix layer in detail.
A Reed-Solomon code of block length n and message length k has minimum
distance n - k + 1. That splits decoding into two regimes, and CompPoly
implements one algorithm for each.
| Unique decoding | List decoding | |
|---|---|---|
| Radius | up to (n - k) / 2 errors |
beyond it, up to the Johnson bound |
| Output | at most one message | a list of candidates |
| Algorithm here | Gao's key-equation decoder ([Gao02]) | Guruswami-Sudan ([GS99]) |
| Entry point | ReedSolomon.Gao.decode |
GuruswamiSudan.decode |
| Cost | one extended-Euclid run | interpolation plus root finding |
Use Gao unless you genuinely need to decode past half the minimum distance: it
is far cheaper, it returns a decisive answer, and its refusal carries
information (see decode_none_farness below). Reach for Guruswami-Sudan when
the application is proximity testing or soft decoding, where a candidate list is
the point.
Univariate/ReedSolomon.lean fixes
the code itself: Domain (an array of distinct evaluation points), messagePoly,
and encode, which evaluates the message polynomial on the domain. For
1 ≤ k < n ≤ #F that is an (n, k, n - k + 1) code.
ReedSolomon/NTTEncode.lean
then identifies the forward NTT with that encoder. Over the domain induced
by a radix-2 NTT domain — the node array #[ω⁰, ω¹, …, ω^(n-1)], nodup because
powers of a primitive n-th root below n are pairwise distinct — the forward
transform of a message polynomial's coefficients is the codeword:
forwardImpl_eq_encodetiesNTT.Forward.forwardImpl(natural order,O(n log n)) to the definitionalReedSolomon.encode, exactly, for every message of length at most the domain size. No padding is needed, becausemessagePolytrims and so the degree boundk ≤ D.nsuffices.nttCodeword_eq_encodeis the same statement for the length-indexed packaging.
So the fast encoder needs no separate correctness argument: it is the specification, transported.
| Layer | File | Owns |
|---|---|---|
| Decoder | ReedSolomon/GaoDecoder.lean |
nodalPoly, receivedInterpolant, partialGcd, decode |
| Correctness | ReedSolomon/GaoCorrectness.lean |
decode_sound, decode_eq_some, decode_eq_none_iff, decode_none_farness |
The algorithm interpolates the received word, then runs a partial extended
Euclid against the nodal polynomial and stops at the degree threshold; the
message falls out of the resulting Bézout relation. decode returns
Option (CPolynomial F).
The correctness layer is stronger than plain soundness, and the extra results are the reason to prefer this decoder:
decode_sound— a returned polynomial really is within the decoding radius.decode_eq_some/decode_unique— completeness and uniqueness inside the radius.decode_eq_none_iff— an iff, so refusal is characterized, not merely allowed.decode_none_farness— refusal is a certificate that the received word is far from every codeword. A verifier can use a failed decode as positive evidence, which is what proximity testing needs.
Supporting uniqueness machinery (bezout_solutions_cross_mul, error locators,
Hamming distance) lives in the same correctness file, sectioned by role.
The 40-file GuruswamiSudan/ subtree follows the interpolation-and-root-finding
decomposition of [GS99]: fit a bivariate Q(X, Y) vanishing to prescribed
multiplicity at every received point, then recover every Y = f(X) root of Q
with deg f < k. Each candidate is then checked against the received word.
The important structural fact: the core is backend-parametric. Interpolation
and root finding are each supplied as a context carrying both the operation and
the contract the correctness proofs consume. Core.lean and
CoreCorrectness.lean never mention a concrete algorithm, so a new backend costs
a context instance and inherits every theorem.
| Layer | File | Owns |
|---|---|---|
| Contexts | GuruswamiSudan/Context.lean |
GSInterpParams, LinearKernelContext, GSInterpContext, FieldRootContext, GSRootContext, ValidInterpolationWitness, DistinctXCoordinates |
| Core | GuruswamiSudan/Core.lean |
gsCore, backend-parametric |
| Core correctness | GuruswamiSudan/CoreCorrectness.lean |
gsCore_sound, gsCore_complete_of_interpolate, gsCore_complete_of_roots_all_valid_witnesses |
| Candidate filtering | Filter.lean, FilterCorrectness.lean |
gsFilteredCore_sound, mem_gsFilteredCore_iff, gsFilteredCore_complete_of_enough_matches |
| Concrete instances | Implementations.lean |
named dense / Lee-O'Sullivan / Roth-Ruckenstein combinations with specialized correctness theorems |
| Executable API | Executable.lean |
GSReceivedWord, GSExecParams, GSParamSelector, decodeWithParams, decode |
| Shared helpers | Polynomial.lean, PolynomialCorrectness.lean, Util.lean |
polynomial operations used by both kernels |
Both produce a valid witness in the sense of ValidInterpolationWitness; they
differ in how the constrained linear system is solved.
| Backend | Files | When to use |
|---|---|---|
| Dense | Interpolation/Dense/{Algorithm,Correctness}.lean |
Small parameters. Builds the constraint matrix explicitly and calls the dense kernel solver. Simple, and the easiest to reason about. |
| Lee-O'Sullivan | Interpolation/LeeOSullivan/ ([LOS06]) |
Larger parameters. Works from a Gröbner-basis perspective: build a module basis, then shift-reduce it with Mulders-Storjohann. leeOSullivanInterpolate_sound and leeOSullivanInterpolate_complete, with the argument split across nine files under Correctness/. |
Interpolation/Basic.lean holds the constraints and normalized-witness helpers
shared by both, and Interpolation/Correctness.lean the shared results
(interpolationWitnessIsValidBool_iff, lowMessageDegreeInterpolation_sound).
Both find the Y-roots of the interpolated Q that are polynomials of bounded
degree, and both come with soundness and completeness.
| Backend | Files | Character |
|---|---|---|
| Roth-Ruckenstein | Root/RothRuckenstein/ ([RR00]) |
Coefficient-by-coefficient recursion; the classical choice. rothRuckensteinRootsYDegreeLt_sound / _complete. |
| Alekhnovich | Root/Alekhnovich/ ([Ale05]) |
Divide-and-conquer over polynomial Diophantine equations; better asymptotics. alekhnovichRootsYDegreeLt_sound, alekhnovichRootPrefixesWithFuel_complete. |
Shared infrastructure: Root/Common/ (helpers for bounded bivariate root
backends), Root/ShiftedSubstitution/ (substituting Y = f(X) + X^t Y, the step
both recursions are built from), and Root/FieldRoots/ — the univariate
field-root dependency, behind an explicit FieldRootContext so it can be
replaced for large concrete fields. Root/FieldRoots/FiniteField.lean is the
generic instance and Root/FieldRoots/KoalaBear.lean a concrete one.
That context is where this subtree meets Univariate/Roots/.
CompPoly/Univariate/Roots/ is a
general-purpose root finder, used by the Guruswami-Sudan root search but not
specific to it.
| File | Owns |
|---|---|
Context.lean |
FiniteFieldContext, LinearFactorProductSplitter, IsLinearFactor and the candidate predicates |
Backend.lean |
rootsInFiniteFieldWith, rootsInFiniteField — the pipeline entry points |
Splitter.lean |
represented-linear-factor helpers and xPowModWith |
Extraction.lean |
candidate extraction, validation, and deduplication |
RootProduct.lean |
the product of linear factors over a root set |
Correctness.lean |
monicNormalize_root_iff, gcdMonic_root_iff_left_right, and the divisibility transport lemmas |
SmoothSubgroup/ |
subgroup-refinement splitting ([MOV92]) for fields whose multiplicative group admits a smooth schedule |
The pipeline consumes a LinearFactorProductSplitter; SmoothSubgroup/ supplies
a contract-bearing smooth context plus an adapter to that interface. A field with
no smooth refinement schedule needs a different splitter — that is the open work
here. Benchmarked as univariate-roots-finite-field-*.
- Encoding, or tying a transform to
ReedSolomon.encode:ReedSolomon/NTTEncode.lean - Unique decoding, or using decode failure as a proximity certificate:
ReedSolomon/GaoCorrectness.lean - Changing what the GS decoder does without touching proofs: add a context
instance in
GuruswamiSudan/Context.leanand register it inImplementations.lean - A new interpolation or root-finding algorithm: implement against the context
interface;
Core/CoreCorrectnessshould need no change - Root finding over a new field: supply a
LinearFactorProductSplitter, or aFieldRootContextif the caller is the GS root search - Matrix-level work underneath any of this:
../../CompPoly/LinearAlgebra/README.md
- Gao:
GaoDecoder→GaoCorrectness(soundness → completeness → farness) - Guruswami-Sudan:
Context→Core→CoreCorrectness→ one interpolation backend → one root backend →Filter→Executable - Root finding:
Context→Backend→Extraction→Correctness, thenSmoothSubgroup/if the field admits it
Read Context.lean first for GS. The contexts are the interface the rest of the
subtree is written against, and the correctness theorems are unreadable without
knowing which contracts they assume.
- No Berlekamp-Welch. Gao's decoder covers the same unique-decoding regime, so this is only worth adding as a cross-check, or if a downstream specification asks for it by name.
- No FRI or polynomial-commitment integration.
decode_none_farnessis the hook a proximity test would use, but nothing consumes it yet. - Root finding needs a smooth multiplicative group for the only splitter that currently exists.
- List-size bounds are not formalized. Soundness and completeness are proved relative to the supplied parameters; the Johnson-bound analysis that says how many candidates can survive is not.
- [Gao, S., A New Algorithm for Decoding Reed-Solomon Codes][Gao02]
- [Guruswami, V., and Sudan, M., Improved decoding of Reed-Solomon and algebraic-geometry codes][GS99]
- [Lee, K., and O'Sullivan, M. E., List decoding of Reed-Solomon codes from a Groebner basis perspective][LOS06]
- [Roth, R. M., and Ruckenstein, G., Efficient decoding of Reed-Solomon codes beyond half the minimum distance][RR00]
- [Alekhnovich, M., Linear Diophantine Equations Over Polynomials and Soft Decoding of Reed-Solomon Codes][Ale05]
- [Menezes, A. J., van Oorschot, P. C., and Vanstone, S. A., Subgroup Refinement Algorithms for Root Finding in GF(q)][MOV92]
BibTeX entries for these keys are in
../../blueprint/src/references.bib.