Skip to content

Instantly share code, notes, and snippets.

@kripod
Last active August 2, 2020 14:56
Show Gist options
  • Save kripod/3203e25ef7feb3fee2852ca946612559 to your computer and use it in GitHub Desktop.
Save kripod/3203e25ef7feb3fee2852ca946612559 to your computer and use it in GitHub Desktop.
MurmurHash3_x86_32 in TypeScript
// Inspired by: https://github.com/levitation/murmurhash-js
function murmur3a(data: string, seed: number = 0): number {
const len = data.length;
const nBlocks = len >>> 2;
const tailOffset = nBlocks << 2;
let k1;
/* Body */
let i = 0;
for (; i < tailOffset; ++i) {
k1 =
(data.charCodeAt(i) & 0xff) |
((data.charCodeAt(++i) & 0xff) << 8) |
((data.charCodeAt(++i) & 0xff) << 16) |
((data.charCodeAt(++i) & 0xff) << 24);
k1 =
// Math.imul(k1, 0xcc9e2d51):
((k1 * 0xcc9e) << 16) + k1 * 0x2d51;
k1 =
// rotl32(k1, 15):
(k1 << 15) | (k1 >>> 17);
seed ^=
// Math.imul(k1, 0x1b873593):
((k1 * 0x1b87) << 16) + k1 * 0x3593;
seed =
0xe6546b64 +
5 *
// rotl32(seed, 13):
((seed << 13) | (seed >>> 19));
}
/* Tail */
if (tailOffset < len) {
k1 = 0;
for (i = len; i & 3; ) {
k1 <<= 8;
k1 |= data.charCodeAt(--i) & 0xff;
}
k1 =
// Math.imul(k1, 0xcc9e2d51):
((k1 * 0xcc9e) << 16) + k1 * 0x2d51;
k1 =
// rotl32(k1, 15):
(k1 << 15) | (k1 >>> 17);
seed ^=
// Math.imul(k1, 0x1b873593):
((k1 * 0x1b87) << 16) + k1 * 0x3593;
}
/* Finalization */
seed ^= len;
seed ^= seed >>> 16;
seed =
// Math.imul(seed, 0x85ebca6b):
((seed * 0x85eb) << 16) + seed * 0xca6b;
seed ^= seed >>> 13;
seed =
// Math.imul(seed, 0xc2b2ae35):
((seed * 0xc2b2) << 16) + seed * 0xae35;
return (seed ^ (seed >>> 16)) >>> 0;
}
// Source: https://stackoverflow.com/a/31929528
const tests = [
{ data: "", seed: 0, hash: 0 },
{ data: "", seed: 1, hash: 0x514e28b7 },
{ data: "", seed: 0xffffffff, hash: 0x81f16f39 },
{ data: "\xFF\xFF\xFF\xFF", seed: 0, hash: 0x76293b50 },
{ data: "\x21\x43\x65\x87", seed: 0, hash: 0xf55b516b },
{ data: "\x21\x43\x65\x87", seed: 0x5082edee, hash: 0x2362f9de },
{ data: "\x21\x43\x65", seed: 0, hash: 0x7e4a8634 },
{ data: "\x21\x43", seed: 0, hash: 0xa0f7b07a },
{ data: "\x21", seed: 0, hash: 0x72661cf4 },
{ data: "\x00\x00\x00\x00", seed: 0, hash: 0x2362f9de },
{ data: "\x00\x00\x00", seed: 0, hash: 0x85f0b427 },
{ data: "\x00\x00", seed: 0, hash: 0x30f4c306 },
{ data: "\x00", seed: 0, hash: 0x514e28b7 },
{ data: "a".repeat(256), seed: 0x9747b28c, hash: 0x37405bdc },
{
data: unescape(encodeURIComponent("ππππππππ")),
seed: 0x9747b28c,
hash: 0xd58063c1
}
];
tests.forEach(test => {
console.log(murmur3a(test.data, test.seed) === test.hash);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment