/// <summary> /// Initializes a new instance of the <see cref="DynamicArray{T}"/> class. If a capcity is omitted the /// <see cref="DEFAULTCAPACITY"/> is used for the missing dimension capacity. /// </summary> /// <param name="rank"> The dynamic array rank. </param> /// <param name="capacities"> The capacities to be used for the underlying buffer. </param> public DynamicArray(int rank, params int[] capacities) { this.counts = IndexesHelper.Zero(rank); int[] usedCapacities = IndexesHelper.Zero(rank); for (int i = 0; i < rank; ++i) { usedCapacities[i] = (i < capacities.Length ? capacities[i] : DEFAULTCAPACITY); } // NOTE will throw an ArgumentException if rank<1 this.buffer = Array.CreateInstance(typeof(T), usedCapacities); }
/// <summary> /// Ensures the given indexes falls into the lengths and capacities of the underlying array. If not, the /// capacities and lengths are updated accordingly. A new underlyting array may be allocated in order to adapt /// capacities. /// </summary> /// <param name="indexes"> The indexes that must fall within the array. </param> private void UpdateCountsAndCapacities(int[] indexes) { int[] newCounts = IndexesHelper.Zero(this.Rank); int[] newCapacities = IndexesHelper.Zero(this.Rank); bool newArrayNeeded = false; bool newCountsNeeded = false; for (int dimension = 0; dimension < this.Rank; ++dimension) { int requestedIndex = indexes[dimension]; int currentCapacity = this.GetCapacity(dimension); int currentCount = this.GetCount(dimension); newCounts[dimension] = currentCount; newCapacities[dimension] = currentCapacity; if (requestedIndex < currentCount) { continue; } newCountsNeeded = true; newCounts[dimension] = requestedIndex + 1; if (newCounts[dimension] <= currentCapacity) { continue; } newCapacities[dimension] = Math.Max(2 * currentCapacity, newCounts[dimension]); newArrayNeeded = true; } if (!newCountsNeeded) { return; } if (newArrayNeeded) { Array newData = Array.CreateInstance(typeof(T), newCapacities); IndexesEnumerator ienum = new IndexesEnumerator(IndexesHelper.UpperBound(this.buffer)); foreach (int[] idx in ienum) { newData.SetValue(this.buffer.GetValue(idx), idx); } this.buffer = newData; } // NOTE New lengths are set after allocation to avoid lengths corruption on failure. Array.Copy(newCounts, this.counts, this.counts.Length); }
public static IndexesEnumerator Enumerate(Array arr, bool reverse) { return(new IndexesEnumerator(IndexesHelper.UpperBound(arr), IndexesHelper.Zero(arr.Rank), reverse)); }
public IndexesEnumerator(int[] upperBound) : this(upperBound, IndexesHelper.Zero(upperBound.Length), false) { }