static inline void u64to8_le(uint8_t *p, uint64_t v) { U32TO8_LE(p, v.lo); U32TO8_LE(p + 4, v.hi); }
int halfsiphash(const uint8_t *in, const size_t inlen, const uint8_t *k, uint8_t *out, const size_t outlen) { assert((outlen == 4) || (outlen == 8)); uint32_t v0 = 0; uint32_t v1 = 0; uint32_t v2 = 0x6c796765; uint32_t v3 = 0x74656462; uint32_t k0 = U8TO32_LE(k); uint32_t k1 = U8TO32_LE(k + 4); uint32_t m; int i; const uint8_t *end = in + inlen - (inlen % sizeof(uint32_t)); const int left = inlen & 3; uint32_t b = ((uint32_t)inlen) << 24; v3 ^= k1; v2 ^= k0; v1 ^= k1; v0 ^= k0; if (outlen == 8) v1 ^= 0xee; for (; in != end; in += 4) { m = U8TO32_LE(in); v3 ^= m; TRACE; for (i = 0; i < cROUNDS; ++i) SIPROUND; v0 ^= m; } switch (left) { case 3: b |= ((uint32_t)in[2]) << 16; case 2: b |= ((uint32_t)in[1]) << 8; case 1: b |= ((uint32_t)in[0]); break; case 0: break; } v3 ^= b; TRACE; for (i = 0; i < cROUNDS; ++i) SIPROUND; v0 ^= b; if (outlen == 8) v2 ^= 0xee; else v2 ^= 0xff; TRACE; for (i = 0; i < dROUNDS; ++i) SIPROUND; b = v1 ^ v3; U32TO8_LE(out, b); if (outlen == 4) return 0; v1 ^= 0xdd; TRACE; for (i = 0; i < dROUNDS; ++i) SIPROUND; b = v1 ^ v3; U32TO8_LE(out + 4, b); return 0; }