diff options
Diffstat (limited to 'vendor/crc32fast/src/combine.rs')
-rw-r--r-- | vendor/crc32fast/src/combine.rs | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/vendor/crc32fast/src/combine.rs b/vendor/crc32fast/src/combine.rs new file mode 100644 index 0000000..4dd0ee0 --- /dev/null +++ b/vendor/crc32fast/src/combine.rs @@ -0,0 +1,77 @@ +const GF2_DIM: usize = 32; + +fn gf2_matrix_times(mat: &[u32; GF2_DIM], mut vec: u32) -> u32 { + let mut sum = 0; + let mut idx = 0; + while vec > 0 { + if vec & 1 == 1 { + sum ^= mat[idx]; + } + vec >>= 1; + idx += 1; + } + return sum; +} + +fn gf2_matrix_square(square: &mut [u32; GF2_DIM], mat: &[u32; GF2_DIM]) { + for n in 0..GF2_DIM { + square[n] = gf2_matrix_times(mat, mat[n]); + } +} + +pub(crate) fn combine(mut crc1: u32, crc2: u32, mut len2: u64) -> u32 { + let mut row: u32; + let mut even = [0u32; GF2_DIM]; /* even-power-of-two zeros operator */ + let mut odd = [0u32; GF2_DIM]; /* odd-power-of-two zeros operator */ + + /* degenerate case (also disallow negative lengths) */ + if len2 <= 0 { + return crc1; + } + + /* put operator for one zero bit in odd */ + odd[0] = 0xedb88320; /* CRC-32 polynomial */ + row = 1; + for n in 1..GF2_DIM { + odd[n] = row; + row <<= 1; + } + + /* put operator for two zero bits in even */ + gf2_matrix_square(&mut even, &odd); + + /* put operator for four zero bits in odd */ + gf2_matrix_square(&mut odd, &even); + + /* apply len2 zeros to crc1 (first square will put the operator for one + zero byte, eight zero bits, in even) */ + loop { + /* apply zeros operator for this bit of len2 */ + gf2_matrix_square(&mut even, &odd); + if len2 & 1 == 1 { + crc1 = gf2_matrix_times(&even, crc1); + } + len2 >>= 1; + + /* if no more bits set, then done */ + if len2 == 0 { + break; + } + + /* another iteration of the loop with odd and even swapped */ + gf2_matrix_square(&mut odd, &even); + if len2 & 1 == 1 { + crc1 = gf2_matrix_times(&odd, crc1); + } + len2 >>= 1; + + /* if no more bits set, then done */ + if len2 == 0 { + break; + } + } + + /* return combined crc */ + crc1 ^= crc2; + return crc1; +} |