This repository has been archived by the owner on Nov 13, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
MurMurHash3.cs
104 lines (86 loc) · 2.63 KB
/
MurMurHash3.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
using System;
namespace ProtocolModern
{
// https://github.com/sinhpham/MurmurHash3/blob/1f81df67703d70746f30d065781e9d6f2b33bf49/MurmurHash3/MurmurHash3_x86_32.cs
public interface IHashFunc
{
byte[] ComputeHash(byte[] buffer);
byte[] ComputeHash(byte[] buffer, int offset, int count);
}
public sealed class MurmurHash3_32 : IHashFunc
{
public uint Seed { get; set; }
private uint _h1 = 0;
private void HashCore(byte[] array, int ibStart, int cbSize)
{
byte[] data = array;
var len = cbSize;
var nblocks = len / 4;
_h1 = Seed;
const UInt32 c1 = 0xcc9e2d51;
const UInt32 c2 = 0x1b873593;
//----------
// body
UInt32 k1 = 0;
for (int i = 0; i < nblocks; ++i)
{
k1 = BitConverter.ToUInt32(data, ibStart + i * 4);
k1 *= c1;
k1 = RotateLeft32(k1, 15);
k1 *= c2;
_h1 ^= k1;
_h1 = RotateLeft32(_h1, 13);
_h1 = _h1 * 5 + 0xe6546b64;
}
//----------
// tail
k1 = 0;
var tailIdx = ibStart + nblocks * 4;
switch (len & 3)
{
case 3:
k1 ^= (UInt32)(data[tailIdx + 2]) << 16;
goto case 2;
case 2:
k1 ^= (UInt32)(data[tailIdx + 1]) << 8;
goto case 1;
case 1:
k1 ^= (UInt32)(data[tailIdx + 0]);
k1 *= c1; k1 = RotateLeft32(k1, 15); k1 *= c2; _h1 ^= k1;
break;
};
//----------
// finalization
_h1 ^= (UInt32)len;
_h1 = FMix(_h1);
}
uint RotateLeft32(uint x, byte r)
{
return (x << r) | (x >> (32 - r));
}
uint FMix(uint h)
{
h ^= h >> 16;
h *= 0x85ebca6b;
h ^= h >> 13;
h *= 0xc2b2ae35;
h ^= h >> 16;
return h;
}
private byte[] HashFinal()
{
var hashVal = new byte[4];
Array.Copy(BitConverter.GetBytes(_h1), 0, hashVal, 0, 4);
return hashVal;
}
public byte[] ComputeHash(byte[] buffer)
{
return ComputeHash(buffer, 0, buffer.Length);
}
public byte[] ComputeHash(byte[] buffer, int offset, int count)
{
HashCore(buffer, 0, count);
return HashFinal();
}
}
}