Coverage Report

Created: 2025-06-24 06:38

/src/boost/boost/container_hash/detail/hash_mix.hpp
Line
Count
Source (jump to first uncovered line)
1
// Copyright 2022 Peter Dimov
2
// Distributed under the Boost Software License, Version 1.0.
3
// https://www.boost.org/LICENSE_1_0.txt
4
5
#ifndef BOOST_HASH_DETAIL_HASH_MIX_HPP
6
#define BOOST_HASH_DETAIL_HASH_MIX_HPP
7
8
#include <cstdint>
9
#include <cstddef>
10
#include <climits>
11
12
namespace boost
13
{
14
namespace hash_detail
15
{
16
17
template<std::size_t Bits> struct hash_mix_impl;
18
19
// hash_mix for 64 bit size_t
20
//
21
// The general "xmxmx" form of state of the art 64 bit mixers originates
22
// from Murmur3 by Austin Appleby, which uses the following function as
23
// its "final mix":
24
//
25
//  k ^= k >> 33;
26
//  k *= 0xff51afd7ed558ccd;
27
//  k ^= k >> 33;
28
//  k *= 0xc4ceb9fe1a85ec53;
29
//  k ^= k >> 33;
30
//
31
// (https://github.com/aappleby/smhasher/blob/master/src/MurmurHash3.cpp)
32
//
33
// It has subsequently been improved multiple times by different authors
34
// by changing the constants. The most well known improvement is the
35
// so-called "variant 13" function by David Stafford:
36
//
37
//  k ^= k >> 30;
38
//  k *= 0xbf58476d1ce4e5b9;
39
//  k ^= k >> 27;
40
//  k *= 0x94d049bb133111eb;
41
//  k ^= k >> 31;
42
//
43
// (https://zimbry.blogspot.com/2011/09/better-bit-mixing-improving-on.html)
44
//
45
// This mixing function is used in the splitmix64 RNG:
46
// http://xorshift.di.unimi.it/splitmix64.c
47
//
48
// We use Jon Maiga's implementation from
49
// http://jonkagstrom.com/mx3/mx3_rev2.html
50
//
51
//  x ^= x >> 32;
52
//  x *= 0xe9846af9b1a615d;
53
//  x ^= x >> 32;
54
//  x *= 0xe9846af9b1a615d;
55
//  x ^= x >> 28;
56
//
57
// An equally good alternative is Pelle Evensen's Moremur:
58
//
59
//  x ^= x >> 27;
60
//  x *= 0x3C79AC492BA7B653;
61
//  x ^= x >> 33;
62
//  x *= 0x1C69B3F74AC4AE35;
63
//  x ^= x >> 27;
64
//
65
// (https://mostlymangling.blogspot.com/2019/12/stronger-better-morer-moremur-better.html)
66
67
template<> struct hash_mix_impl<64>
68
{
69
    inline static std::uint64_t fn( std::uint64_t x )
70
0
    {
71
0
        std::uint64_t const m = 0xe9846af9b1a615d;
72
73
0
        x ^= x >> 32;
74
0
        x *= m;
75
0
        x ^= x >> 32;
76
0
        x *= m;
77
0
        x ^= x >> 28;
78
79
0
        return x;
80
0
    }
81
};
82
83
// hash_mix for 32 bit size_t
84
//
85
// We use the "best xmxmx" implementation from
86
// https://github.com/skeeto/hash-prospector/issues/19
87
88
template<> struct hash_mix_impl<32>
89
{
90
    inline static std::uint32_t fn( std::uint32_t x )
91
0
    {
92
0
        std::uint32_t const m1 = 0x21f0aaad;
93
0
        std::uint32_t const m2 = 0x735a2d97;
94
0
95
0
        x ^= x >> 16;
96
0
        x *= m1;
97
0
        x ^= x >> 15;
98
0
        x *= m2;
99
0
        x ^= x >> 15;
100
0
101
0
        return x;
102
0
    }
103
};
104
105
inline std::size_t hash_mix( std::size_t v )
106
0
{
107
0
    return hash_mix_impl<sizeof(std::size_t) * CHAR_BIT>::fn( v );
108
0
}
109
110
} // namespace hash_detail
111
} // namespace boost
112
113
#endif // #ifndef BOOST_HASH_DETAIL_HASH_MIX_HPP