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

ArrayComparer.cs

Byte Array Comparer Class

Updated: Dec-22,2020
Updated: May-04,2021

using System;
using System.Collections.Generic;
[Serializable]
public class ArrayComparer : IEqualityComparer<byte[]>
{
    private const ulong M = 0x10000000;
    public bool Equals(byte[] x, byte[] y)
    {
        if (x == null || y == null)
            return false;
        if (x.Length != y.Length)
            return false;
        return x.Compare(y);
    }
    public unsafe int GetHashCode(byte[] obj)
    {
        var cbSize = obj.Length;
        var hash   = 0x811C9DC5;
        fixed (byte* pb = obj)
        {
            var nb = pb;
            while (cbSize >= 4)
            {
                hash   ^= *(uint*) nb;
                hash   *= 0x1000193;
                hash   %= 0x10000000;
                nb     += 4;
                cbSize -= 4;
            }
            switch (cbSize & 3)
            {
                case 3:
                    hash ^= *(uint*) (nb + 2);
                    hash *= 0x1000193;
                    hash %= 0x10000000;
                    goto case 2;
                case 2:
                    hash ^= *(uint*) (nb + 1);
                    hash *= 0x1000193;
                    hash %= 0x10000000;
                    goto case 1;
                case 1:
                    hash ^= *nb;
                    hash *= 0x1000193;
                    hash %= 0x10000000;
                    break;
            }
        }
        return (int) hash;
    }
}

TinyDictionary.cs

A Small Dictionary Class

using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
[DebuggerDisplay("Count = {Count}")]
[Serializable]
public class TinyDictionary<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>>
{
    public MSet15<TKey> Keys;
    public int          Resizes;
    public TValue[]     Values;
    public TinyDictionary() : this(101, EqualityComparer<TKey>.Default)
    {
    }
    public TinyDictionary(int size) : this(size, EqualityComparer<TKey>.Default)
    {
    }
    public TinyDictionary(int size, IEqualityComparer<TKey> comparer)
    {
        if (comparer == null)
            comparer = EqualityComparer<TKey>.Default;
        Keys          = new MSet15<TKey>(size);
        Values        = new TValue[size];
        Keys.Comparer = comparer;
    }
    public TinyDictionary(IEnumerable<KeyValuePair<TKey, TValue>> collection, IEqualityComparer<TKey> comparer = null)
    {
        if (comparer == null)
            comparer = EqualityComparer<TKey>.Default;
        Keys.Comparer = comparer;
        foreach (var kp in collection)
            Add(kp.Key, kp.Value);
    }
    public int Count => Keys.Count;
    public TValue this[TKey key]
    {
        get
        {
            var pos = Keys.FindEntry(key);
            return pos == -1 ? default : Values[pos];
        }
        set => Add(key, value);
    }
    public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
    {
        for (var i = 0; i < Count; i++)
            if (Keys.Slots[i].HashCode > 0)
                yield return new KeyValuePair<TKey, TValue>(Keys.Slots[i].Value, Values[i]);
    }
    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
    public bool Add(TKey key, TValue value)
    {
        if (!Keys.Add(key))
        {
            if (Values.Length != Keys.Slots.Length)
            {
                var nValues = new TValue[Keys.Slots.Length];
                Array.Copy(Values, nValues, Values.Length);
                Values = nValues;
                Resizes++;
            }
            Values[Keys.Position] = value;
            return false;
        }
        Values[Keys.Position] = value;
        return true;
    }
    public void Remove(TKey key)
    {
        var pos = Keys.FindEntry(key);
        if (pos != -1)
        {
            Values[pos] = default;
            Keys.Remove(key);
        }
    }
    public bool ContainsKey(TKey key)
    {
        return Keys.FindEntry(key) != -1;
    }
    public int FindKeyIndex(TKey key)
    {
        return Keys.FindEntry(key);
    }
}

TinySet.cs

