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

Leave a Reply

Your email address will not be published. Required fields are marked *