Mapping64BitToHash32Bit.cs

Maps a 64-Bit Hash Into a 32-Bit Space

using System.Security.Cryptography;
/// <summary>
///     Pros: ~no Collisions within int bit space ~(2,147,483,647)
///     Cons: Maintains a TinyDictionary(byte[],byte[]), non-deterministic across application or
///     method domains
///     Cannot Transform or reuse.
/// </summary>
public class Mapping64BitToHash32Bit : HashAlgorithm
{
    private readonly FNV1a64                        hasher = new FNV1a64();
    public readonly  TinyDictionary<byte[], byte[]> map    = new TinyDictionary<byte[], byte[]>(101, new ArrayComparer());
    private          byte[]                         h64;
    public override  int                            HashSize => 32;
    public override void Initialize()
    {
    }
    /// <inheritdoc />
    /// <summary>
    ///     Compute the 64 Bit hash value and add it and the original array to the map to create a unique position within the
    ///     TinyDictionary.
    /// </summary>
    protected override void HashCore(byte[] bytes, int ibStart, int cbSize)
    {
        h64 = hasher.ComputeHash(bytes, ibStart, cbSize);
        map.Add(h64, bytes);
    }
    /// <inheritdoc />
    /// <summary>
    ///     Return the unique position within the TinyDictionary as the hash value (index).
    /// </summary>
    protected override byte[] HashFinal()
    {
        HashValue = (byte[]) map.FindKeyIndex(h64).GetBytes().Clone();
        return HashValue;
    }
}

FNV1a64.cs

Fowler–Noll–Vo hash function 64-Bit

Updated: Jan-3,2021

using System;
using System.Security.Cryptography;
[Serializable]
public class FNV1a64 : HashAlgorithm
{
    private const ulong K = 0x100000001B3;
    private const ulong M = 0x1000000000000000;
    public        ulong _hash;
    public        ulong Hash;
    public        ulong Seed = 0xCBF29CE484222325;
    public FNV1a64()
    {
        _hash = Seed;
    }
    public FNV1a64(ulong seed)
    {
        Seed  = seed;
        _hash = Seed;
    }
    public override int HashSize => 64;
    public override void Initialize()
    {
        _hash = Seed;
    }
    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;
        fixed (byte* pb = bytes)
        {
            var nb = pb + ibStart;
            while (cbSize >= 8)
            {
                _hash  ^= *(ulong*) nb;
                nb     += 8;
                cbSize -= 8;
                _hash  *= K;
                _hash  %= M;
            }
            switch (cbSize & 7)
            {
                case 7:
                    _hash ^= *(ulong*) (nb + 6);
                    _hash *= K;
                    _hash %= M;
                    goto case 6;
                case 6:
                    _hash ^= *(ulong*) (nb + 5);
                    _hash *= K;
                    _hash %= M;
                    goto case 5;
                case 5:
                    _hash ^= *(ulong*) (nb + 4);
                    _hash *= K;
                    _hash %= M;
                    goto case 4;
                case 4:
                    _hash ^= *(ulong*) (nb + 3);
                    _hash *= K;
                    _hash %= M;
                    goto case 3;
                case 3:
                    _hash ^= *(ulong*) (nb + 2);
                    _hash *= K;
                    _hash %= M;
                    goto case 2;
                case 2:
                    _hash ^= *(ulong*) (nb + 1);
                    _hash *= K;
                    _hash %= M;
                    goto case 1;
                case 1:
                    _hash ^= *nb;
                    _hash *= K;
                    _hash %= M;
                    break;
            }
        }
    }
    public unsafe ulong Hash64(byte[] bytes)
    {
        var cbSize = bytes.Length;
        _hash = Seed;
        fixed (byte* pb = bytes)
        {
            var nb = pb;
            while (cbSize >= 8)
            {
                _hash  ^= *(ulong*) nb;
                nb     += 8;
                cbSize -= 8;
                _hash  *= K;
                _hash  %= M;
            }
            switch (cbSize & 7)
            {
                case 7:
                    _hash ^= *(ulong*) (nb + 6);
                    _hash *= K;
                    _hash %= M;
                    goto case 6;
                case 6:
                    _hash ^= *(ulong*) (nb + 5);
                    _hash *= K;
                    _hash %= M;
                    goto case 5;
                case 5:
                    _hash ^= *(ulong*) (nb + 4);
                    _hash *= K;
                    _hash %= M;
                    goto case 4;
                case 4:
                    _hash ^= *(ulong*) (nb + 3);
                    _hash *= K;
                    _hash %= M;
                    goto case 3;
                case 3:
                    _hash ^= *(ulong*) (nb + 2);
                    _hash *= K;
                    _hash %= M;
                    goto case 2;
                case 2:
                    _hash ^= *(ulong*) (nb + 1);
                    _hash *= K;
                    _hash %= M;
                    goto case 1;
                case 1:
                    _hash ^= *nb;
                    _hash *= K;
                    _hash %= M;
                    break;
            }
        }
        return _hash;
    }
    protected override byte[] HashFinal()
    {
        Hash = _hash;
        return _hash.GetBytes();
    }
}

Mapping160BitTo64BitHash.cs

Maps a 160-Bit Hash Into a 64-Bit Space

using System.Security.Cryptography;
/// <summary>
///     Pros: ~no Collisions within long bit space ~(9,223,372,036,854,775,807)
///     Cons: Maintains a TinyDictionary(byte[],byte[]), non-deterministic across application or
///     method domains
///     Cannot Transform or reuse.
/// </summary>
public class Mapping160BitTo64BitHash : HashAlgorithm
{
    public readonly  TinyDictionary<byte[], byte[]> map = new TinyDictionary<byte[], byte[]>(101, new ArrayComparer());
    private          byte[]                         h160;
    private readonly SHA1Managed                    hasher = new SHA1Managed();
    public override  int                            HashSize => 64;
    public override void Initialize()
    {
    }
    /// <inheritdoc />
    /// <summary>
    ///     Compute the 64 Bit hash value and add it and the original array to the map to create a unique position within the
    ///     TinyDictionary.
    /// </summary>
    protected override void HashCore(byte[] bytes, int ibStart, int cbSize)
    {
        h160 = hasher.ComputeHash(bytes, ibStart, cbSize);
        map.Add(h160, bytes);
    }
    /// <inheritdoc />
    /// <summary>
    ///     Return the unique position within the TinyDictionary as the hash value (index).
    /// </summary>
    protected override byte[] HashFinal()
    {
        HashValue = (byte[])map.FindKeyIndex(h160).GetBytes().Clone();
        return HashValue;
    }
}