123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113 |
- // Copyright 2022 Peter Dimov
- // Distributed under the Boost Software License, Version 1.0.
- // https://www.boost.org/LICENSE_1_0.txt
- #ifndef BOOST_HASH_DETAIL_HASH_MIX_HPP
- #define BOOST_HASH_DETAIL_HASH_MIX_HPP
- #include <cstdint>
- #include <cstddef>
- #include <climits>
- namespace boost
- {
- namespace hash_detail
- {
- template<std::size_t Bits> struct hash_mix_impl;
- // hash_mix for 64 bit size_t
- //
- // The general "xmxmx" form of state of the art 64 bit mixers originates
- // from Murmur3 by Austin Appleby, which uses the following function as
- // its "final mix":
- //
- // k ^= k >> 33;
- // k *= 0xff51afd7ed558ccd;
- // k ^= k >> 33;
- // k *= 0xc4ceb9fe1a85ec53;
- // k ^= k >> 33;
- //
- // (https://github.com/aappleby/smhasher/blob/master/src/MurmurHash3.cpp)
- //
- // It has subsequently been improved multiple times by different authors
- // by changing the constants. The most well known improvement is the
- // so-called "variant 13" function by David Stafford:
- //
- // k ^= k >> 30;
- // k *= 0xbf58476d1ce4e5b9;
- // k ^= k >> 27;
- // k *= 0x94d049bb133111eb;
- // k ^= k >> 31;
- //
- // (https://zimbry.blogspot.com/2011/09/better-bit-mixing-improving-on.html)
- //
- // This mixing function is used in the splitmix64 RNG:
- // http://xorshift.di.unimi.it/splitmix64.c
- //
- // We use Jon Maiga's implementation from
- // http://jonkagstrom.com/mx3/mx3_rev2.html
- //
- // x ^= x >> 32;
- // x *= 0xe9846af9b1a615d;
- // x ^= x >> 32;
- // x *= 0xe9846af9b1a615d;
- // x ^= x >> 28;
- //
- // An equally good alternative is Pelle Evensen's Moremur:
- //
- // x ^= x >> 27;
- // x *= 0x3C79AC492BA7B653;
- // x ^= x >> 33;
- // x *= 0x1C69B3F74AC4AE35;
- // x ^= x >> 27;
- //
- // (https://mostlymangling.blogspot.com/2019/12/stronger-better-morer-moremur-better.html)
- template<> struct hash_mix_impl<64>
- {
- inline static std::uint64_t fn( std::uint64_t x )
- {
- std::uint64_t const m = 0xe9846af9b1a615d;
- x ^= x >> 32;
- x *= m;
- x ^= x >> 32;
- x *= m;
- x ^= x >> 28;
- return x;
- }
- };
- // hash_mix for 32 bit size_t
- //
- // We use the "best xmxmx" implementation from
- // https://github.com/skeeto/hash-prospector/issues/19
- template<> struct hash_mix_impl<32>
- {
- inline static std::uint32_t fn( std::uint32_t x )
- {
- std::uint32_t const m1 = 0x21f0aaad;
- std::uint32_t const m2 = 0x735a2d97;
- x ^= x >> 16;
- x *= m1;
- x ^= x >> 15;
- x *= m2;
- x ^= x >> 15;
- return x;
- }
- };
- inline std::size_t hash_mix( std::size_t v )
- {
- return hash_mix_impl<sizeof(std::size_t) * CHAR_BIT>::fn( v );
- }
- } // namespace hash_detail
- } // namespace boost
- #endif // #ifndef BOOST_HASH_DETAIL_HASH_MIX_HPP
|