|
||||
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
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |