|
|
|
|
using System;
|
|
|
|
|
|
|
|
|
|
namespace ZeroLevel.Services.HashFunctions
|
|
|
|
|
{
|
|
|
|
|
public class Murmur3Unsafe
|
|
|
|
|
: IHash
|
|
|
|
|
{
|
|
|
|
|
private const uint Seed = 0xc58f1a7b;
|
|
|
|
|
|
|
|
|
|
private const UInt32 c1 = 0xcc9e2d51;
|
|
|
|
|
private const UInt32 c2 = 0x1b873593;
|
|
|
|
|
|
|
|
|
|
public unsafe UInt32 Hash(string s)
|
|
|
|
|
{
|
|
|
|
|
fixed (char* input = s)
|
|
|
|
|
{
|
|
|
|
|
return Hash((byte*)input, (uint)s.Length * sizeof(char), Seed);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public unsafe uint Hash(byte[] data)
|
|
|
|
|
{
|
|
|
|
|
fixed (byte* input = &data[0])
|
|
|
|
|
{
|
|
|
|
|
return Hash(input, (uint)data.Length, Seed);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public unsafe uint Hash(byte[] data, int offset, uint len, uint seed)
|
|
|
|
|
{
|
|
|
|
|
fixed (byte* input = &data[offset])
|
|
|
|
|
{
|
|
|
|
|
return Hash(input, len, seed);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private unsafe static uint Hash(byte* data, uint len, uint seed)
|
|
|
|
|
{
|
|
|
|
|
UInt32 nblocks = len / 4;
|
|
|
|
|
UInt32 h1 = seed;
|
|
|
|
|
|
|
|
|
|
//----------
|
|
|
|
|
// body
|
|
|
|
|
|
|
|
|
|
UInt32 k1;
|
|
|
|
|
UInt32* block = (UInt32*)data;
|
|
|
|
|
for (UInt32 i = nblocks; i > 0; --i, ++block)
|
|
|
|
|
{
|
|
|
|
|
k1 = *block;
|
|
|
|
|
|
|
|
|
|
k1 *= c1;
|
|
|
|
|
k1 = Rotl32(k1, 15);
|
|
|
|
|
k1 *= c2;
|
|
|
|
|
|
|
|
|
|
h1 ^= k1;
|
|
|
|
|
h1 = Rotl32(h1, 13);
|
|
|
|
|
h1 = h1 * 5 + 0xe6546b64;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//----------
|
|
|
|
|
// tail
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
k1 = 0;
|
|
|
|
|
uint rem = len & 3;
|
|
|
|
|
byte* tail = (byte*)block;
|
|
|
|
|
if (rem >= 3)
|
|
|
|
|
k1 ^= (uint)(tail[2] << 16);
|
|
|
|
|
if (rem >= 2)
|
|
|
|
|
k1 ^= (uint)(tail[1] << 8);
|
|
|
|
|
if (rem > 0)
|
|
|
|
|
{
|
|
|
|
|
k1 ^= tail[0];
|
|
|
|
|
k1 *= c1;
|
|
|
|
|
k1 = Rotl32(k1, 15);
|
|
|
|
|
k1 *= c2;
|
|
|
|
|
h1 ^= k1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//----------
|
|
|
|
|
// finalization
|
|
|
|
|
|
|
|
|
|
h1 ^= len;
|
|
|
|
|
|
|
|
|
|
h1 ^= h1 >> 16;
|
|
|
|
|
h1 *= 0x85ebca6b;
|
|
|
|
|
h1 ^= h1 >> 13;
|
|
|
|
|
h1 *= 0xc2b2ae35;
|
|
|
|
|
h1 ^= h1 >> 16;
|
|
|
|
|
|
|
|
|
|
return h1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static UInt32 Rotl32(UInt32 x, int r)
|
|
|
|
|
{
|
|
|
|
|
return (x << r) | (x >> (32 - r));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|