Skip to content

Commit

Permalink
README.md - Filling out links
Browse files Browse the repository at this point in the history
  • Loading branch information
geky committed Oct 31, 2024
1 parent 212c7f2 commit ebafec4
Showing 1 changed file with 93 additions and 40 deletions.
133 changes: 93 additions & 40 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,22 +88,21 @@ $ make test -j
Before we get into how the algorithm works, a couple words of warning:

1. I'm not a mathematician! Some of the definitions here are a bit
handwavey, and I'm skipping over the history of [BCH][BCH],
[PGZ][PGZ], [Euclidean methods][Euclidean], etc. I'd encourage you to
also explore [Wikipedia][wikipedia] and other relevant articles to
learn more.
handwavey, and I'm skipping over the history of [BCH][w-bch] codes,
[PGZ][w-pgz], [Euclidean methods][w-euclidean], etc. I'd encourage you
to also explore [Wikipedia][w-rs] and other relevant articles to learn
more.

My goal is to explain, to the best of my (limited) knowledge, how to
implement Reed-Solomon codes, and how/why they work.

2. The following math relies heavily on [finite-fields][finite-fields]
(sometimes called [Galois-fields][finite-fields]) and the related
theory.
2. The following math relies heavily on [finite-fields][w-gf] (sometimes
called Galois-fields) and the related theory.

If you're not familiar with finite-fields, they are an abstraction we
can make over finite numbers (bytes for [GF(256)][gf256], bits for
[GF(2)][gf2]) that let us do most of math without worrying about pesky
things like integer overflow.
can make over finite numbers (bytes for [GF(256)][w-gf256], bits for
[GF(2)][w-gf2]) that let us do most of math without worrying about
pesky things like integer overflow.

But there's not enough space here to fully explain how they work, so
I'd suggest reading some of the above articles first.
Expand All @@ -126,9 +125,9 @@ polynomial", giving us a [systematic code][w-systematic-code].

However, two important differences:

1. Instead of using a binary polynomial in [GF(2)][gf2], we use a
polynomial in a higher-order [finite-field][finite-field], usually
[GF(256)][gf256] because operating on bytes is convenient.
1. Instead of using a binary polynomial in [GF(2)][w-gf2], we use a
polynomial in a higher-order [finite-field][w-gf], usually
[GF(256)][w-gf256] because operating on bytes is convenient.

2. We intentionally construct the polynomial to tell us information about
any errors that may occur.
Expand Down Expand Up @@ -158,8 +157,9 @@ points at $g^i$ where $i < n$ like so:
</p>
We could choose any arbitrary set of fixed points, but usually we choose
$g^i$ where $g$ is a [generator][generator] in GF(256), since it provides
a convenient mapping of integers to unique non-zero elements in GF(256).
$g^i$ where $g$ is a [generator][w-generator] in GF(256), since it
provides a convenient mapping of integers to unique non-zero elements in
GF(256).

Note that for any fixed point $g^i$:

Expand Down Expand Up @@ -435,10 +435,10 @@ syndromes to solve for $e$ errors at unknown locations.
Ok that's the theory, but solving this system of equations efficiently is
still quite difficult.

Enter [Berlekamp-Massey][berlekamp-massey].
Enter [Berlekamp-Massey][w-bm].

A key observation by Massey is that solving for $\Lambda(x)$ is
equivalent to constructing an LFSR that generates the sequence
equivalent to constructing an [LFSR][w-lfsr] that generates the sequence
$S_e, S_{e+1}, \dots, S_{n-1}$ given the initial state
$S_0, S_1, \dots, S_{e-1}$:

Expand All @@ -454,7 +454,7 @@ $S_0, S_1, \dots, S_{e-1}$:

Pretty wild huh.

We can describe such an LFSR with a [recurrence relation][recurrence-relation]
We can describe such an LFSR with a [recurrence relation][w-recurrence-relation]
that might look a bit familiar:

<p align="center">
Expand Down Expand Up @@ -632,8 +632,8 @@ This is all implemented in [ramrsbd_find_l][ramrsbd_find_l].

#### Solving binary LFSRs for fun

Taking a step away from GF(256) for a moment, let's look at a simpler
LFSR in GF(2), aka binary.
Taking a step away from [GF(256)][w-gf256] for a moment, let's look at a
simpler LFSR in [GF(2)][w-gf2], aka binary.

