Coverage Report

Created: 2025-11-09 06:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ogre/OgreMain/src/OgreMurmurHash3.cpp
Line
Count
Source
1
//-----------------------------------------------------------------------------
2
// MurmurHash3 was written by Austin Appleby, and is placed in the public
3
// domain. The author hereby disclaims copyright to this source code.
4
5
// Note - The x86 and x64 versions do _not_ produce the same results, as the
6
// algorithms are optimized for their respective platforms. You can still
7
// compile and run any of them on any platform, but your performance with the
8
// non-native version will be less than optimal.
9
10
#include "OgreStableHeaders.h"
11
12
//-----------------------------------------------------------------------------
13
// Platform-specific functions and macros
14
15
// Microsoft Visual Studio
16
17
#if defined(_MSC_VER)
18
19
#define FORCE_INLINE    __forceinline
20
21
#include <stdlib.h>
22
23
#define ROTL32(x,y) _rotl(x,y)
24
#define ROTL64(x,y) _rotl64(x,y)
25
26
#define BIG_CONSTANT(x) (x)
27
28
// Other compilers
29
30
#else   // defined(_MSC_VER)
31
32
#define FORCE_INLINE inline __attribute__((always_inline))
33
34
inline uint32_t rotl32 ( uint32_t x, int8_t r )
35
0
{
36
0
  return (x << r) | (x >> (32 - r));
37
0
}
38
39
inline uint64_t rotl64 ( uint64_t x, int8_t r )
40
0
{
41
0
  return (x << r) | (x >> (64 - r));
42
0
}
43
44
0
#define ROTL32(x,y) rotl32(x,y)
45
0
#define ROTL64(x,y) rotl64(x,y)
46
47
0
#define BIG_CONSTANT(x) (x##LLU)
48
49
#endif // !defined(_MSC_VER)
50
51
namespace Ogre
52
{
53
//-----------------------------------------------------------------------------
54
// Block read - if your platform needs to do endian-swapping or can only
55
// handle aligned reads, do the conversion here
56
57
FORCE_INLINE uint32_t getblock32 ( const uint32_t * p, int i )
58
0
{
59
0
  return p[i];
60
0
}
61
62
FORCE_INLINE uint64_t getblock64 ( const uint64_t * p, int i )
63
0
{
64
0
  return p[i];
65
0
}
66
67
//-----------------------------------------------------------------------------
68
// Finalization mix - force all bits of a hash block to avalanche
69
70
FORCE_INLINE uint32_t fmix32 ( uint32_t h )
71
0
{
72
0
  h ^= h >> 16;
73
0
  h *= 0x85ebca6b;
74
0
  h ^= h >> 13;
75
0
  h *= 0xc2b2ae35;
76
0
  h ^= h >> 16;
77
78
0
  return h;
79
0
}
80
81
//----------
82
83
FORCE_INLINE uint64_t fmix64 ( uint64_t k )
84
0
{
85
0
  k ^= k >> 33;
86
0
  k *= BIG_CONSTANT(0xff51afd7ed558ccd);
87
0
  k ^= k >> 33;
88
0
  k *= BIG_CONSTANT(0xc4ceb9fe1a85ec53);
89
0
  k ^= k >> 33;
90
91
0
  return k;
92
0
}
93
94
//-----------------------------------------------------------------------------
95
96
void _OgreExport MurmurHash3_x86_32 ( const void * key, const size_t len,
97
                          uint32_t seed, void * out )
98
0
{
99
0
  const uint8_t * data = (const uint8_t*)key;
100
0
  const int nblocks = len / 4;
101
102
0
  uint32_t h1 = seed;
103
104
0
  const uint32_t c1 = 0xcc9e2d51;
105
0
  const uint32_t c2 = 0x1b873593;
106
107
  //----------
108
  // body
109
110
0
  const uint32_t * blocks = (const uint32_t *)(data + nblocks*4);
111
112
0
  for(int i = -nblocks; i; i++)
113
0
  {
114
0
    uint32_t k1 = getblock32(blocks,i);
115
116
0
    k1 *= c1;
117
0
    k1 = ROTL32(k1,15);
118
0
    k1 *= c2;
119
    
120
0
    h1 ^= k1;
121
0
    h1 = ROTL32(h1,13); 
122
0
    h1 = h1*5+0xe6546b64;
123
0
  }
124
125
  //----------
126
  // tail
127
128
0
  const uint8_t * tail = (const uint8_t*)(data + nblocks*4);
129
130
0
  uint32_t k1 = 0;
131
132
0
  switch(len & 3)
133
0
  {
134
0
  case 3: k1 ^= tail[2] << 16; OGRE_FALLTHROUGH;
135
0
  case 2: k1 ^= tail[1] << 8; OGRE_FALLTHROUGH;
136
0
  case 1: k1 ^= tail[0];
137
0
          k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1;
138
0
  };
139
140
  //----------
141
  // finalization
142
143
0
  h1 ^= len;
144
145
0
  h1 = fmix32(h1);
146
147
0
  *(uint32_t*)out = h1;
148
0
} 
149
150
//-----------------------------------------------------------------------------
151
152
void _OgreExport MurmurHash3_x86_128 ( const void * key, const size_t len,
153
                           uint32_t seed, void * out )
154
0
{
155
0
  const uint8_t * data = (const uint8_t*)key;
156
0
  const int nblocks = len / 16;
157
158
0
  uint32_t h1 = seed;
159
0
  uint32_t h2 = seed;
160
0
  uint32_t h3 = seed;
161
0
  uint32_t h4 = seed;
162
163
0
  const uint32_t c1 = 0x239b961b; 
164
0
  const uint32_t c2 = 0xab0e9789;
165
0
  const uint32_t c3 = 0x38b34ae5; 
166
0
  const uint32_t c4 = 0xa1e38b93;
167
168
  //----------
169
  // body
170
171
0
  const uint32_t * blocks = (const uint32_t *)(data + nblocks*16);
172
173
0
  for(int i = -nblocks; i; i++)
174
0
  {
175
0
    uint32_t k1 = getblock32(blocks,i*4+0);
176
0
    uint32_t k2 = getblock32(blocks,i*4+1);
177
0
    uint32_t k3 = getblock32(blocks,i*4+2);
178
0
    uint32_t k4 = getblock32(blocks,i*4+3);
179
180
0
    k1 *= c1; k1  = ROTL32(k1,15); k1 *= c2; h1 ^= k1;
181
182
0
    h1 = ROTL32(h1,19); h1 += h2; h1 = h1*5+0x561ccd1b;
183
184
0
    k2 *= c2; k2  = ROTL32(k2,16); k2 *= c3; h2 ^= k2;
185
186
0
    h2 = ROTL32(h2,17); h2 += h3; h2 = h2*5+0x0bcaa747;
187
188
0
    k3 *= c3; k3  = ROTL32(k3,17); k3 *= c4; h3 ^= k3;
189
190
0
    h3 = ROTL32(h3,15); h3 += h4; h3 = h3*5+0x96cd1c35;
191
192
0
    k4 *= c4; k4  = ROTL32(k4,18); k4 *= c1; h4 ^= k4;
193
194
0
    h4 = ROTL32(h4,13); h4 += h1; h4 = h4*5+0x32ac3b17;
195
0
  }
196
197
  //----------
198
  // tail
199
200
0
  const uint8_t * tail = (const uint8_t*)(data + nblocks*16);
201
202
0
  uint32_t k1 = 0;
203
0
  uint32_t k2 = 0;
204
0
  uint32_t k3 = 0;
205
0
  uint32_t k4 = 0;
206
207
0
  switch(len & 15)
208
0
  {
209
0
  case 15: k4 ^= tail[14] << 16; OGRE_FALLTHROUGH;
210
0
  case 14: k4 ^= tail[13] << 8; OGRE_FALLTHROUGH;
211
0
  case 13: k4 ^= tail[12] << 0;
212
0
           k4 *= c4; k4  = ROTL32(k4,18); k4 *= c1; h4 ^= k4; OGRE_FALLTHROUGH;
213
214
0
  case 12: k3 ^= tail[11] << 24; OGRE_FALLTHROUGH;
215
0
  case 11: k3 ^= tail[10] << 16; OGRE_FALLTHROUGH;
216
0
  case 10: k3 ^= tail[ 9] << 8; OGRE_FALLTHROUGH;
217
0
  case  9: k3 ^= tail[ 8] << 0;
218
0
           k3 *= c3; k3  = ROTL32(k3,17); k3 *= c4; h3 ^= k3; OGRE_FALLTHROUGH;
219
220
0
  case  8: k2 ^= tail[ 7] << 24; OGRE_FALLTHROUGH;
221
0
  case  7: k2 ^= tail[ 6] << 16; OGRE_FALLTHROUGH;
222
0
  case  6: k2 ^= tail[ 5] << 8; OGRE_FALLTHROUGH;
223
0
  case  5: k2 ^= tail[ 4] << 0;
224
0
           k2 *= c2; k2  = ROTL32(k2,16); k2 *= c3; h2 ^= k2; OGRE_FALLTHROUGH;
225
226
0
  case  4: k1 ^= tail[ 3] << 24; OGRE_FALLTHROUGH;
227
0
  case  3: k1 ^= tail[ 2] << 16; OGRE_FALLTHROUGH;
228
0
  case  2: k1 ^= tail[ 1] << 8; OGRE_FALLTHROUGH;
229
0
  case  1: k1 ^= tail[ 0] << 0;
230
0
           k1 *= c1; k1  = ROTL32(k1,15); k1 *= c2; h1 ^= k1;
231
0
  };
232
233
  //----------
234
  // finalization
235
236
0
  h1 ^= len; h2 ^= len; h3 ^= len; h4 ^= len;
237
238
0
  h1 += h2; h1 += h3; h1 += h4;
239
0
  h2 += h1; h3 += h1; h4 += h1;
240
241
0
  h1 = fmix32(h1);
242
0
  h2 = fmix32(h2);
243
0
  h3 = fmix32(h3);
244
0
  h4 = fmix32(h4);
245
246
0
  h1 += h2; h1 += h3; h1 += h4;
247
0
  h2 += h1; h3 += h1; h4 += h1;
248
249
0
  ((uint32_t*)out)[0] = h1;
250
0
  ((uint32_t*)out)[1] = h2;
251
0
  ((uint32_t*)out)[2] = h3;
252
0
  ((uint32_t*)out)[3] = h4;
253
0
}
254
255
//-----------------------------------------------------------------------------
256
257
void _OgreExport MurmurHash3_x64_128 ( const void * key, const size_t len,
258
                           const uint32_t seed, void * out )
259
0
{
260
0
  const uint8_t * data = (const uint8_t*)key;
261
0
  const int nblocks = len / 16;
262
263
0
  uint64_t h1 = seed;
264
0
  uint64_t h2 = seed;
265
266
0
  const uint64_t c1 = BIG_CONSTANT(0x87c37b91114253d5);
267
0
  const uint64_t c2 = BIG_CONSTANT(0x4cf5ad432745937f);
268
269
  //----------
270
  // body
271
272
0
  const uint64_t * blocks = (const uint64_t *)(data);
273
274
0
  for(int i = 0; i < nblocks; i++)
275
0
  {
276
0
    uint64_t k1 = getblock64(blocks,i*2+0);
277
0
    uint64_t k2 = getblock64(blocks,i*2+1);
278
279
0
    k1 *= c1; k1  = ROTL64(k1,31); k1 *= c2; h1 ^= k1;
280
281
0
    h1 = ROTL64(h1,27); h1 += h2; h1 = h1*5+0x52dce729;
282
283
0
    k2 *= c2; k2  = ROTL64(k2,33); k2 *= c1; h2 ^= k2;
284
285
0
    h2 = ROTL64(h2,31); h2 += h1; h2 = h2*5+0x38495ab5;
286
0
  }
287
288
  //----------
289
  // tail
290
291
0
  const uint8_t * tail = (const uint8_t*)(data + nblocks*16);
292
293
0
  uint64_t k1 = 0;
294
0
  uint64_t k2 = 0;
295
296
0
  switch(len & 15)
297
0
  {
298
0
  case 15: k2 ^= ((uint64_t)tail[14]) << 48; OGRE_FALLTHROUGH;
299
0
  case 14: k2 ^= ((uint64_t)tail[13]) << 40; OGRE_FALLTHROUGH;
300
0
  case 13: k2 ^= ((uint64_t)tail[12]) << 32; OGRE_FALLTHROUGH;
301
0
  case 12: k2 ^= ((uint64_t)tail[11]) << 24; OGRE_FALLTHROUGH;
302
0
  case 11: k2 ^= ((uint64_t)tail[10]) << 16; OGRE_FALLTHROUGH;
303
0
  case 10: k2 ^= ((uint64_t)tail[ 9]) << 8; OGRE_FALLTHROUGH;
304
0
  case  9: k2 ^= ((uint64_t)tail[ 8]) << 0;
305
0
           k2 *= c2; k2  = ROTL64(k2,33); k2 *= c1; h2 ^= k2; OGRE_FALLTHROUGH;
306
307
0
  case  8: k1 ^= ((uint64_t)tail[ 7]) << 56; OGRE_FALLTHROUGH;
308
0
  case  7: k1 ^= ((uint64_t)tail[ 6]) << 48; OGRE_FALLTHROUGH;
309
0
  case  6: k1 ^= ((uint64_t)tail[ 5]) << 40; OGRE_FALLTHROUGH;
310
0
  case  5: k1 ^= ((uint64_t)tail[ 4]) << 32; OGRE_FALLTHROUGH;
311
0
  case  4: k1 ^= ((uint64_t)tail[ 3]) << 24; OGRE_FALLTHROUGH;
312
0
  case  3: k1 ^= ((uint64_t)tail[ 2]) << 16; OGRE_FALLTHROUGH;
313
0
  case  2: k1 ^= ((uint64_t)tail[ 1]) << 8; OGRE_FALLTHROUGH;
314
0
  case  1: k1 ^= ((uint64_t)tail[ 0]) << 0;
315
0
           k1 *= c1; k1  = ROTL64(k1,31); k1 *= c2; h1 ^= k1;
316
0
  };
317
318
  //----------
319
  // finalization
320
321
0
  h1 ^= len; h2 ^= len;
322
323
0
  h1 += h2;
324
0
  h2 += h1;
325
326
0
  h1 = fmix64(h1);
327
0
  h2 = fmix64(h2);
328
329
0
  h1 += h2;
330
0
  h2 += h1;
331
332
0
  ((uint64_t*)out)[0] = h1;
333
0
  ((uint64_t*)out)[1] = h2;
334
0
}
335
336
//-----------------------------------------------------------------------------
337
}