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

static uint8_t gfmult(uint8_t a, uint8_t b)
{
  uint8_t v = 0;

  while ( b ) {
    if ( b & 1 ) v ^= a;
    a = (a << 1) ^ (((int8_t)a >> 7) & 0x1d);
    b >>= 1;
  }
  return v;
}

static uint8_t gfpow(uint8_t a, int b)
{
  uint8_t v = 1;

  b %= 255;
  if ( b < 0 )
    b += 255;

  while ( b ) {
    if ( b & 1 ) v = gfmult(v,a);
    a = gfmult(a,a);
    b >>= 1;
  }
  return v;
}

struct matrix {
  uint8_t i, j, flag;
};

int main(int argc, char *argv[])
{
  int maxdisks = (argc > 1) ? atoi(argv[1]) : 64;
  int pi, pj, xi, xj;
  int errors;
  uint8_t qi, qj, i, j, f, g;
  uint8_t gen = 0x02;
  struct matrix matrix[256][256];
  
  if ( 0 ) {
    unsigned char mask[256];
    int err;
    
    for ( i = 2 ; i ; i++ ) {
      err = 0;
      memset(mask, 0, 256);
      for ( j = 1 ; j < 255 ; j++ ) {
	if ( (qi = gfpow(i,j)) < 2 || mask[qi] )
	  err = 1;
	else
	  mask[qi] = 1;
      }
      if ( !err ) {
	printf("Using generator: %02x\n", (gen = i));
	break;
      }
    }
    if ( err ) {
      printf("No generator found.\n");
      exit(1);
    }
  }
  
  for ( pi = 0 ; pi < maxdisks ; pi++ ) {
    qi = gfpow(gen,pi);

    for ( pj = 0 ; pj < maxdisks ; pj++ ) {
      if ( pi == pj )
	continue;

      qj = gfpow(gen,pj);

      printf("pi %3d, pj %3d, qi %02x, qj %02x: ", pi, pj, qi, qj);
      fflush(stdout);

      memset(matrix, 0, sizeof matrix);
      errors = 0;
      for ( xi = 0 ; xi < 256 ; xi++ ) {
	for ( xj = 0 ; xj < 256 ; xj++ ) {
	  i = xi;  j = xj;
	  f = i^j;
	  g = gfmult(qi,i)^gfmult(qj,j);
#if 0
	  printf("i = %02x, j = %02x, f = %02x, g = %02x\n", i, j, f, g);
#endif
	  if ( matrix[f][g].flag ) {
	    errors++;
	  } else {
	    matrix[f][g].i    = i;
	    matrix[f][g].j    = j;
	    matrix[f][g].flag = 1;
	  }
	}
      }

      if ( errors ) {
	printf("%d collisions\n", errors);
	exit(1);
      } else {
	printf("OK\n");
      }
    }
  }

  return 0;
}