A Small HashSet Class

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
[DebuggerTypeProxy(typeof(HashSetDebugView<>))]
[DebuggerDisplay("Count = {" + nameof(Count) + "}")]
[Serializable]
public class TinySet<T>
{
    private  int[]                _hashBuckets;
    private  SizeHelper<T>        _newSize = new SizeHelper<T>();
    internal IEqualityComparer<T> Comparer;
    public   int                  Position;
    internal Slot[]               Slots;
    public TinySet() : this(101, EqualityComparer<T>.Default)
    {
    }
    public TinySet(int size) : this(size, EqualityComparer<T>.Default)
    {
    }
    public TinySet(IEqualityComparer<T> comparer) : this(101, comparer)
    {
    }
    public TinySet(int size, IEqualityComparer<T> comparer)
    {
        if (comparer == null)
            comparer = EqualityComparer<T>.Default;
        Comparer     = comparer;
        _hashBuckets = new int[size];
        Slots        = new Slot[size];
        Count        = 0;
        Position     = -1;
    }
    public TinySet(IEnumerable<T> collection, IEqualityComparer<T> comparer)
    {
        if (comparer == null)
            comparer = EqualityComparer<T>.Default;
        Comparer = comparer;
        if (!(collection is ICollection<T> coll))
            return;
        var size = coll.Count;
        _hashBuckets = new int[size];
        Slots        = new Slot[size];
        UnionWith(coll);
    }
    public int Count
    {
        get;
        private set;
    }
    public T[] ToArray()
    {
        var newArray = new T[Count];
        var copied   = 0;
        for (var i = 0; i < Count && copied < Count; i++)
            if (Slots[i].HashCode > 0)
                newArray[copied++] = Slots[i].Value;
        return newArray;
    }
    public void Create(int size, IEqualityComparer<T> comparer)
    {
        if (comparer == null)
            comparer = EqualityComparer<T>.Default;
        Comparer     = comparer;
        _hashBuckets = new int[size];
        Slots        = new Slot[size];
        Count        = 0;
        Position     = -1;
    }
    public void Clear()
    {
        var size = Slots.Length;
        _hashBuckets = new int[size];
        Slots        = new Slot[size];
        Count        = 0;
        Position     = -1;
    }
    public bool Add(T item)
    {
        return Insert(item, true);
    }
    public bool Contains(T item)
    {
        return Insert(item, false);
    }
    internal bool Insert(T item, bool add)
    {
        var hashCode = Comparer.GetHashCode(item) & int.MaxValue;
        if (FindEntry(item, hashCode) != -1)
            return true;
        if (add)
        {
            if (Count >= Slots.Length)
                SetSizeAndOrForceNewHashCodes(_newSize.GetNewSize(_hashBuckets.Length));
            var hashPos = hashCode % _hashBuckets.Length;
            Slots[Count].Next     = _hashBuckets[hashPos] - 1;
            Slots[Count].Value    = item;
            Slots[Count].HashCode = hashCode;
            _hashBuckets[hashPos] = Count + 1;
            Position              = Count;
            ++Count;
        }
        return false;
    }
    public void ForceNewHashCodes()
    {
        SetSizeAndOrForceNewHashCodes();
    }
    private void SetSizeAndOrForceNewHashCodes(int Size = 0)
    {
        if (Count == 0) return;
        var newSize        = Size == 0 ? Count : Size;
        var newSlots       = new Slot[newSize];
        var newHashBuckets = new int[newSize];
        if (Slots != null)
            Array.Copy(Slots, 0, newSlots, 0, Count);
        for (var i = 0; i < newSize; ++i)
            if (newSlots[i].HashCode > 0 && newSlots[i].Value != null)
                newSlots[i].HashCode = Comparer.GetHashCode(newSlots[i].Value) & int.MaxValue;
        for (var i = 0; i < newSize; ++i)
        {
            var pos = newSlots[i].HashCode % newSize;
            newSlots[i].Next    = newHashBuckets[pos] - 1;
            newHashBuckets[pos] = i                   + 1;
        }
        Slots        = newSlots;
        _hashBuckets = newHashBuckets;
    }
    public void TrimExcess()
    {
        var newHashBuckets = new int[Count];
        var newSlots       = new Slot[Count];
        Array.Copy(Slots, newSlots, Count);
        for (var i = 0; i < Count; i++)
        {
            var pos = newSlots[i].HashCode % Count;
            newSlots[i].Next    = newHashBuckets[pos] - 1;
            newHashBuckets[pos] = i                   + 1;
        }
        _hashBuckets = newHashBuckets;
        Slots        = newSlots;
    }
    public bool Remove(T item)
    {
        if (Count != 0)
        {
            var hashCode = Comparer.GetHashCode(item) & int.MaxValue;
            var iPos     = hashCode % _hashBuckets.Length;
            var tPos     = -1;
            for (var sPos = _hashBuckets[iPos] - 1; sPos >= 0; sPos = Slots[sPos].Next)
            {
                if (Slots[sPos].HashCode == hashCode && Comparer.Equals(Slots[sPos].Value, item))
                {
                    if (tPos < 0)
                        _hashBuckets[iPos] = Slots[sPos].Next + 1;
                    else
                        Slots[tPos].Next = Slots[sPos].Next;
                    Slots[sPos].HashCode = -1;
                    Slots[sPos].Value    = default;
                    Slots[sPos].Next     = 0;
                    --Count;
                    return true;
                }
                tPos = sPos;
            }
        }
        return false;
    }
    private int FindEntry(T item, int hashCode)
    {
        for (var position = _hashBuckets[hashCode % _hashBuckets.Length] - 1; position >= 0; position = Slots[position].Next)
            if (Slots[position].HashCode == hashCode && Comparer.Equals(Slots[position].Value, item))
            {
                Position = position;
                return position;
            }
        return -1;
    }
    public int FindEntry(T item)
    {
        return FindEntry(item, Comparer.GetHashCode(item) & int.MaxValue);
    }
    public void ExceptWith(IEnumerable<T> other)
    {
        if (other == null)
            throw new Exception("The other set must not be null.");
        if (Count == 0)
            return;
        if (Equals(other, this))
            Clear();
        else
            foreach (var obj in other)
                Remove(obj);
    }
    public void UnionWith(IEnumerable<T> other)
    {
        if (other == null)
            throw new Exception("The other set must not be null.");
        foreach (var obj in other)
            Add(obj);
    }
    public bool Overlaps(IEnumerable<T> other)
    {
        if (other == null)
            throw new Exception("The other set must not be null.");
        return Count != 0 && other.Any(Contains);
    }
    public bool ContainsAllElements(IEnumerable<T> other)
    {
        return other.All(Contains);
    }
    public int RemoveWhere(Predicate<T> pred)
    {
        if (pred == null)
            throw new Exception("The Predicate cannot be null.");
        var matches = 0;
        for (var i = 0; i < Count; ++i)
            if (Slots[i].HashCode >= 0)
            {
                var obj = Slots[i].Value;
                if (pred(obj) && Remove(obj))
                    ++matches;
            }
        return matches;
    }
    internal struct Slot
    {
        public int HashCode;
        public int Next;
        public T   Value;
    }
}

SizeHelper.cs

Non-Linear Array Size Adjustment Class

using System;
using System.Collections.Generic;
using Microsoft.VisualBasic.Devices;
public class SizeHelper<T>
{
    private static readonly FixedIntXPrimality bp = new FixedIntXPrimality(64);
    private readonly        int                AllocatedSizeLimit;
    public                  int[]              Curve;
    private                 int                Resizes;
    public SizeHelper()
    {
        var measure   = new MeasureSize<T>();
        var sizeOfOne = measure.GetByteSize();
        var am        = new ComputerInfo().AvailablePhysicalMemory;
        AllocatedSizeLimit = (int) ((long) am / sizeOfOne);
    }
    public int GetNewSize(int currentSize)
    {
        Resizes++;
        if (Curve == null)
            BuildCurve(currentSize);
        foreach (var v in Curve)
            if (v > currentSize)
                return v;
        var nv = GetNextValue(currentSize);
        return nv != -1 ? nv : int.MaxValue;
    }
    private int GetNextValue(int currentValue)
    {
        for (var value = currentValue | 1; value < AllocatedSizeLimit; value += 16384)
        {
            if (value < 0)
                break;
            if (bp.IsPrime(value))
                return value + 1;
        }
        return -1;
    }
    private void BuildCurve(int Size)
    {
        int Sizer(int oldSize)
        {
            try
            {
                oldSize = (int) (uint) oldSize;
                var log     = Math.Log(oldSize);
                var inv     = 1.0 / log * 4;
                var newSize = oldSize   * (1.0 + inv);
                return (int) (uint) newSize;
            }
            catch
            {
                return AllocatedSizeLimit;
            }
        }
        var curlst = new List<int>();
        var value  = Size | 1;
        do
        {
            value = Sizer(value);
            if (value < 0)
                break;
            if (value < AllocatedSizeLimit)
                curlst.Add(value);
        } while (value < AllocatedSizeLimit);
        Curve = curlst.ToArray();
        var dl   = new List<int>();
        var last = 0;
        for (var i = 0; i < Curve.Length; ++i)
        {
            if (i > 0)
                last = Curve[i - 1];
            var v = Curve[i];
            dl.Add(v - last);
        }
        var str = "";
        foreach (var v in dl)
            str += $"{v},";
    }
}

MiscByte.cs

Collection of Miscellaneous Byte Helper Functions

