Skip to content

Instantly share code, notes, and snippets.

@SommerEngineering
Created July 22, 2020 18:16
Show Gist options
  • Save SommerEngineering/e8f61ada40b8ff3ecfe61f5263a666b9 to your computer and use it in GitHub Desktop.
Save SommerEngineering/e8f61ada40b8ff3ecfe61f5263a666b9 to your computer and use it in GitHub Desktop.
public sealed class Infinity1DArray<T>
{
private const int MAX_CAPACITY_ARRAY = 2_147_483_591;
private T[][] chunks = new T[0][];
public Infinity1DArray() { }
public void Extend(ulong extendBy = 1)
{
this.Length += extendBy;
int availableInCurrentChunk = MAX_CAPACITY_ARRAY - this.chunks[^1].Length;
if (extendBy >= (ulong)availableInCurrentChunk)
{
// Extend the current chunk to its max:
var extendedInner = new T[MAX_CAPACITY_ARRAY];
Array.Copy(this.chunks[^1], extendedInner, this.chunks[^1].Length);
this.chunks[^1] = extendedInner;
//
// Now, adding as much new chunks as necessary:
//
ulong leftOver = extendBy - (ulong) availableInCurrentChunk;
if(leftOver == 0)
return;
do
{
int allocating = leftOver >= MAX_CAPACITY_ARRAY ? MAX_CAPACITY_ARRAY : (int)leftOver;
leftOver -= (ulong) allocating;
// First, we allocate space for the new chunk:
var extendedOuter = new T[this.chunks.Length + 1][];
Array.Copy(this.chunks, extendedOuter, this.chunks.Length);
this.chunks = extendedOuter;
// Now, we allocate the inner array i.e. the new chunk itself:
this.chunks[^1] = new T[allocating];
} while (leftOver > 0);
return;
}
// Extend the current chunk as necessary:
var extendedChunk = new T[this.chunks[^1].Length + (int)extendBy];
Array.Copy(this.chunks[^1], extendedChunk, this.chunks[^1].Length);
this.chunks[^1] = extendedChunk;
}
public ulong Length { get; private set; }
public T this[ulong index]
{
get
{
int chunkIndex = (int) (index / (ulong)MAX_CAPACITY_ARRAY);
int elementIndex = (int) (index - (ulong) chunkIndex * MAX_CAPACITY_ARRAY);
return this.chunks[chunkIndex][elementIndex];
}
set
{
int chunkIndex = (int) (index / (ulong)MAX_CAPACITY_ARRAY);
int elementIndex = (int) (index - (ulong) chunkIndex * MAX_CAPACITY_ARRAY);
if (chunkIndex >= this.chunks.Length || elementIndex >= this.chunks[chunkIndex].Length)
throw new IndexOutOfRangeException();
this.chunks[chunkIndex][elementIndex] = value;
}
}
public IEnumerable<T> Items()
{
for (ulong n = 0; n < this.Length; n++)
yield return this[n];
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment