XSCREENSAVER / 3D PIPES

[readonly] markdown buffer

Reed–Solomon Erasure Coding Without the Magic

Jul 29, 2026 · 14 min read

Suppose I split some data across six drives. Three drives disappear. I can still recover the data.

Reed–Solomon does this without storing three complete copies. It turns the original numbers into extra facts. Any three surviving facts are enough to work backwards.

We will build a small version from beginning to end. Each section introduces one operation, shows it, and explains why it exists.

The assumed maths stops at UK GCSE level: substitution, brackets, multiplication, squares and simple equations. No A-level maths is assumed. Anything beyond that is built here, one small operation at a time, before its formal name appears.

1. Choose the answer we want back

Enter text or a number. The default is 42. Every later visual follows the same value.

traceview://reed-solomon/sourceinteractive
Step 1

Choose the exact value we must recover

character 14character 22
What just happened

The value to protect is “42”. It contains 2 characters.

Why we did it

We start with the answer we expect at the end. Every later step must preserve this exact value.

Next

Convert each character into the numbers a computer actually stores.

Choose a value. This exact text must survive the complete journey.

Nothing has been encoded yet. We have only written down the answer that recovery must produce.

2. Turn characters into numbers

Computers store text as numbers. UTF-8 is a standard lookup table: 4 maps to 52, and 2 maps to 50.

traceview://reed-solomon/bytesinteractive
Step 2

Replace each character with its UTF-8 number

Following input42
452
250
UTF-8 bytes = [52, 50]
What just happened

“42” is now the number list [52, 50].

Why we did it

The coding maths works on numbers. UTF-8 is a standard lookup that we can reverse later; it does not lose the original text.

Next

Split the number list into equally sized blocks.

See the UTF-8 number used for every character in your input.

This lookup is reversible. If we recover [52, 50], the same table takes us back to 42.

3. Work with three numbers at a time

Our toy protects blocks of three numbers. If the final block is short, zeroes fill its unused slots.

traceview://reed-solomon/blocksinteractive
Step 3

Put the bytes into three-number blocks

byte 152byte 250
block 1[52, 50, 0]
What just happened

The first working block is [52, 50, 0].

Why we did it

Our small code protects three numbers at a time. A short final block gets zeroes only so it still has three slots; the decoder removes that padding at the end.

Next

Before mixing those three numbers, practise the small wrap-around arithmetic the code uses.

Group the UTF-8 numbers into blocks of three and make any padding visible.

For 42, [52, 50] becomes [52, 50, 0]. The zero is packaging, not new data. We remember the original length so it can be removed later.

4. Keep answers inside one fixed range

The stored numbers must stay a predictable size. First use a tiny set, 0 to 16, so the whole idea fits on screen.

14 × 8 = 112, but 112 is outside that set. Count around the loop and it lands on 10. This is what 112 mod 17 = 10 means: keep the remainder after dividing by 17.

traceview://reed-solomon/fieldinteractive
Step 4 · small rehearsal

Keep every answer inside a fixed set of numbers

Answer10
14 × 8 = 112; 112 mod 17 = 10
Without wrapping112

The result can leave the 0–16 space and keep growing after every operation.

After mod 1710

The result is always one of the same 17 values, so it still fits one toy symbol.

012345678910111213141516
What just happened

14 × 8 became 10 after wrapping around at 17.

Why we did it

Wrapping keeps every result inside one fixed-size symbol instead of letting the numbers grow forever.

Next

Check that this wrapping arithmetic can also be undone.

Use a clock-like loop to see a large answer wrap back into the allowed range.

Our byte example uses a larger loop from 0 to 256. The idea is identical; the larger loop has room for every possible byte.

5. Check that the mixing can be undone

Wrapping is only useful if recovery can reverse the operations. If two starting numbers produce the same answer, we cannot know which one was original.

traceview://reed-solomon/reversibleinteractive
Step 5 · small rehearsal

Make sure the mixing has an undo button

All possible inputsDo any two inputs land on the same answer?
17/17 unique answers
001821637415566147581394101211312111321410151169
What just happened