public static class MiscByte
{
 public static byte[] Add(this byte[] left, byte[] right)
        {
            var l1 = left.Length;
            var l2 = right.Length;

            if (l1 > 0 && l2 > 0)
            {
                var ret = new byte[l1 + l2];
                Buffer.BlockCopy(left, 0, ret, 0, l1);
                Buffer.BlockCopy(right, 0, ret, l1, l2);
                return ret;
            }

            if (l1 > 0 && l2 == 0)
                return left;

            if (l2 > 0 && l1 == 0)
                return right;

            return new byte[0];
        }

        public static byte[] XOR(this byte[] left, byte[] right)
        {
            var l1 = left.Length;
            var l2 = right.Length;

            if (l1 != l2)
                throw new Exception("Error: left and right arrays lengths must be equal.");

            var ret = new byte[l1];

            for (var i = 0; i < l1; ++i)
                ret[i] = (byte)((left[i] ^ right[i]) & 0xff);

            return ret;
        }

        public static byte[] OR(this byte[] left, byte[] right)
        {
            var l1 = left.Length;
            var l2 = right.Length;

            if (l1 != l2)
                throw new Exception("Error: left and right arrays lengths must be equal.");

            var ret = new byte[l1];

            for (var i = 0; i < l1; ++i)
                ret[i] = (byte)((left[i] | right[i]) & 0xff);

            return ret;
        }

        public static byte[] AND(this byte[] left, byte[] right)
        {
            var l1 = left.Length;
            var l2 = right.Length;

            if (l1 != l2)
                throw new Exception("Error: left and right arrays lengths must be equal.");

            var ret = new byte[l1];

            for (var i = 0; i < l1; ++i)
                ret[i] = (byte)(left[i] & right[i] & 0xff);

            return ret;
        }

        public static byte[] NOT(this byte[] left)
        {
            var l1 = left.Length;
            var ret = new byte[l1];

            for (var i = 0; i < l1; ++i)
                ret[i] = (byte)((ushort)~left[i] & 0xff);

            return ret;
        }

        [SecuritySafeCritical]
        public static unsafe byte[] Clone(this byte[] a1)
        {
            if (a1 == null)
                return null;

            var a2 = new byte[a1.Length];

            fixed (byte* p1 = a1, p2 = a2)
            {
                var Len = a1.Length;
                byte* x1 = p1, x2 = p2;

                while (Len > 7)
                {
                    *(long*)x2 = *(long*)x1;
                    x1 += 8;
                    x2 += 8;
                    Len -= 8;
                }

                switch (Len % 8)
                {
                    case 0:
                        break;
                    case 7:
                        *(int*)x2 = *(int*)x1;
                        x1 += 4;
                        x2 += 4;
                        *(short*)x2 = *(short*)x1;
                        x1 += 2;
                        x2 += 2;
                        *x2 = *x1;
                        break;
                    case 6:
                        *(int*)x2 = *(int*)x1;
                        x1 += 4;
                        x2 += 4;
                        *(short*)x2 = *(short*)x1;
                        break;
                    case 5:
                        *(int*)x2 = *(int*)x1;
                        x1 += 4;
                        x2 += 4;
                        *x2 = *x1;
                        break;
                    case 4:
                        *(int*)x2 = *(int*)x1;
                        break;
                    case 3:
                        *(short*)x2 = *(short*)x1;
                        x1 += 2;
                        x2 += 2;
                        *x2 = *x1;
                        break;
                    case 2:
                        *(short*)x2 = *(short*)x1;
                        break;
                    case 1:
                        *x2 = *x1;
                        break;
                }

                return a2;
            }
        }

        [SecuritySafeCritical]
        public static unsafe bool Copy(this byte[] a1, int aindex, byte[] a2, int bindex, int length)
        {
            if (a1 == null || a2 == null)
                return false;

            fixed (byte* p1 = a1, p2 = a2)
            {
                var Len = length;
                byte* x1 = p1 + aindex, x2 = p2 + bindex;

                while (Len > 7)
                {
                    *(long*)x2 = *(long*)x1;
                    x1 += 8;
                    x2 += 8;
                    Len -= 8;
                }

                switch (Len % 8)
                {
                    case 0:
                        break;
                    case 7:
                        *(int*)x2 = *(int*)x1;
                        x1 += 4;
                        x2 += 4;
                        *(short*)x2 = *(short*)x1;
                        x1 += 2;
                        x2 += 2;
                        *x2 = *x1;
                        break;
                    case 6:
                        *(int*)x2 = *(int*)x1;
                        x1 += 4;
                        x2 += 4;
                        *(short*)x2 = *(short*)x1;
                        break;
                    case 5:
                        *(int*)x2 = *(int*)x1;
                        x1 += 4;
                        x2 += 4;
                        *x2 = *x1;
                        break;
                    case 4:
                        *(int*)x2 = *(int*)x1;
                        break;
                    case 3:
                        *(short*)x2 = *(short*)x1;
                        x1 += 2;
                        x2 += 2;
                        *x2 = *x1;
                        break;
                    case 2:
                        *(short*)x2 = *(short*)x1;
                        break;
                    case 1:
                        *x2 = *x1;
                        break;
                }

                return true;
            }
        }
        
        [SecuritySafeCritical]
        public static unsafe byte[] SubByte(this byte[] a1, int aindex, int length)
        {
            if (a1 == null)
                return null;

            if (aindex + length > a1.Length)
                throw new Exception("Error: SubByte - index + length exceed source array length.");

            var a2 = new byte[length];

            fixed (byte* p1 = a1, p2 = a2)
            {
                var Len = length;
                byte* x1 = p1 + aindex, x2 = p2;

                while (Len > 7)
                {
                    *(long*)x2 = *(long*)x1;
                    x1 += 8;
                    x2 += 8;
                    Len -= 8;
                }

                switch (Len % 8)
                {
                    case 0:
                        break;
                    case 7:
                        *(int*)x2 = *(int*)x1;
                        x1 += 4;
                        x2 += 4;
                        *(short*)x2 = *(short*)x1;
                        x1 += 2;
                        x2 += 2;
                        *x2 = *x1;
                        break;
                    case 6:
                        *(int*)x2 = *(int*)x1;
                        x1 += 4;
                        x2 += 4;
                        *(short*)x2 = *(short*)x1;
                        break;
                    case 5:
                        *(int*)x2 = *(int*)x1;
                        x1 += 4;
                        x2 += 4;
                        *x2 = *x1;
                        break;
                    case 4:
                        *(int*)x2 = *(int*)x1;
                        break;
                    case 3:
                        *(short*)x2 = *(short*)x1;
                        x1 += 2;
                        x2 += 2;
                        *x2 = *x1;
                        break;
                    case 2:
                        *(short*)x2 = *(short*)x1;
                        break;
                    case 1:
                        *x2 = *x1;
                        break;
                }

                return a2;
            }
        }

