Skip to content

Commit 41d86c7

Browse files
committed
Add crc32_combine_gen() and crc32_combine_op() for fast combines.
When the same len2 is used repeatedly, it is faster to use crc32_combine_gen() to generate an operator, that is then used to combine CRCs with crc32_combine_op().
1 parent 47cb412 commit 41d86c7

File tree

2 files changed

+97
-0
lines changed

2 files changed

+97
-0
lines changed

crc32.c

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
#define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */
5151
local z_crc_t gf2_matrix_times OF((const z_crc_t *mat, z_crc_t vec));
5252
local uLong crc32_combine_ OF((uLong crc1, uLong crc2, z_off64_t len2));
53+
local void crc32_combine_gen_ OF((z_crc_t *op, z_off64_t len2));
5354

5455
/* ========================================================================= */
5556
local z_crc_t gf2_matrix_times(mat, vec)
@@ -452,3 +453,77 @@ uLong ZEXPORT crc32_combine64(crc1, crc2, len2)
452453
{
453454
return crc32_combine_(crc1, crc2, len2);
454455
}
456+
457+
/* ========================================================================= */
458+
local void crc32_combine_gen_(op, len2)
459+
z_crc_t *op;
460+
z_off64_t len2;
461+
{
462+
z_crc_t row;
463+
int j;
464+
unsigned i;
465+
466+
#ifdef DYNAMIC_CRC_TABLE
467+
if (crc_table_empty)
468+
make_crc_table();
469+
#endif /* DYNAMIC_CRC_TABLE */
470+
471+
/* if len2 is zero or negative, return the identity matrix */
472+
if (len2 <= 0) {
473+
row = 1;
474+
for (j = 0; j < GF2_DIM; j++) {
475+
op[j] = row;
476+
row <<= 1;
477+
}
478+
return;
479+
}
480+
481+
/* at least one bit in len2 is set -- find it, and copy the operator
482+
corresponding to that position into op */
483+
i = 0;
484+
for (;;) {
485+
if (len2 & 1) {
486+
for (j = 0; j < GF2_DIM; j++)
487+
op[j] = crc_comb[i][j];
488+
break;
489+
}
490+
len2 >>= 1;
491+
i = (i + 1) % GF2_DIM;
492+
}
493+
494+
/* for each remaining bit set in len2 (if any), multiply op by the operator
495+
corresponding to that position */
496+
for (;;) {
497+
len2 >>= 1;
498+
i = (i + 1) % GF2_DIM;
499+
if (len2 == 0)
500+
break;
501+
if (len2 & 1)
502+
for (j = 0; j < GF2_DIM; j++)
503+
op[j] = gf2_matrix_times(crc_comb[i], op[j]);
504+
}
505+
}
506+
507+
/* ========================================================================= */
508+
void ZEXPORT crc32_combine_gen(op, len2)
509+
z_crc_t *op;
510+
z_off_t len2;
511+
{
512+
crc32_combine_gen_(op, len2);
513+
}
514+
515+
void ZEXPORT crc32_combine_gen64(op, len2)
516+
z_crc_t *op;
517+
z_off64_t len2;
518+
{
519+
crc32_combine_gen_(op, len2);
520+
}
521+
522+
/* ========================================================================= */
523+
uLong crc32_combine_op(crc1, crc2, op)
524+
uLong crc1;
525+
uLong crc2;
526+
const z_crc_t *op;
527+
{
528+
return gf2_matrix_times(op, crc1) ^ crc2;
529+
}

zlib.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1757,6 +1757,22 @@ ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2));
17571757
len2.
17581758
*/
17591759

1760+
/*
1761+
ZEXTERN void ZEXPORT crc32_combine_gen OF((z_crc_t op[32], z_off_t len2));
1762+
1763+
Generate the operator op corresponding to length len2, to be used with
1764+
crc32_combine_op(). op must have room for 32 z_crc_t values. (32 is the
1765+
number of bits in the CRC.)
1766+
*/
1767+
1768+
ZEXTERN uLong ZEXPORT crc32_combine_op OF((uLong crc1, uLong crc2,
1769+
const z_crc_t *op));
1770+
/*
1771+
Give the same result as crc32_combine(), using op in place of len2. op is
1772+
is generated from len2 by crc32_combine_gen(). This will be faster than
1773+
crc32_combine() if the generated op is used many times.
1774+
*/
1775+
17601776

17611777
/* various hacks, don't look :) */
17621778

@@ -1844,6 +1860,7 @@ ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */
18441860
ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile));
18451861
ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t));
18461862
ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t));
1863+
ZEXTERN void ZEXPORT crc32_combine_gen64 OF((z_crc_t *op, z_off64_t));
18471864
#endif
18481865

18491866
#if !defined(ZLIB_INTERNAL) && defined(Z_WANT64)
@@ -1854,13 +1871,15 @@ ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */
18541871
# define z_gzoffset z_gzoffset64
18551872
# define z_adler32_combine z_adler32_combine64
18561873
# define z_crc32_combine z_crc32_combine64
1874+
# define z_crc32_combine_gen z_crc32_combine64_gen
18571875
# else
18581876
# define gzopen gzopen64
18591877
# define gzseek gzseek64
18601878
# define gztell gztell64
18611879
# define gzoffset gzoffset64
18621880
# define adler32_combine adler32_combine64
18631881
# define crc32_combine crc32_combine64
1882+
# define crc32_combine_gen crc32_combine_gen64
18641883
# endif
18651884
# ifndef Z_LARGE64
18661885
ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));
@@ -1869,6 +1888,7 @@ ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */
18691888
ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile));
18701889
ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t));
18711890
ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t));
1891+
ZEXTERN void ZEXPORT crc32_combine_gen64 OF((z_crc_t *op, z_off_t));
18721892
# endif
18731893
#else
18741894
ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *));
@@ -1877,12 +1897,14 @@ ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */
18771897
ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile));
18781898
ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t));
18791899
ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t));
1900+
ZEXTERN void ZEXPORT crc32_combine_gen OF((z_crc_t *op, z_off_t));
18801901
#endif
18811902

18821903
#else /* Z_SOLO */
18831904

18841905
ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t));
18851906
ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t));
1907+
ZEXTERN void ZEXPORT crc32_combine_gen OF((z_crc_t *op, z_off_t));
18861908

18871909
#endif /* !Z_SOLO */
18881910

0 commit comments

Comments
 (0)