FNV1aX.cs

FNV1a 128…1024Bit Hashing BigInteger

using System;
using System.Numerics;
using System.Security.Cryptography;
using static System.Globalization.CultureInfo;
using static System.Globalization.NumberStyles;
using static System.Numerics.BigInteger;
[Serializable]
public class FNV1aX : HashAlgorithm
{
    private static int        _bitWidth;
    private        BigInteger _h1;
    public         BigInteger _mod;
    public         BigInteger _offset;
    private        BigInteger _prime;
    public FNV1aX(int bitWidth = 128)
    {
        _bitWidth = bitWidth;
        SetBitWidthPom(bitWidth);
        _h1 = _offset;
    }
    public override int HashSize => _bitWidth;
    private void SetBitWidthPom(int bitWidth)
    {
        switch (bitWidth)
        {
            //case 32:
            //    _prime  = Parse("1000193", AllowHexSpecifier, InvariantCulture);
            //    _offset = Parse("811c9dc5", AllowHexSpecifier, InvariantCulture);
            //    _mod    = Parse("10000000", AllowHexSpecifier, InvariantCulture);
            //    break;
            //case 64:
            //    _prime  = Parse("100000001B3", AllowHexSpecifier, InvariantCulture);
            //    _offset = Parse("CBF29CE484222325", AllowHexSpecifier, InvariantCulture);
            //    _mod    = Parse("1000000000000000", AllowHexSpecifier, InvariantCulture);
            //    break;
            case 128:
                _prime = Parse("0000000001000000000000000000013B", AllowHexSpecifier, InvariantCulture);
                _offset = Parse("6c62272e07bb014262b821756295c58d", AllowHexSpecifier, InvariantCulture);
                _mod = Parse("10000000000000000000000000000000", AllowHexSpecifier, InvariantCulture);
                break;
            case 256:
                _prime  = Parse("0000000000000000000001000000000000000000000000000000000000000163", AllowHexSpecifier, InvariantCulture);
                _offset = Parse("dd268dbcaac550362d98c384c4e576ccc8b1536847b6bbb31023b4c8caee0535", AllowHexSpecifier, InvariantCulture);
                _mod    = Parse("1000000000000000000000000000000000000000000000000000000000000000", AllowHexSpecifier, InvariantCulture);
                break;
            case 512:
                _prime = Parse("00000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000157",
                    AllowHexSpecifier, InvariantCulture);
                _offset = Parse("b86db0b1171f4416dca1e50f309990acac87d059c90000000000000000000d21e948f68a34c192f62ea79bc942dbe7ce182036415f56e34bac982aac4afe9fd9",
                    AllowHexSpecifier, InvariantCulture);
                _mod = Parse("10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", AllowHexSpecifier,
                    InvariantCulture);
                break;
            case 1024:
                _prime = Parse(
                    "000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018D",
                    AllowHexSpecifier, InvariantCulture);
                _offset = Parse(
                    "0000000000000000005f7a76758ecc4d32e56d5a591028b74b29fc4223fdada16c3bf34eda3674da9a21d9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004c6d7eb6e73802734510a555f256cc005ae556bde8cc9c6a93b21aff4b16c71ee90b3",
                    AllowHexSpecifier, InvariantCulture);
                _mod = Parse(
                    "1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
                    AllowHexSpecifier, InvariantCulture);
                break;
        }
    }
    public override void Initialize()
    {
        _h1 = _offset;
    }
    protected override void HashCore(byte[] bytes, int ibStart, int cbSize)
    {
        Hash(bytes, ibStart, cbSize);
    }
    private unsafe void Hash(byte[] bytes, int ibStart, int cbSize)
    {
        if (bytes == null)
            return;
        if (ibStart >= bytes.Length || cbSize > bytes.Length)
            return;
        fixed (byte* pb = bytes)
        {
            var nb = pb + ibStart;
            while (cbSize >= 8)
            {
                _h1    ^= *(ulong*) nb;
                _h1    *= _prime;
                _h1    %= _mod;
                nb     += 8;
                cbSize -= 8;
            }
            switch (cbSize & 7)
            {
                case 7:
                    _h1 ^= *(ulong*) (nb + 6);
                    _h1 *= _prime;
                    _h1 %= _mod;
                    goto case 6;
                case 6:
                    _h1 ^= *(ulong*) (nb + 5);
                    _h1 *= _prime;
                    _h1 %= _mod;
                    goto case 5;
                case 5:
                    _h1 ^= *(ulong*) (nb + 4);
                    _h1 *= _prime;
                    _h1 %= _mod;
                    goto case 4;
                case 4:
                    _h1 ^= *(ulong*) (nb + 3);
                    _h1 *= _prime;
                    _h1 %= _mod;
                    goto case 3;
                case 3:
                    _h1 ^= *(ulong*) (nb + 2);
                    _h1 *= _prime;
                    _h1 %= _mod;
                    goto case 2;
                case 2:
                    _h1 ^= *(ulong*) (nb + 1);
                    _h1 *= _prime;
                    _h1 %= _mod;
                    goto case 1;
                case 1:
                    _h1 ^= *nb;
                    _h1 *= _prime;
                    _h1 %= _mod;
                    break;
            }
        }
    }
    protected override byte[] HashFinal()
    {
        return _h1.ToByteArray();
    }
}

