next up previous FITS Documents
Next: ASCII Encoding Up: Example C Code Previous: Example C Code

Accumulating the Checksum

The 1's complement checksum is simple to compute and very fast. A third of the following C code implementation handles odd length input records--a case that does not apply to FITS. Just zero sum32 and step through the FITS records (after initializing the CHECKSUM keyword to '0000000000000000'):

checksum (buf, length, sum32)
char *buf;
int length;                     /* < 2^18, or carry can overflow */
unsigned int *sum32;
{
        /* ints are assumed to be 32 bits */
        unsigned short *sbuf;
        unsigned int hi, lo, hicarry, locarry;
        int len, remain, i;

        sbuf = (unsigned short *) buf;
        len = 2*(length / 4);   /* make sure it's even */
        remain = length % 4;    /* add odd bytes below */

        hi = (*sum32 >> 16);
        lo = (*sum32 << 16) >> 16;
        for (i=0; i < len; i+=2) {
            hi += sbuf[i];
            lo += sbuf[i+1];
        }
        if (remain >= 1) hi += buf[2*len] * 0x100;
        if (remain >= 2) hi += buf[2*len+1];
        if (remain == 3) lo += buf[2*len+2] * 0x100;

        hicarry = hi >> 16;     /* fold carry bits in */
        locarry = lo >> 16;
        while (hicarry || locarry) {
            hi = (hi & 0xFFFF) + locarry;
            lo = (lo & 0xFFFF) + hicarry;
            hicarry = hi >> 16;
            locarry = lo >> 16;
        }
        *sum32 = (hi << 16) + lo;
}

If this routine is adapted to operate on non-FITS data, the restriction on the length of the individual buffers can be relaxed by explicitly folding the carry bits back into the sum frequently enough to avoid overflowing the unsigned integer arithmetic. This is not a problem with FITS data since the logical record size is at most 28,800 bytes.