Every input has a different answer. Multiplying by 15 reverses ×8.

Why we did it

For example, 14 × 8 mod 17 = 10, then 10 × 15 mod 17 = 14. No collision means the mixing can be undone.

Next

Use the same idea with 257 positions so every byte value fits.

Multiply every possible input and look for two inputs that collide.

Using a prime-sized loop—17 in the small visual and 257 in the byte example—means every non-zero multiplication rearranges the values without collisions. That gives it an undo. The formal name is a finite field; remembering “fixed range, no collisions, operations can be reversed” is enough.

6. Give the three source numbers short names

Call the first number a, the second b, and the third c.

traceview://reed-solomon/namesinteractive
Step 6

Give the three source numbers short names

Following input42[52, 50, 0]
source number 152a = 52
source number 250b = 50
source number 30c = 0
What just happened

52, 50, 0 are now called a, b and c.

Why we did it

The letters are only labels. They let us write one short rule while keeping all three original numbers visible.

Next

Give each named value a separate slot in that rule.

Give each source number a letter without changing its value.

For 42, this says a = 52, b = 50, and c = 0. The letters are labels, not extra maths.

7. Put the three numbers into one rule

Use:

p(x) = a + bx + cx²

p(x) just means “the answer this rule makes when we choose an x”. The three source numbers occupy three different slots.

traceview://reed-solomon/ruleinteractive
Step 7

Put the three named values into one reusable rule

Following input42[52, 50, 0]
source 152

becomes the plain number

source 250

becomes the amount of x

source 30

becomes the amount of x²

p(x) = 52 + 50x + 0x² (mod 257)
What just happened

The three source values now occupy the three adjustable slots in p(x): 52, 50 and 0.

Why we did it

Later, recovery only needs to rediscover these three slots. A rule gives us a repeatable way to create extra facts about them.

Next

Put one x value into the rule and calculate the first fact.

Place a, b and c into the plain, x and x-squared slots.

Why use a rule? We can put several different x values into it. Each produces a new fact about the same three source numbers.

8. Substitute one x value

Choose x = 2. Replace every x in the rule with 2.

traceview://reed-solomon/substituteinteractive
Step 8

Replace every x with the chosen number

Following input42[52, 50, 0]
p(2) = 52 + 50×2 + 0×2²
What just happened

p(2) = 52 + 50×2 + 0×2²

Why we did it

The same rule can answer many different x values. A different x will become a different stored fact.

Next

Calculate the square and the two multiplied terms.

Do only the substitution step and leave the arithmetic untouched.

This is the same substitution used in school algebra. The chosen x is also the label that tells us which calculation produced the answer.

9. Work out the multiplied parts

Now calculate , then b × 2, then c × 2².

traceview://reed-solomon/multiplyinteractive
Step 9

Do the square and multiplications

Following input42[52, 50, 0]
52 + 50×2 + 0×4 = 52 + 100 + 0
What just happened

52 + 50×2 + 0×4 = 52 + 100 + 0

Why we did it

All three source slots contribute to the answer, so this shard is not merely a copy of one source value.

Next

Add the three terms and wrap the answer.

Square and multiply without adding the terms yet.

Keeping this separate makes it clear that every source slot contributes to the stored answer.

10. Add, wrap, and store the pair

Add the three terms. Wrap the result into 0 to 256. Call the final answer y.

traceview://reed-solomon/storepointinteractive
Step 10

Add, then wrap into the 0–256 loop

Following input42[52, 50, 0]
52 + 100 + 0 = 152; 152 mod 257 = 152
Store the coordinate(2, 152)a + 2b + 4c = 152
What just happened

52 + 100 + 0 = 152; 152 mod 257 = 152

Why we did it

The stored pair (x=2, y=152) is one equation about the same three source values.

Next

Repeat the same three operations at other x positions.

Finish one calculation and store its x label beside its y answer.

For the default input, x = 2 produces (2, 152). The pair means “putting 2 into the rule produced 152”.

11. Repeat until there are three facts

Repeat Steps 8–10 with different x values. Every result becomes a different equation about the same a, b, and c.

