blob: a7faf7bc080bebf0c0250284251041ad85bf3347 [file]
// Copyright 2011 Google Inc. All Rights Reserved.
//
// Contains the legacy Bob Jenkins Lookup2-based hashing routines. These need to
// always return the same results as their values have been recorded in various
// places and cannot easily be updated.
//
// Original Author: Sanjay Ghemawat
//
// This is based on Bob Jenkins newhash function
// see: http://burtleburtle.net/bob/hash/evahash.html
// According to http://burtleburtle.net/bob/c/lookup2.c,
// his implementation is public domain.
//
// The implementation here is backwards compatible with the google1
// implementation. The google1 implementation used a 'signed char *'
// to load words from memory a byte at a time. See gwshash.cc for an
// implementation that is compatible with Bob Jenkins' lookup2.c.
#include "gutil/hash/jenkins.h"
#include "common/logging.h"
#include "gutil/hash/jenkins_lookup2.h"
#include "gutil/integral_types.h"
static inline uint32 char2unsigned(char c) {
return static_cast<uint32>(static_cast<unsigned char>(c));
}
static inline uint64 char2unsigned64(char c) {
return static_cast<uint64>(static_cast<unsigned char>(c));
}
uint32 Hash32StringWithSeedReferenceImplementation(const char* s, uint32 len, uint32 c) {
uint32 a, b;
uint32 keylen;
a = b = 0x9e3779b9UL; // the golden ratio; an arbitrary value
for (keylen = len; keylen >= 3 * sizeof(a);
keylen -= static_cast<uint32>(3 * sizeof(a)), s += 3 * sizeof(a)) {
a += Google1At(s);
b += Google1At(s + sizeof(a));
c += Google1At(s + sizeof(a) * 2);
mix(a, b, c);
}
c += len;
switch (keylen) { // deal with rest. Cases fall through
case 11:
c += char2unsigned(s[10]) << 24;
case 10:
c += char2unsigned(s[9]) << 16;
case 9:
c += char2unsigned(s[8]) << 8;
// the first byte of c is reserved for the length
case 8:
b += Google1At(s + 4);
a += Google1At(s);
break;
case 7:
b += char2unsigned(s[6]) << 16;
case 6:
b += char2unsigned(s[5]) << 8;
case 5:
b += char2unsigned(s[4]);
case 4:
a += Google1At(s);
break;
case 3:
a += char2unsigned(s[2]) << 16;
case 2:
a += char2unsigned(s[1]) << 8;
case 1:
a += char2unsigned(s[0]);
// case 0 : nothing left to add
}
mix(a, b, c);
return c;
}
uint32 Hash32StringWithSeed(const char* s, uint32 len, uint32 c) {
uint32 a, b;
uint32 keylen;
a = b = 0x9e3779b9UL; // the golden ratio; an arbitrary value
keylen = len;
if (keylen >= 4 * sizeof(a)) {
uint32 word32AtOffset0 = Google1At(s);
do {
a += word32AtOffset0;
b += Google1At(s + sizeof(a));
c += Google1At(s + sizeof(a) * 2);
s += 3 * sizeof(a);
word32AtOffset0 = Google1At(s);
mix(a, b, c);
keylen -= 3 * static_cast<uint32>(sizeof(a));
} while (keylen >= 4 * sizeof(a));
if (keylen >= 3 * sizeof(a)) {
a += word32AtOffset0;
b += Google1At(s + sizeof(a));
c += Google1At(s + sizeof(a) * 2);
s += 3 * sizeof(a);
mix(a, b, c);
keylen -= 3 * static_cast<uint32>(sizeof(a));
DCHECK_LT(keylen, sizeof(a));
c += len;
switch (keylen) { // deal with rest. Cases fall through
case 3:
a += char2unsigned(s[2]) << 16;
case 2:
a += char2unsigned(s[1]) << 8;
case 1:
a += char2unsigned(s[0]);
}
} else {
DCHECK(sizeof(a) <= keylen && keylen < 3 * sizeof(a));
c += len;
switch (keylen) { // deal with rest. Cases fall through
case 11:
c += char2unsigned(s[10]) << 24;
case 10:
c += char2unsigned(s[9]) << 16;
case 9:
c += char2unsigned(s[8]) << 8;
case 8:
b += Google1At(s + 4);
a += word32AtOffset0;
break;
case 7:
b += char2unsigned(s[6]) << 16;
case 6:
b += char2unsigned(s[5]) << 8;
case 5:
b += char2unsigned(s[4]);
case 4:
a += word32AtOffset0;
break;
}
}
} else {
if (keylen >= 3 * sizeof(a)) {
a += Google1At(s);
b += Google1At(s + sizeof(a));
c += Google1At(s + sizeof(a) * 2);
s += 3 * sizeof(a);
mix(a, b, c);
keylen -= 3 * static_cast<uint32>(sizeof(a));
}
c += len;
switch (keylen) { // deal with rest. Cases fall through
case 11:
c += char2unsigned(s[10]) << 24;
case 10:
c += char2unsigned(s[9]) << 16;
case 9:
c += char2unsigned(s[8]) << 8;
case 8:
b += Google1At(s + 4);
a += Google1At(s);
break;
case 7:
b += char2unsigned(s[6]) << 16;
case 6:
b += char2unsigned(s[5]) << 8;
case 5:
b += char2unsigned(s[4]);
case 4:
a += Google1At(s);
break;
case 3:
a += char2unsigned(s[2]) << 16;
case 2:
a += char2unsigned(s[1]) << 8;
case 1:
a += char2unsigned(s[0]);
}
}
mix(a, b, c);
return c;
}
uint64 Hash64StringWithSeed(const char* s, uint32 len, uint64 c) {
uint64 a, b;
uint32 keylen;
a = b = GG_ULONGLONG(0xe08c1d668b756f82); // the golden ratio; an arbitrary value
for (keylen = len; keylen >= 3 * sizeof(a);
keylen -= 3 * static_cast<uint32>(sizeof(a)), s += 3 * sizeof(a)) {
a += Word64At(s);
b += Word64At(s + sizeof(a));
c += Word64At(s + sizeof(a) * 2);
mix(a, b, c);
}
c += len;
switch (keylen) { // deal with rest. Cases fall through
case 23:
c += char2unsigned64(s[22]) << 56;
case 22:
c += char2unsigned64(s[21]) << 48;
case 21:
c += char2unsigned64(s[20]) << 40;
case 20:
c += char2unsigned64(s[19]) << 32;
case 19:
c += char2unsigned64(s[18]) << 24;
case 18:
c += char2unsigned64(s[17]) << 16;
case 17:
c += char2unsigned64(s[16]) << 8;
// the first byte of c is reserved for the length
case 16:
b += Word64At(s + 8);
a += Word64At(s);
break;
case 15:
b += char2unsigned64(s[14]) << 48;
case 14:
b += char2unsigned64(s[13]) << 40;
case 13:
b += char2unsigned64(s[12]) << 32;
case 12:
b += char2unsigned64(s[11]) << 24;
case 11:
b += char2unsigned64(s[10]) << 16;
case 10:
b += char2unsigned64(s[9]) << 8;
case 9:
b += char2unsigned64(s[8]);
case 8:
a += Word64At(s);
break;
case 7:
a += char2unsigned64(s[6]) << 48;
case 6:
a += char2unsigned64(s[5]) << 40;
case 5:
a += char2unsigned64(s[4]) << 32;
case 4:
a += char2unsigned64(s[3]) << 24;
case 3:
a += char2unsigned64(s[2]) << 16;
case 2:
a += char2unsigned64(s[1]) << 8;
case 1:
a += char2unsigned64(s[0]);
// case 0: nothing left to add
}
mix(a, b, c);
return c;
}