-
-
Save calvin2021y/3394e1a7caf178434be6c68fb0a19632 to your computer and use it in GitHub Desktop.
Invertible integer hash functions
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| 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; | |
| } |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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; }