traceview://reed-solomon/factsinteractive
Step 11

Collect one equation for each unknown value

Following input42[52, 50, 0]
Unknown values
a = ?b = ?c = ?
Different equations collected
x=1 gives: a + b + c = 102
1/3 facts
What just happened

1 different equation now describe a, b and c.

Why we did it

There are still three unknowns but only 1 fact, so more than one answer can fit.

Next

Calculate another point to add another independent equation.

Add the equations one at a time and compare their number with the three unknown slots.

One equation cannot tell us three missing numbers. Two still leave choices. Three different equations leave one set of values that makes all three true.

12. See why two facts still allow different answers

This is worth seeing rather than accepting.

traceview://reed-solomon/whyinteractive
Step 12

See why two points are ambiguous and three are not

Following input42[52, 50, 0]
Known(1, 102)(2, 152)
Candidate Ap(x) = 52 + 50x + 0x² (mod 257)
x=1102x=2152x=3202x=4252x=545x=695

Fits both known points.

Candidate Bp(x) = 54 + 47x + 1x² (mod 257)
x=1102x=2152x=3204x=41x=557x=6115

Fits both known points.

What just happened

Two different rules produce exactly the same first two stored points.

Why we did it

Two equations cannot solve three unknown values, so guessing would be unsafe.

Next

Adding more points raises the number of erasures we can survive; it does not make the original data larger.

Show two different rules that fit two facts, then use a third fact to reject one.

That is the central guarantee: three unknown source numbers need three different facts made by the same rule.

13. Make three replacement facts

We need three facts, but we calculate six by using x = 1 through x = 6.

traceview://reed-solomon/sparesinteractive
Step 13

Store six facts even though recovery needs only three

Following input42[52, 50, 0]
Minimum needed
x=1102stored
x=2152stored
x=3202stored

These three equations are enough to recover a, b and c.

Replacement facts
x=4252stored
x=545stored
x=695stored

These use new x values, so they can replace any missing equations above.

What just happened

The same three source values produced six different equations.

Why we did it

Recovery needs any three equations, not these particular first three. Storing six means any three may disappear.

Next

Erase shards and watch three survivors rebuild the source values.

Separate the three facts we need from the three extras that can replace them.

Recovery does not need the first three. It needs any three with different x labels. That is why the extra facts provide protection.

14. Erase some shards

Now lose facts without trying to recover anything yet.

traceview://reed-solomon/lossinteractive
Step 14

Erase shards without doing any recovery yet

Click a shard to mark it missing. Watch only the survivor count for now.

surviving facts3 / 3 needed
What just happened

3 shards are missing; 3 remain.

Why we did it

The source block contains three unknown numbers. We therefore need at least three surviving facts before recovery can even begin.

Next

Write the surviving coordinates back out as equations.

Erase and restore shards while watching the minimum survivor count.

Three survivors are enough for three unknown source numbers. Two survivors are not.

15. Write the surviving facts as equations

Each surviving pair gives an ordinary equation. For example, (3, 202) means:

a + 3b + 9c = 202

traceview://reed-solomon/survivorsinteractive
Step 15

Turn each surviving coordinate back into an equation

(1, 102)a + 1b + 1c = 102
(3, 202)a + 3b + 9c = 202
(5, 45)a + 5b + 25c = 45
What just happened

The three surviving coordinates are now three equations about a, b and c.

Why we did it

A coordinate is not an unexplained magic number. It records which x was used and the y answer produced by the rule.

Next

Build a small selector that can listen to one equation at a time.

Turn each surviving x-and-y pair back into an equation.

The next five sections show how the decoder combines those equations. This is the hardest part, so each section does one small job.

16. Plan a 1-or-0 switch

Start with the first survivor. We want a small rule that produces:

  • 1 at this survivor;
  • 0 at the other two.
traceview://reed-solomon/selectgoalinteractive
Step 16

Decide what one selector must keep

Following input42[52, 50, 0]
Survivors(1, 102)(3, 202)(5, 45)

Decide what this switch must do

