Skip to content

Instantly share code, notes, and snippets.

@mjs3339
Last active November 25, 2018 08:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mjs3339/f4e24b71715c339ce1e758174a147f5b to your computer and use it in GitHub Desktop.
Save mjs3339/f4e24b71715c339ce1e758174a147f5b to your computer and use it in GitHub Desktop.
C# BigArray Class not limited to 2GB of data.
[Serializable]
public class BigArray<T> : IEnumerable<T>, IDisposable
{
private const int ShiftCount = 19;
private const ulong Granularity = 1 << ShiftCount;
private readonly ulong _capacityHold;
private readonly GetObjectSize _gos = new GetObjectSize();
private T[][] _arrays;
private bool _disposed;
private ulong _itemSize;
private ulong _numberOfArrays;
public string Tag;
public BigArray() : this(Granularity)
{
}
public BigArray(ulong size)
{
if(size < Granularity)
size = Granularity;
Resizes = 0;
_capacityHold = size;
if(default(T) != null)
_itemSize = (ulong) _gos.GetSize(default(T));
else
_itemSize = 0;
Initialize(size);
}
public ulong Length {get; private set;}
public ulong Resizes {get; private set;}
public ulong MemoryBytesAllocated{get; private set;}
public T this[ulong index]
{
get
{
if(index >= Length)
throw new Exception($"Getter: Index out of bounds, Index: '{index}' must be less than the Length: '{Length}'.");
return _arrays[index >> ShiftCount][index & (Granularity - 1)];
}
set
{
lock(this)
{
if(index+1 >= Length)
Resize(index + 1);
if(_itemSize == 0)
_itemSize = (ulong)_gos.GetSize(value);
_arrays[index >> ShiftCount][index & (Granularity - 1)] = value;
}
}
}
public void Dispose()
{
Dispose(true);
}
IEnumerator<T> IEnumerable<T>.GetEnumerator()
{
return new Enumerator(this);
}
IEnumerator IEnumerable.GetEnumerator()
{
return new Enumerator(this);
}
public static ulong Sum(IEnumerable<ulong> source)
{
var num1 = 0ul;
foreach(var num2 in source)
checked
{
num1 += num2;
}
return num1;
}
public void Clear()
{
Length = 0;
Resizes = 0;
}
public void Free()
{
Length = 0;
Resizes = 0;
Length = 0;
Resize(_capacityHold);
}
private void Initialize(ulong size)
{
try
{
_numberOfArrays = size / Granularity;
while(_numberOfArrays * Granularity < size)
++_numberOfArrays;
Length = _numberOfArrays * Granularity;
_arrays = new T[_numberOfArrays][];
for(ulong i = 0; i < _numberOfArrays; ++i)
_arrays[i] = new T[Granularity];
if(_itemSize != 0)
lock(this)
{
MemoryBytesAllocated = _itemSize * Length;
}
}
catch(Exception ex)
{
throw new Exception($"'Initialize:BigArray' Exception: {ex.Message}");
}
}
private void Resize(ulong size)
{
if(size <= Length)
return;
try
{
var nah = _numberOfArrays;
Resizes++;
_numberOfArrays = size / Granularity;
while(_numberOfArrays * Granularity < size)
++_numberOfArrays;
Length = _numberOfArrays * Granularity;
var temp = new BigArray<T>(Length);
for(var a = 0ul; a < nah; a++)
Array.Copy(_arrays[a], temp._arrays[a], (int) Granularity);
_arrays = temp._arrays;
if(_itemSize != 0)
lock(this)
{
MemoryBytesAllocated = _itemSize * Length;
}
}
catch(Exception ex)
{
throw new Exception($"'EnsureSize:BigArry' Exception: {ex.Message}");
}
}
public BigArray<T> Copy(ulong newsize)
{
var temp = new BigArray<T>(newsize);
for(var a = 0ul; a < _numberOfArrays; a++)
Array.Copy(_arrays[a], temp._arrays[a], (int) Granularity);
return temp;
}
private void Dispose(bool disposing)
{
if(!_disposed)
if(disposing)
_arrays = null;
_disposed = true;
}
~BigArray()
{
Dispose(true);
}
public bool Equals(BigArray<T> other)
{
if(Length != other.Length)
return false;
for(var i = 0ul; i < Length; i++)
if(!this[i].Equals(other[i]))
return false;
return true;
}
[Serializable]
public struct Enumerator : IEnumerator<T>
{
private readonly BigArray<T> _array;
private ulong _index;
public T Current{get; private set;}
object IEnumerator.Current
{
get
{
if(_index == _array.Length + 1)
throw new Exception($"Enumerator out of range: {_index}");
return Current;
}
}
internal Enumerator(BigArray<T> array)
{
_array = array;
_index = 0;
Current = default;
}
public void Dispose()
{
}
public bool MoveNext()
{
if(_index < _array.Length)
{
Current = _array[_index];
_index++;
return true;
}
_index = _array.Length + 1;
Current = default;
return false;
}
void IEnumerator.Reset()
{
_index = 0;
Current = default;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment