KiCad PCB EDA Suite
Loading...
Searching...
No Matches
mmh3_hash.h
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2024 Alex Shvartzkop <[email protected]>
5 * Copyright (C) 2024 Kicad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, you may find one here:
19 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20 * or you may search the http://www.gnu.org website for the version 2 license,
21 * or you may write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23 */
24
25// Based on https://github.com/aappleby/smhasher/blob/master/src/MurmurHash3.cpp
26//-----------------------------------------------------------------------------
27// MurmurHash3 was written by Austin Appleby, and is placed in the public
28// domain. The author hereby disclaims copyright to this source code.
29
30#ifndef MMH3_HASH_H_
31#define MMH3_HASH_H_
32
33#include <hash_128.h>
34
35//-----------------------------------------------------------------------------
36// Platform-specific functions and macros
37
38// Microsoft Visual Studio
39#if defined( _MSC_VER )
40 #define FORCE_INLINE __forceinline
41 #include <stdlib.h>
42 #define ROTL64( x, y ) _rotl64( x, y )
43 #define BIG_CONSTANT( x ) ( x )
44 // Other compilers
45#else // defined(_MSC_VER)
46 #define FORCE_INLINE inline __attribute__( ( always_inline ) )
47 inline uint64_t mmh3_rotl64( uint64_t x, int8_t r )
48 {
49 return ( x << r ) | ( x >> ( 64 - r ) );
50 }
51 #define ROTL64( x, y ) mmh3_rotl64( x, y )
52 #define BIG_CONSTANT( x ) ( x##LLU )
53#endif // !defined(_MSC_VER)
54
55
60{
61public:
62 MMH3_HASH() { reset( 0 ); };
63
64 MMH3_HASH( uint32_t aSeed = 0 ) { reset( aSeed ); }
65
66 FORCE_INLINE void reset( uint32_t aSeed = 0 )
67 {
68 h1 = aSeed;
69 h2 = aSeed;
70 len = 0;
71 }
72
73 FORCE_INLINE void add( int32_t input )
74 {
75 blocks[( len % 16 ) / 4] = input;
76 len += 4;
77
78 if( len % 16 == 0 )
79 hashBlock();
80 }
81
83 {
84 hashTail();
85
86 HASH_128 h128;
87 hashFinal( h128 );
88
89 return h128;
90 }
91
92private:
93
94 // Block read - if your platform needs to do endian-swapping or can only
95 // handle aligned reads, do the conversion here
96 FORCE_INLINE uint64_t getblock64( int i )
97 {
98 return blocks64[i]; //
99 }
100
102 {
103 static const uint64_t c1 = BIG_CONSTANT( 0x87c37b91114253d5 );
104 static const uint64_t c2 = BIG_CONSTANT( 0x4cf5ad432745937f );
105
106 uint64_t k1 = getblock64( 0 );
107 uint64_t k2 = getblock64( 1 );
108
109 k1 *= c1; k1 = ROTL64(k1,31); k1 *= c2; h1 ^= k1;
110
111 h1 = ROTL64(h1,27); h1 += h2; h1 = h1*5+0x52dce729;
112
113 k2 *= c2; k2 = ROTL64(k2,33); k2 *= c1; h2 ^= k2;
114
115 h2 = ROTL64(h2,31); h2 += h1; h2 = h2*5+0x38495ab5;
116 }
117
119 {
120 const uint8_t * tail = (const uint8_t*)(blocks);
121
122 static const uint64_t c1 = BIG_CONSTANT( 0x87c37b91114253d5 );
123 static const uint64_t c2 = BIG_CONSTANT( 0x4cf5ad432745937f );
124
125 uint64_t k1 = 0;
126 uint64_t k2 = 0;
127
128 switch( len & 15)
129 {
130 case 15: k2 ^= ((uint64_t)tail[14]) << 48; [[fallthrough]];
131 case 14: k2 ^= ((uint64_t)tail[13]) << 40; [[fallthrough]];
132 case 13: k2 ^= ((uint64_t)tail[12]) << 32; [[fallthrough]];
133 case 12: k2 ^= ((uint64_t)tail[11]) << 24; [[fallthrough]];
134 case 11: k2 ^= ((uint64_t)tail[10]) << 16; [[fallthrough]];
135 case 10: k2 ^= ((uint64_t)tail[ 9]) << 8; [[fallthrough]];
136 case 9: k2 ^= ((uint64_t)tail[ 8]) << 0;
137 k2 *= c2; k2 = ROTL64(k2,33); k2 *= c1; h2 ^= k2;
138 [[fallthrough]];
139
140 case 8: k1 ^= ((uint64_t)tail[ 7]) << 56; [[fallthrough]];
141 case 7: k1 ^= ((uint64_t)tail[ 6]) << 48; [[fallthrough]];
142 case 6: k1 ^= ((uint64_t)tail[ 5]) << 40; [[fallthrough]];
143 case 5: k1 ^= ((uint64_t)tail[ 4]) << 32; [[fallthrough]];
144 case 4: k1 ^= ((uint64_t)tail[ 3]) << 24; [[fallthrough]];
145 case 3: k1 ^= ((uint64_t)tail[ 2]) << 16; [[fallthrough]];
146 case 2: k1 ^= ((uint64_t)tail[ 1]) << 8; [[fallthrough]];
147 case 1: k1 ^= ((uint64_t)tail[ 0]) << 0;
148 k1 *= c1; k1 = ROTL64(k1,31); k1 *= c2; h1 ^= k1;
149 };
150 }
151
152 // Finalization mix - force all bits of a hash block to avalanche
153 static FORCE_INLINE uint64_t fmix64( uint64_t k )
154 {
155 k ^= k >> 33;
156 k *= BIG_CONSTANT( 0xff51afd7ed558ccd );
157 k ^= k >> 33;
158 k *= BIG_CONSTANT( 0xc4ceb9fe1a85ec53 );
159 k ^= k >> 33;
160
161 return k;
162 }
163
165 {
166 h1 ^= len;
167 h2 ^= len;
168
169 h1 += h2;
170 h2 += h1;
171
172 h1 = fmix64( h1 );
173 h2 = fmix64( h2 );
174
175 h1 += h2;
176 h2 += h1;
177
178 out.Value64[0] = h1;
179 out.Value64[1] = h2;
180 }
181
182private:
183 uint64_t h1;
184 uint64_t h2;
185 union
186 {
187 uint32_t blocks[4];
188 uint64_t blocks64[2];
189 };
190 uint32_t len;
191};
192
193
194#undef FORCE_INLINE
195#undef ROTL64
196#undef BIG_CONSTANT
197
198
199#endif // MMH3_HASH_H_
A streaming C++ equivalent for MurmurHash3_x64_128.
Definition: mmh3_hash.h:60
MMH3_HASH(uint32_t aSeed=0)
Definition: mmh3_hash.h:64
FORCE_INLINE void hashBlock()
Definition: mmh3_hash.h:101
FORCE_INLINE void add(int32_t input)
Definition: mmh3_hash.h:73
uint32_t blocks[4]
Definition: mmh3_hash.h:187
MMH3_HASH()
Definition: mmh3_hash.h:62
FORCE_INLINE HASH_128 digest()
Definition: mmh3_hash.h:82
uint64_t blocks64[2]
Definition: mmh3_hash.h:188
static FORCE_INLINE uint64_t fmix64(uint64_t k)
Definition: mmh3_hash.h:153
uint64_t h2
Definition: mmh3_hash.h:184
FORCE_INLINE void reset(uint32_t aSeed=0)
Definition: mmh3_hash.h:66
FORCE_INLINE uint64_t getblock64(int i)
Definition: mmh3_hash.h:96
uint32_t len
Definition: mmh3_hash.h:190
FORCE_INLINE void hashTail()
Definition: mmh3_hash.h:118
uint64_t h1
Definition: mmh3_hash.h:183
FORCE_INLINE void hashFinal(HASH_128 &out)
Definition: mmh3_hash.h:164
uint64_t mmh3_rotl64(uint64_t x, int8_t r)
Definition: mmh3_hash.h:47
#define ROTL64(x, y)
Definition: mmh3_hash.h:51
#define BIG_CONSTANT(x)
Definition: mmh3_hash.h:52
#define FORCE_INLINE
Definition: mmh3_hash.h:46
A storage class for 128-bit hash value.
Definition: hash_128.h:36
uint64_t Value64[2]
Definition: hash_128.h:61