Finished create with range implementation
thorsten/ExaArray#5 (comment)
This commit is contained in:
		
							parent
							
								
									4dcfa391d2
								
							
						
					
					
						commit
						1c30d49965
					
				@ -32,14 +32,33 @@ namespace Exa
 | 
			
		||||
            return next;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Creates a new ExaArray1D from another, respecting the given range.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <remarks>
 | 
			
		||||
        /// When <c>T</c> is a value type, data gets copied as values. When <c>T</c> is a reference type, the pointers
 | 
			
		||||
        /// to the original objects are copied. Thus, this factory method does not create a deep copy.
 | 
			
		||||
        ///
 | 
			
		||||
        /// Performance: O(n)
 | 
			
		||||
        ///
 | 
			
		||||
        /// The indices are inclusive.
 | 
			
		||||
        /// </remarks>
 | 
			
		||||
        /// <param name="other">The instance from which the new instance is to be created.</param>
 | 
			
		||||
        /// <param name="indexFrom">The first source element which should be part of the new array.</param>
 | 
			
		||||
        /// <param name="indexTo">The last source element which should be part of the new array.</param>
 | 
			
		||||
        /// <returns>The new instance</returns>
 | 
			
		||||
        /// <exception cref="IndexOutOfRangeException">Throws, when one or both of the indices are out of range.</exception>
 | 
			
		||||
        public static ExaArray1D<T> CreateFrom(ExaArray1D<T> other, ulong indexFrom, ulong indexTo)
 | 
			
		||||
        {
 | 
			
		||||
            if (indexTo < indexFrom)
 | 
			
		||||
                throw new IndexOutOfRangeException("Index to must be greater than index from.");
 | 
			
		||||
            
 | 
			
		||||
            if (indexTo >= other.Length || indexFrom >= other.Length)
 | 
			
		||||
                throw new IndexOutOfRangeException("Index to must be greater than index from.");
 | 
			
		||||
                throw new IndexOutOfRangeException("Index to must be within the range of the source.");
 | 
			
		||||
            
 | 
			
		||||
            //
 | 
			
		||||
            // Determine the source start chunk and index.
 | 
			
		||||
            //
 | 
			
		||||
            int sourceChunkIndexTo = -1;
 | 
			
		||||
            int sourceElementIndexTo = -1;
 | 
			
		||||
            switch (other.OptimizationStrategy)
 | 
			
		||||
@ -54,6 +73,9 @@ namespace Exa
 | 
			
		||||
                    break;
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
            //
 | 
			
		||||
            // Determine the source end chunk and index.
 | 
			
		||||
            //
 | 
			
		||||
            int sourceChunkIndexFrom = -1;
 | 
			
		||||
            int sourceElementIndexFrom = -1;
 | 
			
		||||
            switch (other.OptimizationStrategy)
 | 
			
		||||
@ -68,7 +90,12 @@ namespace Exa
 | 
			
		||||
                    break;
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
            // How many element we have to copy?
 | 
			
		||||
            ulong newRange = indexTo - indexFrom + 1;
 | 
			
		||||
            
 | 
			
		||||
            //
 | 
			
		||||
            // Determine, how many total chunks we need for the copy.
 | 
			
		||||
            //
 | 
			
		||||
            int destChunks = -1;
 | 
			
		||||
            switch (other.OptimizationStrategy)
 | 
			
		||||
            {
 | 
			
		||||
@ -80,20 +107,29 @@ namespace Exa
 | 
			
		||||
                    break;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Create the copy and allocate the needed number of outer chunk.
 | 
			
		||||
            var next = new ExaArray1D<T>(other.OptimizationStrategy)
 | 
			
		||||
            {
 | 
			
		||||
                Length = newRange,
 | 
			
		||||
                chunks = new T[destChunks][],
 | 
			
		||||
            };
 | 
			
		||||
            
 | 
			
		||||
            //
 | 
			
		||||
            // Variables for the copy process.
 | 
			
		||||
            //
 | 
			
		||||
            
 | 
			
		||||
            int sourceChunkIndex = sourceChunkIndexFrom;
 | 
			
		||||
            int destinChunkIndex = 0;
 | 
			
		||||
            int destinationChunkIndex = 0;
 | 
			
		||||
            int sourceElementIndex = sourceElementIndexFrom;
 | 
			
		||||
            int destinElementIndex = 0;
 | 
			
		||||
            ulong leftOver = newRange;
 | 
			
		||||
            int destinationElementIndex = 0;
 | 
			
		||||
            ulong leftOverTotal = newRange;
 | 
			
		||||
 | 
			
		||||
            do
 | 
			
		||||
            {
 | 
			
		||||
                //
 | 
			
		||||
                // Determine how many elements we copy next.
 | 
			
		||||
                //
 | 
			
		||||
 | 
			
		||||
                uint numberToCopy = 0;
 | 
			
		||||
                
 | 
			
		||||
                // Case: small number of elements from first chunk only
 | 
			
		||||
@ -105,36 +141,47 @@ namespace Exa
 | 
			
		||||
                    numberToCopy = (uint) (other.maxArrayCapacity - sourceElementIndex);
 | 
			
		||||
                    
 | 
			
		||||
                // Case: multiple chunks + we are in the middle of huge copy process + next chunk does __not__ exist
 | 
			
		||||
                else if (next.chunks[destinChunkIndex] == null && sourceElementIndex == 0 && leftOver >= other.maxArrayCapacity)
 | 
			
		||||
                else if (next.chunks[destinationChunkIndex] == null && sourceElementIndex == 0 && leftOverTotal >= other.maxArrayCapacity)
 | 
			
		||||
                    numberToCopy = other.maxArrayCapacity;
 | 
			
		||||
                
 | 
			
		||||
                // Case: multiple chunks + we are in the middle of huge copy process + next chunk does exist
 | 
			
		||||
                else if (next.chunks[destinChunkIndex] != null && sourceElementIndex == 0 && leftOver >= other.maxArrayCapacity)
 | 
			
		||||
                    numberToCopy = (uint) (other.maxArrayCapacity - next.chunks[destinChunkIndex].Length);
 | 
			
		||||
                else if (next.chunks[destinationChunkIndex] != null && sourceElementIndex == 0 && leftOverTotal >= other.maxArrayCapacity)
 | 
			
		||||
                    numberToCopy = (uint) (other.maxArrayCapacity - next.chunks[destinationChunkIndex].Length);
 | 
			
		||||
                
 | 
			
		||||
                // Case: multiple chunks + this seems to be the last chunk
 | 
			
		||||
                else if (sourceElementIndex == 0 && leftOver < other.maxArrayCapacity)
 | 
			
		||||
                    numberToCopy = (uint) leftOver;
 | 
			
		||||
                else if (sourceElementIndex == 0 && leftOverTotal < other.maxArrayCapacity)
 | 
			
		||||
                    numberToCopy = (uint) leftOverTotal;
 | 
			
		||||
                
 | 
			
		||||
                if(next.chunks[destinChunkIndex] == null)
 | 
			
		||||
                    next.chunks[destinChunkIndex] = new T[numberToCopy];
 | 
			
		||||
                //
 | 
			
		||||
                // Can we allocate an entire chunk or do we have to fill up the existing
 | 
			
		||||
                // chunk first?
 | 
			
		||||
                //
 | 
			
		||||
                if(next.chunks[destinationChunkIndex] == null)
 | 
			
		||||
                    next.chunks[destinationChunkIndex] = new T[numberToCopy];
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    var extended = new T[next.chunks[destinChunkIndex].Length + numberToCopy];
 | 
			
		||||
                    Array.Copy(next.chunks[destinChunkIndex], extended, next.chunks[destinChunkIndex].Length);
 | 
			
		||||
                    next.chunks[destinChunkIndex] = extended;
 | 
			
		||||
                    var extended = new T[next.chunks[destinationChunkIndex].Length + numberToCopy];
 | 
			
		||||
                    Array.Copy(next.chunks[destinationChunkIndex], extended, next.chunks[destinationChunkIndex].Length);
 | 
			
		||||
                    next.chunks[destinationChunkIndex] = extended;
 | 
			
		||||
                }
 | 
			
		||||
                
 | 
			
		||||
                Array.Copy(other.chunks[sourceChunkIndex], sourceElementIndex, next.chunks[destinChunkIndex], destinElementIndex, numberToCopy);
 | 
			
		||||
                // Copy the data:
 | 
			
		||||
                Array.Copy(other.chunks[sourceChunkIndex], sourceElementIndex, next.chunks[destinationChunkIndex], destinationElementIndex, numberToCopy);
 | 
			
		||||
 | 
			
		||||
                var needNewChunk = next.chunks[destinChunkIndex].Length == next.maxArrayCapacity;
 | 
			
		||||
                leftOver -= numberToCopy;
 | 
			
		||||
                sourceChunkIndex++;
 | 
			
		||||
                destinChunkIndex = needNewChunk ? destinChunkIndex + 1 : destinChunkIndex;
 | 
			
		||||
                sourceElementIndex = 0;
 | 
			
		||||
                destinElementIndex = (int) (needNewChunk ? 0 : numberToCopy);
 | 
			
		||||
                //
 | 
			
		||||
                // Update the state machine.
 | 
			
		||||
                //
 | 
			
		||||
                var needNewDestinationChunk = next.chunks[destinationChunkIndex].Length == next.maxArrayCapacity;
 | 
			
		||||
                var readNextSourceChunk = sourceElementIndex + numberToCopy == other.maxArrayCapacity;
 | 
			
		||||
                var leftOverCurrentSourceChunk = (int) (readNextSourceChunk ? 0 : other.maxArrayCapacity - sourceElementIndex - numberToCopy);
 | 
			
		||||
                
 | 
			
		||||
            } while (leftOver > 0);
 | 
			
		||||
                leftOverTotal -= numberToCopy;
 | 
			
		||||
                sourceChunkIndex = readNextSourceChunk ? sourceChunkIndex + 1 : sourceChunkIndex;
 | 
			
		||||
                destinationChunkIndex = needNewDestinationChunk ? destinationChunkIndex + 1 : destinationChunkIndex;
 | 
			
		||||
                sourceElementIndex = leftOverCurrentSourceChunk;
 | 
			
		||||
                destinationElementIndex = (int) (needNewDestinationChunk ? 0 : numberToCopy);
 | 
			
		||||
 | 
			
		||||
            } while (leftOverTotal > 0);
 | 
			
		||||
            return next;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user