Example Zobrist Hashing 64-Bit
using System;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
/// <summary>
///
/// https://en.wikipedia.org/wiki/Zobrist_hashing
///
/// </summary>
public class ZOB64 : HashAlgorithm
{
private readonly ulong starthash = 0x391615744853B307;
private ulong[] _table;
private ulong hash;
private uint hash32;
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 s1 = (int) seed;
var s2 = (int) (seed >> 32);
var rnd = new Random(s1);
var rnd1 = new Random(s2);
var tt = new DynHashSet32<ulong>();
_table = new ulong[256];
var u = new ZOB32State();
for(var i = 0; i < 256; i++)
{
ulong v;
do
{
u.hi = (uint) rnd.Next();
u.lo = (uint) rnd1.Next();
v = u.hash64;
} 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;
}
}