//Copyright Michael Niedermayer 2005 / GPL

#include <stdio.h>
#include <string.h>

#define BLOCK_SIZE (1<<19) // MAX is 1<<20
#define TRYS 500
#define G  0x04C11DB7

static int get_error(unsigned int crc, unsigned int len, int *error){
    int i;

    for(i=0; i<len; i++){
        if(!(crc & ~255)){
            *error= crc;
            return i;
        }
        crc= (crc>>1) ^ (((G>>1)|0x80000000) & (-(crc&1)));
    }
    return -1;
}

static int get_crc(char *val, int len){
    int j, v=0;
    for(j=0; j<len; j++){
        if(val[j] & ~1) fprintf(stderr, "error3\n");
        v= ((v<<1) + val[j]) ^ (G & (v>>31));
    }
    return v;
}

main(){
    unsigned int i,j,k,v,crc;
    char val[BLOCK_SIZE];
    int error;

    for(i=0; i<TRYS; i++){
        int e;

        memset(val, 0, sizeof(val));
        for(j=0; j<BLOCK_SIZE-32; j++){
            val[j]= rand()&1;
        }
        v= get_crc(val, BLOCK_SIZE);
        crc= v;
        for(j=BLOCK_SIZE-32; j<BLOCK_SIZE; j++){
            val[j]= v>>31;
            v<<=1;
        }
        v= get_crc(val, BLOCK_SIZE);
        if(v) fprintf(stderr, "error\n");

        j= rand() % (BLOCK_SIZE-7);
        error = (rand() % 128) + 128;
        for(k=0; k<8; k++){
            val[BLOCK_SIZE - j - k - 1] ^= (error>>k)&1;
        }
        v= get_crc(val, BLOCK_SIZE);

        k= get_error(v, BLOCK_SIZE, &e);
        if(k != j || error != e ) 
            fprintf(stderr, "error2 %d %d %X %X %X %X\n", j, k, error, e, v, crc);
        fprintf(stderr, ".");
    }
    fprintf(stderr, "\n");
}

