Практическое качество хеш-функции в некоторой степени зависит от того, какие свойства вам нужны и как распределяются ваши данные.
Если вам не нужно защищаться от злонамеренного ввода, пытаясь засорить вашу таблицу множеством конфликтующих значенийдостаточно простой функции.
Для коротких целых чисел Крис Уэллонс провел немало анализа , используя свою программу hash-prospector .
Упомянутая им хорошая 64-битная функция такова: здесь :
uint64_t splittable64(uint64_t x)
{
x ^= x >> 30;
x *= UINT64_C(0xbf58476d1ce4e5b9);
x ^= x >> 27;
x *= UINT64_C(0x94d049bb133111eb);
x ^= x >> 31;
return x;
}
Вы можете хешировать обе половины 128-битного целого и объединять их через XOR, вращатьодин из них, если вы ожидаете, что половинки часто идентичны.Таким образом, ваше решение может выглядеть примерно так:
class hash128i
{
public:
std::size_t operator()(const __m128i &r) const
{
uint64_t lower_hash = splittable64(static_cast<uint64_t>(r));
uint64_t upper_hash = splittable64(static_cast<uint64_t>(r >> 64));
uint64_t rotated_upper = upper_hash << 31 | upper_hash >> 33;
return lower_hash ^ rotated_upper;
}
};
Если ваша хеш-таблица должна быть защищена от злонамеренного ввода, вы можете использовать хеш-функцию с ключом, заполненную случайным ключом.Посмотрите на SIPHash .