ceph/branches/sage/pgs/crush/Hash.h
sageweil 9213a23f14 eek
git-svn-id: https://ceph.svn.sf.net/svnroot/ceph@1138 29311d96-e01e-0410-9327-a35deaab8ce9
2007-02-28 18:42:55 +00:00

288 lines
7.1 KiB
C++

// Robert Jenkins' function for mixing 32-bit values
// http://burtleburtle.net/bob/hash/evahash.html
// a, b = random bits, c = input and output
#define hashmix(a,b,c) \
a=a-b; a=a-c; a=a^(c>>13); \
b=b-c; b=b-a; b=b^(a<<8); \
c=c-a; c=c-b; c=c^(b>>13); \
a=a-b; a=a-c; a=a^(c>>12); \
b=b-c; b=b-a; b=b^(a<<16); \
c=c-a; c=c-b; c=c^(b>>5); \
a=a-b; a=a-c; a=a^(c>>3); \
b=b-c; b=b-a; b=b^(a<<10); \
c=c-a; c=c-b; c=c^(b>>15);
namespace crush {
class Hash {
int seed;
public:
int get_seed() { return seed; }
void set_seed(int s) { seed = s; }
Hash(int s) {
unsigned int hash = 1315423911;
int x = 231232;
int y = 1232;
hashmix(s, x, hash);
hashmix(y, s, hash);
seed = s;
}
inline int operator()(int a) {
unsigned int hash = seed ^ a;
int b = a;
int x = 231232;
int y = 1232;
hashmix(b, x, hash);
hashmix(y, a, hash);
return (hash & 0x7FFFFFFF);
}
inline int operator()(int a, int b) {
unsigned int hash = seed ^ a ^ b;
int x = 231232;
int y = 1232;
hashmix(a, b, hash);
hashmix(x, a, hash);
hashmix(b, y, hash);
return (hash & 0x7FFFFFFF);
}
inline int operator()(int a, int b, int c) {
unsigned int hash = seed ^ a ^ b ^ c;
int x = 231232;
int y = 1232;
hashmix(a, b, hash);
hashmix(c, x, hash);
hashmix(y, a, hash);
hashmix(b, x, hash);
hashmix(y, c, hash);
return (hash & 0x7FFFFFFF);
}
inline int operator()(int a, int b, int c, int d) {
unsigned int hash = seed ^a ^ b ^ c ^ d;
int x = 231232;
int y = 1232;
hashmix(a, b, hash);
hashmix(c, d, hash);
hashmix(a, x, hash);
hashmix(y, b, hash);
hashmix(c, x, hash);
hashmix(y, d, hash);
return (hash & 0x7FFFFFFF);
}
inline int operator()(int a, int b, int c, int d, int e) {
unsigned int hash = seed ^ a ^ b ^ c ^ d ^ e;
int x = 231232;
int y = 1232;
hashmix(a, b, hash);
hashmix(c, d, hash);
hashmix(e, x, hash);
hashmix(y, a, hash);
hashmix(b, x, hash);
hashmix(y, c, hash);
hashmix(d, x, hash);
hashmix(y, e, hash);
return (hash & 0x7FFFFFFF);
}
};
}
#if 0
//return myhash(a) ^ seed;
return myhash(a, seed);
}
int operator()(int a, int b) {
//return myhash( myhash(a) ^ myhash(b) ^ seed );
return myhash(a, b, seed);
}
int operator()(int a, int b, int c) {
//return myhash( myhash(a ^ seed) ^ myhash(b ^ seed) ^ myhash(c ^ seed) ^ seed );
return myhash(a, b, c, seed);
}
int operator()(int a, int b, int c, int d) {
//return myhash( myhash(a ^ seed) ^ myhash(b ^ seed) ^ myhash(c ^ seed) ^ myhash(d ^ seed) ^ seed );
return myhash(a, b, c, d, seed);
}
// ethan's rush hash?
if (0)
return (n ^ 0xdead1234) * (884811920 * 3 + 1);
if (1) {
// before
hash ^= ((hash << 5) + (n&255) + (hash >> 2));
hashmix(a, b, hash);
n = n >> 8;
hash ^= ((hash << 5) + (n&255) + (hash >> 2));
hashmix(a, b, hash);
n = n >> 8;
hash ^= ((hash << 5) + (n&255) + (hash >> 2));
hashmix(a, b, hash);
n = n >> 8;
hash ^= ((hash << 5) + (n&255) + (hash >> 2));
hashmix(a, b, hash);
n = n >> 8;
//return hash;
return (hash & 0x7FFFFFFF);
}
// JS
// a little better than RS
// + jenkin's mixing thing (which sucks on its own but helps tons here)
// best so far
if (1) {
unsigned int hash = 1315423911;
int a = 231232;
int b = 1232;
for(unsigned int i = 0; i < 4; i++)
{
hash ^= ((hash << 5) + (n&255) + (hash >> 2));
hashmix(a, b, hash);
n = n >> 8;
}
return (hash & 0x7FFFFFFF);
}
// Robert jenkins' 96 bit mix
// sucks
if (0) {
int c = n;
int a = 12378912;
int b = 2982827;
a=a-b; a=a-c; a=a^(c>>13);
b=b-c; b=b-a; b=b^(a<<8);
c=c-a; c=c-b; c=c^(b>>13);
a=a-b; a=a-c; a=a^(c>>12);
b=b-c; b=b-a; b=b^(a<<16);
c=c-a; c=c-b; c=c^(b>>5);
a=a-b; a=a-c; a=a^(c>>3);
b=b-c; b=b-a; b=b^(a<<10);
c=c-a; c=c-b; c=c^(b>>15);
return c;
}
// robert jenkins 32-bit
// sucks
if (0) {
n += (n << 12);
n ^= (n >> 22);
n += (n << 4);
n ^= (n >> 9);
n += (n << 10);
n ^= (n >> 2);
n += (n << 7);
n ^= (n >> 12);
return n;
}
// djb2
if (0) {
unsigned int hash = 5381;
for (int i=0; i<4; i++) {
hash = ((hash << 5) + hash) + ((n&255) ^ 123);
n = n >> 8;
}
return hash;
}
// SDBM
if (1) {
unsigned int hash = 0;
for(unsigned int i = 0; i < 4; i++)
{
hash = (n&255) + (hash << 6) + (hash << 16) - hash;
n = n >> 8;
}
return (hash & 0x7FFFFFFF);
}
// PJW
// horrid
if (0) {
unsigned int BitsInUnsignedInt = (unsigned int)(sizeof(unsigned int) * 8);
unsigned int ThreeQuarters = (unsigned int)((BitsInUnsignedInt * 3) / 4);
unsigned int OneEighth = (unsigned int)(BitsInUnsignedInt / 8);
unsigned int HighBits = (unsigned int)(0xFFFFFFFF) << (BitsInUnsignedInt - OneEighth);
unsigned int hash = 0;
unsigned int test = 0;
for(unsigned int i = 0; i < 4; i++)
{
hash = (hash << OneEighth) + (n&255);
if((test = hash & HighBits) != 0)
{
hash = (( hash ^ (test >> ThreeQuarters)) & (~HighBits));
}
n = n >> 8;
}
return (hash & 0x7FFFFFFF);
}
// RS Hash function, from Robert Sedgwicks Algorithms in C book, w/ some changes.
if (0) {
unsigned int b = 378551;
unsigned int a = 63689;
unsigned int hash = 0;
for(unsigned int i=0; i<4; i++)
{
hash = hash * a + (n&0xff);
a = a * b;
n = n >> 8;
}
return (hash & 0x7FFFFFFF);
}
// DJB
// worse than rs
if (0) {
unsigned int hash = 5381;
for(unsigned int i = 0; i < 4; i++)
{
hash = ((hash << 5) + hash) + (n&255);
n = n >> 8;
}
return (hash & 0x7FFFFFFF);
}
// AP
// even worse
if (1) {
unsigned int hash = 0;
for(unsigned int i = 0; i < 4; i++)
{
hash ^= ((i & 1) == 0) ? ( (hash << 7) ^ (n&255) ^ (hash >> 3)) :
(~((hash << 11) ^ (n&255) ^ (hash >> 5)));
n = n >> 8;
}
return (hash & 0x7FFFFFFF);
}
#endif