Consider this binary sequence generated by a minimal LFSR that I know and
you don't :)
Expand Down Expand Up @@ -886,10 +886,10 @@ know $X_j$ is the location of an error:
</p>
Wikipedia and other resources often mention an optimization called
[Chien's search][chiens-search] being applied here, but from reading up
on the algorithm it seems to only be useful for hardware implementations.
In software Chien's search doesn't actually improve our runtime over
brute force with Horner's method and log tables ( $O(ne)$ vs $O(ne)$ ).
[Chien's search][w-chien] being applied here, but from reading up on the
algorithm it seems to only be useful for hardware implementations. In
software Chien's search doesn't actually improve our runtime over brute
force with Horner's method and log tables ( $O(ne)$ vs $O(ne)$ ).

### Finding the error magnitudes

Expand Down Expand Up @@ -921,7 +921,7 @@ and $e$ unknowns, which we can, in theory, solve for:

But again, solving this system of equations is easier said than done.

Enter [Forney's algorithm][forneys-algorithm].
Enter [Forney's algorithm][w-forney].

Assuming we know an error-locator $X_j$, the following formula will spit
out an error-magnitude $Y_j$:
Expand Down Expand Up @@ -953,7 +953,7 @@ our syndromes are a polynomial now):
>
</p>
And $\Lambda'(x)$, the [formal derivative][formal-derivative] of the
And $\Lambda'(x)$, the [formal derivative][w-formal-derivative] of the
error-locator, can be calculated like so:

<p align="center">
Expand Down Expand Up @@ -1000,7 +1000,7 @@ $S_i = \sum_{k \in E} Y_k X_k^i x^i$:
>
</p>
The sum on the right turns out to be a [geometric series][geometric-series]:
The sum on the right turns out to be a [geometric series][w-geometric-series]:

<p align="center">
<img
Expand Down Expand Up @@ -1090,7 +1090,7 @@ $X_j$, which we _do_ know and can in theory remove with more math.
#### The formal derivative of the error-locator polynomial

But Forney has one last trick up his sleeve: The
[formal derivative][formal-derivative] of the error-locator polynomial,
[formal derivative][w-formal-derivative] of the error-locator polynomial,
$\Lambda'(x)$.

What the heck is a formal derivative?
Expand Down Expand Up @@ -1124,7 +1124,7 @@ addition is xor in our field, this just has the effect of canceling out
every other term.

Quite a few properties of derivatives still hold in finite-fields. Of
particular interest to us is the [product rule][product-rule]:
particular interest to us is the [product rule][w-product-rule]:

<p align="center">
<img
Expand Down Expand Up @@ -1324,7 +1324,7 @@ noting:
Division with an implicit 1 is implemented in
[ramrsbd_gf_p_divmod1][ramrsbd_gf_p_divmod1], which has the extra
benefit of being able to skip the normalization step during
[synthetic division][synthetic division], so that's nice.
[synthetic division][w-synthetic-division], so that's nice.

2. Store the generator polynomial in ROM.

Expand Down Expand Up @@ -1416,7 +1416,7 @@ noting:

This sort of fused derivative evaluation is implemented in
[ramrsbd_gf_p_deval][ramrsbd_gf_p_deval] via a modified
[Horner's method][horners-method].
[Horner's method][w-horner].

Unfortunately, we still need at least 3 buffers for Berlekamp-Massey
( $S_i$, $\Lambda(i)$, and $C(i)$ ), so this doesn't actually save us
Expand Down Expand Up @@ -1467,19 +1467,19 @@ And some caveats:
for GF(256) is fine, but 128 KiBs of tables for GF(2^16)? Not so
much...

1. If you have [carryless-multiplication][clmul] hardware available,
1. If you have [carryless-multiplication][w-clmul] hardware available,
GF(2^n) multiplication can be implemented efficiently by combining
multiplication and [Barret reduction][barret-reduction].
multiplication and [Barret reduction][w-barret-reduction].

Division can then be implemented on top of multiplication by
leveraging the fact that $a^{2^n-2} = a^{-1}$ for any element $a$
in GF(2^n). [Binary exponentiation][binary-exponentiation] can make
this somewhat efficient.
in GF(2^n). [Binary exponentiation][w-binary-exponentiation] can
make this somewhat efficient.

2. In the same way GF(256) is defined as an
[extension field][extension-field] of GF(2), we can define GF(2^16)
as an extension field of GF(256), where each element is a 2 byte
polynomial containing digits in GF(256).
[extension field][w-extension-field] of GF(2), we can define
GF(2^16) as an extension field of GF(256), where each element is a
2 byte polynomial containing digits in GF(256).

This can be convenient if you already need GF(256) tables for other
parts of the codebase.
Expand Down Expand Up @@ -1593,12 +1593,65 @@ And some caveats:
- [Gill, J. - EE387 Notes #7][gill-notes7]
- [Truong, T. K., Hsu, I. S., Eastman, W. L., Reed, I. S. - A Simplified Procedure for Correcting Both Errors and Erasures of a Reed-Solomon Code Using the Euclidean Algorithm][truong-spcbeerscuea]

- [Wikipedia - Reed Solomon][wikipedia-rs]
- [Wikiversity - Reed Solomon for coders][wikiversity-rs]

- [Wikipedia - Reed Solomon][w-rs]
- [Wikipedia - Berlekamp-Massey algorithm][w-bm]
- [Wikipedia - Forney Algorithm][w-forney]

- [Wikipedia - BCH Code][w-bch]
- [Wikipedia - Finite field arithmetic][w-gf]
- [Wikipedia - GF(2)][w-gf2]
- [Wikipedia - Systematic Code][w-systematic-code]
- [Wikipedia - Primitive element (finite field)][w-generator]
- [Wikipedia - Linear-feedback shift register (LFSR)][w-lfsr]
- [Wikipedia - Recurrence Relation][w-recurrence-relation]
- [Wikipedia - Chien search][w-chien]
- [Wikipedia - Formal derivative][w-formal-derivative]
- [Wikipedia - Geometric series][w-geometric-series]
- [Wikipedia - Product rule][w-product-rule]
- [Wikipedia - Synthetic division][w-synthetic-division]
- [Wikipedia - Horner's method][w-horner]
- [Wikipedia - Carry-less product][w-clmul]
- [Wikipedia - Barret reduction][w-barret-reduction]
- [Wikipedia - Exponentiation by squaring][w-binary-exponentiation]
- [Wikipedia - Field extension][w-extension-field]

[massey-srsbchd]: http://crypto.stanford.edu/~mironov/cs359/massey.pdf
[gill-notes7]: https://web.archive.org/web/20140630172526/http://web.stanford.edu/class/ee387/handouts/notes7.pdf
[truong-spcbeerscuea]: https://ntrs.nasa.gov/api/citations/19880003316/downloads/19880003316.pdf
[wikipedia-rs]: https://en.wikipedia.org/wiki/Reed%E2%80%93Solomon_error_correction

[wikiversity-rs]: https://en.wikiversity.org/wiki/Reed%E2%80%93Solomon_codes_for_coders

[w-rs]: https://en.wikipedia.org/wiki/Reed%E2%80%93Solomon_error_correction
[w-bm]: https://en.wikipedia.org/wiki/Berlekamp%E2%80%93Massey_algorithm
[w-forney]: https://en.wikipedia.org/wiki/Forney_algorithm

[w-bch]: https://en.wikipedia.org/wiki/BCH_code
[w-pgz]: https://en.wikipedia.org/wiki/Reed%E2%80%93Solomon_error_correction#Peterson%E2%80%93Gorenstein%E2%80%93Zierler_decoder
[w-euclidean]: https://en.wikipedia.org/wiki/Reed%E2%80%93Solomon_error_correction#Euclidean_decoder
[w-gf]: https://en.wikipedia.org/wiki/Finite_field_arithmetic
[w-gf2]: https://en.wikipedia.org/wiki/GF(2)
[w-gf256]: https://en.wikipedia.org/wiki/Finite_field_arithmetic#Effective_polynomial_representation
[w-systematic-code]: https://en.wikipedia.org/wiki/Systematic_code
[w-generator]: https://en.wikipedia.org/wiki/Primitive_element_(finite_field)
[w-lfsr]: https://en.wikipedia.org/wiki/Linear-feedback_shift_register
[w-recurrence-relation]: https://en.wikipedia.org/wiki/Recurrence_relation
[w-chien]: https://en.wikipedia.org/wiki/Chien_search
[w-formal-derivative]: https://en.wikipedia.org/wiki/Formal_derivative
[w-geometric-series]: https://en.wikipedia.org/wiki/Geometric_series
[w-product-rule]: https://en.wikipedia.org/wiki/Product_rule
[w-synthetic-division]: https://en.wikipedia.org/wiki/Synthetic_division
[w-horner]: https://en.wikipedia.org/wiki/Horner%27s_method
[w-clmul]: https://en.wikipedia.org/wiki/Carry-less_product
[w-barret-reduction]: https://en.wikipedia.org/wiki/Barrett_reduction
[w-binary-exponentiation]: https://en.wikipedia.org/wiki/Exponentiation_by_squaring
[w-extension-field]: https://en.wikipedia.org/wiki/Field_extension

[littlefs]: https://github.com/littlefs-project/littlefs
[ramcrc32bd]: https://github.com/geky/ramcrc32bd

[bm-lfsr-solver.py]: bm-lfsr-solver.py
[bm-lfsr256-solver.py]: bm-lfsr256-solver.py
[rs-poly.py]: rs-poly.py

0 comments on commit ebafec4

Please sign in to comment.