(it turns out the meaning of life is not 42
, i's 5381
and 33
!)
"cyrb53" (actually 64 bits (2x 32 bits in parallel), but limited to Javascript 53-bit integers)
Uses Math.imul()
.
"cyrb32"
Uses Math.imul()
.
export const cyrb32: Hasher = (value: string): string => {
let h = 9
for (let index = value.length; index--; ) {
h = Math.imul(h ^ value.charCodeAt(index), 0x5f356495)
}
return 'tw-' + ((h ^ (h >>> 9)) >>> 0).toString(36)
}
https://github.com/unjs/murmurhash-es
/**
* JS Implementation of MurmurHash2
*
*
* @param {Uint8Array | string} str ASCII only
* @param {number} seed Positive integer only
* @return {number} 32-bit positive integer hash
*/
export function murmurHashV2(str, seed = 0) {
if (typeof str === 'string') {
str = createBuffer(str);
}
let l = str.length
let h = seed ^ l
let i = 0
let k
while (l >= 4) {
k =
((str[i] & 0xff)) |
((str[++i] & 0xff) << 8) |
((str[++i] & 0xff) << 16) |
((str[++i] & 0xff) << 24);
k = (((k & 0xffff) * 0x5bd1e995) + ((((k >>> 16) * 0x5bd1e995) & 0xffff) << 16));
k ^= k >>> 24;
k = (((k & 0xffff) * 0x5bd1e995) + ((((k >>> 16) * 0x5bd1e995) & 0xffff) << 16));
h = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16)) ^ k;
l -= 4;
++i;
}
switch (l) {
case 3: h ^= (str[i + 2] & 0xff) << 16;
case 2: h ^= (str[i + 1] & 0xff) << 8;
case 1: h ^= (str[i] & 0xff);
h = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16));
}
h ^= h >>> 13;
h = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16));
h ^= h >>> 15;
return h >>> 0;
};
/**
* JS Implementation of MurmurHash3 (r136) (as of May 20, 2011)
*
* @param {Uint8Array | string} key ASCII only
* @param {number} seed Positive integer only
* @return {number} 32-bit positive integer hash
*/
export function murmurHashV3(key, seed = 0) {
if (typeof key === 'string') {
key = createBuffer(key);
}
let remainder, bytes, h1, h1b, c1, c2, k1, i;
remainder = key.length & 3; // key.length % 4
bytes = key.length - remainder;
h1 = seed;
c1 = 0xcc9e2d51;
c2 = 0x1b873593;
i = 0;
while (i < bytes) {
k1 =
((key[i] & 0xff)) |
((key[++i] & 0xff) << 8) |
((key[++i] & 0xff) << 16) |
((key[++i] & 0xff) << 24);
++i;
k1 = ((((k1 & 0xffff) * c1) + ((((k1 >>> 16) * c1) & 0xffff) << 16))) & 0xffffffff;
k1 = (k1 << 15) | (k1 >>> 17);
k1 = ((((k1 & 0xffff) * c2) + ((((k1 >>> 16) * c2) & 0xffff) << 16))) & 0xffffffff;
h1 ^= k1;
h1 = (h1 << 13) | (h1 >>> 19);
h1b = ((((h1 & 0xffff) * 5) + ((((h1 >>> 16) * 5) & 0xffff) << 16))) & 0xffffffff;
h1 = (((h1b & 0xffff) + 0x6b64) + ((((h1b >>> 16) + 0xe654) & 0xffff) << 16));
}
k1 = 0;
switch (remainder) {
case 3: k1 ^= (key[i + 2] & 0xff) << 16;
case 2: k1 ^= (key[i + 1] & 0xff) << 8;
case 1: k1 ^= (key[i] & 0xff);
k1 = (((k1 & 0xffff) * c1) + ((((k1 >>> 16) * c1) & 0xffff) << 16)) & 0xffffffff;
k1 = (k1 << 15) | (k1 >>> 17);
k1 = (((k1 & 0xffff) * c2) + ((((k1 >>> 16) * c2) & 0xffff) << 16)) & 0xffffffff;
h1 ^= k1;
}
h1 ^= key.length;
h1 ^= h1 >>> 16;
h1 = (((h1 & 0xffff) * 0x85ebca6b) + ((((h1 >>> 16) * 0x85ebca6b) & 0xffff) << 16)) & 0xffffffff;
h1 ^= h1 >>> 13;
h1 = ((((h1 & 0xffff) * 0xc2b2ae35) + ((((h1 >>> 16) * 0xc2b2ae35) & 0xffff) << 16))) & 0xffffffff;
h1 ^= h1 >>> 16;
return h1 >>> 0;
}
"cyrb32"
Uses Math.imul()
polyfill.
const imul =
Math.imul ||
((opA: number, opB: number): number => {
/* eslint-disable unicorn/prefer-math-trunc */
// Ensure that opB is an integer. opA will automatically be coerced.
opB |= 0
// Floating points give us 53 bits of precision to work with plus 1 sign bit
// automatically handled for our convienence:
// 1. 0x003fffff /*opA & 0x000fffff*/ * 0x7fffffff /*opB*/ = 0x1fffff7fc00001
// 0x1fffff7fc00001 < Number.MAX_SAFE_INTEGER /*0x1fffffffffffff*/
let result = (opA & 0x003fffff) * opB
// 2. We can remove an integer coersion from the statement above because:
// 0x1fffff7fc00001 + 0xffc00000 = 0x1fffffff800001
// 0x1fffffff800001 < Number.MAX_SAFE_INTEGER /*0x1fffffffffffff*/
if (opA & 0xffc00000 /* !== 0 */) result += ((opA & 0xffc00000) * opB) | 0
return result | 0
/* eslint-enable unicorn/prefer-math-trunc */
})
// Based on https://stackoverflow.com/a/52171480
export const cyrb32: Hasher = (value: string): string => {
let h = 9
for (let index = value.length; index--; ) {
h = imul(h ^ value.charCodeAt(index), 0x5f356495)
}
return '_' + ((h ^ (h >>> 9)) >>> 0).toString(36)
}
let i = 0, l = str.length, out = 11;
while (i < l) out = (101 * out + str.charCodeAt(i++)) >>> 0
const c = 'go' + out;
See improved perf proposal: cristianbote/goober#271
var hash = function (str) {
var h = 5381, i = str.length;
while (i) h = (h * 33) ^ str.charCodeAt(--i);
return '_' + (h >>> 0).toString(36);
};
const hashCode = string =>
[...string].reduce(
(hash, char) => ((hash << 5) - hash + char.charCodeAt(0)) | 0,
0
);
export function hash(str: string): string {
str = str.replace(/\r/g, '');
let hash = 5381;
let i = str.length;
while (i--) hash = ((hash << 5) - hash) ^ str.charCodeAt(i);
return (hash >>> 0).toString(36);
}
"djb2"
export default function hash(text: string): string {
if (!text) {
return '';
}
let hashValue = 5381;
let index = text.length - 1;
while (index) {
hashValue = (hashValue * 33) ^ text.charCodeAt(index);
index -= 1;
}
return (hashValue >>> 0).toString(16);
}
(truncated MD5)
const crypto = require('crypto');
module.exports = input => {
if (typeof input !== 'string' && !Buffer.isBuffer(input)) {
throw new TypeError('Expected a Buffer or string');
}
return crypto.createHash('md5').update(input).digest('hex').slice(0, 10);
};
export function createHash(str) {
let i = str.length;
if (i === 0) return 0;
let hash = 5381;
while (i) hash = (hash * 33) ^ str.charCodeAt(--i);
return hash >>> 0;
}
function hash(text) {
'use strict';
var hash = 5381,
index = text.length;
while (index) {
hash = (hash * 33) ^ text.charCodeAt(--index);
}
return hash >>> 0;
}
"djb2"-ish
export const SEED = 5381;
// When we have separate strings it's useful to run a progressive
// version of djb2 where we pretend that we're still looping over
// the same string
export const phash = (h: number, x: string): number => {
let i = x.length;
while (i) {
h = (h * 33) ^ x.charCodeAt(--i);
}
return h;
};
// This is a djb2 hashing function
export const hash = (x: string): number => {
return phash(SEED, x);
};
function hash(str) {
var hash = 5381,
i = str.length;
while(i) {
hash = (hash * 33) ^ str.charCodeAt(--i);
}
/* JavaScript does bitwise operations (like XOR, above) on 32-bit signed
* integers. Since we want the results to be always positive, convert the
* signed int to an unsigned by doing an unsigned bitshift. */
return hash >>> 0;
}
const sdbm = string => {
let hash = 0;
for (let i = 0; i < string.length; i++) {
hash = string.charCodeAt(i) + (hash << 6) + (hash << 16) - hash;
}
// Convert it to an unsigned 32-bit integer
return hash >>> 0;
};
function fnv1a(string) {
// Handle Unicode code points > 0x7f
let hash = Number(FNV_OFFSETS[32]);
let isUnicoded = false;
for (let i = 0; i < string.length; i++) {
let characterCode = string.charCodeAt(i);
// Non-ASCII characters trigger the Unicode escape logic
if (characterCode > 0x7F && !isUnicoded) {
string = unescape(encodeURIComponent(string));
characterCode = string.charCodeAt(i);
isUnicoded = true;
}
hash ^= characterCode;
hash += (hash << 1) + (hash << 4) + (hash << 7) + (hash << 8) + (hash << 24);
}
return hash >>> 0;
}
const MAGIC_CONSTANT = 5381;
const djb2a = string => {
let hash = MAGIC_CONSTANT;
for (let i = 0; i < string.length; i++) {
// Equivalent to: `hash * 33 ^ string.charCodeAt(i)`
hash = ((hash << 5) + hash) ^ string.charCodeAt(i);
}
// Convert it to an unsigned 32-bit integer
return hash >>> 0;
};
"dbj2" spinoff
export function getIntegerHashValue(string) {
let index = string.length,
hashA = 5381,
hashB = 52711,
charCode;
while (index--) {
charCode = charCodeAt.call(string, index);
hashA = (hashA * 33) ^ charCode;
hashB = (hashB * 33) ^ charCode;
}
return (hashA >>> 0) * 4096 + (hashB >>> 0);
}
Based on "murmur" hash (see below)
export default function murmur2(str: string) {
// 'm' and 'r' are mixing constants generated offline.
// They're not really 'magic', they just happen to work well.
// const m = 0x5bd1e995;
// const r = 24;
// Initialize the hash
var h = 0
// Mix 4 bytes at a time into the hash
var k,
i = 0,
len = str.length
for (; len >= 4; ++i, len -= 4) {
k =
(str.charCodeAt(i) & 0xff) |
((str.charCodeAt(++i) & 0xff) << 8) |
((str.charCodeAt(++i) & 0xff) << 16) |
((str.charCodeAt(++i) & 0xff) << 24)
k =
/* Math.imul(k, m): */
(k & 0xffff) * 0x5bd1e995 + (((k >>> 16) * 0xe995) << 16)
k ^= /* k >>> r: */ k >>> 24
h =
/* Math.imul(k, m): */
((k & 0xffff) * 0x5bd1e995 + (((k >>> 16) * 0xe995) << 16)) ^
/* Math.imul(h, m): */
((h & 0xffff) * 0x5bd1e995 + (((h >>> 16) * 0xe995) << 16))
}
// Handle the last few bytes of the input array
switch (len) {
case 3:
h ^= (str.charCodeAt(i + 2) & 0xff) << 16
case 2:
h ^= (str.charCodeAt(i + 1) & 0xff) << 8
case 1:
h ^= str.charCodeAt(i) & 0xff
h =
/* Math.imul(h, m): */
(h & 0xffff) * 0x5bd1e995 + (((h >>> 16) * 0xe995) << 16)
}
// Do a few final mixes of the hash to ensure the last few
// bytes are well-incorporated.
h ^= h >>> 13
h =
/* Math.imul(h, m): */
(h & 0xffff) * 0x5bd1e995 + (((h >>> 16) * 0xe995) << 16)
return ((h ^ (h >>> 15)) >>> 0).toString(36)
}
"murmur" hash
function doHash(str: string, seed: number = 0) {
const m = 0x5bd1e995;
const r = 24;
let h = seed ^ str.length;
let length = str.length;
let currentIndex = 0;
while (length >= 4) {
let k = UInt32(str, currentIndex);
k = Umul32(k, m);
k ^= k >>> r;
k = Umul32(k, m);
h = Umul32(h, m);
h ^= k;
currentIndex += 4;
length -= 4;
}
switch (length) {
case 3:
h ^= UInt16(str, currentIndex);
h ^= str.charCodeAt(currentIndex + 2) << 16;
h = Umul32(h, m);
break;
case 2:
h ^= UInt16(str, currentIndex);
h = Umul32(h, m);
break;
case 1:
h ^= str.charCodeAt(currentIndex);
h = Umul32(h, m);
break;
}
h ^= h >>> 13;
h = Umul32(h, m);
h ^= h >>> 15;
return h >>> 0;
}
Murmur
let l = str.length;
let h = seed ^ l;
let i = 0;
let k;
while (l >= 4) {
k =
(str.charCodeAt(i) & 0xff) |
((str.charCodeAt(++i) & 0xff) << 8) |
((str.charCodeAt(++i) & 0xff) << 16) |
((str.charCodeAt(++i) & 0xff) << 24);
k = (k & 0xffff) * 0x5bd1e995 + ((((k >>> 16) * 0x5bd1e995) & 0xffff) << 16);
k ^= k >>> 24;
k = (k & 0xffff) * 0x5bd1e995 + ((((k >>> 16) * 0x5bd1e995) & 0xffff) << 16);
h = ((h & 0xffff) * 0x5bd1e995 + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16)) ^ k;
l -= 4;
++i;
}
switch (l) {
case 3:
h ^= (str.charCodeAt(i + 2) & 0xff) << 16;
case 2:
h ^= (str.charCodeAt(i + 1) & 0xff) << 8;
case 1:
h ^= str.charCodeAt(i) & 0xff;
h = (h & 0xffff) * 0x5bd1e995 + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16);
}
h ^= h >>> 13;
h = (h & 0xffff) * 0x5bd1e995 + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16);
h ^= h >>> 15;
return (h >>> 0).toString(36);
function murmurhash3_32_gc(key, seed) {
var remainder, bytes, h1, h1b, c1, c1b, c2, c2b, k1, i;
remainder = key.length & 3; // key.length % 4
bytes = key.length - remainder;
h1 = seed;
c1 = 0xcc9e2d51;
c2 = 0x1b873593;
i = 0;
while (i < bytes) {
k1 =
((key.charCodeAt(i) & 0xff)) |
((key.charCodeAt(++i) & 0xff) << 8) |
((key.charCodeAt(++i) & 0xff) << 16) |
((key.charCodeAt(++i) & 0xff) << 24);
++i;
k1 = ((((k1 & 0xffff) * c1) + ((((k1 >>> 16) * c1) & 0xffff) << 16))) & 0xffffffff;
k1 = (k1 << 15) | (k1 >>> 17);
k1 = ((((k1 & 0xffff) * c2) + ((((k1 >>> 16) * c2) & 0xffff) << 16))) & 0xffffffff;
h1 ^= k1;
h1 = (h1 << 13) | (h1 >>> 19);
h1b = ((((h1 & 0xffff) * 5) + ((((h1 >>> 16) * 5) & 0xffff) << 16))) & 0xffffffff;
h1 = (((h1b & 0xffff) + 0x6b64) + ((((h1b >>> 16) + 0xe654) & 0xffff) << 16));
}
k1 = 0;
switch (remainder) {
case 3: k1 ^= (key.charCodeAt(i + 2) & 0xff) << 16;
case 2: k1 ^= (key.charCodeAt(i + 1) & 0xff) << 8;
case 1: k1 ^= (key.charCodeAt(i) & 0xff);
k1 = (((k1 & 0xffff) * c1) + ((((k1 >>> 16) * c1) & 0xffff) << 16)) & 0xffffffff;
k1 = (k1 << 15) | (k1 >>> 17);
k1 = (((k1 & 0xffff) * c2) + ((((k1 >>> 16) * c2) & 0xffff) << 16)) & 0xffffffff;
h1 ^= k1;
}
h1 ^= key.length;
h1 ^= h1 >>> 16;
h1 = (((h1 & 0xffff) * 0x85ebca6b) + ((((h1 >>> 16) * 0x85ebca6b) & 0xffff) << 16)) & 0xffffffff;
h1 ^= h1 >>> 13;
h1 = ((((h1 & 0xffff) * 0xc2b2ae35) + ((((h1 >>> 16) * 0xc2b2ae35) & 0xffff) << 16))) & 0xffffffff;
h1 ^= h1 >>> 16;
return h1 >>> 0;
}
export function hash (value, length) {
return (((((((length << 2) ^ charat(value, 0)) << 2) ^ charat(value, 1)) << 2) ^ charat(value, 2)) << 2) ^ charat(value, 3)
}