/* Program to compute various checksums.  The input to each function is an
   array of m bytes; the output is an unsigned 32-bit integer.  The input
   bytes are considered to be a huge integer, given most-significant-byte
   first.   */

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>

unsigned int
mod255( unsigned char *x, int m )
{
  int i;
  unsigned int sum=0;

  assert(m>=0);
  assert(m<(1<<24));		/* else `sum' might overflow 32 bits */
  for(i=0; i<m; i++)
    sum += x[i];		/* add up the 8-bit "digits" of `x[]' */
  while(sum>255)
    sum = (sum&0xFF)+(sum>>8);	/* add up the 8-bit "digits" of `sum' */
  return sum;
}

unsigned int
mod257( unsigned char *x, int m )
{
  int i;
  unsigned int sumeven=0, sumodd=0, sum;
  assert(m>=0);
  assert(m<(1<<24));		/* else the sums might overflow 32 bits */
  for(i=m-1; i>=0; i-=2)
    sumeven += x[i];		/* add up the even 8-bit "digits" of `x[]' */
  for(i=m-2; i>=0; i-=2)
    sumodd += x[i];		/* add up the odd 8-bit "digits" of `x[]' */
  sumeven %=257; sumodd %=257;	/* reduce modulo 257 in 32-bit arithmetic */
  if(sumeven<sumodd) sumeven += 257; /* insure a positive difference */
  sum = sumeven-sumodd;		/* always in the range [1,...,257] */
  assert(sum>=1); assert(sum<=257);
  return sum;
}


int
main(void)
{
  char inname[2048], *in;
  int len;
  FILE *infile;

  printf("Checksums -- \n");
  printf("Enter input file name: ");
  scanf("%s", inname);
  infile = fopen(inname, "rb");  assert(infile);
  printf("Enter input file length (bytes): ");
  scanf("%d", &len);   assert(len>0);
  in = (unsigned char *)calloc(len, sizeof(unsigned char));  assert(in);
  fread(in, sizeof(unsigned char), len, infile);
  fclose(infile);

  printf("Mod255 checksum: %u\n", mod255(in, len) );
  printf("Mod257 checksum: %u\n", mod257(in, len) );

  free(in);
  exit(0);
}
