Compute A 16-bit Sum With Carry
Join the DZone community and get the full member experience.
Join For Free
/**************************************************************************/
/* compute a 16-bit sum with carry */
/* nice feature of sum with carry is that it is byte order independent */
/* carry from hi-bit of one byte goes into lo-bit of other byte */
/* NOTE: assumes data in buf is in net format */
/**************************************************************************/
u_short
xsum(buf,len)
char *buf;
int len;
{
register u_short *sp;
register int slen;
register u_long sum; /* >= 32-bit space to keep sum */
union { u_short s; u_char c[2]; } xun;
int unaligned;
sum = 0;
unaligned = ((unsigned long)buf) & 0x1;
/* If buffer isn't short aligned, need to get fisst byte */
if (unaligned != 0) {
xun.s = 0;
xun.c[1] = buf[0];
sum = xun.s;
buf++; len--;
}
slen = len/2; /* length in shorts */
/* LINT NOTE: next line has possible ptr alignment message, even
though we've made sure that buf is aligned */
for(sp = (u_short *)buf; slen > 0; slen--,sp++) {
sum += *sp;
}
/* is there a trailing odd byte? */
if ((len & 0x1) != 0) {
#ifdef DEBUG
printf("xsum extra: 0x%X (sum: 0x%X, len %d.)\n", buf[len-1], sum, len);
#endif
xun.s = 0; xun.c[0] = buf[len - 1];
sum += xun.s;
}
/* Fold in all the carries to get a single 16 bit value */
sum = (sum & 0xFFFF) + (((unsigned long)(sum & 0xFFFF0000))>>16);
if (sum > 0xFFFF)
{ sum = (sum & 0xFFFF) + 1; }
if (unaligned != 0) /* byteswap */
{ sum = ((sum & 0xFF)<<8) + ((sum & 0xFF00)>>8); }
return (sum);
}
Opinions expressed by DZone contributors are their own.
Comments