def _Py_HashBytes(val, _len): if (_len == 0): return process_return(0) if (_len < _Py_HASH_CUTOFF): # TODO: this branch needs testing, needs a CPython setup for it! # /* Optimize hashing of very small strings with inline DJBX33A. */ _hash = _Py_uhash_t(5381) # /* DJBX33A starts with 5381 */ for idx in range(_len): _hash = ((_hash << 5) + _hash) + np.uint8(grab_byte(val, idx)) _hash ^= _len _hash ^= _load_hashsecret('djbx33a_suffix') else: tmp = _siphash24(types.uint64(_load_hashsecret('siphash_k0')), types.uint64(_load_hashsecret('siphash_k1')), val, _len) _hash = process_return(tmp) return process_return(_hash)
def _siphash24(k0, k1, src, src_sz): b = types.uint64(src_sz) << 56 v0 = k0 ^ types.uint64(0x736f6d6570736575) v1 = k1 ^ types.uint64(0x646f72616e646f6d) v2 = k0 ^ types.uint64(0x6c7967656e657261) v3 = k1 ^ types.uint64(0x7465646279746573) idx = 0 while (src_sz >= 8): mi = grab_uint64_t(src, idx) idx += 1 src_sz -= 8 v3 ^= mi v0, v1, v2, v3 = _DOUBLE_ROUND(v0, v1, v2, v3) v0 ^= mi # this is the switch fallthrough: # https://github.com/python/cpython/blob/d1dd6be613381b996b9071443ef081de8e5f3aff/Python/pyhash.c#L390-L400 # noqa: E501 t = types.uint64(0x0) boffset = idx * 8 ohexefef = types.uint64(0xff) if src_sz >= 7: jmp = (6 * 8) mask = ~types.uint64(ohexefef << jmp) t = (t & mask) | (types.uint64(grab_byte(src, boffset + 6)) << jmp) if src_sz >= 6: jmp = (5 * 8) mask = ~types.uint64(ohexefef << jmp) t = (t & mask) | (types.uint64(grab_byte(src, boffset + 5)) << jmp) if src_sz >= 5: jmp = (4 * 8) mask = ~types.uint64(ohexefef << jmp) t = (t & mask) | (types.uint64(grab_byte(src, boffset + 4)) << jmp) if src_sz >= 4: t &= types.uint64(0xffffffff00000000) for i in range(4): jmp = i * 8 mask = ~types.uint64(ohexefef << jmp) t = (t & mask) | (types.uint64(grab_byte(src, boffset + i)) << jmp) if src_sz >= 3: jmp = (2 * 8) mask = ~types.uint64(ohexefef << jmp) t = (t & mask) | (types.uint64(grab_byte(src, boffset + 2)) << jmp) if src_sz >= 2: jmp = (1 * 8) mask = ~types.uint64(ohexefef << jmp) t = (t & mask) | (types.uint64(grab_byte(src, boffset + 1)) << jmp) if src_sz >= 1: mask = ~(ohexefef) t = (t & mask) | (types.uint64(grab_byte(src, boffset + 0))) b |= t v3 ^= b v0, v1, v2, v3 = _DOUBLE_ROUND(v0, v1, v2, v3) v0 ^= b v2 ^= ohexefef v0, v1, v2, v3 = _DOUBLE_ROUND(v0, v1, v2, v3) v0, v1, v2, v3 = _DOUBLE_ROUND(v0, v1, v2, v3) t = (v0 ^ v1) ^ (v2 ^ v3) return t