Skip to content

Instantly share code, notes, and snippets.

@calvin2021y
Forked from lh3/inthash.c
Created November 25, 2021 09:39
Show Gist options
  • Save calvin2021y/3394e1a7caf178434be6c68fb0a19632 to your computer and use it in GitHub Desktop.
Save calvin2021y/3394e1a7caf178434be6c68fb0a19632 to your computer and use it in GitHub Desktop.
Invertible integer hash functions
/*
For any 1<k<=64, let mask=(1<<k)-1. hash_64() is a bijection on [0,1<<k), which means
hash_64(x, mask)==hash_64(y, mask) if and only if x==y. hash_64i() is the inversion of
hash_64(): hash_64i(hash_64(x, mask), mask) == hash_64(hash_64i(x, mask), mask) == x.
*/
// Thomas Wang's integer hash functions. See <https://gist.github.com/lh3/59882d6b96166dfc3d8d> for a snapshot.
uint64_t hash_64(uint64_t key, uint64_t mask)
{
key = (~key + (key << 21)) & mask; // key = (key << 21) - key - 1;
key = key ^ key >> 24;
key = ((key + (key << 3)) + (key << 8)) & mask; // key * 265
key = key ^ key >> 14;
key = ((key + (key << 2)) + (key << 4)) & mask; // key * 21
key = key ^ key >> 28;
key = (key + (key << 31)) & mask;
return key;
}
// The inversion of hash_64(). Modified from <https://naml.us/blog/tag/invertible>
uint64_t hash_64i(uint64_t key, uint64_t mask)
{
uint64_t tmp;
// Invert key = key + (key << 31)
tmp = (key - (key << 31));
key = (key - (tmp << 31)) & mask;
// Invert key = key ^ (key >> 28)
tmp = key ^ key >> 28;
key = key ^ tmp >> 28;
// Invert key *= 21
key = (key * 14933078535860113213ull) & mask;
// Invert key = key ^ (key >> 14)
tmp = key ^ key >> 14;
tmp = key ^ tmp >> 14;
tmp = key ^ tmp >> 14;
key = key ^ tmp >> 14;
// Invert key *= 265
key = (key * 15244667743933553977ull) & mask;
// Invert key = key ^ (key >> 24)
tmp = key ^ key >> 24;
key = key ^ tmp >> 24;
// Invert key = (~key) + (key << 21)
tmp = ~key;
tmp = ~(key - (tmp << 21));
tmp = ~(key - (tmp << 21));
key = ~(key - (tmp << 21)) & mask;
return key;
}
@calvin2021y
Copy link
Author

Tomas Wang

uint32_t hash32shift(uint32_t key)
{
  key = ~key + (key << 15); // key = (key << 15) - key - 1;
  key = key ^ (key >> 12);
  key = key + (key << 2);
  key = key ^ (key >> 4);
  key = key * 2057; // key = (key + (key << 3)) + (key << 11);
  key = key ^ (key >> 16);
  return key;
}

Bob Jenkins' 32 bit integer hash function
uint32_t hash( uint32_t a)
{
   a = (a+0x7ed55d16) + (a<<12);
   a = (a^0xc761c23c) ^ (a>>19);
   a = (a+0x165667b1) + (a<<5);
   a = (a+0xd3a2646c) ^ (a<<9);
   a =(a+0xfd7046c5) + (a<<3); // <<和 +的组合是可逆的
   a = (a^0xb55a4f09) ^ (a>>16); 
   return a;
}

这六个数是随机数, 通过设置合理的6个数,你可以找到对应的perfect hash.

 

64 bit Mix Functions
uint64_t hash64shift(uint64_t key)
{
  key = (~key) + (key << 21); // key = (key << 21) - key - 1;
  key = key ^ (key >> 24);
  key = (key + (key << 3)) + (key << 8); // key * 265
  key = key ^ (key >> 14);
  key = (key + (key << 2)) + (key << 4); // key * 21
  key = key ^ (key >> 28);
  key = key + (key << 31);
  return key;
}

64 bit to 32 bit Mix Functions
uint32_t hash64_32shift(uint64_t key)
{
  key = (~key) + (key << 18); // key = (key << 18) - key - 1;
  key = key ^ (key >> 31);
  key = key * 21; // key = (key + (key << 2)) + (key << 4);
  key = key ^ (key >> 11);
  key = key + (key << 6);
  key = key ^ (key >> 22);
  return (int) key;
}

Bob Jenkins' 96 bit Mix Function
uint32_t mix(uint32_t a, uint32_t b, uint32_t 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);
  return c;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment