You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Zero/ZeroLevel/Services/HashFunctions/XXHashUnsafe.cs

125 lines
3.6 KiB

using System;
namespace ZeroLevel.Services.HashFunctions
{
public class XXHashUnsafe
: IHash
{
private const uint Seed = 0xc58f1a7b;
private const uint PRIME1 = 2654435761U;
private const uint PRIME2 = 2246822519U;
private const uint PRIME3 = 3266489917U;
private const uint PRIME4 = 668265263U;
private const int PRIME5 = 0x165667b1;
private uint _bias;
public XXHashUnsafe(uint bias = 0) => _bias = bias;
public unsafe UInt32 Hash(string s)
{
fixed (char* input = s)
{
return Hash((byte*)input, (uint)s.Length * sizeof(char), Seed, _bias);
}
}
public unsafe uint Hash(byte[] data)
{
fixed (byte* input = &data[0])
{
return Hash(input, (uint)data.Length, Seed, _bias);
}
}
public unsafe uint Hash(byte[] data, int offset, uint len, uint seed)
{
fixed (byte* input = &data[offset])
{
return Hash(input, len, seed, _bias);
}
}
private unsafe static uint Hash(byte* data, uint len, uint seed, uint bias)
{
if (len < 16)
return HashSmall(data, len, seed, bias);
uint v1 = seed + PRIME1 + bias;
uint v2 = v1 * PRIME2 + len;
uint v3 = v2 * PRIME3;
uint v4 = v3 * PRIME4;
uint* p = (uint*)data;
uint* limit = (uint*)(data + len - 16);
while (p < limit)
{
v1 += Rotl32(v1, 13); v1 *= PRIME1; v1 += *p; p++;
v2 += Rotl32(v2, 11); v2 *= PRIME1; v2 += *p; p++;
v3 += Rotl32(v3, 17); v3 *= PRIME1; v3 += *p; p++;
v4 += Rotl32(v4, 19); v4 *= PRIME1; v4 += *p; p++;
}
p = limit;
v1 += Rotl32(v1, 17); v2 += Rotl32(v2, 19); v3 += Rotl32(v3, 13); v4 += Rotl32(v4, 11);
v1 *= PRIME1; v2 *= PRIME1; v3 *= PRIME1; v4 *= PRIME1;
v1 += *p; p++; v2 += *p; p++; v3 += *p; p++; v4 += *p;
v1 *= PRIME2; v2 *= PRIME2; v3 *= PRIME2; v4 *= PRIME2;
v1 += Rotl32(v1, 11); v2 += Rotl32(v2, 17); v3 += Rotl32(v3, 19); v4 += Rotl32(v4, 13);
v1 *= PRIME3; v2 *= PRIME3; v3 *= PRIME3; v4 *= PRIME3;
uint crc = v1 + Rotl32(v2, 3) + Rotl32(v3, 6) + Rotl32(v4, 9);
crc ^= crc >> 11;
crc += (PRIME4 + len) * PRIME1;
crc ^= crc >> 15;
crc *= PRIME2;
crc ^= crc >> 13;
return crc;
}
private unsafe static uint HashSmall(byte* data, uint len, uint seed, uint bias)
{
byte* p = data;
byte* bEnd = data + len;
byte* limit = bEnd - 4;
uint idx = seed + PRIME1 + bias;
uint crc = PRIME5;
while (p < limit)
{
crc += (*(uint*)p) + idx;
idx++;
crc += Rotl32(crc, 17) * PRIME4;
crc *= PRIME1;
p += 4;
}
while (p < bEnd)
{
crc += (*p) + idx;
idx++;
crc *= PRIME1;
p++;
}
crc += len;
crc ^= crc >> 15;
crc *= PRIME2;
crc ^= crc >> 13;
crc *= PRIME3;
crc ^= crc >> 16;
return crc;
}
private static UInt32 Rotl32(UInt32 x, int r)
{
return (x << r) | (x >> (32 - r));
}
}
}

Powered by TurnKey Linux.