Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:30:23

0001 // Copyright 2022 Peter Dimov
0002 // Distributed under the Boost Software License, Version 1.0.
0003 // https://www.boost.org/LICENSE_1_0.txt
0004 
0005 #ifndef BOOST_HASH_DETAIL_HASH_MIX_HPP
0006 #define BOOST_HASH_DETAIL_HASH_MIX_HPP
0007 
0008 #include <cstdint>
0009 #include <cstddef>
0010 #include <climits>
0011 
0012 namespace boost
0013 {
0014 namespace hash_detail
0015 {
0016 
0017 template<std::size_t Bits> struct hash_mix_impl;
0018 
0019 // hash_mix for 64 bit size_t
0020 //
0021 // The general "xmxmx" form of state of the art 64 bit mixers originates
0022 // from Murmur3 by Austin Appleby, which uses the following function as
0023 // its "final mix":
0024 //
0025 //  k ^= k >> 33;
0026 //  k *= 0xff51afd7ed558ccd;
0027 //  k ^= k >> 33;
0028 //  k *= 0xc4ceb9fe1a85ec53;
0029 //  k ^= k >> 33;
0030 //
0031 // (https://github.com/aappleby/smhasher/blob/master/src/MurmurHash3.cpp)
0032 //
0033 // It has subsequently been improved multiple times by different authors
0034 // by changing the constants. The most well known improvement is the
0035 // so-called "variant 13" function by David Stafford:
0036 //
0037 //  k ^= k >> 30;
0038 //  k *= 0xbf58476d1ce4e5b9;
0039 //  k ^= k >> 27;
0040 //  k *= 0x94d049bb133111eb;
0041 //  k ^= k >> 31;
0042 //
0043 // (https://zimbry.blogspot.com/2011/09/better-bit-mixing-improving-on.html)
0044 //
0045 // This mixing function is used in the splitmix64 RNG:
0046 // http://xorshift.di.unimi.it/splitmix64.c
0047 //
0048 // We use Jon Maiga's implementation from
0049 // http://jonkagstrom.com/mx3/mx3_rev2.html
0050 //
0051 //  x ^= x >> 32;
0052 //  x *= 0xe9846af9b1a615d;
0053 //  x ^= x >> 32;
0054 //  x *= 0xe9846af9b1a615d;
0055 //  x ^= x >> 28;
0056 //
0057 // An equally good alternative is Pelle Evensen's Moremur:
0058 //
0059 //  x ^= x >> 27;
0060 //  x *= 0x3C79AC492BA7B653;
0061 //  x ^= x >> 33;
0062 //  x *= 0x1C69B3F74AC4AE35;
0063 //  x ^= x >> 27;
0064 //
0065 // (https://mostlymangling.blogspot.com/2019/12/stronger-better-morer-moremur-better.html)
0066 
0067 template<> struct hash_mix_impl<64>
0068 {
0069     inline static std::uint64_t fn( std::uint64_t x )
0070     {
0071         std::uint64_t const m = 0xe9846af9b1a615d;
0072 
0073         x ^= x >> 32;
0074         x *= m;
0075         x ^= x >> 32;
0076         x *= m;
0077         x ^= x >> 28;
0078 
0079         return x;
0080     }
0081 };
0082 
0083 // hash_mix for 32 bit size_t
0084 //
0085 // We use the "best xmxmx" implementation from
0086 // https://github.com/skeeto/hash-prospector/issues/19
0087 
0088 template<> struct hash_mix_impl<32>
0089 {
0090     inline static std::uint32_t fn( std::uint32_t x )
0091     {
0092         std::uint32_t const m1 = 0x21f0aaad;
0093         std::uint32_t const m2 = 0x735a2d97;
0094 
0095         x ^= x >> 16;
0096         x *= m1;
0097         x ^= x >> 15;
0098         x *= m2;
0099         x ^= x >> 15;
0100 
0101         return x;
0102     }
0103 };
0104 
0105 inline std::size_t hash_mix( std::size_t v )
0106 {
0107     return hash_mix_impl<sizeof(std::size_t) * CHAR_BIT>::fn( v );
0108 }
0109 
0110 } // namespace hash_detail
0111 } // namespace boost
0112 
0113 #endif // #ifndef BOOST_HASH_DETAIL_HASH_MIX_HPP