       [SecuritySafeCritical]
        public static byte[] CloneTo(this byte[] a1)
        {
            var a1l = a1.Length;
            var copy = new byte[a1l];
            a1.Copy(copy);
            return copy;
        }

        [SecuritySafeCritical]
        public static unsafe bool Copy(this byte[] a1, byte[] a2)
        {
            if (a1 == null || a2 == null || a1.Length != a2.Length)
                return false;

            fixed (byte* p1 = a1, p2 = a2)
            {
                var Len = a1.Length;
                byte* x1 = p1, x2 = p2;

                while (Len > 7)
                {
                    *(long*)x2 = *(long*)x1;
                    x1 += 8;
                    x2 += 8;
                    Len -= 8;
                }

                switch (Len % 8)
                {
                    case 0:
                        break;
                    case 7:
                        *(int*)x2 = *(int*)x1;
                        x1 += 4;
                        x2 += 4;
                        *(short*)x2 = *(short*)x1;
                        x1 += 2;
                        x2 += 2;
                        *x2 = *x1;
                        break;
                    case 6:
                        *(int*)x2 = *(int*)x1;
                        x1 += 4;
                        x2 += 4;
                        *(short*)x2 = *(short*)x1;
                        break;
                    case 5:
                        *(int*)x2 = *(int*)x1;
                        x1 += 4;
                        x2 += 4;
                        *x2 = *x1;
                        break;
                    case 4:
                        *(int*)x2 = *(int*)x1;
                        break;
                    case 3:
                        *(short*)x2 = *(short*)x1;
                        x1 += 2;
                        x2 += 2;
                        *x2 = *x1;
                        break;
                    case 2:
                        *(short*)x2 = *(short*)x1;
                        break;
                    case 1:
                        *x2 = *x1;
                        break;
                }

                return true;
            }
        }

        public static bool Compare(this short[] a1, short[] a2)
        {
            var b1 = a1.GetBytes();
            var b2 = a2.GetBytes();

            return b1.Compare(b2);
        }

        public static bool Compare(this byte[] a1, short[] a2)
        {
            var b2 = a2.GetBytes();

            return a1.Compare(b2);
        }

        public static bool Compare(this ushort[] a1, ushort[] a2)
        {
            var b1 = a1.GetBytes();
            var b2 = a2.GetBytes();

            return b1.Compare(b2);
        }

        public static bool Compare(this int[] a1, int[] a2)
        {
            var b1 = a1.GetBytes();
            var b2 = a2.GetBytes();

            return b1.Compare(b2);
        }

        public static bool Compare(this uint[] a1, uint[] a2)
        {
            var b1 = a1.GetBytes();
            var b2 = a2.GetBytes();

            return b1.Compare(b2);
        }

        public static bool Compare(this long[] a1, long[] a2)
        {
            var b1 = a1.GetBytes();
            var b2 = a2.GetBytes();

            return b1.Compare(b2);
        }

        public static bool Compare(this ulong[] a1, ulong[] a2)
        {
            var b1 = a1.GetBytes();
            var b2 = a2.GetBytes();

            return b1.Compare(b2);
        }

        public static bool Compare(this double[] a1, double[] a2)
        {
            var b1 = a1.GetBytes();
            var b2 = a2.GetBytes();

            return b1.Compare(b2);
        }

        public static bool Compare(this float[] a1, float[] a2)
        {
            var b1 = a1.GetBytes();
            var b2 = a2.GetBytes();

            return b1.Compare(b2);
        }

        [SecuritySafeCritical]
        public static unsafe bool Compare(this byte[] a1, byte[] a2)
        {
            if (a1 == null && a2 == null)
                return true;

            if (a1 == null || a2 == null || a1.Length != a2.Length)
                return false;

            fixed (byte* p1 = a1, p2 = a2)
            {
                var Len = a1.Length;
                byte* x1 = p1, x2 = p2;

                while (Len > 7)
                {
                    if (*(long*)x2 != *(long*)x1)
                        return false;
                    x1 += 8;
                    x2 += 8;
                    Len -= 8;
                }

                switch (Len % 8)
                {
                    case 0:
                        break;
                    case 7:
                        if (*(int*)x2 != *(int*)x1)
                            return false;
                        x1 += 4;
                        x2 += 4;
                        if (*(short*)x2 != *(short*)x1)
                            return false;
                        x1 += 2;
                        x2 += 2;
                        if (*x2 != *x1)
                            return false;
                        break;
                    case 6:
                        if (*(int*)x2 != *(int*)x1)
                            return false;
                        x1 += 4;
                        x2 += 4;
                        if (*(short*)x2 != *(short*)x1)
                            return false;
                        break;
                    case 5:
                        if (*(int*)x2 != *(int*)x1)
                            return false;
                        x1 += 4;
                        x2 += 4;
                        if (*x2 != *x1)
                            return false;
                        break;
                    case 4:
                        if (*(int*)x2 != *(int*)x1)
                            return false;
                        break;
                    case 3:
                        if (*(short*)x2 != *(short*)x1)
                            return false;
                        x1 += 2;
                        x2 += 2;
                        if (*x2 != *x1)
                            return false;
                        break;
                    case 2:
                        if (*(short*)x2 != *(short*)x1)
                            return false;
                        break;
                    case 1:
                        if (*x2 != *x1)
                            return false;
                        break;
                }

                return true;
            }
        }

        [SecuritySafeCritical]
        public static unsafe bool Fill(this byte[] a1, byte b1)
        {
            if (a1 == null)
                return false;

            byte[] fbl = { b1, b1, b1, b1, b1, b1, b1, b1 };
            byte[] fbi = { b1, b1, b1, b1 };
            byte[] fbs = { b1, b1 };
            byte[] fbb = { b1 };

            fixed (byte* p1 = a1, p8 = fbl, p4 = fbi, p2 = fbs, p0 = fbb)
            {
                var Len = a1.Length;
                var x1 = p1;

                while (Len > 7)
                {
                    *(long*)x1 = *(long*)p8;
                    x1 += 8;
                    Len -= 8;
                }

                switch (Len % 8)
                {
                    case 0:
                        break;
                    case 7:
                        *(int*)x1 = *(int*)p4;
                        x1 += 4;
                        *(short*)x1 = *(short*)p2;
                        x1 += 2;
                        *x1 = *p0;
                        break;
                    case 6:
                        *(int*)x1 = *(int*)p4;
                        x1 += 4;
                        *(short*)x1 = *(short*)p2;
                        break;
                    case 5:
                        *(int*)x1 = *(int*)p4;
                        x1 += 4;
                        *x1 = *p0;
                        break;
                    case 4:
                        *(int*)x1 = *(int*)p4;
                        break;
                    case 3:
                        *(short*)x1 = *(short*)p2;
                        x1 += 2;
                        *x1 = *p0;
                        break;
                    case 2:
                        *(short*)x1 = *(short*)p2;
                        break;
                    case 1:
                        *x1 = *p0;
                        break;
                }

                return true;
            }
        }