at x=1: make 1at x=3: make 0at x=5: make 0

Multiplying by 1 keeps a number. Multiplying by 0 removes it.

What just happened

We want a switch that is 1 at x=1 and 0 at x=3 and x=5.

Why we did it

Multiplying the switch by 102 will keep 102 at its own position and add nothing at the other two.

Next

Create zeroes at the two points this selector must ignore.

Choose one survivor to keep and mark the other two to be ignored.

Why 1 and 0? Multiplying by 1 keeps a number. Multiplying by 0 removes it.

17. Make zeroes at the ignored positions

The bracket (x − 3) becomes zero when x = 3. Multiplying by a zero makes the whole result zero.

traceview://reed-solomon/selectzerosinteractive
Step 17

Force that selector to zero at the other points

Following input42[52, 50, 0]
Survivors(1, 102)(3, 202)(5, 45)

Make the switch zero at the other two positions

(x − 3)(x − 5)
x=3: (33)(35) = 0x=5: (53)(55) = 0
What just happened

The factors (x−3) and (x−5) force the switch to zero at the other two x positions.

Why we did it

If either factor is zero, their product is zero. This mutes both other survivors.

Next

Adjust the selector so its own point produces exactly one.

Use one bracket for each x position the switch must ignore.

Two brackets create two zeroes. The switch now ignores the other two survivors.

18. Make the kept position equal one

At its own x, the switch is not necessarily 1 yet. Use the reversible wrap-around multiplication from Step 5 to scale its answer to 1.

traceview://reed-solomon/selectoneinteractive
Step 18

Make the selector equal one at its own point

Following input42[52, 50, 0]
Survivors(1, 102)(3, 202)(5, 45)

Make the switch equal 1 at its own position

at x=1: (13)(15) = 8

We got 8, but we need 1. In our 0–256 number loop, 8 × 225 mod 257 = 1. Multiply the whole switch by 225.

L1(x) = 225(x−3)(x−5) mod 257
L(1) = 1L(3) = 0L(5) = 0
What just happened

At x=1, the two factors produce 8. Multiplying by 225 changes that result to 1 after wrapping.

Why we did it

Now the same switch is 1 at its own point and 0 at both other points: exactly the pattern we asked for.

Next

Multiply the selector by the stored y value.

Find the multiplier that changes the kept result to 1 without changing either zero.

The switch now gives the pattern [1, 0, 0] across the three survivor positions.

19. Put the stored y value into the switch

Multiply the switch by the survivor’s y value.

traceview://reed-solomon/selectscaleinteractive
Step 19

Put the survivor’s stored value into the selector

Following input42[52, 50, 0]
Survivors(1, 102)(3, 202)(5, 45)

Put this survivor's stored value into the switch

102 × L1(x)

At the three survivor positions: 102 × [1, 0, 0] = [102, 0, 0]

What just happened

At the survivor positions, 102 × [1, 0, 0] becomes [102, 0, 0].

Why we did it

The kept position now contains 102; the two ignored positions still contain zero.

Next

Expand the brackets so this piece becomes three slot numbers.

Scale the 1-or-0 pattern by the value stored in that survivor.

The pattern [1, 0, 0] becomes [y, 0, 0]. This restores one survivor without affecting the other two.

20. Turn one bracketed rule into three slot numbers

The previous visual produced a rule with brackets. We still need the three plain, x, and slot numbers hidden inside it.

Expand the brackets using ordinary school algebra:

(x − 3)(x − 5) = x² − 8x + 15

traceview://reed-solomon/selectexpandinteractive
Step 20

Turn the bracketed rule into three slot numbers

Following input42[52, 50, 0]
Survivors(1, 102)(3, 202)(5, 45)

Expand the brackets, then read the three slots

(x−3)(x−5) = x² − 8x + 15
plain slot102 × 225 × (15)

wrap at 257 → 127

x slot102 × 225 × (-8)

wrap at 257 → 155

x² slot102 × 225 × (1)

wrap at 257 → 77

What just happened

Expanding the brackets and collecting the plain, x and x² parts produces [127, 155, 77].

