Convert-UUlib
view release on metacpan or search on metacpan
uulib/crc32.c view on Meta::CPAN
}
else
{
uint32_t one = *current++ ^ ecb_bswap32(crc);
uint32_t two = *current++;
uint32_t three = *current++;
uint32_t four = *current++;
crc = crc32_lookup[ 0][ four & 0xFF] ^
crc32_lookup[ 1][(four >> 8) & 0xFF] ^
crc32_lookup[ 2][(four >> 16) & 0xFF] ^
crc32_lookup[ 3][(four >> 24) & 0xFF] ^
crc32_lookup[ 4][ three & 0xFF] ^
crc32_lookup[ 5][(three >> 8) & 0xFF] ^
crc32_lookup[ 6][(three >> 16) & 0xFF] ^
crc32_lookup[ 7][(three >> 24) & 0xFF] ^
crc32_lookup[ 8][ two & 0xFF] ^
crc32_lookup[ 9][(two >> 8) & 0xFF] ^
crc32_lookup[10][(two >> 16) & 0xFF] ^
crc32_lookup[11][(two >> 24) & 0xFF] ^
crc32_lookup[12][ one & 0xFF] ^
crc32_lookup[13][(one >> 8) & 0xFF] ^
crc32_lookup[14][(one >> 16) & 0xFF] ^
crc32_lookup[15][(one >> 24) & 0xFF];
}
}
len -= bytes_at_once;
}
const uint8_t* current_char = (const uint8_t*) current;
/* remaining 1 to 15 bytes (standard algorithm) */
while (len-- != 0)
crc = (crc >> 8) ^ crc32_lookup[0][(crc & 0xFF) ^ *current_char++];
return ~crc;
}
/* merge two CRC32 such that result = crc32(dataB, lengthB, crc32(dataA, lengthA)) */
uint32_t uu_crc32_combine(uint32_t crcA, uint32_t crcB, size_t lengthB)
{
int i;
/*
* based on Mark Adler's crc_combine from
* https://github.com/madler/pigz/blob/master/pigz.c
* main idea:
* - if you have two equally-sized blocks A and B,
* then you can create a block C = A ^ B
* which has the property crc(C) = crc(A) ^ crc(B)
* - if you append length(B) zeros to A and call it A' (think of it as AAAA000)
* and prepend length(A) zeros to B and call it B' (think of it as 0000BBB)
* then exists a C' = A' ^ B'
* - remember: if you XOR someting with zero, it remains unchanged: X ^ 0 = X
* - that means C' = A concat B so that crc(A concat B) = crc(C') = crc(A') ^ crc(B')
* - the trick is to compute crc(A') based on crc(A)
* and crc(B') based on crc(B)
* - since B' starts with many zeros, the crc of those initial zeros is still zero
* - that means crc(B') = crc(B)
* - unfortunately the trailing zeros of A' change the crc, so usually crc(A') != crc(A)
* - the following code is a fast algorithm to compute crc(A')
* - starting with crc(A) and appending length(B) zeros, needing just log2(length(B)) iterations
* - the details are explained by the original author at
* https://stackoverflow.com/questions/23122312/crc-calculation-of-a-mostly-static-data-stream/23126768
*
* notes:
* - I squeezed everything into one function to keep global namespace clean (original code two helper functions)
* - most original comments are still in place, I added comments where these helper functions where made inline code
* - performance-wise there isn't any differenze to the original zlib/pigz code
*/
/* degenerated case */
if (lengthB == 0)
return crcA;
/* CRC32 => 32 bits */
const uint32_t CrcBits = 32;
uint32_t odd [CrcBits]; /* odd-power-of-two zeros operator */
uint32_t even[CrcBits]; /* even-power-of-two zeros operator */
/* put operator for one zero bit in odd */
odd[0] = Polynomial;
for (i = 1; i < CrcBits; i++)
odd[i] = 1 << (i - 1);
/* put operator for two zero bits in even */
/* same as gf2_matrix_square(even, odd); */
for (i = 0; i < CrcBits; i++)
{
int j;
uint32_t vec = odd[i];
even[i] = 0;
for (j = 0; vec != 0; j++, vec >>= 1)
if (vec & 1)
even[i] ^= odd[j];
}
/* put operator for four zero bits in odd */
/* same as gf2_matrix_square(odd, even); */
for (i = 0; i < CrcBits; i++)
{
int j;
uint32_t vec = even[i];
odd[i] = 0;
for (j = 0; vec != 0; j++, vec >>= 1)
if (vec & 1)
odd[i] ^= even[j];
}
/* the following loop becomes much shorter if I keep swapping even and odd */
uint32_t* a = even;
uint32_t* b = odd;
/* apply secondLength zeros to firstCrc32 */
for (; lengthB > 0; lengthB >>= 1)
{
/* same as gf2_matrix_square(a, b); */
for (i = 0; i < CrcBits; i++)
{
int j;
uint32_t vec = b[i];
a[i] = 0;
for (j = 0; vec != 0; j++, vec >>= 1)
( run in 0.808 second using v1.01-cache-2.11-cpan-96521ef73a4 )