|
| 1 | +DESCRIPTION = "MurmurHash3 with seed 0x4CDC03" |
| 2 | +TYPE = 'unsigned_int' |
| 3 | +# Test must match the exact hash of the string 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789' |
| 4 | +TEST_1 = 0x991F78B3 |
| 5 | + |
| 6 | +def murmur_hash_finalize(hash_value): |
| 7 | + hash_value = (hash_value ^ (hash_value >> 16)) & 0xFFFFFFFF |
| 8 | + hash_value = (hash_value * 0x85EBCA6B) & 0xFFFFFFFF |
| 9 | + hash_value = (hash_value ^ (hash_value >> 13)) & 0xFFFFFFFF |
| 10 | + hash_value = (hash_value * 0xC2B2AE35) & 0xFFFFFFFF |
| 11 | + hash_value = (hash_value ^ (hash_value >> 16)) & 0xFFFFFFFF |
| 12 | + return hash_value |
| 13 | + |
| 14 | +def hash(data): |
| 15 | + if isinstance(data, str): |
| 16 | + data = data.encode('ascii') |
| 17 | + |
| 18 | + length = len(data) |
| 19 | + hash_val = 0x4CDC03 |
| 20 | + |
| 21 | + c1 = 0xCC9E2D51 |
| 22 | + c2 = 0x1B873593 |
| 23 | + |
| 24 | + num_chunks = length // 4 |
| 25 | + for i in range(-num_chunks, 0): |
| 26 | + chunk_offset = (num_chunks + i) * 4 |
| 27 | + |
| 28 | + chunk = 0 |
| 29 | + for j in range(4): |
| 30 | + chunk |= data[chunk_offset + j] << (j * 8) |
| 31 | + |
| 32 | + chunk = (chunk * c1) & 0xFFFFFFFF |
| 33 | + chunk = ((chunk << 15) | (chunk >> 17)) & 0xFFFFFFFF |
| 34 | + chunk = (chunk * c2) & 0xFFFFFFFF |
| 35 | + hash_val ^= chunk |
| 36 | + hash_val = ((hash_val << 13) | (hash_val >> 19)) & 0xFFFFFFFF |
| 37 | + hash_val = ((hash_val * 5) - 0x19AB949C) & 0xFFFFFFFF |
| 38 | + |
| 39 | + remaining = length & 3 |
| 40 | + if remaining > 0: |
| 41 | + tail = 0 |
| 42 | + tail_start = num_chunks * 4 |
| 43 | + |
| 44 | + if remaining == 3: |
| 45 | + tail ^= data[tail_start + 2] << 16 |
| 46 | + if remaining >= 2: |
| 47 | + tail ^= data[tail_start + 1] << 8 |
| 48 | + if remaining >= 1: |
| 49 | + tail ^= data[tail_start] |
| 50 | + |
| 51 | + tail = (tail * c1) & 0xFFFFFFFF |
| 52 | + tail = ((tail << 15) | (tail >> 17)) & 0xFFFFFFFF |
| 53 | + tail = (tail * c2) & 0xFFFFFFFF |
| 54 | + hash_val ^= tail |
| 55 | + |
| 56 | + hash_val ^= length |
| 57 | + return murmur_hash_finalize(hash_val) |
0 commit comments