murmur-32
Version:
MurmurHash3 x86 32-bit implemented in JavaScript.
75 lines (59 loc) • 1.56 kB
JavaScript
import encodeUtf8 from 'encode-utf8'
import fmix from 'fmix'
const C = new Uint32Array([
0xcc9e2d51,
0x1b873593
])
function rotl (m, n) {
return (m << n) | (m >>> (32 - n))
}
function body (key, hash) {
const blocks = (key.byteLength / 4) | 0
const view32 = new Uint32Array(key, 0, blocks)
for (let i = 0; i < blocks; i++) {
view32[i] = Math.imul(view32[i], C[0])
view32[i] = rotl(view32[i], 15)
view32[i] = Math.imul(view32[i], C[1])
hash[0] = (hash[0] ^ view32[i])
hash[0] = rotl(hash[0], 13)
hash[0] = Math.imul(hash[0], 5) + 0xe6546b64
}
}
function tail (key, hash) {
const blocks = (key.byteLength / 4) | 0
const reminder = (key.byteLength % 4)
let k = 0
const tail = new Uint8Array(key, blocks * 4, reminder)
switch (reminder) {
case 3:
k = (k ^ (tail[2] << 16))
// fallthrough
case 2:
k = (k ^ (tail[1] << 8))
// fallthrough
case 1:
k = (k ^ (tail[0] << 0))
k = Math.imul(k, C[0])
k = rotl(k, 15)
k = Math.imul(k, C[1])
hash[0] = (hash[0] ^ k)
}
}
function finalize (key, hash) {
hash[0] = (hash[0] ^ key.byteLength)
hash[0] = fmix(hash[0])
}
export default function murmur (key, seed) {
seed = (seed ? (seed | 0) : 0)
if (typeof key === 'string') {
key = encodeUtf8(key)
}
if (!(key instanceof ArrayBuffer)) {
throw new TypeError('Expected key to be ArrayBuffer or string')
}
const hash = new Uint32Array([seed])
body(key, hash)
tail(key, hash)
finalize(key, hash)
return hash.buffer
}