// hash/crc16 — CRC-16 checksum. Pure ww. // // Inline polynomial-shift per byte (no precomputed tables). Slower // than a table-driven CRC by ~8x per byte but matches the // table-driven answer bit-for-bit. // // Polynomials are given in reversed form, matching Hare. package crc16; def CCITT: u16 = 0x8408u16; // X.25, Bluetooth, XMODEM def CMDA2000: u16 = 0xE613u16; // CDMA2000 infra def DECT: u16 = 0x91A0u16; // DECT cordless def ANSI: u16 = 0xA001u16; // Modbus, USB, ANSI X3.28 // sum16 — fold `buf` under `poly` and return ~cval. Initial value is // ~0u16, matching the streaming CRC-16 contract for a single // write-then-sum. Per byte: XOR low byte of cval with msg byte to form // an 8-bit index, run 8 polynomial shifts on that index, XOR the // result with the high byte of cval shifted down. export fn sum16(buf: []u8, poly: u16) u16 = { let c: u16 = 0xFFFFu16; let i: i32 = 0; for (i < buf.len) { let t: u16 = (c & 0xFFu16) ^ (buf[i]: u16); let z: i32 = 0; for (z < 8) { if ((t & 1u16) == 1u16) { t = (t >> 1u16) ^ poly; } else { t = t >> 1u16; }; z += 1; }; c = t ^ (c >> 8u16); i += 1; }; return ~c; }; export fn sum16ccitt(buf: []u8) u16 = { return sum16(buf, CCITT); }; export fn sum16cmda2000(buf: []u8) u16 = { return sum16(buf, CMDA2000); }; export fn sum16dect(buf: []u8) u16 = { return sum16(buf, DECT); }; export fn sum16ansi(buf: []u8) u16 = { return sum16(buf, ANSI); };