107 lines
3.3 KiB
C#
107 lines
3.3 KiB
C#
// ReSharper disable InconsistentNaming
|
|
|
|
namespace Standart.Hash.xxHash
|
|
{
|
|
using System.Runtime.CompilerServices;
|
|
|
|
public static partial class xxHash64
|
|
{
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
private static unsafe ulong XXH64(byte* input, int len, ulong seed)
|
|
{
|
|
ulong h64;
|
|
|
|
if (len >= 32)
|
|
{
|
|
byte* end = input + len;
|
|
byte* limit = end - 31;
|
|
|
|
ulong v1 = seed + XXH_PRIME64_1 + XXH_PRIME64_2;
|
|
ulong v2 = seed + XXH_PRIME64_2;
|
|
ulong v3 = seed + 0;
|
|
ulong v4 = seed - XXH_PRIME64_1;
|
|
|
|
do
|
|
{
|
|
v1 = XXH64_round(v1, *(ulong*) input); input += 8;
|
|
v2 = XXH64_round(v2, *(ulong*) input); input += 8;
|
|
v3 = XXH64_round(v3, *(ulong*) input); input += 8;
|
|
v4 = XXH64_round(v4, *(ulong*) input); input += 8;
|
|
} while (input < limit);
|
|
|
|
h64 = XXH_rotl64(v1, 1) +
|
|
XXH_rotl64(v2, 7) +
|
|
XXH_rotl64(v3, 12) +
|
|
XXH_rotl64(v4, 18);
|
|
|
|
h64 = XXH64_mergeRound(h64, v1);
|
|
h64 = XXH64_mergeRound(h64, v2);
|
|
h64 = XXH64_mergeRound(h64, v3);
|
|
h64 = XXH64_mergeRound(h64, v4);
|
|
}
|
|
else
|
|
{
|
|
h64 = seed + XXH_PRIME64_5;
|
|
}
|
|
|
|
h64 += (ulong)len;
|
|
|
|
return XXH64_finalize(h64, input, len);
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
private static ulong XXH64_round(ulong acc, ulong input)
|
|
{
|
|
acc += input * XXH_PRIME64_2;
|
|
acc = XXH_rotl64(acc, 31);
|
|
acc *= XXH_PRIME64_1;
|
|
return acc;
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
private static ulong XXH64_mergeRound(ulong acc, ulong val)
|
|
{
|
|
val = XXH64_round(0, val);
|
|
acc ^= val;
|
|
acc = acc * XXH_PRIME64_1 + XXH_PRIME64_4;
|
|
return acc;
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
private static ulong XXH64_avalanche(ulong hash)
|
|
{
|
|
hash ^= hash >> 33;
|
|
hash *= XXH_PRIME64_2;
|
|
hash ^= hash >> 29;
|
|
hash *= XXH_PRIME64_3;
|
|
hash ^= hash >> 32;
|
|
return hash;
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
private static unsafe ulong XXH64_finalize(ulong hash, byte* ptr, int len)
|
|
{
|
|
len &= 31;
|
|
while (len >= 8) {
|
|
ulong k1 = XXH64_round(0, *(ulong*)ptr);
|
|
ptr += 8;
|
|
hash ^= k1;
|
|
hash = XXH_rotl64(hash,27) * XXH_PRIME64_1 + XXH_PRIME64_4;
|
|
len -= 8;
|
|
}
|
|
if (len >= 4) {
|
|
hash ^= *(uint*)ptr * XXH_PRIME64_1;
|
|
ptr += 4;
|
|
hash = XXH_rotl64(hash, 23) * XXH_PRIME64_2 + XXH_PRIME64_3;
|
|
len -= 4;
|
|
}
|
|
while (len > 0) {
|
|
hash ^= (*ptr++) * XXH_PRIME64_5;
|
|
hash = XXH_rotl64(hash, 11) * XXH_PRIME64_1;
|
|
--len;
|
|
}
|
|
return XXH64_avalanche(hash);
|
|
}
|
|
}
|
|
}
|