aboutsummaryrefslogtreecommitdiff
path: root/crc32.c
diff options
context:
space:
mode:
Diffstat (limited to 'crc32.c')
-rw-r--r--crc32.c194
1 files changed, 103 insertions, 91 deletions
diff --git a/crc32.c b/crc32.c
index e72636a..5ccfe09 100644
--- a/crc32.c
+++ b/crc32.c
@@ -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 */
48local 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)); 51local z_crc_t gf2_matrix_times OF((const z_crc_t *mat, z_crc_t vec));
50local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat));
51local uLong crc32_combine_ OF((uLong crc1, uLong crc2, z_off64_t len2)); 52local uLong crc32_combine_ OF((uLong crc1, uLong crc2, z_off64_t len2));
52 53
54/* ========================================================================= */
55local 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
56local volatile int crc_table_empty = 1; 74local volatile int crc_table_empty = 1;
57local z_crc_t FAR crc_table[TBLS][256]; 75local z_crc_t FAR crc_table[TBLS][256];
76local z_crc_t FAR crc_comb[GF2_DIM][GF2_DIM];
58local void make_crc_table OF((void)); 77local void make_crc_table OF((void));
78local 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/* ========================================================================= */
84local 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
165local void write_table(out, table) 234local 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
247int 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/* ========================================================================= */
344local 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/* ========================================================================= */
361local 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/* ========================================================================= */
372local uLong crc32_combine_(crc1, crc2, len2) 419local 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/* ========================================================================= */