ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Convert-UUlib/uulib/crc32.c
(Generate patch)

Comparing Convert-UUlib/uulib/crc32.c (file contents):
Revision 1.3 by root, Thu Feb 27 06:14:28 2020 UTC vs.
Revision 1.4 by root, Thu Feb 27 16:17:16 2020 UTC

25 */ 25 */
26 26
27#include "crc32.h" 27#include "crc32.h"
28 28
29#include "ecb.h" 29#include "ecb.h"
30#include <stdio.h>//D 30
31#define Polynomial 0xedb88320
31 32
32static const uint32_t crc32_lookup[16][256] = 33static const uint32_t crc32_lookup[16][256] =
33{ 34{
34 /* same algorithm as crc32_bitwise 35 /* same algorithm as crc32_bitwise
35 36
682 crc = (crc >> 8) ^ crc32_lookup[0][(crc & 0xFF) ^ *current_char++]; 683 crc = (crc >> 8) ^ crc32_lookup[0][(crc & 0xFF) ^ *current_char++];
683 684
684 return ~crc; 685 return ~crc;
685} 686}
686 687
688/* merge two CRC32 such that result = crc32(dataB, lengthB, crc32(dataA, lengthA)) */
689uint32_t uu_crc32_combine(uint32_t crcA, uint32_t crcB, size_t lengthB)
690{
691 /*
692 * based on Mark Adler's crc_combine from
693 * https://github.com/madler/pigz/blob/master/pigz.c
694
695 * main idea:
696 * - if you have two equally-sized blocks A and B,
697 * then you can create a block C = A ^ B
698 * which has the property crc(C) = crc(A) ^ crc(B)
699 * - if you append length(B) zeros to A and call it A' (think of it as AAAA000)
700 * and prepend length(A) zeros to B and call it B' (think of it as 0000BBB)
701 * then exists a C' = A' ^ B'
702 * - remember: if you XOR someting with zero, it remains unchanged: X ^ 0 = X
703 * - that means C' = A concat B so that crc(A concat B) = crc(C') = crc(A') ^ crc(B')
704 * - the trick is to compute crc(A') based on crc(A)
705 * and crc(B') based on crc(B)
706 * - since B' starts with many zeros, the crc of those initial zeros is still zero
707 * - that means crc(B') = crc(B)
708 * - unfortunately the trailing zeros of A' change the crc, so usually crc(A') != crc(A)
709 * - the following code is a fast algorithm to compute crc(A')
710 * - starting with crc(A) and appending length(B) zeros, needing just log2(length(B)) iterations
711 * - the details are explained by the original author at
712 * https://stackoverflow.com/questions/23122312/crc-calculation-of-a-mostly-static-data-stream/23126768
713 *
714 * notes:
715 * - I squeezed everything into one function to keep global namespace clean (original code two helper functions)
716 * - most original comments are still in place, I added comments where these helper functions where made inline code
717 * - performance-wise there isn't any differenze to the original zlib/pigz code
718 */
719
720 /* degenerated case */
721 if (lengthB == 0)
722 return crcA;
723
724 /* CRC32 => 32 bits */
725 const uint32_t CrcBits = 32;
726
727 uint32_t odd [CrcBits]; /* odd-power-of-two zeros operator */
728 uint32_t even[CrcBits]; /* even-power-of-two zeros operator */
729
730 /* put operator for one zero bit in odd */
731 odd[0] = Polynomial;
732 for (int i = 1; i < CrcBits; i++)
733 odd[i] = 1 << (i - 1);
734
735 /* put operator for two zero bits in even */
736 /* same as gf2_matrix_square(even, odd); */
737 for (int i = 0; i < CrcBits; i++)
738 {
739 uint32_t vec = odd[i];
740 even[i] = 0;
741 for (int j = 0; vec != 0; j++, vec >>= 1)
742 if (vec & 1)
743 even[i] ^= odd[j];
744 }
745 /* put operator for four zero bits in odd */
746 /* same as gf2_matrix_square(odd, even); */
747 for (int i = 0; i < CrcBits; i++)
748 {
749 uint32_t vec = even[i];
750 odd[i] = 0;
751 for (int j = 0; vec != 0; j++, vec >>= 1)
752 if (vec & 1)
753 odd[i] ^= even[j];
754 }
755
756 /* the following loop becomes much shorter if I keep swapping even and odd */
757 uint32_t* a = even;
758 uint32_t* b = odd;
759 /* apply secondLength zeros to firstCrc32 */
760 for (; lengthB > 0; lengthB >>= 1)
761 {
762 /* same as gf2_matrix_square(a, b); */
763 for (int i = 0; i < CrcBits; i++)
764 {
765 uint32_t vec = b[i];
766 a[i] = 0;
767 for (int j = 0; vec != 0; j++, vec >>= 1)
768 if (vec & 1)
769 a[i] ^= b[j];
770 }
771
772 /* apply zeros operator for this bit */
773 if (lengthB & 1)
774 {
775 /* same as firstCrc32 = gf2_matrix_times(a, firstCrc32); */
776 uint32_t sum = 0;
777 for (int i = 0; crcA != 0; i++, crcA >>= 1)
778 if (crcA & 1)
779 sum ^= a[i];
780 crcA = sum;
781 }
782
783 /* switch even and odd */
784 uint32_t* t = a; a = b; b = t;
785 }
786
787 /* return combined crc */
788 return crcA ^ crcB;
789}
790

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines