diff options
Diffstat (limited to 'crc32.c')
-rw-r--r-- | crc32.c | 194 |
1 files changed, 103 insertions, 91 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* crc32.c -- compute the CRC-32 of a data stream | 1 | /* crc32.c -- compute the CRC-32 of a data stream |
2 | * Copyright (C) 1995-2006, 2010, 2011, 2012, 2016 Mark Adler | 2 | * Copyright (C) 1995-2006, 2010, 2011, 2012, 2016, 2018 Mark Adler |
3 | * For conditions of distribution and use, see copyright notice in zlib.h | 3 | * For conditions of distribution and use, see copyright notice in zlib.h |
4 | * | 4 | * |
5 | * Thanks to Rodney Brown <rbrown64@csc.com.au> for his contribution of faster | 5 | * Thanks to Rodney Brown <rbrown64@csc.com.au> for his contribution of faster |
@@ -18,7 +18,9 @@ | |||
18 | first call get_crc_table() to initialize the tables before allowing more than | 18 | first call get_crc_table() to initialize the tables before allowing more than |
19 | one thread to use crc32(). | 19 | one thread to use crc32(). |
20 | 20 | ||
21 | DYNAMIC_CRC_TABLE and MAKECRCH can be #defined to write out crc32.h. | 21 | DYNAMIC_CRC_TABLE and MAKECRCH can be #defined to write out crc32.h. A main() |
22 | routine is also produced, so that this one source file can be compiled to an | ||
23 | executable. | ||
22 | */ | 24 | */ |
23 | 25 | ||
24 | #ifdef MAKECRCH | 26 | #ifdef MAKECRCH |
@@ -45,20 +47,50 @@ | |||
45 | #endif /* BYFOUR */ | 47 | #endif /* BYFOUR */ |
46 | 48 | ||
47 | /* Local functions for crc concatenation */ | 49 | /* Local functions for crc concatenation */ |
48 | local unsigned long gf2_matrix_times OF((unsigned long *mat, | 50 | #define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */ |
49 | unsigned long vec)); | 51 | local z_crc_t gf2_matrix_times OF((const z_crc_t *mat, z_crc_t vec)); |
50 | local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat)); | ||
51 | local uLong crc32_combine_ OF((uLong crc1, uLong crc2, z_off64_t len2)); | 52 | local uLong crc32_combine_ OF((uLong crc1, uLong crc2, z_off64_t len2)); |
52 | 53 | ||
54 | /* ========================================================================= */ | ||
55 | local z_crc_t gf2_matrix_times(mat, vec) | ||
56 | const z_crc_t *mat; | ||
57 | z_crc_t vec; | ||
58 | { | ||
59 | z_crc_t sum; | ||
60 | |||
61 | sum = 0; | ||
62 | while (vec) { | ||
63 | if (vec & 1) | ||
64 | sum ^= *mat; | ||
65 | vec >>= 1; | ||
66 | mat++; | ||
67 | } | ||
68 | return sum; | ||
69 | } | ||
70 | |||
53 | 71 | ||
54 | #ifdef DYNAMIC_CRC_TABLE | 72 | #ifdef DYNAMIC_CRC_TABLE |
55 | 73 | ||
56 | local volatile int crc_table_empty = 1; | 74 | local volatile int crc_table_empty = 1; |
57 | local z_crc_t FAR crc_table[TBLS][256]; | 75 | local z_crc_t FAR crc_table[TBLS][256]; |
76 | local z_crc_t FAR crc_comb[GF2_DIM][GF2_DIM]; | ||
58 | local void make_crc_table OF((void)); | 77 | local void make_crc_table OF((void)); |
78 | local void gf2_matrix_square OF((z_crc_t *square, const z_crc_t *mat)); | ||
59 | #ifdef MAKECRCH | 79 | #ifdef MAKECRCH |
60 | local void write_table OF((FILE *, const z_crc_t FAR *)); | 80 | local void write_table OF((FILE *, const z_crc_t FAR *, int)); |
61 | #endif /* MAKECRCH */ | 81 | #endif /* MAKECRCH */ |
82 | |||
83 | /* ========================================================================= */ | ||
84 | local void gf2_matrix_square(square, mat) | ||
85 | z_crc_t *square; | ||
86 | const z_crc_t *mat; | ||
87 | { | ||
88 | int n; | ||
89 | |||
90 | for (n = 0; n < GF2_DIM; n++) | ||
91 | square[n] = gf2_matrix_times(mat, mat[n]); | ||
92 | } | ||
93 | |||
62 | /* | 94 | /* |
63 | Generate tables for a byte-wise 32-bit CRC calculation on the polynomial: | 95 | Generate tables for a byte-wise 32-bit CRC calculation on the polynomial: |
64 | x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. | 96 | x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. |
@@ -127,6 +159,33 @@ local void make_crc_table() | |||
127 | } | 159 | } |
128 | #endif /* BYFOUR */ | 160 | #endif /* BYFOUR */ |
129 | 161 | ||
162 | /* generate zero operators table for crc32_combine() */ | ||
163 | |||
164 | /* generate the operator to apply a single zero bit to a CRC -- the | ||
165 | first row adds the polynomial if the low bit is a 1, and the | ||
166 | remaining rows shift the CRC right one bit */ | ||
167 | k = GF2_DIM - 3; | ||
168 | crc_comb[k][0] = 0xedb88320UL; /* CRC-32 polynomial */ | ||
169 | z_crc_t row = 1; | ||
170 | for (n = 1; n < GF2_DIM; n++) { | ||
171 | crc_comb[k][n] = row; | ||
172 | row <<= 1; | ||
173 | } | ||
174 | |||
175 | /* generate operators that apply 2, 4, and 8 zeros to a CRC, putting | ||
176 | the last one, the operator for one zero byte, at the 0 position */ | ||
177 | gf2_matrix_square(crc_comb[k + 1], crc_comb[k]); | ||
178 | gf2_matrix_square(crc_comb[k + 2], crc_comb[k + 1]); | ||
179 | gf2_matrix_square(crc_comb[0], crc_comb[k + 2]); | ||
180 | |||
181 | /* generate operators for applying 2^n zero bytes to a CRC, filling out | ||
182 | the remainder of the table -- the operators repeat after GF2_DIM | ||
183 | values of n, so the table only needs GF2_DIM entries, regardless of | ||
184 | the size of the length being processed */ | ||
185 | for (n = 1; n < k; n++) | ||
186 | gf2_matrix_square(crc_comb[n], crc_comb[n - 1]); | ||
187 | |||
188 | /* mark tables as complete, in case someone else is waiting */ | ||
130 | crc_table_empty = 0; | 189 | crc_table_empty = 0; |
131 | } | 190 | } |
132 | else { /* not first */ | 191 | else { /* not first */ |
@@ -134,50 +193,68 @@ local void make_crc_table() | |||
134 | while (crc_table_empty) | 193 | while (crc_table_empty) |
135 | ; | 194 | ; |
136 | } | 195 | } |
137 | |||
138 | #ifdef MAKECRCH | 196 | #ifdef MAKECRCH |
139 | /* write out CRC tables to crc32.h */ | ||
140 | { | 197 | { |
141 | FILE *out; | 198 | FILE *out; |
142 | 199 | ||
143 | out = fopen("crc32.h", "w"); | 200 | out = fopen("crc32.h", "w"); |
144 | if (out == NULL) return; | 201 | if (out == NULL) return; |
202 | |||
203 | /* write out CRC table to crc32.h */ | ||
145 | fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n"); | 204 | fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n"); |
146 | fprintf(out, " * Generated automatically by crc32.c\n */\n\n"); | 205 | fprintf(out, " * Generated automatically by crc32.c\n */\n\n"); |
147 | fprintf(out, "local const z_crc_t FAR "); | 206 | fprintf(out, "local const z_crc_t FAR "); |
148 | fprintf(out, "crc_table[TBLS][256] =\n{\n {\n"); | 207 | fprintf(out, "crc_table[%d][256] =\n{\n {\n", TBLS); |
149 | write_table(out, crc_table[0]); | 208 | write_table(out, crc_table[0], 256); |
150 | # ifdef BYFOUR | 209 | # ifdef BYFOUR |
151 | fprintf(out, "#ifdef BYFOUR\n"); | 210 | fprintf(out, "#ifdef BYFOUR\n"); |
152 | for (k = 1; k < 8; k++) { | 211 | for (k = 1; k < 8; k++) { |
153 | fprintf(out, " },\n {\n"); | 212 | fprintf(out, " },\n {\n"); |
154 | write_table(out, crc_table[k]); | 213 | write_table(out, crc_table[k], 256); |
155 | } | 214 | } |
156 | fprintf(out, "#endif\n"); | 215 | fprintf(out, "#endif\n"); |
157 | # endif /* BYFOUR */ | 216 | # endif /* BYFOUR */ |
158 | fprintf(out, " }\n};\n"); | 217 | fprintf(out, " }\n};\n"); |
218 | |||
219 | /* write out zero operator table to crc32.h */ | ||
220 | fprintf(out, "\nlocal const z_crc_t FAR "); | ||
221 | fprintf(out, "crc_comb[%d][%d] =\n{\n {\n", GF2_DIM, GF2_DIM); | ||
222 | write_table(out, crc_comb[0], GF2_DIM); | ||
223 | for (k = 1; k < GF2_DIM; k++) { | ||
224 | fprintf(out, " },\n {\n"); | ||
225 | write_table(out, crc_comb[k], GF2_DIM); | ||
226 | } | ||
227 | fprintf(out, " }\n};\n"); | ||
159 | fclose(out); | 228 | fclose(out); |
160 | } | 229 | } |
161 | #endif /* MAKECRCH */ | 230 | #endif /* MAKECRCH */ |
162 | } | 231 | } |
163 | 232 | ||
164 | #ifdef MAKECRCH | 233 | #ifdef MAKECRCH |
165 | local void write_table(out, table) | 234 | local void write_table(out, table, k) |
166 | FILE *out; | 235 | FILE *out; |
167 | const z_crc_t FAR *table; | 236 | const z_crc_t FAR *table; |
237 | int k; | ||
168 | { | 238 | { |
169 | int n; | 239 | int n; |
170 | 240 | ||
171 | for (n = 0; n < 256; n++) | 241 | for (n = 0; n < k; n++) |
172 | fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", | 242 | fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", |
173 | (unsigned long)(table[n]), | 243 | (unsigned long)(table[n]), |
174 | n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", ")); | 244 | n == k - 1 ? "\n" : (n % 5 == 4 ? ",\n" : ", ")); |
245 | } | ||
246 | |||
247 | int main() | ||
248 | { | ||
249 | make_crc_table(); | ||
250 | return 0; | ||
175 | } | 251 | } |
176 | #endif /* MAKECRCH */ | 252 | #endif /* MAKECRCH */ |
177 | 253 | ||
178 | #else /* !DYNAMIC_CRC_TABLE */ | 254 | #else /* !DYNAMIC_CRC_TABLE */ |
179 | /* ======================================================================== | 255 | /* ======================================================================== |
180 | * Tables of CRC-32s of all single-byte values, made by make_crc_table(). | 256 | * Tables of CRC-32s of all single-byte values, made by make_crc_table(), |
257 | * and tables of zero operator matrices for crc32_combine(). | ||
181 | */ | 258 | */ |
182 | #include "crc32.h" | 259 | #include "crc32.h" |
183 | #endif /* DYNAMIC_CRC_TABLE */ | 260 | #endif /* DYNAMIC_CRC_TABLE */ |
@@ -338,36 +415,6 @@ local unsigned long crc32_big(crc, buf, len) | |||
338 | 415 | ||
339 | #endif /* BYFOUR */ | 416 | #endif /* BYFOUR */ |
340 | 417 | ||
341 | #define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */ | ||
342 | |||
343 | /* ========================================================================= */ | ||
344 | local unsigned long gf2_matrix_times(mat, vec) | ||
345 | unsigned long *mat; | ||
346 | unsigned long vec; | ||
347 | { | ||
348 | unsigned long sum; | ||
349 | |||
350 | sum = 0; | ||
351 | while (vec) { | ||
352 | if (vec & 1) | ||
353 | sum ^= *mat; | ||
354 | vec >>= 1; | ||
355 | mat++; | ||
356 | } | ||
357 | return sum; | ||
358 | } | ||
359 | |||
360 | /* ========================================================================= */ | ||
361 | local void gf2_matrix_square(square, mat) | ||
362 | unsigned long *square; | ||
363 | unsigned long *mat; | ||
364 | { | ||
365 | int n; | ||
366 | |||
367 | for (n = 0; n < GF2_DIM; n++) | ||
368 | square[n] = gf2_matrix_times(mat, mat[n]); | ||
369 | } | ||
370 | |||
371 | /* ========================================================================= */ | 418 | /* ========================================================================= */ |
372 | local uLong crc32_combine_(crc1, crc2, len2) | 419 | local uLong crc32_combine_(crc1, crc2, len2) |
373 | uLong crc1; | 420 | uLong crc1; |
@@ -375,53 +422,18 @@ local uLong crc32_combine_(crc1, crc2, len2) | |||
375 | z_off64_t len2; | 422 | z_off64_t len2; |
376 | { | 423 | { |
377 | int n; | 424 | int n; |
378 | unsigned long row; | ||
379 | unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */ | ||
380 | unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */ | ||
381 | |||
382 | /* degenerate case (also disallow negative lengths) */ | ||
383 | if (len2 <= 0) | ||
384 | return crc1; | ||
385 | |||
386 | /* put operator for one zero bit in odd */ | ||
387 | odd[0] = 0xedb88320UL; /* CRC-32 polynomial */ | ||
388 | row = 1; | ||
389 | for (n = 1; n < GF2_DIM; n++) { | ||
390 | odd[n] = row; | ||
391 | row <<= 1; | ||
392 | } | ||
393 | 425 | ||
394 | /* put operator for two zero bits in even */ | 426 | #ifdef DYNAMIC_CRC_TABLE |
395 | gf2_matrix_square(even, odd); | 427 | if (crc_table_empty) |
396 | 428 | make_crc_table(); | |
397 | /* put operator for four zero bits in odd */ | 429 | #endif /* DYNAMIC_CRC_TABLE */ |
398 | gf2_matrix_square(odd, even); | 430 | |
399 | 431 | if (len2 > 0) | |
400 | /* apply len2 zeros to crc1 (first square will put the operator for one | 432 | /* operator for 2^n zeros repeats every GF2_DIM n values */ |
401 | zero byte, eight zero bits, in even) */ | 433 | for (n = 0; len2; n = (n + 1) % GF2_DIM, len2 >>= 1) |
402 | do { | 434 | if (len2 & 1) |
403 | /* apply zeros operator for this bit of len2 */ | 435 | crc1 = gf2_matrix_times(crc_comb[n], crc1); |
404 | gf2_matrix_square(even, odd); | 436 | return crc1 ^ crc2; |
405 | if (len2 & 1) | ||
406 | crc1 = gf2_matrix_times(even, crc1); | ||
407 | len2 >>= 1; | ||
408 | |||
409 | /* if no more bits set, then done */ | ||
410 | if (len2 == 0) | ||
411 | break; | ||
412 | |||
413 | /* another iteration of the loop with odd and even swapped */ | ||
414 | gf2_matrix_square(odd, even); | ||
415 | if (len2 & 1) | ||
416 | crc1 = gf2_matrix_times(odd, crc1); | ||
417 | len2 >>= 1; | ||
418 | |||
419 | /* if no more bits set, then done */ | ||
420 | } while (len2 != 0); | ||
421 | |||
422 | /* return combined crc */ | ||
423 | crc1 ^= crc2; | ||
424 | return crc1; | ||
425 | } | 437 | } |
426 | 438 | ||
427 | /* ========================================================================= */ | 439 | /* ========================================================================= */ |