        [SecuritySafeCritical]
        public static unsafe bool Fill(this int[] a1, int i1)
        {
            if (a1 == null)
                return false;

            int[] fbl = { i1, i1 };
            int[] fbi = { i1 };

            fixed (int* p1 = a1, p8 = fbl, p4 = fbi)
            {
                var Len = a1.Length;
                var x1 = p1;

                while (Len > 1)
                {
                    *(long*)x1 = *(long*)p8;
                    x1 += 2;
                    Len -= 2;
                }

                if (Len == 1)
                    *x1 = *p4;

                return true;
            }
        }

        [SecuritySafeCritical]
        public static unsafe bool Fill(this long[] a1, long i1)
        {
            if (a1 == null)
                return false;

            long[] fbi = { i1 };

            fixed (long* p1 = a1, p = fbi)
            {
                var Len = a1.Length;
                var x1 = p1;

                while (Len > 1)
                {
                    *x1 = *p;
                    x1 += 1;
                    Len -= 1;
                }

                return true;
            }
        }

        [SecuritySafeCritical]
        public static unsafe bool Fill(this ulong[] a1, ulong i1)
        {
            if (a1 == null)
                return false;

            ulong[] fbi = { i1 };

            fixed (ulong* p1 = a1, p = fbi)
            {
                var Len = a1.Length;
                var x1 = p1;

                while (Len > 1)
                {
                    *x1 = *p;
                    x1 += 1;
                    Len -= 1;
                }

                return true;
            }
        }
}

ArrayMixer.cs

Uses Sha3 to Shuffle Primitive Arrays

using System;
public class ArrayMixer
{
    private readonly SHA3ModInt _alg;
    private readonly int        _moveSize;
    public ArrayMixer() : this(256, 24)
    {
    }
    public ArrayMixer(int hashSize) : this(hashSize, 24)
    {
    }
    public ArrayMixer(int hashSize, int rounds)
    {
        _alg      = new SHA3ModInt(hashSize, rounds);
        _moveSize = _alg.ComputeHash(2.GetBytes()).Length;
    }
    public byte[] Mix(byte[] buf, int iterations = 1000)
    {
        var bufferSize = buf.Length;
        var lBuffer    = new byte[_moveSize];
        var oBuffer    = new byte[bufferSize];
        for (var i = 0; i < iterations; ++i)
        {
            var bytesSuffled = 0;
            var moveSize     = _moveSize;
            var p            = 0;
            while (true)
            {
                var rBytesShuffle = bufferSize - bytesSuffled;
                if (rBytesShuffle < moveSize)
                    moveSize = rBytesShuffle;
                if (rBytesShuffle <= 0)
                    break;
                Buffer.BlockCopy(buf, p, lBuffer, 0, moveSize);
                lBuffer = _alg.ComputeHash(lBuffer);
                Buffer.BlockCopy(lBuffer, 0, oBuffer, p, moveSize);
                p            += moveSize;
                bytesSuffled += moveSize;
            }
            Buffer.BlockCopy(oBuffer, 0, buf, 0, bufferSize);
        }
        lBuffer.Fill(0);
        oBuffer.Fill(0);
        return buf;
    }
    public ushort[] Mix(ushort[] buf, int iterations = 1000)
    {
        var bb = buf.GetBytes();
        return Mix(bb, iterations).ToUShortArray();
    }
    public uint[] Mix(uint[] buf, int iterations = 1000)
    {
        var bb = buf.GetBytes();
        return Mix(bb, iterations).ToUIntArray();
    }
    public ulong[] Mix(ulong[] buf, int iterations = 1000)
    {
        var bb = buf.GetBytes();
        return Mix(bb, iterations).ToULongArray();
    }
    /// <summary>
    ///     Will round up finalSize to the nearest 8 byte boundary.
    /// </summary>
    /// <param name="ba"></param>
    /// <param name="finalSize"></param>
    /// <returns></returns>
    private static ulong[] ByteArrayToULongArray(byte[] ba, int finalSize)
    {
        var minSize = ba.Length / 8;
        if (finalSize < minSize)
            finalSize = minSize;
        ba = PadULong(ba);
        var os = finalSize / 8;
        if (os * 8 < finalSize)
            os++;
        var result = new ulong[os];
        for (var i = 0; i < ba.Length; i += 8)
            Buffer.BlockCopy(ba, i, result, i, 8);
        return result;
    }
    private static byte[] PadULong(byte[] ba)
    {
        var s = ba.Length % 8;
        switch (s)
        {
            case 0:
                break;
            case 1:
                Array.Resize(ref ba, ba.Length + 7);
                ba[ba.Length - 1] = 0x80;
                ba[ba.Length - 2] = 0x80;
                ba[ba.Length - 3] = 0x80;
                ba[ba.Length - 4] = 0x80;
                ba[ba.Length - 5] = 0x80;
                ba[ba.Length - 6] = 0x80;
                ba[ba.Length - 7] = 0x80;
                break;
            case 2:
                Array.Resize(ref ba, ba.Length + 6);
                ba[ba.Length - 1] = 0x80;
                ba[ba.Length - 2] = 0x80;
                ba[ba.Length - 3] = 0x80;
                ba[ba.Length - 4] = 0x80;
                ba[ba.Length - 5] = 0x80;
                ba[ba.Length - 6] = 0x80;
                break;
            case 3:
                Array.Resize(ref ba, ba.Length + 5);
                ba[ba.Length - 1] = 0x80;
                ba[ba.Length - 2] = 0x80;
                ba[ba.Length - 3] = 0x80;
                ba[ba.Length - 4] = 0x80;
                ba[ba.Length - 5] = 0x80;
                break;
            case 4:
                Array.Resize(ref ba, ba.Length + 4);
                ba[ba.Length - 1] = 0x80;
                ba[ba.Length - 2] = 0x80;
                ba[ba.Length - 3] = 0x80;
                ba[ba.Length - 4] = 0x80;
                break;
            case 5:
                Array.Resize(ref ba, ba.Length + 3);
                ba[ba.Length - 1] = 0x80;
                ba[ba.Length - 2] = 0x80;
                ba[ba.Length - 3] = 0x80;
                break;
            case 6:
                Array.Resize(ref ba, ba.Length + 2);
                ba[ba.Length - 1] = 0x80;
                ba[ba.Length - 2] = 0x80;
                break;
            case 7:
                Array.Resize(ref ba, ba.Length + 1);
                ba[ba.Length - 1] = 0x80;
                break;
        }
        return ba;
    }
    private static void Expand(ulong[] x, int iterations = 1)
    {
        var size = x.Length;
        for (var k = 0; k < iterations; ++k)
        for (var i = 0; i < size; ++i)
        {
            ulong n = 0;
            var   j = 0;
            while (j < size)
            {
                n ^= x[j];
                ++j;
            }
            x[i] = (n << 1) | (n >> 56);
        }
    }
    /// <summary>
    ///     ExpandAndMixArray resizes the array by extrusion then mixes the array using a Sha3 one way hash
    /// </summary>
    /// <param name="ba">The buffer</param>
    /// <param name="size">The final desired size</param>
    /// <param name="iterations">The number of iterations to mix the final array</param>
    public byte[] ExpandAndMixArray(byte[] ba, int size, int iterations = 1000)
    {
        var ula = ByteArrayToULongArray(ba, size);
        Expand(ula, 1);
        var array = ula.GetBytes();
        return Mix(array, iterations);
    }
    public ushort[] ExpandAndMixArray(ushort[] ba, int size, int iterations = 1000)
    {
        var bb = ba.GetBytes();
        return ExpandAndMixArray(bb, size, iterations).ToUShortArray();
    }
    public uint[] ExpandAndMixArray(uint[] ba, int size, int iterations = 1000)
    {
        var bb = ba.GetBytes();
        return ExpandAndMixArray(bb, size, iterations).ToUIntArray();
    }
    public ulong[] ExpandAndMixArray(ulong[] ba, int size, int iterations = 1000)
    {
        var bb = ba.GetBytes();
        return ExpandAndMixArray(bb, size, iterations).ToULongArray();
    }
}

