私のキーは 64 ビットのアドレスで、出力は 1 バイトの数値 (0-255) です。衝突は許容されますが、発生する可能性は低くなければなりません。また、ピジョン ホール効果を最小限に抑えるために、挿入する要素の数が少なく、255 以下とします。
アドレスは、プログラム内の関数のアドレスです。
uint64_t addr = ...
uint8_t hash = addr & 0xFF;
あなたの要求をすべて満たしていると思います。
2 つの LSB (最下位バイト) を XOR し、これがうまく分配されない場合は、3 番目のバイトを追加します。
この背後にある理論的根拠は次のとおりです。関数アドレスは均一に分散されません。通常、問題は下位 (lsb) ビットにあります。関数は通常、4/8/16 で割り切れるアドレスで開始する必要があるため、2 ~ 4 lsb はおそらく無意味です。次のバイトと XOR することで、これらの問題のほとんどを取り除く必要があり、それでもかなり高速です。
関数アドレスは、整列されている可能性が非常に高いと思います (たとえば、この質問を参照してください)。これは、アライメントによっては、最下位ビットをスキップしたいことを示しているようです。
したがって、おそらくビット 3 から始まる 8 ビットを取得します。つまり、最下位 3 ビット (ビット 0 から 2) をスキップします。
const uint8_t hash = (address >> 3);
これは、一連のアドレスを調べれば明らかです。16 進数では、右端の桁に注意してください。
どうですか:
uint64_t data = 0x12131212121211B12;
uint32_t d1 = (data >> 32) ^ (uint32_t)(data);
uint16_t d2 = (d1 >> 16) ^ (uint16_t)(d1);
uint8_t d3 = (d2 >> 8) ^ (uint8_t)(d2);
return d3;
8バイトのすべてのビットを3つのシフトと3つのxor命令で組み合わせました.