/* Hash function calculates 32bit hash value from the given object. HASH2INDEX macro maps the hash value to the bucket number. (On 64 bit architecture, it's OK to calculate 64bit, but the upper bits are discarded by HASH2INDEX to maintain compatibility. */
/* For String * * Usually, "shift+add" scheme for string hasing works well. But * I found that it works well only if you take the lower bits. * Unfortunately, we need to take higher bits for multiplicative * hashing of integers and addresses. So, in HASH2INDEX function, * I take both lower bits and higher bits. */
#define STRING_HASH(hv, chars, size) \ do { \ int i_ = (size); \ (hv) = 0; \ while (i_-- > 0) { \ (hv) = ((hv)<<5) - (hv) + ((unsigned char)*chars++); \ } \ } while (0)
h = h * 31 + c
どっかで、Javaも 31 * h + c だと聞いたような
コメントに、ハッシュの上位はあまりよくない、ので HASH2INDEX を使う、と書いてある:
/* HASH2INDEX Map a hash value to bucket number. We fix the word length to 32bits, since the multiplication constant above is fixed. */ #define HASH2INDEX(tabsiz, bits, hashval) \ (((hashval)+((hashval)>>(32-(bits)))) & ((tabsiz) - 1))
/* ## returns the `main' position of an element in a table (that is, the index ## of its hash value) */ static Node *mainposition(const Table *t, const TValue *key) { switch (ttype(key)) { case LUA_TNUMBER: return hashnum(t, nvalue(key)); case LUA_TSTRING: return hashstr(t, rawtsvalue(key)); case LUA_TBOOLEAN: ...
if (table->entries_packed) { int i; for (i = 0; i < table->num_entries; i++) { if ((st_data_t)table->bins[i*2] == key) { if (value !=0) *value = (st_data_t)table->bins[i*2+1]; return1; } } return0; }
int rb_str_hash(VALUE str) { return hash((constvoid *)RSTRING_PTR(str), RSTRING_LEN(str), 0); }
/* MurmurHash described in [http://murmurhash.googlepages.com/](http://murmurhash.googlepages.com/) */ unsignedint hash(constunsignedchar * data, int len, unsignedint h) { constunsignedint m = 0x7fd652ad; constint r = 16;
h += 0xdeadbeef;
if (len >= 4) { #if !UNALIGNED_WORD_ACCESS int align = (VALUE)data & 3; if (align) { uint32_t t = 0, d = 0; int sl, sr, pack;
switch (align) { #ifdef WORDS_BIGENDIAN case1: t |= data[2]; case2: t |= data[1] << 8; case3: t |= data[0] << 16; #else case1: t |= data[2] << 16; case2: t |= data[1] << 8; case3: t |= data[0]; #endif }
#ifdef WORDS_BIGENDIAN t >>= (8 * align) - 8; #else t <<= (8 * align); #endif
data += 4-align; len -= 4-align;
sl = 8 * (4-align); sr = 8 * align;
while (len >= 4) { d = *(uint32_t *)data; #ifdef WORDS_BIGENDIAN t = (t << sr) | (d >> sl); #else t = (t >> sr) | (d << sl); #endif h += t; h *= m; h ^= h >> r; t = d;
data += 4; len -= 4; }
pack = len < align ? len : align; d = 0; switch (pack) { #ifdef WORDS_BIGENDIAN case3: d |= data[2] << 8; case2: d |= data[1] << 16; case1: d |= data[0] << 24; case0: h += (t << sr) | (d >> sl); #else case3: d |= data[2] << 16; case2: d |= data[1] << 8; case1: d |= data[0]; case0: h += (t >> sr) | (d << sl); #endif h *= m; h ^= h >> r; }
data += pack; len -= pack; } else #endif { do { h += *(uint32_t *)data; h *= m; h ^= h >> r;
data += 4; len -= 4; } while (len >= 4); } }
switch(len) { #ifdef WORDS_BIGENDIAN case3: h += data[2] << 8; case2: h += data[1] << 16; case1: h += data[0] << 24; #else case3: h += data[2] << 16; case2: h += data[1] << 8; case1: h += data[0]; #endif h *= m; h ^= h >> r; }