Fnv1a64Fast.cs

FNV1a 64Bit Hashing Fast

using System.Security.Cryptography;
/// <summary>
///     https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function
///     Very fast up to 2GBpS.
/// </summary>
public class Fnv1a64Fast : HashAlgorithm
{
    private const    ulong _prime  = 0x100000001B3;
    private readonly ulong _offset = 0xCBF29CE484222325;
    private          ulong _hash;
    public           ulong Hashf;
    public Fnv1a64Fast()
    {
        _hash = _offset;
    }
    public Fnv1a64Fast(ulong seed)
    {
        _offset = seed;
        _hash   = _offset;
    }
    public override int HashSize => 64;
    public override void Initialize()
    {
        _hash = _offset;
    }
    protected override void HashCore(byte[] bytes, int ibStart, int cbSize)
    {
        Hash64(bytes, ibStart, cbSize);
    }
    private unsafe void Hash64(byte[] bytes, int ibStart, int cbSize)
    {
        if (bytes == null)
            return;
        if (ibStart >= bytes.Length || cbSize > bytes.Length)
            return;
        unchecked
        {
            fixed (byte* pb = bytes)
            {
                var nb = pb + ibStart;
                while (cbSize >= 8)
                {
                    _hash  ^= *(ulong*) nb;
                    _hash  *= _prime;
                    nb     += 8;
                    cbSize -= 8;
                }
                switch (cbSize & 7)
                {
                    case 7:
                        _hash ^= *(ulong*) (nb + 6);
                        _hash *= _prime;
                        goto case 6;
                    case 6:
                        _hash ^= *(ulong*) (nb + 5);
                        _hash *= _prime;
                        goto case 5;
                    case 5:
                        _hash ^= *(ulong*) (nb + 4);
                        _hash *= _prime;
                        goto case 4;
                    case 4:
                        _hash ^= *(ulong*) (nb + 3);
                        _hash *= _prime;
                        goto case 3;
                    case 3:
                        _hash ^= *(ulong*) (nb + 2);
                        _hash *= _prime;
                        goto case 2;
                    case 2:
                        _hash ^= *(ulong*) (nb + 1);
                        _hash *= _prime;
                        goto case 1;
                    case 1:
                        _hash ^= *nb;
                        _hash *= _prime;
                        break;
                }
            }
        }
        _hash = _hash ^ (_hash >> 32);
        Hashf = _hash;
    }
    protected override byte[] HashFinal()
    {
        var ba = new byte[8];
        unsafe
        {
            fixed (byte* ptr = ba)
            {
                *(ulong*) ptr = _hash;
            }
        }
        return ba;
    }
}

FNV1a32Fast.cs

FNV1a 32 Bit Fast Hashing

