Skip to content

Instantly share code, notes, and snippets.

@mjs3339
Last active March 14, 2023 01:40
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mjs3339/239f7c259fb87065beb0a35accceee68 to your computer and use it in GitHub Desktop.
Save mjs3339/239f7c259fb87065beb0a35accceee68 to your computer and use it in GitHub Desktop.
C# 64 Bit Implementation of the Zobrist Hashing Algorithm.
public class ZOB64 : HashAlgorithm
{
private ulong[] _table;
private ulong hash;
private uint hash32;
private readonly ulong starthash = 0x391615744853B307;
private ZOB32State zhs;
public ZOB64()
{
hash = starthash;
BuildTable(0x7965CBDDD4A9E7AF);
}
public override int HashSize => 64;
public override void Initialize()
{
hash = starthash;
}
protected override void HashCore(byte[] bytes, int ibStart, int cbSize)
{
Hash64(bytes, ibStart, cbSize);
}
private static ulong RotateLeft(ulong value, int count)
{
return (value << count) | (value >> (64 - count % 64));
}
private unsafe void Hash64(byte[] bytes, int ibStart, int cbSize)
{
if (bytes == null)
return;
if (ibStart >= bytes.Length || cbSize > bytes.Length)
return;
var i = 1;
fixed (byte* pb = bytes)
{
var nb = pb + ibStart;
while (cbSize >= 1)
{
hash ^= RotateLeft(_table[*nb], i++);
nb += 1;
cbSize -= 1;
}
}
}
protected override byte[] HashFinal()
{
zhs.hash64 = hash;
hash32 = zhs.hi ^ zhs.lo;
return hash.GetBytes();
}
public void BuildTable(ulong seed)
{
var rnd = new CRng1(seed.GetBytes());
var tt = new CHashSet<ulong>(256);
_table = new ulong[256];
for (var i = 0; i < 256; i++)
{
ulong v;
do
{
v = rnd.NextULong();
} while (tt.Contains(v));
tt.Add(v);
_table[i] = v;
}
}
[StructLayout(LayoutKind.Explicit)]
public struct ZOB32State
{
[FieldOffset(0)] public ulong hash64;
[FieldOffset(0)] public uint lo;
[FieldOffset(4)] public uint hi;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment