diff options
author | Mauro Carvalho Chehab <mchehab@s-opensource.com> | 2017-05-14 08:56:02 -0400 |
---|---|---|
committer | Jonathan Corbet <corbet@lwn.net> | 2017-07-14 15:51:30 -0400 |
commit | 2e4e6f30f7ff84632e893786fab5e8ff44ff3e03 (patch) | |
tree | 33e07f82369ecaec0605fbe7c59b961a7e390b56 /Documentation/crc32.txt | |
parent | e8cb6f1edc57e5c729ce4e37a54a5f84fac0c6a4 (diff) |
crc32.txt: standardize document format
Each text file under Documentation follows a different
format. Some doesn't even have titles!
Change its representation to follow the adopted standard,
using ReST markups for it to be parseable by Sphinx:
- Add a title for the document;
- Mark literal blocks.
While here, replace a comma by a dot at the end of a paragraph.
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
Signed-off-by: Jonathan Corbet <corbet@lwn.net>
Diffstat (limited to 'Documentation/crc32.txt')
-rw-r--r-- | Documentation/crc32.txt | 75 |
1 files changed, 41 insertions, 34 deletions
diff --git a/Documentation/crc32.txt b/Documentation/crc32.txt index a08a7dd9d625..8a6860f33b4e 100644 --- a/Documentation/crc32.txt +++ b/Documentation/crc32.txt | |||
@@ -1,4 +1,6 @@ | |||
1 | A brief CRC tutorial. | 1 | ================================= |
2 | brief tutorial on CRC computation | ||
3 | ================================= | ||
2 | 4 | ||
3 | A CRC is a long-division remainder. You add the CRC to the message, | 5 | A CRC is a long-division remainder. You add the CRC to the message, |
4 | and the whole thing (message+CRC) is a multiple of the given | 6 | and the whole thing (message+CRC) is a multiple of the given |
@@ -8,7 +10,8 @@ remainder computed on the message+CRC is 0. This latter approach | |||
8 | is used by a lot of hardware implementations, and is why so many | 10 | is used by a lot of hardware implementations, and is why so many |
9 | protocols put the end-of-frame flag after the CRC. | 11 | protocols put the end-of-frame flag after the CRC. |
10 | 12 | ||
11 | It's actually the same long division you learned in school, except that | 13 | It's actually the same long division you learned in school, except that: |
14 | |||
12 | - We're working in binary, so the digits are only 0 and 1, and | 15 | - We're working in binary, so the digits are only 0 and 1, and |
13 | - When dividing polynomials, there are no carries. Rather than add and | 16 | - When dividing polynomials, there are no carries. Rather than add and |
14 | subtract, we just xor. Thus, we tend to get a bit sloppy about | 17 | subtract, we just xor. Thus, we tend to get a bit sloppy about |
@@ -40,11 +43,12 @@ throw the quotient bit away, but subtract the appropriate multiple of | |||
40 | the polynomial from the remainder and we're back to where we started, | 43 | the polynomial from the remainder and we're back to where we started, |
41 | ready to process the next bit. | 44 | ready to process the next bit. |
42 | 45 | ||
43 | A big-endian CRC written this way would be coded like: | 46 | A big-endian CRC written this way would be coded like:: |
44 | for (i = 0; i < input_bits; i++) { | 47 | |
45 | multiple = remainder & 0x80000000 ? CRCPOLY : 0; | 48 | for (i = 0; i < input_bits; i++) { |
46 | remainder = (remainder << 1 | next_input_bit()) ^ multiple; | 49 | multiple = remainder & 0x80000000 ? CRCPOLY : 0; |
47 | } | 50 | remainder = (remainder << 1 | next_input_bit()) ^ multiple; |
51 | } | ||
48 | 52 | ||
49 | Notice how, to get at bit 32 of the shifted remainder, we look | 53 | Notice how, to get at bit 32 of the shifted remainder, we look |
50 | at bit 31 of the remainder *before* shifting it. | 54 | at bit 31 of the remainder *before* shifting it. |
@@ -54,25 +58,26 @@ the remainder don't actually affect any decision-making until | |||
54 | 32 bits later. Thus, the first 32 cycles of this are pretty boring. | 58 | 32 bits later. Thus, the first 32 cycles of this are pretty boring. |
55 | Also, to add the CRC to a message, we need a 32-bit-long hole for it at | 59 | Also, to add the CRC to a message, we need a 32-bit-long hole for it at |
56 | the end, so we have to add 32 extra cycles shifting in zeros at the | 60 | the end, so we have to add 32 extra cycles shifting in zeros at the |
57 | end of every message, | 61 | end of every message. |
58 | 62 | ||
59 | These details lead to a standard trick: rearrange merging in the | 63 | These details lead to a standard trick: rearrange merging in the |
60 | next_input_bit() until the moment it's needed. Then the first 32 cycles | 64 | next_input_bit() until the moment it's needed. Then the first 32 cycles |
61 | can be precomputed, and merging in the final 32 zero bits to make room | 65 | can be precomputed, and merging in the final 32 zero bits to make room |
62 | for the CRC can be skipped entirely. This changes the code to: | 66 | for the CRC can be skipped entirely. This changes the code to:: |
63 | 67 | ||
64 | for (i = 0; i < input_bits; i++) { | 68 | for (i = 0; i < input_bits; i++) { |
65 | remainder ^= next_input_bit() << 31; | 69 | remainder ^= next_input_bit() << 31; |
66 | multiple = (remainder & 0x80000000) ? CRCPOLY : 0; | 70 | multiple = (remainder & 0x80000000) ? CRCPOLY : 0; |
67 | remainder = (remainder << 1) ^ multiple; | 71 | remainder = (remainder << 1) ^ multiple; |
68 | } | 72 | } |
69 | 73 | ||
70 | With this optimization, the little-endian code is particularly simple: | 74 | With this optimization, the little-endian code is particularly simple:: |
71 | for (i = 0; i < input_bits; i++) { | 75 | |
72 | remainder ^= next_input_bit(); | 76 | for (i = 0; i < input_bits; i++) { |
73 | multiple = (remainder & 1) ? CRCPOLY : 0; | 77 | remainder ^= next_input_bit(); |
74 | remainder = (remainder >> 1) ^ multiple; | 78 | multiple = (remainder & 1) ? CRCPOLY : 0; |
75 | } | 79 | remainder = (remainder >> 1) ^ multiple; |
80 | } | ||
76 | 81 | ||
77 | The most significant coefficient of the remainder polynomial is stored | 82 | The most significant coefficient of the remainder polynomial is stored |
78 | in the least significant bit of the binary "remainder" variable. | 83 | in the least significant bit of the binary "remainder" variable. |
@@ -81,23 +86,25 @@ be bit-reversed) and next_input_bit(). | |||
81 | 86 | ||
82 | As long as next_input_bit is returning the bits in a sensible order, we don't | 87 | As long as next_input_bit is returning the bits in a sensible order, we don't |
83 | *have* to wait until the last possible moment to merge in additional bits. | 88 | *have* to wait until the last possible moment to merge in additional bits. |
84 | We can do it 8 bits at a time rather than 1 bit at a time: | 89 | We can do it 8 bits at a time rather than 1 bit at a time:: |
85 | for (i = 0; i < input_bytes; i++) { | 90 | |
86 | remainder ^= next_input_byte() << 24; | 91 | for (i = 0; i < input_bytes; i++) { |
87 | for (j = 0; j < 8; j++) { | 92 | remainder ^= next_input_byte() << 24; |
88 | multiple = (remainder & 0x80000000) ? CRCPOLY : 0; | 93 | for (j = 0; j < 8; j++) { |
89 | remainder = (remainder << 1) ^ multiple; | 94 | multiple = (remainder & 0x80000000) ? CRCPOLY : 0; |
95 | remainder = (remainder << 1) ^ multiple; | ||
96 | } | ||
90 | } | 97 | } |
91 | } | ||
92 | 98 | ||
93 | Or in little-endian: | 99 | Or in little-endian:: |
94 | for (i = 0; i < input_bytes; i++) { | 100 | |
95 | remainder ^= next_input_byte(); | 101 | for (i = 0; i < input_bytes; i++) { |
96 | for (j = 0; j < 8; j++) { | 102 | remainder ^= next_input_byte(); |
97 | multiple = (remainder & 1) ? CRCPOLY : 0; | 103 | for (j = 0; j < 8; j++) { |
98 | remainder = (remainder >> 1) ^ multiple; | 104 | multiple = (remainder & 1) ? CRCPOLY : 0; |
105 | remainder = (remainder >> 1) ^ multiple; | ||
106 | } | ||
99 | } | 107 | } |
100 | } | ||
101 | 108 | ||
102 | If the input is a multiple of 32 bits, you can even XOR in a 32-bit | 109 | If the input is a multiple of 32 bits, you can even XOR in a 32-bit |
103 | word at a time and increase the inner loop count to 32. | 110 | word at a time and increase the inner loop count to 32. |