using System.Security.Cryptography;
/// <summary>
///     https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function
///     Very fast 2GBpS.
/// </summary>
public class FNV1a32Fast : HashAlgorithm
{
    private const    ulong _prime = 0x100000001B3;
    private          ulong _hash;
    private readonly ulong _offset = 0xCBF29CE484222325;
    public           uint  Hashf;
    public FNV1a32Fast()
    {
        _hash = _offset;
    }
    public FNV1a32Fast(ulong seed)
    {
        _offset = seed;
        _hash   = _offset;
    }
    public override int HashSize => 32;
    public override void Initialize()
    {
        _hash = _offset;
    }
    protected override void HashCore(byte[] bytes, int ibStart, int cbSize)
    {
        Hash64(bytes, ibStart, cbSize);
    }
    private unsafe void Hash64(byte[] bytes, int ibStart, int cbSize)
    {
        if (bytes == null)
            return;
        if (ibStart >= bytes.Length || cbSize > bytes.Length)
            return;
        unchecked
        {
            fixed (byte* pb = bytes)
            {
                var nb = pb + ibStart;
                while (cbSize >= 8)
                {
                    _hash  ^= *(ulong*) nb;
                    _hash  *= _prime;
                    nb     += 8;
                    cbSize -= 8;
                }
                switch (cbSize & 7)
                {
                    case 7:
                        _hash ^= *(ulong*) (nb + 6);
                        _hash *= _prime;
                        goto case 6;
                    case 6:
                        _hash ^= *(ulong*) (nb + 5);
                        _hash *= _prime;
                        goto case 5;
                    case 5:
                        _hash ^= *(ulong*) (nb + 4);
                        _hash *= _prime;
                        goto case 4;
                    case 4:
                        _hash ^= *(ulong*) (nb + 3);
                        _hash *= _prime;
                        goto case 3;
                    case 3:
                        _hash ^= *(ulong*) (nb + 2);
                        _hash *= _prime;
                        goto case 2;
                    case 2:
                        _hash ^= *(ulong*) (nb + 1);
                        _hash *= _prime;
                        goto case 1;
                    case 1:
                        _hash ^= *nb;
                        _hash *= _prime;
                        break;
                }
            }
        }
        var usb = (uint) (_hash >> 32);
        var lsb = (uint) _hash;
        Hashf = usb ^ lsb;
    }
    protected override byte[] HashFinal()
    {
        var ba = new byte[4];
        unsafe
        {
            fixed (byte* ptr = ba)
            {
                *(uint*) ptr = Hashf;
            }
        }
        return ba;
    }
}

FNV1a128b.cs

FNV1a Patterned 128Bit Hashing Algorithm using BigInteger

using System.Numerics;
using System.Security.Cryptography;
public class FNV1a128b : HashAlgorithm
{
    private readonly BigInteger K = "309485009821345068724781371".BigIntegerBase10();
    private readonly BigInteger M = "340282366920938463463374607431768211456".BigIntegerBase10();
    private          BigInteger _hash;
    private readonly BigInteger Seed = "144066263297769815596495629667062367629".BigIntegerBase10();
    public FNV1a128b()
    {
        _hash = Seed;
    }
    public FNV1a128b(BigInteger seed)
    {
        Seed  = seed;
        _hash = Seed;
    }
    public override int HashSize => 128;
    public override void Initialize()
    {
        _hash = Seed;
    }
    protected override void HashCore(byte[] bytes, int ibStart, int cbSize)
    {
        Hash128(bytes, ibStart, cbSize);
    }
    protected override byte[] HashFinal()
    {
        return _hash.ToByteArray();
    }
    private unsafe void Hash128(byte[] bytes, int ibStart, int cbSize)
    {
        fixed (byte* pb = bytes)
        {
            var np = pb + ibStart;
            for (; cbSize > 0; --cbSize, np++)
                _hash = ((_hash ^ *np) * K) % M;
        }
    }
}

Sha16512.cs

Variable 16Bit to 512Bit Hashing Algorithm

using System;
using System.Security.Cryptography;
[Serializable]
public class Sha16512 : HashAlgorithm
{
    private int           _bitWidth;
    private SHA512Managed _hash = new SHA512Managed();
    public Sha16512(int bitWidth)
    {
        if (bitWidth < 16 || bitWidth > 512)
            throw new ArgumentException($"Bit Width {bitWidth} must be between 16 and 512.");
        _bitWidth = bitWidth;
    }
    public override int HashSize => _bitWidth;
    public override void Initialize()
    {
    }
    protected override void HashCore(byte[] bytes, int ibStart, int cbSize)
    {
        var buf = bytes.SubByte(ibStart, cbSize);
        HashValue = _hash.ComputeHash(buf).SubByte(0, _bitWidth >> 3);
    }
    protected override byte[] HashFinal()
    {
        return (byte[]) HashValue.Clone();
    }
}

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