#include <stdio.h>
#include <stdint.h>
 
 
uint32_t crc_table[256];
 
/* Run this function previously */
void make_crc_table(void) {
    for (uint32_t i = 0; i < 256; i++) {
        uint32_t c = i;
        for (int j = 0; j < 8; j++) {
            c = (c & 1) ? (0xEDB88320 ^ (c >> 1)) : (c >> 1);
        }
        crc_table[i] = c;
    }
}
 
uint32_t crc32_wikipedia(const uint8_t *buf, size_t len) {
    uint32_t c = 0xFFFFFFFF;
    for (size_t i = 0; i < len; i++) {
        c = crc_table[(c ^ buf[i]) & 0xFF] ^ (c >> 8);
    }
    return c ^ 0xFFFFFFFF;
}
 
 
 
const uint32_t Polynomial = 0xEDB88320;
 
 uint32_t crc32_bitwise(const void* data, size_t length, uint32_t previousCrc32 = 0) { 
     uint32_t crc = ~previousCrc32; // same as previousCrc32 ^ 0xFFFFFFFF 
     unsigned char* current = (unsigned char*) data; 
     while (length--) { 
         crc ^= *current++; 
         for (unsigned int j = 0; j < 8; j++) 
         if (crc & 1) crc = (crc >> 1) ^ Polynomial; else crc = crc >> 1; 
 
     } 
     return ~crc; // same as crc ^ 0xFFFFFFFF 
} 
 
 
int main()
{
    make_crc_table();
    printf("%08x\n", crc32_wikipedia((const uint8_t *)"abcdefghijklmnopqrstuvwxyz", 26));
    printf("%08x\n", crc32_bitwise("abcdefghijklmnopqrstuvwxyz", 26, 0));
}
				I2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxzdGRpbnQuaD4KIAoKdWludDMyX3QgY3JjX3RhYmxlWzI1Nl07CiAKLyogUnVuIHRoaXMgZnVuY3Rpb24gcHJldmlvdXNseSAqLwp2b2lkIG1ha2VfY3JjX3RhYmxlKHZvaWQpIHsKICAgIGZvciAodWludDMyX3QgaSA9IDA7IGkgPCAyNTY7IGkrKykgewogICAgICAgIHVpbnQzMl90IGMgPSBpOwogICAgICAgIGZvciAoaW50IGogPSAwOyBqIDwgODsgaisrKSB7CiAgICAgICAgICAgIGMgPSAoYyAmIDEpID8gKDB4RURCODgzMjAgXiAoYyA+PiAxKSkgOiAoYyA+PiAxKTsKICAgICAgICB9CiAgICAgICAgY3JjX3RhYmxlW2ldID0gYzsKICAgIH0KfQogCnVpbnQzMl90IGNyYzMyX3dpa2lwZWRpYShjb25zdCB1aW50OF90ICpidWYsIHNpemVfdCBsZW4pIHsKICAgIHVpbnQzMl90IGMgPSAweEZGRkZGRkZGOwogICAgZm9yIChzaXplX3QgaSA9IDA7IGkgPCBsZW47IGkrKykgewogICAgICAgIGMgPSBjcmNfdGFibGVbKGMgXiBidWZbaV0pICYgMHhGRl0gXiAoYyA+PiA4KTsKICAgIH0KICAgIHJldHVybiBjIF4gMHhGRkZGRkZGRjsKfQoKCgpjb25zdCB1aW50MzJfdCBQb2x5bm9taWFsID0gMHhFREI4ODMyMDsKCiB1aW50MzJfdCBjcmMzMl9iaXR3aXNlKGNvbnN0IHZvaWQqIGRhdGEsIHNpemVfdCBsZW5ndGgsIHVpbnQzMl90IHByZXZpb3VzQ3JjMzIgPSAwKSB7IAogICAgIHVpbnQzMl90IGNyYyA9IH5wcmV2aW91c0NyYzMyOyAvLyBzYW1lIGFzIHByZXZpb3VzQ3JjMzIgXiAweEZGRkZGRkZGIAogICAgIHVuc2lnbmVkIGNoYXIqIGN1cnJlbnQgPSAodW5zaWduZWQgY2hhciopIGRhdGE7IAogICAgIHdoaWxlIChsZW5ndGgtLSkgeyAKICAgICAgICAgY3JjIF49ICpjdXJyZW50Kys7IAogICAgICAgICBmb3IgKHVuc2lnbmVkIGludCBqID0gMDsgaiA8IDg7IGorKykgCiAgICAgICAgIGlmIChjcmMgJiAxKSBjcmMgPSAoY3JjID4+IDEpIF4gUG9seW5vbWlhbDsgZWxzZSBjcmMgPSBjcmMgPj4gMTsgCiAgICAgICAgIAogICAgIH0gCiAgICAgcmV0dXJuIH5jcmM7IC8vIHNhbWUgYXMgY3JjIF4gMHhGRkZGRkZGRiAKfSAKCgppbnQgbWFpbigpCnsKICAgIG1ha2VfY3JjX3RhYmxlKCk7CiAgICBwcmludGYoIiUwOHhcbiIsIGNyYzMyX3dpa2lwZWRpYSgoY29uc3QgdWludDhfdCAqKSJhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5eiIsIDI2KSk7CiAgICBwcmludGYoIiUwOHhcbiIsIGNyYzMyX2JpdHdpc2UoImFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6IiwgMjYsIDApKTsKfQ==