Why we did it

We need the three slot numbers because those are the original values the decoder is trying to rebuild.

Next

Repeat for the other survivors, then add their slot numbers.

Expand the brackets and calculate the plain, x and x-squared slots separately.

This is where each three-number piece comes from. It is not a new trick: the values are the plain, x, and slots after expanding, multiplying and wrapping.

21. Add the three restored pieces

Repeat Steps 16–20 for each survivor, then add their three sets of slot numbers.

traceview://reed-solomon/selectsuminteractive
Step 21

Add the three selector pieces

Following input42[52, 50, 0]
Survivors(1, 102)(3, 202)(5, 45)

Add the three pieces

[127, 155, 77] +[133, 46, 78] +[49, 106, 102]= [52, 50, 0]

p(x) = 52 + 50x + 0x² (mod 257)

What just happened

The three pieces add to [52, 50, 0], which means p(x) = 52 + 50x + 0x² (mod 257).

Why we did it

Each piece restores one survivor without changing the other two. Their sum therefore matches all three survivors at once.

Next

Read the three recovered slot numbers back as the original byte block.

Add the three pieces and reveal the recovered a, b and c slot values.

The result is the original three-number block. The formal name for this recovery method is Lagrange interpolation; the name is less important than the six operations above.

22. Turn the recovered numbers back into text

Remove any zero padding, then reverse the UTF-8 lookup from Step 2.

traceview://reed-solomon/decodeblockinteractive
Step 22

Turn the recovered numbers back into text

Recovered three slots[52, 50, 0]

These match the numbers placed in a, b and c earlier.

Remove end padding[52, 50]

The added zero only filled an unused slot.

UTF-8 lookup backwards42

The same number table from Step 2 returns the original characters.

What just happened

The first block [52, 50, 0] decodes to “42”.

Why we did it

Encoding never threw the original numbers away. Recovery rebuilt them, so reversing the UTF-8 lookup gives the same text.

Next

The complete input has now made the full round trip.

Remove the packaging zero and turn the recovered numbers back into characters.

For a longer input, the same process runs separately for every three-number block. The decoded pieces are then joined.

23. Missing and secretly wrong are different problems

An erasure means we know exactly which shard is unavailable. An error means a shard supplies a wrong value and pretends it is valid.

traceview://reed-solomon/capacityinteractive
Step 23

Choose the protection you are paying for

datadatadataextraextraextra
Known missing locations3 erasures

Any 3 of the 6 correct stored values are enough.

Unknown bad locations1 errors

Finding which stored values lied costs roughly twice as much protection.

What just happened

The 3 extra stored facts let any 3 known missing shards disappear while 3 useful facts remain.

Why we did it

When a missing position is known, recovery can ignore it immediately. A secretly wrong value must be found before it can be repaired.

Next

Real systems use checksums to identify a bad shard, then treat it as missing.

Change the number of original and extra stored values to compare erasure and error protection.

Known missing positions are easier: the decoder immediately uses the remaining facts. A hidden wrong value must first be located, which consumes more of the extra protection.

The complete automatic run

The final workbench repeats the complete journey using the same input as the detailed explainer.

It now has 24 stages. Each stage shows one operation for five seconds. Pause it or choose a numbered stage when you want more time.

traceview://reed-solomon/pipelineinteractive
Final workbench

Send your own value through the whole journey

input · step 1 of 24

Choose the exact text to protect

Original input42

Nothing has been encoded yet. This is the value every later step must preserve.

Why this step exists

This is the answer the final stage must return without changing a character.

What just happened

Stage 1 is showing one operation only. The next stage appears after five seconds.

Why we did it

Encoding and recovery are the same small ideas from the earlier toys, repeated once for every three-byte block.

Enter your own text, encode it into six shards, erase three, then recover the original value step by step.

This remains an educational code rather than a production storage format. Real implementations use byte-sized fields, fast arithmetic, many blocks and metadata that identifies every shard. The useful mental model stays the same: turn three source numbers into more than three facts, then use any three surviving facts to rebuild the source numbers.

Sources