diff options
| author | Mark Adler <madler@alumni.caltech.edu> | 2018-11-04 10:31:46 -0800 |
|---|---|---|
| committer | Mark Adler <madler@alumni.caltech.edu> | 2018-11-04 10:31:46 -0800 |
| commit | 41d86c73b21191a3fa9ea5f476fc9f1fc5e4f8b3 (patch) | |
| tree | ccb2cf4ee7f9f8713706d77dd8289178e2fbb7b1 | |
| parent | 47cb41295751ee1b1b7e0acbfb847ea24324d5aa (diff) | |
| download | zlib-41d86c73b21191a3fa9ea5f476fc9f1fc5e4f8b3.tar.gz zlib-41d86c73b21191a3fa9ea5f476fc9f1fc5e4f8b3.tar.bz2 zlib-41d86c73b21191a3fa9ea5f476fc9f1fc5e4f8b3.zip | |
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().
| -rw-r--r-- | crc32.c | 75 | ||||
| -rw-r--r-- | zlib.h | 22 |
2 files changed, 97 insertions, 0 deletions
| @@ -50,6 +50,7 @@ | |||
| 50 | #define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */ | 50 | #define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */ |
| 51 | local z_crc_t gf2_matrix_times OF((const z_crc_t *mat, z_crc_t vec)); | 51 | local z_crc_t gf2_matrix_times OF((const z_crc_t *mat, z_crc_t vec)); |
| 52 | 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)); |
| 53 | local void crc32_combine_gen_ OF((z_crc_t *op, z_off64_t len2)); | ||
| 53 | 54 | ||
| 54 | /* ========================================================================= */ | 55 | /* ========================================================================= */ |
| 55 | local z_crc_t gf2_matrix_times(mat, vec) | 56 | local z_crc_t gf2_matrix_times(mat, vec) |
| @@ -452,3 +453,77 @@ uLong ZEXPORT crc32_combine64(crc1, crc2, len2) | |||
| 452 | { | 453 | { |
| 453 | return crc32_combine_(crc1, crc2, len2); | 454 | return crc32_combine_(crc1, crc2, len2); |
| 454 | } | 455 | } |
| 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 | } | ||
| @@ -1757,6 +1757,22 @@ ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); | |||
| 1757 | len2. | 1757 | len2. |
| 1758 | */ | 1758 | */ |
| 1759 | 1759 | ||
| 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 | |||
| 1760 | 1776 | ||
| 1761 | /* various hacks, don't look :) */ | 1777 | /* various hacks, don't look :) */ |
| 1762 | 1778 | ||
| @@ -1844,6 +1860,7 @@ ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */ | |||
| 1844 | ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); | 1860 | ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); |
| 1845 | ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t)); | 1861 | ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t)); |
| 1846 | ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t)); | 1862 | 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)); | ||
| 1847 | #endif | 1864 | #endif |
| 1848 | 1865 | ||
| 1849 | #if !defined(ZLIB_INTERNAL) && defined(Z_WANT64) | 1866 | #if !defined(ZLIB_INTERNAL) && defined(Z_WANT64) |
| @@ -1854,6 +1871,7 @@ ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */ | |||
| 1854 | # define z_gzoffset z_gzoffset64 | 1871 | # define z_gzoffset z_gzoffset64 |
| 1855 | # define z_adler32_combine z_adler32_combine64 | 1872 | # define z_adler32_combine z_adler32_combine64 |
| 1856 | # define z_crc32_combine z_crc32_combine64 | 1873 | # define z_crc32_combine z_crc32_combine64 |
| 1874 | # define z_crc32_combine_gen z_crc32_combine64_gen | ||
| 1857 | # else | 1875 | # else |
| 1858 | # define gzopen gzopen64 | 1876 | # define gzopen gzopen64 |
| 1859 | # define gzseek gzseek64 | 1877 | # define gzseek gzseek64 |
| @@ -1861,6 +1879,7 @@ ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */ | |||
| 1861 | # define gzoffset gzoffset64 | 1879 | # define gzoffset gzoffset64 |
| 1862 | # define adler32_combine adler32_combine64 | 1880 | # define adler32_combine adler32_combine64 |
| 1863 | # define crc32_combine crc32_combine64 | 1881 | # define crc32_combine crc32_combine64 |
| 1882 | # define crc32_combine_gen crc32_combine_gen64 | ||
| 1864 | # endif | 1883 | # endif |
| 1865 | # ifndef Z_LARGE64 | 1884 | # ifndef Z_LARGE64 |
| 1866 | ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); | 1885 | ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); |
| @@ -1869,6 +1888,7 @@ ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */ | |||
| 1869 | ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile)); | 1888 | ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile)); |
| 1870 | ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); | 1889 | ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); |
| 1871 | ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); | 1890 | 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)); | ||
| 1872 | # endif | 1892 | # endif |
| 1873 | #else | 1893 | #else |
| 1874 | ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *)); | 1894 | ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *)); |
| @@ -1877,12 +1897,14 @@ ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */ | |||
| 1877 | ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile)); | 1897 | ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile)); |
| 1878 | ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); | 1898 | ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); |
| 1879 | ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); | 1899 | 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)); | ||
| 1880 | #endif | 1901 | #endif |
| 1881 | 1902 | ||
| 1882 | #else /* Z_SOLO */ | 1903 | #else /* Z_SOLO */ |
| 1883 | 1904 | ||
| 1884 | ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); | 1905 | ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); |
| 1885 | ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); | 1906 | 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)); | ||
| 1886 | 1908 | ||
| 1887 | #endif /* !Z_SOLO */ | 1909 | #endif /* !Z_SOLO */ |
| 1888 | 1910 | ||
