in Microsoft.Azure.Cosmos/src/MurmurHash3.cs [191:340]
public static unsafe UInt128 Hash128(ReadOnlySpan<byte> span, UInt128 seed)
{
if (!BitConverter.IsLittleEndian)
{
throw new InvalidOperationException("Host machine needs to be little endian.");
}
const ulong c1 = 0x87c37b91114253d5;
const ulong c2 = 0x4cf5ad432745937f;
(ulong h1, ulong h2) = (seed.GetLow(), seed.GetHigh());
// body
unchecked
{
fixed (byte* words = span)
{
int position;
for (position = 0; position < span.Length - 15; position += 16)
{
ulong k1 = *(ulong*)(words + position);
ulong k2 = *(ulong*)(words + position + 8);
// k1, h1
k1 *= c1;
k1 = MurmurHash3.RotateLeft64(k1, 31);
k1 *= c2;
h1 ^= k1;
h1 = MurmurHash3.RotateLeft64(h1, 27);
h1 += h2;
h1 = (h1 * 5) + 0x52dce729;
// k2, h2
k2 *= c2;
k2 = MurmurHash3.RotateLeft64(k2, 33);
k2 *= c1;
h2 ^= k2;
h2 = MurmurHash3.RotateLeft64(h2, 31);
h2 += h1;
h2 = (h2 * 5) + 0x38495ab5;
}
{
// tail
ulong k1 = 0;
ulong k2 = 0;
int n = span.Length & 15;
if (n >= 15)
{
k2 ^= (ulong)words[position + 14] << 48;
}
if (n >= 14)
{
k2 ^= (ulong)words[position + 13] << 40;
}
if (n >= 13)
{
k2 ^= (ulong)words[position + 12] << 32;
}
if (n >= 12)
{
k2 ^= (ulong)words[position + 11] << 24;
}
if (n >= 11)
{
k2 ^= (ulong)words[position + 10] << 16;
}
if (n >= 10)
{
k2 ^= (ulong)words[position + 09] << 8;
}
if (n >= 9)
{
k2 ^= (ulong)words[position + 08] << 0;
}
k2 *= c2;
k2 = MurmurHash3.RotateLeft64(k2, 33);
k2 *= c1;
h2 ^= k2;
if (n >= 8)
{
k1 ^= (ulong)words[position + 7] << 56;
}
if (n >= 7)
{
k1 ^= (ulong)words[position + 6] << 48;
}
if (n >= 6)
{
k1 ^= (ulong)words[position + 5] << 40;
}
if (n >= 5)
{
k1 ^= (ulong)words[position + 4] << 32;
}
if (n >= 4)
{
k1 ^= (ulong)words[position + 3] << 24;
}
if (n >= 3)
{
k1 ^= (ulong)words[position + 2] << 16;
}
if (n >= 2)
{
k1 ^= (ulong)words[position + 1] << 8;
}
if (n >= 1)
{
k1 ^= (ulong)words[position + 0] << 0;
}
k1 *= c1;
k1 = MurmurHash3.RotateLeft64(k1, 31);
k1 *= c2;
h1 ^= k1;
}
}
// finalization
h1 ^= (ulong)span.Length;
h2 ^= (ulong)span.Length;
h1 += h2;
h2 += h1;
h1 = MurmurHash3.Mix(h1);
h2 = MurmurHash3.Mix(h2);
h1 += h2;
h2 += h1;
}
return UInt128.Create(h1, h2);
}