[comp.std.mumps] $CRC - CHECKSUM PROPOSAL

BROWN%FORUM.VA.GOV@plus5.UUCP (04/24/87)

detect all burst errors of 16 bits or less and at least 99.997%
of all longer burst errors (see {U}Computer Networks{u} by Andrew
S. Tanenbaum).  
 
 
PROPOSAL:
 
add in section 1.2.7:
 
$CRC    calculates a 16 bit cyclic redundancy checksum
 
 
add in section 3.2.8:
 
$CRC({U}expr1{u},[{U}intexpr2{u}])
 
calculates a CRC (Cyclic Redundancy Checksum) using the polyno-
mial 1021(hex).  The result will be in the closed interval [0-
65535].  The input data is {U}expr1{u}.  The optional second
argument, {U}intexpr1{u}, is an input from a previous invocation
of $CRC.  It is necessary for calculation of strings longer than
255 characters.  
Note that 2 extra nulls ($C(0,0) should be concatenated to the
end of the specified string for most communication systems (this
allows for the 2 byte checksum field).
 
 
 
METHODOLOGY
 
To calculate the 16 bit CRC the message bits are considered to be
the coefficients of a polynomial. This message polynomial is
first multiplied by X^16 and then divided by the generator poly-
nomial (X^16 + X^12 + X^5 + 1) using modulo two arithmetic.  The
remainder left after the division is the desired CRC.  For a
message block of 128 bytes or 1024 bits, the message polynomial
will be of order X^1023. The high order bit of the first byte of
the message block is the coefficient of X^1023 in the message
polynomial.  The low order bit of the last byte of the message
block is the coefficient of X^0 in the message polynomial.
 
 
Example of CRC Calculation written in C:
 
  /*
  * This function calculates the CRC
  * The first argument is a pointer to the message block.
  * The second argument is the number of bytes in the message
  block.
  * The function returns an integer which contains the CRC.
  * The low order 16 bits are the coefficients of the CRC.
  */
 
     int calcrc(ptr, count)
     char *ptr;
     int count;
     {
         int crc, i;
 
         crc = 0;
         while(--count >= 0) {
             crc = crc ^ (int)*ptr++ << 8;
             for(i = 0; i < 8; ++i)
                 if(crc & 0x8000)
                     crc = crc << 1 ^ 0x1021;
                 else
                     crc = crc << 1;
             }
         return (crc & 0xFFFF);
     }