BoyerMooreGeneric.cs

C# Boyer Moore Generic Search Algorithm

Updated: March 13, 2022

using System;
using System.Collections.Generic;
public class BoyerMooreGeneric<T>
{
private readonly IEqualityComparer<T> _comparer;
private Dictionary<T, int> _jumpTable;
private T[] _pattern;
private int _patternLength;
public BoyerMooreGeneric()
{
_comparer = EqualityComparer<T>.Default;
}
public BoyerMooreGeneric(T[] pattern)
{
_comparer = EqualityComparer<T>.Default;
SetPattern(pattern);
}
public BoyerMooreGeneric(T[] pattern, IEqualityComparer<T> comparer)
{
if (comparer == null)
_comparer = EqualityComparer<T>.Default;
else
_comparer = comparer;
SetPattern(pattern);
}
public BoyerMooreGeneric(IEqualityComparer<T> comparer)
{
if (comparer == null)
_comparer = EqualityComparer<T>.Default;
else
_comparer = comparer;
}
public void SetPattern(T[] pattern)
{
_pattern = pattern;
_jumpTable = new Dictionary<T, int>();
_patternLength = _pattern.Length;
for (var index = 0; index < _patternLength - 1; index++)
_jumpTable[_pattern[index]] = _patternLength - index - 1;
}
public int Search(T[] searchArray, int startIndex = 0)
{
if (_pattern == null)
throw new Exception("Pattern has not been set.");
if (_patternLength > searchArray.Length)
throw new Exception("Search Pattern length exceeds search array length.");
var scArr = searchArray.SubArray(startIndex, searchArray.Length - startIndex);
var index = startIndex;
var limit = searchArray.Length - _patternLength;
var patternLengthMinusOne = _patternLength - 1;
var Moves = 0;
var a0 = 0;
var b0 = 0;
while (index <= limit)
{
var j = patternLengthMinusOne;
while (j >= 0 && _comparer.Equals(_pattern[j], scArr[index + j]))
j--;
if (j < 0)
return index;
if (_jumpTable.TryGetValue(scArr[index + j], out var j0))
{
index += j0;
a0++;
}
else
{
index += _patternLength;
b0++;
}
Moves++;
}
return -1;
}
public List<int> SearchAll(T[] searchArray, int startIndex = 0)
{
if (searchArray == null)
throw new Exception("Search array has not been set.");
if (_pattern == null)
throw new Exception("Pattern has not been set.");
var scArr = searchArray.SubArray(startIndex, searchArray.Length - startIndex);
var scLen = searchArray.Length;
if (_patternLength > scArr.Length)
throw new Exception("Search Pattern length exceeds search array length.");
var index = 0;
var lst = new List<int>();
while (index <= scLen - _patternLength)
{
var j = _patternLength - 1;
while (j >= 0 && _comparer.Equals(_pattern[j], scArr[index + j]))
j--;
if (j < 0)
lst.Add(index);
if (_jumpTable.TryGetValue(scArr[index + j], out var j0))
index += j0;
else
index += _patternLength;
}
return lst;
}
public int SuperSearch(T[] searchArray, int nth, int start = 0)
{
var e = start;
var c = 0;
do
{
e = Search(searchArray, e);
if (e == -1)
return -1;
c++;
e++;
} while (c < nth);
return e - 1;
}
public IEnumerable<(T[] partialPattern, int idx)> SearchPartialAll(T[] pattern, T[] searchArray, int MinimumSearchLength = 3)
{
SetPattern(pattern);
var len = searchArray.Length;
var lst = new List<(T[] partialPattern, int idx)>();
if (len < MinimumSearchLength)
throw new Exception("Search Pattern less than minimum search length.");
var offset = 0;
var wl = MinimumSearchLength;
var pDic = new Dictionary<int, int>();
int ol = 0, il = 0;
do
{
ol++;
var tpat = new T[wl];
Array.Copy(searchArray, offset, tpat, 0, wl);
SetPattern(tpat);
var idxl = SearchAll(searchArray);
if (idxl.Count > 0)
foreach (var idx in idxl)
lst.Add((tpat, idx));
if (pDic.ContainsKey(wl))
pDic[wl] += idxl.Count;
else
pDic.Add(wl, idxl.Count);
if (offset + wl >= len)
{
il++;
if (pDic.ContainsKey(wl))
if (pDic[wl] == 0)
{
pDic.Remove(wl);
break;
}
offset = 0;
ol = 0;
wl++;
continue;
}
offset++;
} while (wl != len + 1);
return lst;
}
}
using System; using System.Collections.Generic; public class BoyerMooreGeneric<T> { private readonly IEqualityComparer<T> _comparer; private Dictionary<T, int> _jumpTable; private T[] _pattern; private int _patternLength; public BoyerMooreGeneric() { _comparer = EqualityComparer<T>.Default; } public BoyerMooreGeneric(T[] pattern) { _comparer = EqualityComparer<T>.Default; SetPattern(pattern); } public BoyerMooreGeneric(T[] pattern, IEqualityComparer<T> comparer) { if (comparer == null) _comparer = EqualityComparer<T>.Default; else _comparer = comparer; SetPattern(pattern); } public BoyerMooreGeneric(IEqualityComparer<T> comparer) { if (comparer == null) _comparer = EqualityComparer<T>.Default; else _comparer = comparer; } public void SetPattern(T[] pattern) { _pattern = pattern; _jumpTable = new Dictionary<T, int>(); _patternLength = _pattern.Length; for (var index = 0; index < _patternLength - 1; index++) _jumpTable[_pattern[index]] = _patternLength - index - 1; } public int Search(T[] searchArray, int startIndex = 0) { if (_pattern == null) throw new Exception("Pattern has not been set."); if (_patternLength > searchArray.Length) throw new Exception("Search Pattern length exceeds search array length."); var scArr = searchArray.SubArray(startIndex, searchArray.Length - startIndex); var index = startIndex; var limit = searchArray.Length - _patternLength; var patternLengthMinusOne = _patternLength - 1; var Moves = 0; var a0 = 0; var b0 = 0; while (index <= limit) { var j = patternLengthMinusOne; while (j >= 0 && _comparer.Equals(_pattern[j], scArr[index + j])) j--; if (j < 0) return index; if (_jumpTable.TryGetValue(scArr[index + j], out var j0)) { index += j0; a0++; } else { index += _patternLength; b0++; } Moves++; } return -1; } public List<int> SearchAll(T[] searchArray, int startIndex = 0) { if (searchArray == null) throw new Exception("Search array has not been set."); if (_pattern == null) throw new Exception("Pattern has not been set."); var scArr = searchArray.SubArray(startIndex, searchArray.Length - startIndex); var scLen = searchArray.Length; if (_patternLength > scArr.Length) throw new Exception("Search Pattern length exceeds search array length."); var index = 0; var lst = new List<int>(); while (index <= scLen - _patternLength) { var j = _patternLength - 1; while (j >= 0 && _comparer.Equals(_pattern[j], scArr[index + j])) j--; if (j < 0) lst.Add(index); if (_jumpTable.TryGetValue(scArr[index + j], out var j0)) index += j0; else index += _patternLength; } return lst; } public int SuperSearch(T[] searchArray, int nth, int start = 0) { var e = start; var c = 0; do { e = Search(searchArray, e); if (e == -1) return -1; c++; e++; } while (c < nth); return e - 1; } public IEnumerable<(T[] partialPattern, int idx)> SearchPartialAll(T[] pattern, T[] searchArray, int MinimumSearchLength = 3) { SetPattern(pattern); var len = searchArray.Length; var lst = new List<(T[] partialPattern, int idx)>(); if (len < MinimumSearchLength) throw new Exception("Search Pattern less than minimum search length."); var offset = 0; var wl = MinimumSearchLength; var pDic = new Dictionary<int, int>(); int ol = 0, il = 0; do { ol++; var tpat = new T[wl]; Array.Copy(searchArray, offset, tpat, 0, wl); SetPattern(tpat); var idxl = SearchAll(searchArray); if (idxl.Count > 0) foreach (var idx in idxl) lst.Add((tpat, idx)); if (pDic.ContainsKey(wl)) pDic[wl] += idxl.Count; else pDic.Add(wl, idxl.Count); if (offset + wl >= len) { il++; if (pDic.ContainsKey(wl)) if (pDic[wl] == 0) { pDic.Remove(wl); break; } offset = 0; ol = 0; wl++; continue; } offset++; } while (wl != len + 1); return lst; } }
using System;
using System.Collections.Generic;
public class BoyerMooreGeneric<T>
{
    private readonly IEqualityComparer<T> _comparer;
    private          Dictionary<T, int>   _jumpTable;
    private          T[]                  _pattern;
    private          int                  _patternLength;
    public BoyerMooreGeneric()
    {
        _comparer = EqualityComparer<T>.Default;
    }
    public BoyerMooreGeneric(T[] pattern)
    {
        _comparer = EqualityComparer<T>.Default;
        SetPattern(pattern);
    }
    public BoyerMooreGeneric(T[] pattern, IEqualityComparer<T> comparer)
    {
        if (comparer == null)
            _comparer = EqualityComparer<T>.Default;
        else
            _comparer = comparer;
        SetPattern(pattern);
    }
    public BoyerMooreGeneric(IEqualityComparer<T> comparer)
    {
        if (comparer == null)
            _comparer = EqualityComparer<T>.Default;
        else
            _comparer = comparer;
    }
    public void SetPattern(T[] pattern)
    {
        _pattern       = pattern;
        _jumpTable     = new Dictionary<T, int>();
        _patternLength = _pattern.Length;
        for (var index = 0; index < _patternLength - 1; index++)
            _jumpTable[_pattern[index]] = _patternLength - index - 1;
    }
    public int Search(T[] searchArray, int startIndex = 0)
    {
        if (_pattern == null)
            throw new Exception("Pattern has not been set.");
        if (_patternLength > searchArray.Length)
            throw new Exception("Search Pattern length exceeds search array length.");
        var scArr                 = searchArray.SubArray(startIndex, searchArray.Length - startIndex);
        var index                 = startIndex;
        var limit                 = searchArray.Length - _patternLength;
        var patternLengthMinusOne = _patternLength     - 1;
        var Moves                 = 0;
        var a0                    = 0;
        var b0                    = 0;
        while (index <= limit)
        {
            var j = patternLengthMinusOne;
            while (j >= 0 && _comparer.Equals(_pattern[j], scArr[index + j]))
                j--;
            if (j < 0)
                return index;
            if (_jumpTable.TryGetValue(scArr[index + j], out var j0))
            {
                index += j0;
                a0++;
            }
            else
            {
                index += _patternLength;
                b0++;
            }
            Moves++;
        }
        return -1;
    }
    public List<int> SearchAll(T[] searchArray, int startIndex = 0)
    {
        if (searchArray == null)
            throw new Exception("Search array has not been set.");
        if (_pattern == null)
            throw new Exception("Pattern has not been set.");
        var scArr = searchArray.SubArray(startIndex, searchArray.Length - startIndex);
        var scLen = searchArray.Length;
        if (_patternLength > scArr.Length)
            throw new Exception("Search Pattern length exceeds search array length.");
        var index = 0;
        var lst   = new List<int>();
        while (index <= scLen - _patternLength)
        {
            var j = _patternLength - 1;
            while (j >= 0 && _comparer.Equals(_pattern[j], scArr[index + j]))
                j--;
            if (j < 0)
                lst.Add(index);
            if (_jumpTable.TryGetValue(scArr[index + j], out var j0))
                index += j0;
            else
                index += _patternLength;
        }
        return lst;
    }
    public int SuperSearch(T[] searchArray, int nth, int start = 0)
    {
        var e = start;
        var c = 0;
        do
        {
            e = Search(searchArray, e);
            if (e == -1)
                return -1;
            c++;
            e++;
        } while (c < nth);
        return e - 1;
    }
    public IEnumerable<(T[] partialPattern, int idx)> SearchPartialAll(T[] pattern, T[] searchArray, int MinimumSearchLength = 3)
    {
        SetPattern(pattern);
        var len = searchArray.Length;
        var lst = new List<(T[] partialPattern, int idx)>();
        if (len < MinimumSearchLength)
            throw new Exception("Search Pattern less than minimum search length.");
        var offset = 0;
        var wl     = MinimumSearchLength;
        var pDic   = new Dictionary<int, int>();
        int ol     = 0, il = 0;
        do
        {
            ol++;
            var tpat = new T[wl];
            Array.Copy(searchArray, offset, tpat, 0, wl);
            SetPattern(tpat);
            var idxl = SearchAll(searchArray);
            if (idxl.Count > 0)
                foreach (var idx in idxl)
                    lst.Add((tpat, idx));
            if (pDic.ContainsKey(wl))
                pDic[wl] += idxl.Count;
            else
                pDic.Add(wl, idxl.Count);
            if (offset + wl >= len)
            {
                il++;
                if (pDic.ContainsKey(wl))
                    if (pDic[wl] == 0)
                    {
                        pDic.Remove(wl);
                        break;
                    }
                offset = 0;
                ol     = 0;
                wl++;
                continue;
            }
            offset++;
        } while (wl != len + 1);
        return lst;
    }
}

EntropyEx.cs

Generic Entropy Class

using System;
using System.Collections.Generic;
using System.Text;
public class EntropyEx<T>
{
private const double NaturalLogOfTwo = 0.69314718055994530941723212145818;
private readonly Dictionary<T, int> _histograpm = new Dictionary<T, int>();
private bool _histograpmStatus;
private readonly int _size;
public EntropyEx()
{
_histograpm.Clear();
_histograpmStatus = false;
_size = GetSize();
}
public double Entropy(string str)
{
var s = str.GetBytes(Encoding.Default);
var histograpmL = new Dictionary<byte, int>();
foreach (var c in s)
if (!histograpmL.ContainsKey(c))
histograpmL.Add(c, 1);
else
histograpmL[c] += 1;
var e = 0.0;
foreach (var v in histograpmL.Values)
{
if (v <= 0)
continue;
var r = v / (double)s.Length;
e -= r * (Math.Log(r) / NaturalLogOfTwo);
}
return e / 8 * 100.0;
}
public double Entropy(T[] s)
{
if (_histograpmStatus)
{
_histograpm.Clear();
_histograpmStatus = false;
}
foreach (var c in s)
if (!_histograpm.ContainsKey(c))
_histograpm.Add(c, 1);
else
_histograpm[c] += 1;
_histograpmStatus = true;
var e = 0.0;
foreach (var v in _histograpm.Values)
{
if (v <= 0)
continue;
var r = v / (double) s.Length;
e -= r * (Math.Log(r) / NaturalLogOfTwo);
}
return e / _size * 100.0;
}
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.GetBytes();
}
private int GetSize()
{
var size = 0;
switch (Type.GetTypeCode(typeof(T)))
{
case TypeCode.Boolean:
size = 1;
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 = 192;
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 within this context.");
}
return size;
}
}
using System; using System.Collections.Generic; using System.Text; public class EntropyEx<T> { private const double NaturalLogOfTwo = 0.69314718055994530941723212145818; private readonly Dictionary<T, int> _histograpm = new Dictionary<T, int>(); private bool _histograpmStatus; private readonly int _size; public EntropyEx() { _histograpm.Clear(); _histograpmStatus = false; _size = GetSize(); } public double Entropy(string str) { var s = str.GetBytes(Encoding.Default); var histograpmL = new Dictionary<byte, int>(); foreach (var c in s) if (!histograpmL.ContainsKey(c)) histograpmL.Add(c, 1); else histograpmL[c] += 1; var e = 0.0; foreach (var v in histograpmL.Values) { if (v <= 0) continue; var r = v / (double)s.Length; e -= r * (Math.Log(r) / NaturalLogOfTwo); } return e / 8 * 100.0; } public double Entropy(T[] s) { if (_histograpmStatus) { _histograpm.Clear(); _histograpmStatus = false; } foreach (var c in s) if (!_histograpm.ContainsKey(c)) _histograpm.Add(c, 1); else _histograpm[c] += 1; _histograpmStatus = true; var e = 0.0; foreach (var v in _histograpm.Values) { if (v <= 0) continue; var r = v / (double) s.Length; e -= r * (Math.Log(r) / NaturalLogOfTwo); } return e / _size * 100.0; } 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.GetBytes(); } private int GetSize() { var size = 0; switch (Type.GetTypeCode(typeof(T))) { case TypeCode.Boolean: size = 1; 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 = 192; 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 within this context."); } return size; } }
using System;
using System.Collections.Generic;
using System.Text;
public class EntropyEx<T>
{
    private const    double             NaturalLogOfTwo = 0.69314718055994530941723212145818;
    private readonly Dictionary<T, int> _histograpm     = new Dictionary<T, int>();
    private          bool               _histograpmStatus;
    private readonly int                _size;
    public EntropyEx()
    {
        _histograpm.Clear();
        _histograpmStatus = false;
        _size             = GetSize();
    }
    public double Entropy(string str)
    {
        var s = str.GetBytes(Encoding.Default);
        var histograpmL = new Dictionary<byte, int>();
        foreach (var c in s)
            if (!histograpmL.ContainsKey(c))
                histograpmL.Add(c, 1);
            else
                histograpmL[c] += 1;
        var e = 0.0;
        foreach (var v in histograpmL.Values)
        {
            if (v <= 0)
                continue;
            var r = v             / (double)s.Length;
            e -= r * (Math.Log(r) / NaturalLogOfTwo);
        }
        return e / 8 * 100.0;
    }
    public double Entropy(T[] s)
    {
        if (_histograpmStatus)
        {
            _histograpm.Clear();
            _histograpmStatus = false;
        }
        foreach (var c in s)
            if (!_histograpm.ContainsKey(c))
                _histograpm.Add(c, 1);
            else
                _histograpm[c] += 1;
        _histograpmStatus = true;
        var e = 0.0;
        foreach (var v in _histograpm.Values)
        {
            if (v <= 0)
                continue;
            var r = v             / (double) s.Length;
            e -= r * (Math.Log(r) / NaturalLogOfTwo);
        }
        return e / _size * 100.0;
    }
    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.GetBytes();
    }
    private int GetSize()
    {
        var size = 0;
        switch (Type.GetTypeCode(typeof(T)))
        {
            case TypeCode.Boolean:
                size = 1;
                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 = 192;
                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 within this context.");
        }
        return size;
    }
}

MiniArray.cs

A Small Generic Array Class

using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
[Serializable]
public class MiniArray<T> : IEnumerable<T>
{
public T[] Array;
public MiniArray() : this(101)
{
}
public MiniArray(int cap)
{
Count = 0;
Array = new T[cap];
}
public int Count
{
get;
private set;
}
public T this[int index]
{
get
{
if (index > Array.Length)
throw new Exception("Error: Index out of range.");
return Array[index];
}
set
{
EnsureSize();
Array[index] = value;
Count++;
}
}
IEnumerator<T> IEnumerable<T>.GetEnumerator()
{
return new Enumerator<T>(this);
}
IEnumerator IEnumerable.GetEnumerator()
{
return new Enumerator<T>(this);
}
private void EnsureSize()
{
if (Count >= Array.Length)
{
var NewLength = Array.Length == 0 ? 1 : Array.Length * 2;
var newtArray = new T[NewLength];
System.Array.Copy(Array, 0, newtArray, 0, Array.Length);
Array = newtArray;
}
}
public void Add(T item)
{
EnsureSize();
Array[Count] = item;
Count++;
}
public T[] ToArray()
{
var newtArray = new T[Count];
System.Array.Copy(Array, 0, newtArray, 0, Count);
return newtArray;
}
public IEnumerable<T> All()
{
for (var i = 0; i < Count; ++i)
yield return Array[i];
}
public void Clean()
{
var newtArray = new T[Count];
System.Array.Copy(Array, 0, newtArray, 0, Count);
Array = newtArray;
}
public void Clear()
{
System.Array.Clear(Array, 0, Count);
Count = 0;
}
}
[Serializable]
[StructLayout(LayoutKind.Sequential)]
public struct Enumerator<T> : IEnumerator<T>
{
private readonly MiniArray<T> thing;
private int index;
internal Enumerator(MiniArray<T> thing)
{
this.thing = thing;
index = 0;
Current = default;
}
public void Dispose()
{
}
public bool MoveNext()
{
var tthing = thing;
if (index < tthing.Count)
{
Current = tthing[index];
index++;
return true;
}
index = thing.Count + 1;
Current = default;
return false;
}
public T Current
{
get;
private set;
}
object IEnumerator.Current => Current;
void IEnumerator.Reset()
{
index = 0;
Current = default;
}
}
using System; using System.Collections; using System.Collections.Generic; using System.Runtime.InteropServices; [Serializable] public class MiniArray<T> : IEnumerable<T> { public T[] Array; public MiniArray() : this(101) { } public MiniArray(int cap) { Count = 0; Array = new T[cap]; } public int Count { get; private set; } public T this[int index] { get { if (index > Array.Length) throw new Exception("Error: Index out of range."); return Array[index]; } set { EnsureSize(); Array[index] = value; Count++; } } IEnumerator<T> IEnumerable<T>.GetEnumerator() { return new Enumerator<T>(this); } IEnumerator IEnumerable.GetEnumerator() { return new Enumerator<T>(this); } private void EnsureSize() { if (Count >= Array.Length) { var NewLength = Array.Length == 0 ? 1 : Array.Length * 2; var newtArray = new T[NewLength]; System.Array.Copy(Array, 0, newtArray, 0, Array.Length); Array = newtArray; } } public void Add(T item) { EnsureSize(); Array[Count] = item; Count++; } public T[] ToArray() { var newtArray = new T[Count]; System.Array.Copy(Array, 0, newtArray, 0, Count); return newtArray; } public IEnumerable<T> All() { for (var i = 0; i < Count; ++i) yield return Array[i]; } public void Clean() { var newtArray = new T[Count]; System.Array.Copy(Array, 0, newtArray, 0, Count); Array = newtArray; } public void Clear() { System.Array.Clear(Array, 0, Count); Count = 0; } } [Serializable] [StructLayout(LayoutKind.Sequential)] public struct Enumerator<T> : IEnumerator<T> { private readonly MiniArray<T> thing; private int index; internal Enumerator(MiniArray<T> thing) { this.thing = thing; index = 0; Current = default; } public void Dispose() { } public bool MoveNext() { var tthing = thing; if (index < tthing.Count) { Current = tthing[index]; index++; return true; } index = thing.Count + 1; Current = default; return false; } public T Current { get; private set; } object IEnumerator.Current => Current; void IEnumerator.Reset() { index = 0; Current = default; } }
using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
[Serializable]
public class MiniArray<T> : IEnumerable<T>
{
    public T[] Array;
    public MiniArray() : this(101)
    {
    }
    public MiniArray(int cap)
    {
        Count = 0;
        Array = new T[cap];
    }
    public int Count
    {
        get;
        private set;
    }
    public T this[int index]
    {
        get
        {
            if (index > Array.Length)
                throw new Exception("Error: Index out of range.");
            return Array[index];
        }
        set
        {
            EnsureSize();
            Array[index] = value;
            Count++;
        }
    }
    IEnumerator<T> IEnumerable<T>.GetEnumerator()
    {
        return new Enumerator<T>(this);
    }
    IEnumerator IEnumerable.GetEnumerator()
    {
        return new Enumerator<T>(this);
    }
    private void EnsureSize()
    {
        if (Count >= Array.Length)
        {
            var NewLength = Array.Length == 0 ? 1 : Array.Length * 2;
            var newtArray = new T[NewLength];
            System.Array.Copy(Array, 0, newtArray, 0, Array.Length);
            Array = newtArray;
        }
    }
    public void Add(T item)
    {
        EnsureSize();
        Array[Count] = item;
        Count++;
    }
    public T[] ToArray()
    {
        var newtArray = new T[Count];
        System.Array.Copy(Array, 0, newtArray, 0, Count);
        return newtArray;
    }
    public IEnumerable<T> All()
    {
        for (var i = 0; i < Count; ++i)
            yield return Array[i];
    }
    public void Clean()
    {
        var newtArray = new T[Count];
        System.Array.Copy(Array, 0, newtArray, 0, Count);
        Array = newtArray;
    }
    public void Clear()
    {
        System.Array.Clear(Array, 0, Count);
        Count = 0;
    }
}
[Serializable]
[StructLayout(LayoutKind.Sequential)]
public struct Enumerator<T> : IEnumerator<T>
{
    private readonly MiniArray<T> thing;
    private          int          index;
    internal Enumerator(MiniArray<T> thing)
    {
        this.thing = thing;
        index      = 0;
        Current    = default;
    }
    public void Dispose()
    {
    }
    public bool MoveNext()
    {
        var tthing = thing;
        if (index < tthing.Count)
        {
            Current = tthing[index];
            index++;
            return true;
        }
        index   = thing.Count + 1;
        Current = default;
        return false;
    }
    public T Current
    {
        get;
        private set;
    }
    object IEnumerator.Current => Current;
    void IEnumerator.Reset()
    {
        index   = 0;
        Current = default;
    }
}

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