ZOB64.cs

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;
    }
}