int crc32(byte[] data) {
int crc = ~0;
for (byte b : data) {
crc ^= b & 0xFF;
for (int i = 0; i < 8; i++)
crc = (crc >>> 1) ^ ((crc & 1) * 0xEDB88320);
}
return ~crc;
}
Or smooshed down slightly (with caveats): int crc32(byte[] data) {
int crc = ~0;
for (int i = 0; i < data.length * 8; i++) {
crc ^= (data[i / 8] >> (i % 8)) & 1;
crc = (crc >>> 1) ^ ((crc & 1) * 0xEDB88320);
}
return ~crc;
}
But one reason that many CRC implementations are large is because they include a pre-computed table of 256× 32-bit constants so that one byte can processed at a time. For example: https://github.com/madler/zlib/blob/7cdaaa09095e9266dee21314...Java CRC32 nowadays uses intrinsics and avx128 for crc32.
The Huffman decoding implementation is also bigger in production implementations for both speed and error checking. Two Huffman trees need to be exactly complete except in the special case of a single code, and in most cases they are flattened to two-level tables for speed (though the latest desktop CPUs have enough L1 cache to use single-level).
Finally, the LZ copy typically has special cases added for using wider than byte copies for non-overlapping, non-wrapping runs. This is a significant decoding speed optimization.
More reasons it's an odd comparison.