telescope-0.2.0: src/checksum.c
#include "checksum.h"
#include <stdio.h>
// From FITS standard 4.0
int sum(int* array, int size) {
int total = 0;
for (int i = 0; i < size; i++) {
total += array[i];
}
return total;
}
// J.5. Example C code for accumulating the checksum
// --------------------------------------------------
unsigned int checksum (
unsigned char *buf,
int length)
{
unsigned int sum32 = 0;
unsigned int hi, lo, hicarry, locarry, i;
// Accumulate the sum of the high-order 16 bits and the */
// low-order 16 bits of each 32-bit word, separately. */
// The first byte in each pair is the most significant. */
// This algorithm works on both big and little endian machines.
hi = (sum32 >> 16);
lo = sum32 & 0xFFFF;
for (i=0; i < length; i+=4) {
hi += ((buf[i] << 8) + buf[i+1]);
lo += ((buf[i+2] << 8) + buf[i+3]);
}
// fold carry bits from each 16 bit sum into the other sum
hicarry = hi >> 16;
locarry = lo >> 16;
while (hicarry || locarry) {
hi = (hi & 0xFFFF) + locarry;
lo = (lo & 0xFFFF) + hicarry;
hicarry = hi >> 16;
locarry = lo >> 16;
}
// Concatenate the high and low parts to form the full 32-bit checksum
return (hi << 16) + lo;
}
// J.6. Example C code for ASCII encoding
// --------------------------------------------------
unsigned int exclude[13] = {0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60 };
int offset = 0x30; /* ASCII 0 (zero) */
unsigned long mask[4] = { 0xff000000, 0xff0000, 0xff00, 0xff };
void char_encode (
unsigned int value, // 1's complement of the checksum value to be encoded
char *ascii) // Output 16-character encoded string
{
int byte, quotient, remainder, ch[4], check, i, j, k; char asc[32];
for (i=0; i < 4; i++) {
/* each byte becomes four */
byte = (value & mask[i]) >> ((3 - i) * 8);
quotient = byte / 4 + offset;
remainder = byte % 4;
for (j=0; j < 4; j++)
ch[j] = quotient;
ch[0] += remainder;
// avoid ASCII punctuation
for (check=1; check;)
for (check=0, k=0; k < 13; k++)
for (j=0; j < 4; j+=2)
if (ch[j]==exclude[k] || ch[j+1]==exclude[k]) {
ch[j]++;
ch[j+1]--;
check++;
}
// assign the bytes
for (j=0; j < 4; j++)
asc[4*j+i] = ch[j];
}
// Permute the bytes for FITS
for (i=0; i < 16; i++)
ascii[i] = asc[(i+15)%16];
// terminate the string
ascii[16] = 0;
}