Distance, Detection and Correction
November 14, 202650 min readbeginner
Minimum distance decides what a code can do. The chapter proves what a distance of d detects and corrects, with and without erasures, then works through single parity, ISBN and Luhn check digits, rectangular parity and Gray codes.
The previous chapter, Capacity and Shannon's Theorem, closed on a random code of 16 codewords of 12 bits in which two pairs of codewords differed in only 2 positions, so the code barely beat sending each message bit three times. The coding theorem proves that good codes exist but builds none, and a random draw leaves to chance the property that matters most, the distance between codewords. This chapter makes that distance the design target.
Channels, Signals and Likelihoods built the binary symmetric channel , which flips each bit independently with probability , and the binary erasure channel, which loses a bit openly instead of flipping it, and Capacity and Shannon's Theorem measured how many bits per use such channels carry.
The chapter defines the distance between two words, pictures every word of bits as a corner of a cube, and proves from the smallest distance between codewords how many errors a code detects, how many it corrects, and how many errors and erasures it handles together. The same counting then prices the checks in daily use, single parity, the ISBN and Luhn check digits and rectangular parity, and the chapter ends with the Gray code, which uses a distance of one on purpose.
Every number in the chapter is recomputed by ch08_distance_detection_and_correction.py in the python/ folder of the companion repository ecc-book-lab, and the charts are drawn by ch08_charts.py in the same folder.
01.Distance and Weight
Take and and compare them position by position from the left. They disagree in positions 2, 3 and 5, so three single-bit flips turn one into the other, and no fewer will do, since each disagreeing position must be flipped at least once. XOR, written , gives 1 where two bits differ and 0 where they agree, so marks the disagreements in one step, as Figure 1 shows.
Distance is never negative, it is zero only for equal words, and it is symmetric. The fourth property of a distance, the triangle inequality, rests on a lemma that uses the bitwise AND, written , which is 1 only where both words hold a 1. For the example, .
On the example the right side is , the weight of .
Proof. Let count the positions where both words hold a 1, and and the positions where only or only does. Then , and . The XOR is 1 exactly in the positions where one word holds a 1, so .
Proof. Let and . XOR can be regrouped freely, like addition, and a word XORed with itself is all zeros, so . By Equation 1 and Equation 2,
since a weight is never negative.
Equality holds when is all zeros, so that no flip on the way from to is undone on the way to . With , and the inequality reads , and the detour costs two extra flips.
Errors fit the same picture. Write what the channel does as an error pattern , a word with a 1 wherever a bit flipped. A sent codeword arrives as , at distance from , so the received word lies exactly as far from what was sent as the number of errors.
02.Minimum Distance
The four words , , and form a small code, called in this chapter. Table 1 lists all six pairs of its codewords.
Table 1. Every pair of codewords of , with the XOR that marks their differences and its weight
| First codeword | Second codeword | XOR | Distance |
|---|---|---|---|
| 00000 | 01101 | 01101 | 3 |
| 00000 | 10110 | 10110 | 3 |
| 00000 | 11011 | 11011 | 4 |
| 01101 | 10110 | 11011 | 4 |
| 01101 | 11011 | 10110 | 3 |
| 10110 | 11011 | 01101 | 3 |
Source: reproduced by ch08_distance_detection_and_correction.py.
No two codewords are fewer than 3 flips apart, and that single number turns out to decide what the code can detect and correct.
is a code of rate . For scale, the four 2-bit words have , the even-weight 3-bit words , , and have , and the repetition code of The Repetition Code, with codewords and , has . Checking every pair takes comparisons, but every XOR in the table is itself a codeword of , and that gives a shortcut.
Proof. Such a code contains the all-zero word , since . For different codewords and , the distance is the weight of a nonzero codeword. Conversely, every nonzero codeword has weight , a distance between two codewords. The two lists hold the same numbers, so they have the same smallest value.
For the nonzero weights are 3, 3 and 4, so follows from three weights instead of six distances. Codes closed under XOR are the subject of the Part Linear Block Codes.
The random code of the previous chapter shows what happens without design. Figure 2 counts its 120 pairs by distance. The mean is 6.11, near the expected for random words, but two pairs, with and with , sit at distance 2. That is what chance predicts. A second random word lies within distance 2 of a first when it is one of the such words, which happens with probability , so 120 pairs are expected to hold 2.31 close pairs. The dots give the same expectation, , at every distance .
Those two pairs dominate the failures. At the previous chapter's decoder fails on a block with probability 0.0032306, and the four codewords in the close pairs, a quarter of the code, account for 0.82 of that, because one flip in either position where a close pair differs leaves the received word halfway between them.
03.The Geometry of the Binary Cube
The Repetition Code drew the eight 3-bit words as the corners of a cube, with an edge between words that differ in one bit. The -cube does the same for all words of bits. Each word has neighbors and each edge joins two words, so the -cube has edges, 12 for and 32 for . Walking an edge flips one bit, so the shortest walk from to has exactly edges, since each differing position must be flipped once and flipping them one at a time suffices.
Table 2 lists the radius-1 balls of in the 3-cube, and those of the fourfold code , with codewords and , in the 4-cube.
Table 2. Balls of radius 1 around the codewords of and , and the words of the 4-cube that neither ball reaches
| Code | Center | Words in the ball | Size |
|---|---|---|---|
| 000 | 000, 001, 010, 100 | 4 | |
| 111 | 111, 110, 101, 011 | 4 | |
| 0000 | 0000, 0001, 0010, 0100, 1000 | 5 | |
| 1111 | 1111, 1110, 1101, 1011, 0111 | 5 | |
| in neither ball | 0011, 0101, 0110, 1001, 1010, 1100 | 6 |
Source: reproduced by ch08_distance_detection_and_correction.py.
The two balls of share no word and hold all 8, as Figure 3 shows, so every received word is within one flip of exactly one codeword. The balls of hold 10 of the 16 words. The six words of weight 2 lie at distance 2 from both codewords and point to neither, and Figure 4 draws them in the middle column.
Proof. The words at distance exactly from are the words with , and different patterns give different words. A pattern of weight is a choice of positions out of , and Counting Errors with the Binomial Distribution counted such choices. Adding over from 0 to gives the ball.
For the sum is , the sizes 4 and 5 in the table. If the balls of radius around codewords share no word, they hold of the words, so
This is the sphere-packing bound, also called the Hamming bound after Hamming's 1950 paper [1], and Correcting Errors shows that it applies to every code that corrects errors. For the four balls of size hold 24 of the 32 words. Sixteen codewords of 6 bits cannot correct one error, since exceeds , but at length 7 the count is , and the Hamming code of the Part Linear Block Codes fills the 7-cube with no word to spare.
04.Detecting Errors
Send from and let the channel flip positions 3 and 4, the pattern . The received word is at distances 3, 2, 4 and 1 from , , and . It is not a codeword, so the receiver knows something went wrong, though its nearest codeword, , was not the one sent. Flip positions 1, 3 and 4 instead, the pattern , and the receiver gets , a codeword, with no sign that anything happened.
Proof. Let be sent and . The received word is at distance from , so it differs from . If it were another codeword , then , contradicting the definition of , so it is flagged. For the second part, take codewords and at distance exactly . The pattern has weight and turns into , which the detector accepts.
For the guarantee covers one and two errors, and the pattern that escaped is the XOR of two codewords at distance 3. Most heavier patterns are caught as well, and for a code closed under XOR the escapes are easy to name. The word is a codeword exactly when is, so the patterns that escape are the nonzero codewords, whichever codeword was sent. Write for the number of codewords of weight . Each pattern of weight occurs on with probability , so the probability of an undetected error is
has and , so , which is at , against for any error at all. Of the ten patterns of weight 3, only the two that are codewords escape.
05.Correcting Errors
Suppose delivers . Its distances to the four codewords are 4, 3, 1 and 2, so the nearest is , one flip away. Decisions by Bayes' Rule showed why nearest is right. On with and equally likely codewords, a codeword at distance from the received word has likelihood , which shrinks as grows, so the nearest codeword is the most likely one.
Proof. If a word were within of two codewords and , the triangle inequality would give , which is impossible, so the balls are disjoint. A pattern with leaves in the ball of and no other, and the decoder returns . The condition means , whose largest whole solution is the rounded-down value. For the last part, take codewords and at distance and flip of the positions where they differ, starting from . If , the word reached is within of and is miscorrected. If , it is from both and is flagged.
As runs from 1 to 7, runs through 0, 0, 1, 1, 2, 2 and 3, about half the detection guarantee , because a corrected word must stay nearer its own codeword than any other. An even distance leaves a word exactly halfway, which Figure 5 shows being flagged.
Proof. Since , the condition gives , so the correction bound covers weights up to . Now let . The received word is more than from , so the decoder cannot return . If it returned another codeword , then would be within of the received word, and the triangle inequality would give , which is impossible. So the word is flagged.
, with , takes and , correcting to and flagging . , with , can correct one error and flag two or three, or correct two and flag nothing beyond them, in which case three errors on , such as , are miscorrected to . Which is better depends on whether a wrong answer costs more than a resend, the question of the next chapter.
06.Errors and Erasures Together
An erasure is a symbol marked as lost, the event of the binary erasure channel in Three Discrete Channels, and the receiver knows where it is. Take the code with codewords , , and , whose minimum distance is 4. Send , erase position 3 and flip position 6. The receiver gets and compares only the five positions it trusts, as Table 3 shows.
Table 3. Decoding the received word 11?010 from the code on the five positions that were not erased
| Codeword | On positions 1, 2, 4, 5, 6 | Received on those positions | Distance |
|---|---|---|---|
| 000000 | 00000 | 11010 | 3 |
| 001111 | 00111 | 11010 | 4 |
| 110011 | 11011 | 11010 | 1 |
| 111100 | 11100 | 11010 | 2 |
Source: reproduced by ch08_distance_detection_and_correction.py.
The nearest codeword on those positions is , the one sent, recovered despite one error and one erasure.
Proof. Delete the erased positions from every codeword. Each deletion removes at most one difference between two codewords, so the shortened codewords still differ pairwise in at least positions, and since , no two have become equal. On the kept positions the received word holds exactly errors. By the correction bound, nearest-codeword decoding recovers the sent codeword when , which is .
The bound is tight. The codewords and differ in positions 3 to 6, and erasing those four, so that , leaves both reading . An erasure costs half an error, so with no errors a code fills erasures, twice the errors it corrects. For that allows up to 3 erasures, or one error with one erasure. Even single parity, with , fills one erasure, since the missing bit must make the count of 1s even, the idea behind Parity as a spare disk.
07.Single Parity
The even-weight code of bits, the single parity check of Detecting Instead of Correcting, holds every word with an even number of 1s. Flipping one bit makes the count odd, so , and parity does better than the detection bound promises.
Proof. The checker computes the XOR of all received bits. For this equals the XOR of the bits of , which is 0 because has even weight, combined with the XOR of the bits of , which is 1 exactly when is odd.
Detecting Instead of Correcting wrote and for the total probability of the even-weight and the odd-weight error patterns on , and showed from the binomial theorem that and . Subtracting the two gives , the chance that the checker raises its alarm.
For and , , so the alarm sounds with probability 0.074618. Some error occurs with probability , so errors slip through with probability 0.0026368. The share of corrupted words the checker flags is its coverage,
which here is 0.96587, or 96.6%. The approximation keeps terms up to . By the binomial theorem and , so the alarm probability is about and the chance of some error about . Dividing both by and writing , the coverage is about , which is 0.965 for . Misses grow with length because they are mostly pairs of errors, and a longer word holds more pairs.
Figure 6 plots the coverage. At a 32-bit word covers 0.86561 and a 64-bit word 0.76469. At every received word is equally likely and half have even weight, so the coverage is , which is for .
In hardware the XOR of all the bits is the parity tree of The parity tree, and a lab later in this Part checks the parity detection formula against simulated channels.
08.Check Digits
People who copy numbers make two common mistakes. A substitution replaces one digit with another, and an adjacent swap exchanges two neighbors, typing 72 for 27. A check digit is an extra digit chosen so that a weighted sum of all the digits meets a fixed rule, and Gallian surveys the schemes in use [2] [3]. Catching every substitution means that two valid numbers differ in at least two digits, a minimum distance of 2, which says nothing yet about swaps. The arithmetic uses congruence. For a modulus , means that is a multiple of , so because .
ISBN-10
An ISBN-10 is ten digits , read from the left, of which the tenth is the check, chosen so that
The weights run from 10 down to 1, and a check value of 10 is written X. Table 4 finds the check digit for 0-13-042672, the start of the ISBN of Lin and Costello's textbook [4].
Table 4. The ISBN-10 check digit for 0-13-042672, with weights
| Position | Digit | Weight | Product |
|---|---|---|---|
| 1 | 0 | 10 | 0 |
| 2 | 1 | 9 | 9 |
| 3 | 3 | 8 | 24 |
| 4 | 0 | 7 | 0 |
| 5 | 4 | 6 | 24 |
| 6 | 2 | 5 | 10 |
| 7 | 6 | 4 | 24 |
| 8 | 7 | 3 | 21 |
| 9 | 2 | 2 | 4 |
| Sum | 116 |
Source: reproduced by ch08_distance_detection_and_correction.py.
The sum 116 leaves remainder 6 modulo 11, so the check digit, with weight 1, is , and 0-13-042672-5 has weighted sum .
Proof. Substituting for where the weight is changes the sum by , with and nonzero and between and 10, so neither factor is a multiple of 11. Because 11 is prime, a product is a multiple of 11 only when a factor is, which is Euclid's lemma, so the change is not a multiple of 11. Swapping at weight with at weight changes the sum by . The weights differ, so is nonzero and between and 9, and again neither factor is a multiple of 11.
The proof needs a prime modulus and distinct weights, and the price is the eleventh symbol X.
ISBN-13
Since 1 January 2007 ISBNs have 13 digits. An older book's ISBN-13 puts 978 in front of the first nine digits of its ISBN-10 and computes a new check digit by the rule of the 13-digit EAN barcode on retail goods, with weights alternating 1 and 3 from the left and modulus 10,
Table 5. The ISBN-13 check digit for 978-0-13-042672, with weights alternating 1 and 3
| Position | Digit | Weight | Term |
|---|---|---|---|
| 1 | 9 | 1 | 9 |
| 2 | 7 | 3 | 21 |
| 3 | 8 | 1 | 8 |
| 4 | 0 | 3 | 0 |
| 5 | 1 | 1 | 1 |
| 6 | 3 | 3 | 9 |
| 7 | 0 | 1 | 0 |
| 8 | 4 | 3 | 12 |
| 9 | 2 | 1 | 2 |
| 10 | 6 | 3 | 18 |
| 11 | 7 | 1 | 7 |
| 12 | 2 | 3 | 6 |
| Sum | 93 |
Source: reproduced by ch08_distance_detection_and_correction.py.
Table 5 applies the rule to the same book. The terms add to 93, so the check digit 7 brings the sum to 100, and the number is 978-0-13-042672-7.
Proof. A substitution changes the sum by with equal to 1 or 3. For the change is nonzero and between and 9. For , if were a multiple of 10, so would be , and hence , which is impossible. Neighbors carry the weights 1 and 3, so a swap changes the sum by , a multiple of 10 exactly when is a multiple of 5, that is, when the digits differ by 5. Positions two apart carry equal weights, so a swap there changes nothing.
The pairs that differ by 5, such as 2 and 7, are 10 of the 90 ordered pairs of different digits, so ISBN-13 catches , or 88.9%, of adjacent swaps. The worked example An ISBN-13 Swap That Slips Through follows one. The weights are not to blame. In any weighted sum modulo 10, an even weight makes a multiple of 10 and a weight divisible by 5 makes one, so some substitution in that position escapes. Catching every substitution therefore forces odd weights, the difference of two odd weights is even, and an even number times 5 is a multiple of 10. No weighted sum of decimal digits modulo 10 catches every substitution and every adjacent swap.
The Luhn formula
The Luhn formula, patented by Hans Peter Luhn of IBM in 1960 [5] and used on payment card numbers, escapes that limit by not being a weighted sum. Number the digits from the right, the check digit being digit 1. Every digit in an even position is doubled, and 9 is subtracted when the result exceeds 9. Writing for the -th digit from the right and for the doubled value, a number is valid when
Doubling sends the digits to , each digit exactly once. For 314159265, the first nine digits of , the check digit is 3. Table 6 checks 3141592653 and two corrupted copies.
Table 6. The Luhn check on 3141592653 and on two corrupted copies, with the terms listed from the left
| Number | Change | Terms | Sum | Verdict |
|---|---|---|---|---|
| 3141592653 | none | 6, 1, 8, 1, 1, 9, 4, 6, 1, 3 | 40 | valid |
| 3141582653 | the 9 becomes 8 | 6, 1, 8, 1, 1, 8, 4, 6, 1, 3 | 39 | caught |
| 3141952653 | 5 and 9 swapped | 6, 1, 8, 1, 9, 5, 4, 6, 1, 3 | 44 | caught |
Source: reproduced by ch08_distance_detection_and_correction.py.
Proof. A substitution changes the sum by or by . Both are nonzero, the second because sends different digits to different digits, and both lie between and 9, so neither is a multiple of 10. Of two neighbors exactly one is doubled. If starts in the doubled position, the pair contributes before the swap and after, a change of with . For , takes the values , so lies between and 8 and is a multiple of 10 only when it is 0. The function repeats only the value 0, at and , so only that swap escapes. Positions two apart are both doubled or both not, so a swap there leaves the sum unchanged.
The swap in the table changed the sum by . Only 2 of the 90 ordered pairs escape, so Luhn catches 97.8% of adjacent swaps. The companion script confirms this on numbers of 10 and 16 digits and on all 10,000 valid five-digit strings, and shows that the weights 1, 3, 1, 3, 1 in place of doubling let 10 pairs through. Figure 7 compares the three schemes.
09.Rectangular Parity
One parity bit detects an error but cannot locate it. Arrange the data in a grid with a parity bit for each row and each column, and the crossing of a failed row and a failed column points at the error. Figure 8 sends 16 data bits as a 4 by 4 array with rows 1011, 0110, 1101 and 0010. The row parities are 1, 0, 1 and 1, the column parities 0, 0, 1 and 0, and a corner bit, 1, makes both the parity row and the parity column even. The channel flips the data bit in row 3, column 2.
Table 7. The received array, with the data bit in row 3, column 2 flipped, and the check on each row and column
| Column 1 | Column 2 | Column 3 | Column 4 | Parity | Check | |
|---|---|---|---|---|---|---|
| Row 1 | 1 | 0 | 1 | 1 | 1 | even |
| Row 2 | 0 | 1 | 1 | 0 | 0 | even |
| Row 3 | 1 | 0 | 0 | 1 | 1 | odd |
| Row 4 | 0 | 0 | 1 | 0 | 1 | even |
| Parity | 0 | 0 | 1 | 0 | 1 | even |
| Check | even | odd | even | even | even |
Source: reproduced by ch08_distance_detection_and_correction.py.
In Table 7 only row 3 and column 2 fail, so the decoder flips the bit where they cross. The scheme spends 25 bits on 16, a rate of , and its power follows from its minimum distance.
Proof. The XOR of two valid arrays is valid, since each parity bit is the XOR of the bits it covers, so it suffices to find the smallest weight of a nonzero valid array, in which every row and column holds an even number of 1s. A row holding a 1 holds at least two, in columns and , and each of those columns holds a second 1 in another row, so the weight is at least 4. With exactly four, the second 1s of columns and share a row, or each of their rows would hold a single 1, so the array is a rectangle. Conversely every row and column of a rectangle is even, and an array whose rows and columns are all even is valid, because its data bits produce exactly the parity bits present. Two rows and two columns can be chosen in ways.
With the budget allows correcting one error and detecting two, the guarantee of at a rate of 0.64 instead of 0.25. The companion script confirms that all 25 single errors are corrected and all 300 double errors flagged. Three errors can deceive the decoder. With errors at , and , written as (row, column), row 1 and column 1 hold two errors each and stay even, so only row 3 and column 3 fail, the signature of one error at . Flipping that bit completes a rectangle and delivers a valid array that was not sent. Grid codes like this, called product codes, go back to Elias [6], and later Parts build much stronger ones.
10.Gray Codes
A rotary sensor reports which of eight sectors a shaft points into, as a 3-bit word read from three tracks. In plain binary the boundary from sector 3, , to sector 4, , changes all three bits, and since the tracks never switch at exactly the same instant, a reading mid-change can catch any of the combinations, such as , sector 7. If neighboring sectors had words differing in one bit, a reading mid-change could only return one of the two sectors involved.
The reflected construction builds one for every . Start from the 1-bit list 0, 1. To go from bits to , write the list with a 0 in front, then the same list reversed with a 1 in front. This gives 00, 01, 11, 10, and then 000, 001, 011, 010, 110, 111, 101, 100, the walk of Figure 9. Inside each half neighbors differ in one bit because the shorter list did, and at the middle and at the wrap the two words differ only in the front bit.
A formula gives the word in position directly. Write in binary, with bits numbered from 0 at the right to at the left, and let be shifted right one place, dropping its last bit and putting a 0 in front. Then
Table 8 applies it to every 4-bit position and reproduces the reflected list, whose first eight entries without their leading 0 are the 3-bit list. The companion script confirms that the formula and the construction agree for every length up to 8.
Table 8. The 4-bit reflected Gray code from , with the 3-bit code beside its first eight entries
| Position | Binary | 4-bit Gray | 3-bit Gray | |
|---|---|---|---|---|
| 0 | 0000 | 0000 | 0000 | 000 |
| 1 | 0001 | 0000 | 0001 | 001 |
| 2 | 0010 | 0001 | 0011 | 011 |
| 3 | 0011 | 0001 | 0010 | 010 |
| 4 | 0100 | 0010 | 0110 | 110 |
| 5 | 0101 | 0010 | 0111 | 111 |
| 6 | 0110 | 0011 | 0101 | 101 |
| 7 | 0111 | 0011 | 0100 | 100 |
| 8 | 1000 | 0100 | 1100 | |
| 9 | 1001 | 0100 | 1101 | |
| 10 | 1010 | 0101 | 1111 | |
| 11 | 1011 | 0101 | 1110 | |
| 12 | 1100 | 0110 | 1010 | |
| 13 | 1101 | 0110 | 1011 | |
| 14 | 1110 | 0111 | 1001 | |
| 15 | 1111 | 0111 | 1000 |
Source: reproduced by ch08_distance_detection_and_correction.py.
Proof. Since , it ends in a 0 followed by 1s. Adding 1 turns those 1s into 0s and that 0 into a 1, so is 1s at the right end. Shifting distributes over XOR, so , and since is 1s at the right end, the XOR has a single 1, in bit . For the wrap, is all 1s, and , which differs from in the top bit only.
To convert back, run the formula from the top bit down. XORing with gives
For the shift is , and , the entry for position 11. Going back from , , , and , which is again.
In the Gray code sector 3 is and sector 4 is , so the boundary changes one bit and a reading mid-change returns 3 or 4. Frank Gray's 1953 patent described this reflected binary code [7], and the same property makes Gray codes common in shaft encoders and in counters read by circuits on a different clock. As a code, a Gray code has minimum distance 1 and protects nothing against noise. It uses distance the other way, placing consecutive values as close as possible, so an uncertain reading costs one step and never a jump across the range.
11.Looking Ahead
A code of minimum distance detects errors, corrects , and handles errors with erasures whenever . The same counting priced single parity through the parity detection formula, the ISBN and Luhn check digits, and the rectangular array that locates one error.
A guarantee says what a code can do, not what a system should do with it. The next chapter, Error-Control Strategies and Performance, weighs forward error correction against retransmission, prices the retransmission schemes stop-and-wait, go-back-N and selective repeat, measures decoded error rates and coding gain, and defines the reliability measures of real systems, the failure rate in FIT, silent data corruption and the detected but unrecoverable error. The undetected-error probability of Detecting Errors and the parity detection formula are its raw inputs. Hamming's paper [1] introduced much of this chapter's geometry, and Lin and Costello [4] and MacKay [8] carry it further.
12.Worked Examples
13.Exercises
References
- [1]Hamming, Richard W. (1950). “Error Detecting and Error Correcting Codes.” Bell System Technical Journal, 29(2), pp. 147–160. doi:10.1002/j.1538-7305.1950.tb00463.x
- [2]Gallian, Joseph A. (1991). “The Mathematics of Identification Numbers.” The College Mathematics Journal, 22(3), pp. 194–202. doi:10.1080/07468342.1991.11973381
- [3]Gallian, Joseph A. (1996). “Error Detection Methods.” ACM Computing Surveys, 28(3), pp. 504–517. doi:10.1145/243439.243457
- [4]Lin, Shu and Costello, Jr., Daniel J. (2004). “Error Control Coding: Fundamentals and Applications.” 2nd edition. Pearson Prentice Hall.
- [5]Luhn, Hans Peter (1960). “Computer for Verifying Numbers.” U.S. Patent 2,950,048. https://patents.google.com/patent/US2950048A/en
- [6]Elias, Peter (1954). “Error-free Coding.” Transactions of the IRE Professional Group on Information Theory, 4(4), pp. 29–37. doi:10.1109/TIT.1954.1057464
- [7]Gray, Frank (1953). “Pulse Code Communication.” U.S. Patent 2,632,058. https://patents.google.com/patent/US2632058A/en
- [8]MacKay, David J. C. (2003). “Information Theory, Inference, and Learning Algorithms.” Cambridge University Press. The author's site offers the whole book free to read on screen. https://www.inference.org.uk/itila/book.html
— Anirban
Hardware–software at the seam where compilers meet microcode.