namespace Nikse.SubtitleEdit.Core
{
// The MurmurHash3 algorithm was created by Austin Appleby and put into the public domain. See http://code.google.com/p/smhasher
// This code is based on https://gist.github.com/automatonic/3725443
public class MurMurHash3
{
private const uint seed = 144;
///
/// Fast hashing of byte array
///
/// Byte array to hash
/// Hash value
public static uint Hash(byte[] arr)
{
const uint c1 = 0xcc9e2d51;
const uint c2 = 0x1b873593;
uint h1 = seed;
uint k1 = 0;
int length = arr.Length / 4;
for (int i = 0; i < length; i++)
{
int idx = i * 4;
k1 = (uint)(arr[idx] | arr[idx + 1] << 8 | arr[idx + 2] << 16 | arr[idx + 3] << 24);
// bitmagic hash
k1 *= c1;
k1 = rotl32(k1, 15);
k1 *= c2;
h1 ^= k1;
h1 = rotl32(h1, 13);
h1 = h1 * 5 + 0xe6546b64;
}
switch (arr.Length % 4)
{
case 3:
k1 = (uint)(arr[arr.Length - 3] | arr[arr.Length - 2] << 8 | arr[arr.Length - 1] << 16);
k1 *= c1;
k1 = rotl32(k1, 15);
k1 *= c2;
h1 ^= k1;
break;
case 2:
k1 = (uint)(arr[arr.Length - 2] | arr[arr.Length - 1] << 8);
k1 *= c1;
k1 = rotl32(k1, 15);
k1 *= c2;
h1 ^= k1;
break;
case 1:
k1 = (uint)(arr[arr.Length - 1]);
k1 *= c1;
k1 = rotl32(k1, 15);
k1 *= c2;
h1 ^= k1;
break;
}
// finalization, magic chants to wrap it all up
h1 ^= (uint)arr.Length;
h1 = fmix(h1);
unchecked //ignore overflow
{
return h1;
}
}
private static uint rotl32(uint x, byte r)
{
return (x << r) | (x >> (32 - r));
}
private static uint fmix(uint h)
{
h ^= h >> 16;
h *= 0x85ebca6b;
h ^= h >> 13;
h *= 0xc2b2ae35;
h ^= h >> 16;
return h;
}
}
}