-
-
Notifications
You must be signed in to change notification settings - Fork 32
/
Murmur3Hash.cs
76 lines (69 loc) · 2.28 KB
/
Murmur3Hash.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
using System;
using System.Collections.Generic;
using System.Text;
#if !NET461 && !NETCOREAPP3_0 && !NETSTANDARD1_0 && !NETSTANDARD2_0 && !NETSTANDARD2_1
using static System.Numerics.BitOperations;
#endif
#pragma warning disable CA1815, CA1721
namespace Nito.Comparers.Internals
{
/// <summary>
/// A hash combiner that is implemented with the Murmur 3 algorithm. This is a mutable struct for performance reasons.
/// </summary>
public struct Murmur3Hash
{
private uint _len;
private uint _hash;
/// <summary>
/// Gets the current result of the hash function.
/// </summary>
public int HashCode
{
get
{
unchecked
{
var result = _hash ^ _len;
result ^= result >> 16;
result *= 0x85ebca6b;
result ^= result >> 13;
result *= 0xc2b2ae35;
result ^= result >> 16;
return (int)result;
}
}
}
/// <summary>
/// Creates a new hash, starting at <paramref name="seed"/>.
/// </summary>
/// <param name="seed">The seed for the hash. Defaults to the FNV hash offset, for no particular reason.</param>
public static Murmur3Hash Create(int seed = unchecked((int)2166136261))
{
var result = new Murmur3Hash();
result._hash = unchecked((uint)seed);
return result;
}
/// <summary>
/// Adds the specified integer to this hash.
/// </summary>
/// <param name="data">The integer to hash.</param>
public void Combine(int data)
{
unchecked
{
_len += 4;
var k = (uint)data;
k *= 0xcc9e2d51;
k = RotateLeft(k, 15);
k *= 0x1b873593;
_hash ^= k;
_hash = RotateLeft(_hash, 13);
_hash *= 5;
_hash += 0xe6546b64;
}
}
#if NET461 || NETCOREAPP3_0 || NETSTANDARD1_0 || NETSTANDARD2_0 || NETSTANDARD2_1
private static uint RotateLeft(uint value, int bits) => (value << bits) | (value >> (32 - bits));
#endif
}
}