RngJitterSource.cs

CPU RAM Jitter Driven RNG Data Source

using System;
using System.Diagnostics;
using System.Security.Cryptography;
using System.Threading;
public class RngJitterSource : RandomNumberGenerator
{
    /// <summary>
    ///     Recalculate buffer every 1000 milliseconds
    /// </summary>
    private const int ReSecureThresholdBf = 1000;
    private readonly SHA3ModInt _algorithm;
    private readonly object     _cacheLock = new object();
    private readonly int        _moveSize;
    /// <summary>
    ///     Just in case you need access to the underlying data
    /// </summary>
    public readonly JitterEx Jitter;
    private readonly Stopwatch tmr;
    private          byte[]    _cacheBuffer;
    private          int       _cacheSize;
    private volatile int       _ptr;
    private volatile int       BytesRemainingInCache;
    /// <summary>
    ///     If you want to use this as a flat memory pool
    ///     Use in conjunction with DataReady -- DataReady.WaitOne(); -- use data
    /// </summary>
    public volatile byte[] Cache;
    public  int    cacheFills;
    private Thread CacheThread;
    /// <summary>
    ///     See Cache above
    /// </summary>
    public AutoResetEvent DataReady = new AutoResetEvent(false);
    private bool Filled;
    public  int  ResecureCount;
    public RngJitterSource() : this(1024 * 1024, 1024, 256, 4)
    {
    }
    public RngJitterSource(int cacheSize) : this(cacheSize, 1024, 256, 4)
    {
    }
    public RngJitterSource(int cacheSize, int seedSize) : this(cacheSize, seedSize, 256, 4)
    {
    }
    public RngJitterSource(int cacheSize, int seedSize, int sha3Size) : this(cacheSize, seedSize, sha3Size, 4)
    {
    }
    public RngJitterSource(int cacheSize, int seedSize, int sha3Size, int sha3Rounds)
    {
        _cacheSize   = cacheSize;
        Jitter       = new JitterEx();
        _cacheBuffer = new byte[seedSize];
        Jitter.GetBytes(_cacheBuffer);
        Cache                 = new byte[_cacheSize];
        _ptr                  = 0;
        BytesRemainingInCache = 0;
        _algorithm            = new SHA3ModInt(sha3Size, sha3Rounds);
        _moveSize             = _algorithm.ComputeHash(2.GetBytes()).Length;
        Filled                = false;
        tmr                   = new Stopwatch();
        CacheThread           = new Thread(KeepFullCache) {Priority = ThreadPriority.Highest};
        CacheThread.Start();
    }
    public void Abort()
    {
        CacheThread.Abort();
    }
    protected override void Dispose(bool disposing)
    {
        _algorithm.Dispose();
    }
    public override void GetBytes(byte[] data)
    {
        if (data.Length > _cacheSize)
        {
            _cacheSize            = data.Length;
            Cache                 = new byte[_cacheSize];
            _ptr                  = 0;
            BytesRemainingInCache = 0;
            if (CacheThread.IsAlive)
                CacheThread.Abort();
            DataReady   = new AutoResetEvent(false);
            CacheThread = new Thread(KeepFullCache) {Priority = ThreadPriority.Highest};
            CacheThread.Start();
        }
        while (_ptr < data.Length)
            Thread.Sleep(10);
        DataReady.WaitOne();
        Buffer.BlockCopy(Cache, _ptr - data.Length, data, 0, data.Length);
        _ptr                  -= data.Length;
        BytesRemainingInCache -= data.Length;
    }
    private void KeepFullCache()
    {
        while (true)
            if (BytesRemainingInCache < _moveSize)
                lock (_cacheLock)
                {
                    var moveSize = _moveSize;
                    cacheFills++;
                    var bufferFills = 0;
                    tmr.Start();
                    while (true)
                    {
                        bufferFills++;
                        if (tmr.Elapsed.TotalMilliseconds >= ReSecureThresholdBf)
                        {
                            Jitter.GetBytes(_cacheBuffer);
                            tmr.Restart();
                            ResecureCount++;
                        }
                        var remainingBytesToMove = _cacheSize - _ptr;
                        if (remainingBytesToMove < moveSize)
                            moveSize = remainingBytesToMove;
                        if (remainingBytesToMove <= 0 || _ptr >= _cacheSize)
                            break;
                        _cacheBuffer = _algorithm.ComputeHash(_cacheBuffer);
                        Buffer.BlockCopy(_cacheBuffer, 0, Cache, _ptr, moveSize);
                        _ptr += moveSize;
                    }
                    tmr.Stop();
                    _ptr                  = _cacheSize;
                    BytesRemainingInCache = _cacheSize;
                    DataReady.Set();
                }
            else
                DataReady.Set();
    }
}

EntropyGeneric.cs

Detect Entropy Levels from Primitive Data Arrays

