1 Linux内核进程管理里
将2^32做黄金分割的魔数常量0x9e370001UL。来自Linux内核进程管理里,PID转表索引的Hash计算。
unsigned long hash_long(unsigned long val, unsigned int bits)
{
unsigned long hash = val * 0x9e370001UL;
return hash >> (32 - bits);
}
2 iOS的CoreFoundation库里
CFBasicHash.c
// Prime numbers. Values above 100 have been adjusted up so that the
// malloced block size will be just below a multiple of 512; values
// above 1200 have been adjusted up to just below a multiple of 4096.
static const uintptr_t __CFBasicHashTableSizes[64] = {
0, 3, 7, 13, 23, 41, 71, 127, 191, 251, 383, 631, 1087, 1723,
2803, 4523, 7351, 11959, 19447, 31231, 50683, 81919, 132607,
214519, 346607, 561109, 907759, 1468927, 2376191, 3845119,
6221311, 10066421, 16287743, 26354171, 42641881, 68996069,
111638519, 180634607, 292272623, 472907251,
#if __LP64__
765180413UL, 1238087663UL, 2003267557UL, 3241355263UL, 5244622819UL,
#if 0
8485977589UL, 13730600407UL, 22216578047UL, 35947178479UL,
58163756537UL, 94110934997UL, 152274691561UL, 246385626107UL,
398660317687UL, 645045943807UL, 1043706260983UL, 1688752204787UL,
2732458465769UL, 4421210670577UL, 7153669136377UL,
11574879807461UL, 18728548943849UL, 30303428750843UL
#endif
#endif
};
(里面有dtrace探针)
3 iOS的runtime库里
#ifdef __arm64__
// 64 bit hash from https://gist.github.com/badboy/6267743.
static inline NSUInteger pointerHash(void *v) {
uintptr_t key = reinterpret_cast<uintptr_t>(v);
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;
}
#else
// Robert Jenkin's 32 bit int hash.
static inline NSUInteger pointerHash(void *v) {
uintptr_t a = reinterpret_cast<uintptr_t>(v);
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 (NSUInteger)a;
}
#endif
hashtable2.mm
指针/字符串的异或线性分桶
uintptr_t NXPtrHash (const void *info, const void *data) {
return (((uintptr_t) data) >> 16) ^ ((uintptr_t) data);
};
uintptr_t NXStrHash (const void *info, const void *data) {
uintptr_t hash = 0;
unsigned char *s = (unsigned char *) data;
/* unsigned to avoid a sign-extend */
/* unroll the loop */
if (s) for (; ; ) {
if (*s == '\0') break;
hash ^= (uintptr_t) *s++;
if (*s == '\0') break;
hash ^= (uintptr_t) *s++ << 8;
if (*s == '\0') break;
hash ^= (uintptr_t) *s++ << 16;
if (*s == '\0') break;
hash ^= (uintptr_t) *s++ << 24;
}
return hash;
};
objc-private.h
// Pointer hash function.
// This is not a terrific hash, but it is fast
// and not outrageously flawed for our purposes.
// Based on principles from http://locklessinc.com/articles/fast_hash/
// and evaluation ideas from http://floodyberry.com/noncryptohashzoo/
#if __LP64__
static inline uint32_t ptr_hash(uint64_t key)
{
key ^= key >> 4;
key *= 0x8a970be7488fda55;
key ^= __builtin_bswap64(key);
return (uint32_t)key;
}
#else
static inline uint32_t ptr_hash(uint32_t key)
{
key ^= key >> 4;
key *= 0x5052acdb;
key ^= __builtin_bswap32(key);
return key;
}
#endif