public IndexesEnumerator(int[] endIndexes, int[] beginIndexes, bool reverse)
        {
            if (endIndexes.Length != beginIndexes.Length)
            {
                throw new ArgumentException("UpperBound and LowerBound arrays must have the same length.");
            }

            this.endIdxs   = (int[])endIndexes.Clone();
            this.beginIdxs = (int[])beginIndexes.Clone();
            this.reverse   = reverse;

            if ((reverse && IndexesHelper.Less(this.endIdxs, this.beginIdxs)) ||
                (!reverse && IndexesHelper.Less(this.beginIdxs, this.endIdxs)))
            {
                this.currentIdxs = (int[])beginIndexes.Clone();
                if (reverse)
                {
                    ++this.currentIdxs[this.currentIdxs.Length - 1];
                }
                else
                {
                    --this.currentIdxs[this.currentIdxs.Length - 1];
                }
            }
            else
            {
                // NOTE do pervent enumeration
                this.currentIdxs = this.endIdxs;
            }
        }
Пример #2
0
        /// <summary> Resizes the <see cref="DynamicArray{T}"/> to the given new counts. </summary>
        /// <param name="newCounts"> The new lengths of the <see ref="DynamicArray{T}"/>. </param>
        /// <remarks> If the <paramref name="newCounts"/> ith element is larger than the ith count, the new added
        /// elements are set to <c>default(<typeparamref name="T"/>)</c>. If <paramref name="newCounts"/> ith element
        /// is less then the ith count, the <see ref="DynamicArray{T}"/> is shrank to fit to the new count value,
        /// and the removed elements will be lost. </remarks>
        public void Resize(params int[] newCounts)
        {
            this.CheckIndexesLength(newCounts);

            if (IndexesHelper.ElementsEqual(this.counts, newCounts))
            {
                return;
            }

            int[] oldCounts = IndexesHelper.Clone(this.counts);
            this.UpdateCountsAndCapacities(IndexesHelper.Add(newCounts, -1));
            for (int dim = 0; dim < this.Rank; ++dim)
            {
                // NOTE When this.buffer is shrank dismissed values are reset to default(T)
                IndexesEnumerator ienum = new IndexesEnumerator(
                    IndexesHelper.TakeMinOnIthDim(oldCounts, newCounts, dim - 1),
                    IndexesHelper.ProjectOnIthDim(newCounts, dim));
                foreach (int[] indexes in ienum)
                {
                    this.buffer.SetValue(default(T), indexes);
                }
            }

            Array.Copy(newCounts, this.counts, this.counts.Length);
            ++this.changeCount;
        }
Пример #3
0
        /// <summary> Strongly typed implementation of <see cref="ICollection{T}.CopyTo"/>. </summary>
        /// <param name="darray"> The <see cref="DynamicArray{T}"/> where to copy the values. </param>
        /// <param name="indexes">The zero-based indexes offset in darray at which copying begins. </param>
        public void CopyTo(DynamicArray <T> darray, params int[] indexes)
        {
            DynamicArrayEnumerator <T> enumerator = this.GetEnumerator();

            foreach (T elt in enumerator)
            {
                darray.SetValue(elt, IndexesHelper.Add(enumerator.GetIndexes(), indexes));
            }
        }
Пример #4
0
        /// <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);
        }
Пример #5
0
        /// <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);
        }
Пример #6
0
        /// <summary>
        /// Inserts the given <see cref="Array"/> within the given dimension and at the given position.
        /// </summary>
        /// <param name="arr"> An array to insert in the <see cref="DynamicArray{T}"/>.
        /// It must be not <see langword="null"/> and it must have a rank equal to <see cref="DynamicArray{T}.Rank"/>.
        /// </param>
        /// <param name="dimension"> The dimension where the elements of the <paramref name="arr"/> will be inserted.
        /// </param>
        /// <param name="indexes"> The position where the first element of the <paramref name="arr"/> will be inserted.
        /// </param>
        /// <exception cref="RankException"> If <paramref name="arr"/> has a rank not equal to
        /// <see cref="DynamicArray{T}.Rank"/>.</exception>
        /// <exception cref="ArgumentException"> If <paramref name="arr"/> has one of its lengths equal to zero.
        /// </exception>
        /// <exception cref="NullReferenceException"> If arr is <see langword="null"/></exception>
        public void Insert(Array arr, int dimension, params int[] indexes)
        {
            this.CheckIndexesLength(indexes);

            if (arr.Rank != this.Rank)
            {
                throw new RankException("Inserted array must have the same rank as this array");
            }

            for (int dim = 0; dim < this.Rank; ++dim)
            {
                if (arr.GetLength(dim) > 0)
                {
                    continue;
                }

                throw new ArgumentException("Inserted array must have non null lengths.", "arr");
            }

            int[] oldCounts = IndexesHelper.Clone(this.counts);
            int   dataCount = arr.GetLength(dimension);

            int[] lastIndices = IndexesHelper.Add(indexes, IndexesHelper.MaxIndexes(arr));
            lastIndices[dimension] = Math.Max(oldCounts[dimension], indexes[dimension]) + dataCount - 1;

            this.UpdateCountsAndCapacities(lastIndices);

            int[] rangeLowerBound = IndexesHelper.Add(indexes, -1);
            if (indexes[dimension] < oldCounts[dimension])
            {
                int[] rangeMax = IndexesHelper.Add(IndexesHelper.MaxIndexes(arr), indexes);
                rangeMax[dimension] = oldCounts[dimension] - 1;
                var rangeToMove = new IndexesEnumerator(rangeLowerBound, rangeMax, true);
                foreach (int[] source in rangeToMove)
                {
                    int[] destination = IndexesHelper.Clone(source);
                    destination[dimension] += dataCount;
                    this.buffer.SetValue(this.buffer.GetValue(source), destination);
                }
            }

            foreach (int[] source in IndexesEnumerator.Enumerate(arr))
            {
                int[] destination = IndexesHelper.Add(source, indexes);
                this.buffer.SetValue(arr.GetValue(source), destination);
            }

            ++this.changeCount;
        }
 public bool MoveNext()
 {
     return(this.reverse
         ? IndexesHelper.Dec(this.currentIdxs, this.endIdxs, this.beginIdxs)
         : IndexesHelper.Inc(this.currentIdxs, this.endIdxs, this.beginIdxs));
 }
 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)
 {
 }
Пример #10
0
 /// <summary>
 /// Resizes the <see cref="DynamicArray{T}"/> by adding each ith given value to the corresponding ith dimension.
 /// </summary>
 /// <param name="addedCounts"> The amounts to add to each dimension count. </param>
 public void Extend(params int[] addedCounts)
 {
     this.CheckIndexesLength(addedCounts);
     this.Resize(IndexesHelper.Add(this.counts, addedCounts));
 }