using System;
using System.Collections.Generic;
public class EntropyGeneric<T>
{
    private const    double             NaturalLogOfTwo = 0.69314718055994530941723212145818;
    private readonly Dictionary<T, int> _hist           = new Dictionary<T, int>();
    private          bool               _mapStatus;
    public EntropyGeneric()
    {
        _hist.Clear();
        _mapStatus = false;
    }
    public (double entropy, int perfect) Entropy(T[] s)
    {
        if (_mapStatus)
        {
            _hist.Clear();
            _mapStatus = false;
        }
        foreach (var c in s)
            if (!_hist.ContainsKey(c))
                _hist.Add(c, 1);
            else
                _hist[c] += 1;
        _mapStatus = true;
        var e = 0.0;
        foreach (var v in _hist.Values)
        {
            if (v <= 0)
                continue;
            var r = v             / (double) s.Length;
            e -= r * (Math.Log(r) / NaturalLogOfTwo);
        }
        return (e, GetSize());
    }
    private byte[] ConvertTypeByteArray(T[] ia)
    {
        switch (Type.GetTypeCode(typeof(T)))
        {
            case TypeCode.Boolean:
                break;
            case TypeCode.Char:
                break;
            case TypeCode.SByte:
                break;
            case TypeCode.Byte:
                break;
            case TypeCode.Int16:
                break;
            case TypeCode.UInt16:
                break;
            case TypeCode.Int32:
                break;
            case TypeCode.UInt32:
                break;
            case TypeCode.Single:
                break;
            case TypeCode.String:
                break;
            case TypeCode.Decimal:
                break;
            case TypeCode.Int64:
                break;
            case TypeCode.UInt64:
                break;
            case TypeCode.Double:
                break;
            case TypeCode.DateTime:
                break;
            default:
                throw new ArgumentException("Type is not a valid primitive.");
        }
        return ia.GetBytesObject();
    }
    private int GetSize()
    {
        var size = 0;
        switch (Type.GetTypeCode(typeof(T)))
        {
            case TypeCode.Boolean:
                size = 8;
                break;
            case TypeCode.Char:
                size = 16;
                break;
            case TypeCode.SByte:
                size = 8;
                break;
            case TypeCode.Byte:
                size = 8;
                break;
            case TypeCode.Int16:
                size = 16;
                break;
            case TypeCode.UInt16:
                size = 16;
                break;
            case TypeCode.Int32:
                size = 32;
                break;
            case TypeCode.UInt32:
                size = 32;
                break;
            case TypeCode.Single:
                size = 32;
                break;
            case TypeCode.String:
                size = 32;
                break;
            case TypeCode.Decimal:
                size = 96;
                break;
            case TypeCode.Int64:
                size = 64;
                break;
            case TypeCode.UInt64:
                size = 64;
                break;
            case TypeCode.Double:
                size = 64;
                break;
            case TypeCode.DateTime:
                size = 64;
                break;
            default:
                throw new ArgumentException("Type is not a valid primitive.");
        }
        return size;
    }
}

EntropySource.cs

Using PC Data Creates a Strong Entropy Source

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading;
public class EntropySource
{
    private const int Sha3BitSize           = 256;
    private const int Sha3BitBufferMoveSize = Sha3BitSize >> 3;
    private const int CpuDataLength         = 256;
    private const int JitterDataSize        = 256;
    [DllImport("kernel32.dll")]
    private static extern int GetTickCount();
    [DllImport("kernel32.dll")]
    internal static extern bool QueryPerformanceCounter(out long lpPerformanceCount);
    [DllImport("kernel32.dll")]
    internal static extern bool QueryPerformanceFrequency(out long lpFrequency);
    public static byte[] GetBuffer(int bufferSize)
    {
        var rhb = new byte[0];
        var rho = new byte[bufferSize];
        var EntropyThread = new Thread(() =>
        {
            var el        = new List<string>();
            var hashBytes = new HashSet<byte[]>(new ArrayComparer());
            var sw        = new Stopwatch();
            sw.Start();
            AddLocalUserData(hashBytes);
            AddProcessInformation(hashBytes, el);
            AddJitterInformation(hashBytes);
            GetWmiInfor("Win32_PerfRawData_PerfOS_Processor",              hashBytes);
            GetWmiInfor("Win32_PerfRawData_PerfOS_System",                 hashBytes);
            GetWmiInfor("Win32_PerfRawData_Counters_ProcessorInformation", hashBytes);
            GetWmiInfor("Win32_PerfRawData_Counters_Synchronization",      hashBytes);
            GetWmiInfor("Win32_PerfRawData_PerfDisk_LogicalDisk",          hashBytes);
            GetWmiInfor("Win32_PerfRawData_PerfDisk_PhysicalDisk",         hashBytes);
            GetWmiInfor("Win32_PerfFormattedData_PerfOS_Cache",            hashBytes);
            GetWmiInfor("Win32_PerfFormattedData_PerfOS_Memory",           hashBytes);
            GetWmiInfor("Win32_PerfFormattedData_PerfOS_Objects",          hashBytes);
            CpuInfo(hashBytes);
            sw.Stop();
            hashBytes.Add(sw.Elapsed.Ticks.GetBytes());
            rhb = HashBytesToArray(hashBytes);
            AddHistogramInforamation(rhb, hashBytes);
            rhb = HashBytesToArray(hashBytes);
            hashBytes.Clear();
            var div = bufferSize / Sha3BitBufferMoveSize;
            if (div * Sha3BitBufferMoveSize < bufferSize)
                div++;
            var segSize = rhb.Length / div;
            var aseg    = new byte[segSize];
            for (var i = 0; i < div; ++i)
            {
                Buffer.BlockCopy(rhb,                                            i * segSize, aseg, 0,                         segSize);
                Buffer.BlockCopy(new SHA3Managed(Sha3BitSize).ComputeHash(aseg), 0,           rho,  i * Sha3BitBufferMoveSize, Sha3BitBufferMoveSize);
            }
        }) {Priority = ThreadPriority.Highest};
        EntropyThread.Start();
        EntropyThread.Join();
        return rho;
    }
    private static void GetWmiInfor(string key, HashSet<byte[]> hashBytes)
    {
        var wmi = new WMIServices();
        wmi.GetProperties(key);
        foreach (var v in wmi.EntriesList)
        foreach (var p in v.Value)
            hashBytes.Add(p.GetBytesObject());
    }
    private static void CpuInfo(HashSet<byte[]> hashBytes)
    {
        var lhashBytes = new HashSet<byte[]>();
        var dump       = CpuTotalPc.CPULoad;
        do
        {
            var l = (byte) CpuTotalPc.CPULoad;
            if (l != 0)
                lhashBytes.Add(new[] {l});
            Thread.Sleep(1);
        } while (lhashBytes.Count < CpuDataLength);
        foreach (var b in lhashBytes)
            hashBytes.Add(b);
    }
    private static void AddHistogramInforamation(byte[] rhb, HashSet<byte[]> hashBytes)
    {
        var FFTArray = Histogram(rhb);
        for (var i = 0; i < FFTArray.Length; ++i)
            hashBytes.Add(FFTArray[i].GetBytes());
    }
    private static void AddJitterInformation(HashSet<byte[]> hashBytes)
    {
        hashBytes.Add(new JitterEx(JitterDataSize).GetBuffer());
    }
    private static void AddProcessInformation(HashSet<byte[]> hashBytes, List<string> el)
    {
        foreach (var p in Process.GetProcesses())
        {
            try
            {
                hashBytes.Add(p.Id.GetBytes());
            }
            catch (Exception ex)
            {
                el.Add($"{ex.Message} hashBytes.Add(p.Id.GetBytes())");
            }
            try
            {
                hashBytes.Add(p.HandleCount.GetBytes());
            }
            catch (Exception ex)
            {
                el.Add($"{ex.Message} hashBytes.Add(p.HandleCount.GetBytes())");
            }
            try
            {
                hashBytes.Add(p.NonpagedSystemMemorySize64.GetBytes());
            }
            catch (Exception ex)
            {
                el.Add($"{ex.Message} hashBytes.Add(p.NonpagedSystemMemorySize64.GetBytes())");
            }
            try
            {
                hashBytes.Add(p.PagedMemorySize64.GetBytes());
            }
            catch (Exception ex)
            {
                el.Add($"{ex.Message} hashBytes.Add(p.PagedMemorySize64.GetBytes())");
            }
            try
            {
                hashBytes.Add(p.PagedSystemMemorySize64.GetBytes());
            }
            catch (Exception ex)
            {
                el.Add($"{ex.Message} hashBytes.Add(p.PagedSystemMemorySize64.GetBytes())");
            }
            try
            {
                hashBytes.Add(p.PeakPagedMemorySize64.GetBytes());
            }
            catch (Exception ex)
            {
                el.Add($"{ex.Message} hashBytes.Add(p.PeakPagedMemorySize64.GetBytes())");
            }
            try
            {
                hashBytes.Add(p.PeakVirtualMemorySize64.GetBytes());
            }
            catch (Exception ex)
            {
                el.Add($"{ex.Message} hashBytes.Add(p.PeakVirtualMemorySize64.GetBytes())");
            }
            try
            {
                hashBytes.Add(p.PeakWorkingSet64.GetBytes());
            }
            catch (Exception ex)
            {
                el.Add($"{ex.Message} hashBytes.Add(p.PeakWorkingSet64.GetBytes()");
            }
            try
            {
                hashBytes.Add(p.PrivateMemorySize64.GetBytes());
            }
            catch (Exception ex)
            {
                el.Add($"{ex.Message} hashBytes.Add(p.PrivateMemorySize64.GetBytes())");
            }
            try
            {
                hashBytes.Add(p.ProcessName.GetBytes());
            }
            catch (Exception ex)
            {
                el.Add($"{ex.Message} hashBytes.Add(p.ProcessName.GetBytes())");
            }
            try
            {
                hashBytes.Add(p.Threads.Count.GetBytes());
            }
            catch (Exception ex)
            {
                el.Add($"{ex.Message} hashBytes.Add(p.Threads.Count.GetBytes())");
            }
            try
            {
                hashBytes.Add(p.SessionId.GetBytes());
            }
            catch (Exception ex)
            {
                el.Add($"{ex.Message} hashBytes.Add(p.SessionId.GetBytes())");
            }
            for (var i = 0; i < p.Threads.Count; i++)
            {
                try
                {
                    hashBytes.Add(p.Threads[i].CurrentPriority.GetBytes());
                }
                catch (Exception ex)
                {
                    el.Add($"{ex.Message} hashBytes.Add(p.Threads[i].CurrentPriority.GetBytes())");
                }
                try
                {
                    hashBytes.Add(p.Threads[i].Id.GetBytes());
                }
                catch (Exception ex)
                {
                    el.Add($"{ex.Message} hashBytes.Add(p.Threads[i].Id.GetBytes())");
                }
                try
                {
                    hashBytes.Add(p.Threads[i].StartAddress.ToString().GetBytes());
                }
                catch (Exception ex)
                {
                    el.Add($"{ex.Message} hashBytes.Add(p.Threads[i].StartAddress.ToString().GetBytes())");
                }
            }
            try
            {
                hashBytes.Add(p.VirtualMemorySize64.GetBytes());
            }
            catch (Exception ex)
            {
                el.Add($"{ex.Message} hashBytes.Add(p.VirtualMemorySize64.GetBytes()))");
            }
            try
            {
                hashBytes.Add(p.WorkingSet64.GetBytes());
            }
            catch (Exception ex)
            {
                el.Add($"{ex.Message} hashBytes.Add(p.WorkingSet64.GetBytes()))");
            }
        }
    }
    private static void AddLocalUserData(HashSet<byte[]> hashBytes)
    {
        hashBytes.Add(Process.GetCurrentProcess().Id.GetBytes());
        hashBytes.Add(Thread.CurrentThread.ManagedThreadId.GetBytes());
        hashBytes.Add(GetTickCount().GetBytes());
        hashBytes.Add(Process.GetProcesses().Length.GetBytes());
        QueryPerformanceFrequency(out var freq);
        hashBytes.Add(freq.GetBytes());
        for (var i = 0; i < 128; i++)
        {
            QueryPerformanceCounter(out var query);
            hashBytes.Add(query.GetBytes());
        }
        hashBytes.Add(DateTime.Now.Ticks.GetBytes());
        hashBytes.Add(Environment.UserName.GetBytes());
        hashBytes.Add(Environment.MachineName.GetBytes());
        hashBytes.Add(Environment.OSVersion.ToString().GetBytes());
        hashBytes.Add(Environment.ProcessorCount.GetBytes());
        hashBytes.Add(Environment.UserDomainName.GetBytes());
        hashBytes.Add(Environment.StackTrace.GetBytes());
        hashBytes.Add(Environment.GetLogicalDrives().GetBytes());
        hashBytes.Add(MemoryInfo.GetValues().GetBytesObjectSerial());
        hashBytes.Add(MemoryInfo.GetSystemPerformanceInformation().GetBytesObjectSerial());
    }
    private static byte[] HashBytesToArray(HashSet<byte[]> hashBytes)
    {
        byte[] rhb;
        var    ptr   = 0;
        var    count = 0;
        var    arr   = hashBytes.ToArray();
        foreach (var hba in arr)
            count += hba.Length;
        hashBytes.Add(count.GetBytes());
        arr   =  hashBytes.ToArray();
        count += arr.Last().Length;
        rhb   =  new byte[count];
        foreach (var hba in arr)
        {
            Buffer.BlockCopy(hba, 0, rhb, ptr, hba.Length);
            ptr += hba.Length;
        }
        return rhb;
    }
    private static int[] Histogram(IEnumerable<byte> ba)
    {
        var map = new int[256];
        foreach (var i in ba)
            map[i]++;
        return map;
    }
}