Skip to content

Instantly share code, notes, and snippets.

@azyobuzin
Created September 16, 2017 16:38
Show Gist options
  • Save azyobuzin/f396b8ef7f583a2935e723c3eee5d951 to your computer and use it in GitHub Desktop.
Save azyobuzin/f396b8ef7f583a2935e723c3eee5d951 to your computer and use it in GitHub Desktop.
public static int GetDistance(ArraySegment<byte> bs1, ArraySegment<byte> bs2)
{
if (bs1.Count != bs2.Count) throw new ArgumentException("bs1 と b2 の長さが違います。");
var count = bs1.Count;
var distance = 0;
var i = 0;
if (Vector.IsHardwareAccelerated)
{
var vecSize = Vector<byte>.Count;
for (; i + vecSize <= count; i += vecSize)
{
var vec1 = Vector.AsVectorUInt64(new Vector<byte>(bs1.Array, bs1.Offset + i));
var vec2 = Vector.AsVectorUInt64(new Vector<byte>(bs2.Array, bs2.Offset + i));
var weight = vec1 ^ vec2;
// Vector にビットシフトが入ったら全部 Vector でやりたい
for (var j = 0; j < Vector<ulong>.Count; j++)
distance += popcount64c(weight[j]);
}
}
while (count - i is var left && left > 0)
{
ulong v;
if (left >= 8)
{
v = Unsafe.ReadUnaligned<ulong>(ref bs1.Array[bs1.Offset + i])
^ Unsafe.ReadUnaligned<ulong>(ref bs2.Array[bs2.Offset + i]);
i += 8;
}
else if (left >= 4)
{
v = Unsafe.ReadUnaligned<uint>(ref bs1.Array[bs1.Offset + i])
^ Unsafe.ReadUnaligned<uint>(ref bs2.Array[bs2.Offset + i]);
i += 4;
}
else
{
v = (uint)bs1.Array[bs1.Offset + i] ^ bs2.Array[bs2.Offset + i];
i++;
}
distance += popcount64c(v);
}
return distance;
// https://en.wikipedia.org/wiki/Hamming_weight
int popcount64c(ulong x)
{
x -= (x >> 1) & 0x5555555555555555;
x = (x & 0x3333333333333333) + ((x >> 2) & 0x3333333333333333);
x = (x + (x >> 4)) & 0x0f0f0f0f0f0f0f0f;
return (int)((x * 0x0101010101010101) >> 56);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment