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;
|
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)
|
public static ExaArray1D<T> CreateFrom(ExaArray1D<T> other, ulong indexFrom, ulong indexTo)
|
||||||
{
|
{
|
||||||
if (indexTo < indexFrom)
|
if (indexTo < indexFrom)
|
||||||
throw new IndexOutOfRangeException("Index to must be greater than index from.");
|
throw new IndexOutOfRangeException("Index to must be greater than index from.");
|
||||||
|
|
||||||
if (indexTo >= other.Length || indexFrom >= other.Length)
|
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 sourceChunkIndexTo = -1;
|
||||||
int sourceElementIndexTo = -1;
|
int sourceElementIndexTo = -1;
|
||||||
switch (other.OptimizationStrategy)
|
switch (other.OptimizationStrategy)
|
||||||
@ -54,6 +73,9 @@ namespace Exa
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Determine the source end chunk and index.
|
||||||
|
//
|
||||||
int sourceChunkIndexFrom = -1;
|
int sourceChunkIndexFrom = -1;
|
||||||
int sourceElementIndexFrom = -1;
|
int sourceElementIndexFrom = -1;
|
||||||
switch (other.OptimizationStrategy)
|
switch (other.OptimizationStrategy)
|
||||||
@ -68,7 +90,12 @@ namespace Exa
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// How many element we have to copy?
|
||||||
ulong newRange = indexTo - indexFrom + 1;
|
ulong newRange = indexTo - indexFrom + 1;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Determine, how many total chunks we need for the copy.
|
||||||
|
//
|
||||||
int destChunks = -1;
|
int destChunks = -1;
|
||||||
switch (other.OptimizationStrategy)
|
switch (other.OptimizationStrategy)
|
||||||
{
|
{
|
||||||
@ -80,20 +107,29 @@ namespace Exa
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create the copy and allocate the needed number of outer chunk.
|
||||||
var next = new ExaArray1D<T>(other.OptimizationStrategy)
|
var next = new ExaArray1D<T>(other.OptimizationStrategy)
|
||||||
{
|
{
|
||||||
Length = newRange,
|
Length = newRange,
|
||||||
chunks = new T[destChunks][],
|
chunks = new T[destChunks][],
|
||||||
};
|
};
|
||||||
|
|
||||||
int sourceChunkIndex = sourceChunkIndexFrom;
|
|
||||||
int destinChunkIndex = 0;
|
|
||||||
int sourceElementIndex = sourceElementIndexFrom;
|
|
||||||
int destinElementIndex = 0;
|
|
||||||
ulong leftOver = newRange;
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Variables for the copy process.
|
||||||
|
//
|
||||||
|
|
||||||
|
int sourceChunkIndex = sourceChunkIndexFrom;
|
||||||
|
int destinationChunkIndex = 0;
|
||||||
|
int sourceElementIndex = sourceElementIndexFrom;
|
||||||
|
int destinationElementIndex = 0;
|
||||||
|
ulong leftOverTotal = newRange;
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
//
|
||||||
|
// Determine how many elements we copy next.
|
||||||
|
//
|
||||||
|
|
||||||
uint numberToCopy = 0;
|
uint numberToCopy = 0;
|
||||||
|
|
||||||
// Case: small number of elements from first chunk only
|
// Case: small number of elements from first chunk only
|
||||||
@ -105,36 +141,47 @@ namespace Exa
|
|||||||
numberToCopy = (uint) (other.maxArrayCapacity - sourceElementIndex);
|
numberToCopy = (uint) (other.maxArrayCapacity - sourceElementIndex);
|
||||||
|
|
||||||
// Case: multiple chunks + we are in the middle of huge copy process + next chunk does __not__ exist
|
// 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;
|
numberToCopy = other.maxArrayCapacity;
|
||||||
|
|
||||||
// Case: multiple chunks + we are in the middle of huge copy process + next chunk does exist
|
// 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)
|
else if (next.chunks[destinationChunkIndex] != null && sourceElementIndex == 0 && leftOverTotal >= other.maxArrayCapacity)
|
||||||
numberToCopy = (uint) (other.maxArrayCapacity - next.chunks[destinChunkIndex].Length);
|
numberToCopy = (uint) (other.maxArrayCapacity - next.chunks[destinationChunkIndex].Length);
|
||||||
|
|
||||||
// Case: multiple chunks + this seems to be the last chunk
|
// Case: multiple chunks + this seems to be the last chunk
|
||||||
else if (sourceElementIndex == 0 && leftOver < other.maxArrayCapacity)
|
else if (sourceElementIndex == 0 && leftOverTotal < other.maxArrayCapacity)
|
||||||
numberToCopy = (uint) leftOver;
|
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
|
else
|
||||||
{
|
{
|
||||||
var extended = new T[next.chunks[destinChunkIndex].Length + numberToCopy];
|
var extended = new T[next.chunks[destinationChunkIndex].Length + numberToCopy];
|
||||||
Array.Copy(next.chunks[destinChunkIndex], extended, next.chunks[destinChunkIndex].Length);
|
Array.Copy(next.chunks[destinationChunkIndex], extended, next.chunks[destinationChunkIndex].Length);
|
||||||
next.chunks[destinChunkIndex] = extended;
|
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;
|
// Update the state machine.
|
||||||
sourceChunkIndex++;
|
//
|
||||||
destinChunkIndex = needNewChunk ? destinChunkIndex + 1 : destinChunkIndex;
|
var needNewDestinationChunk = next.chunks[destinationChunkIndex].Length == next.maxArrayCapacity;
|
||||||
sourceElementIndex = 0;
|
var readNextSourceChunk = sourceElementIndex + numberToCopy == other.maxArrayCapacity;
|
||||||
destinElementIndex = (int) (needNewChunk ? 0 : numberToCopy);
|
var leftOverCurrentSourceChunk = (int) (readNextSourceChunk ? 0 : other.maxArrayCapacity - sourceElementIndex - numberToCopy);
|
||||||
|
|
||||||
|
leftOverTotal -= numberToCopy;
|
||||||
|
sourceChunkIndex = readNextSourceChunk ? sourceChunkIndex + 1 : sourceChunkIndex;
|
||||||
|
destinationChunkIndex = needNewDestinationChunk ? destinationChunkIndex + 1 : destinationChunkIndex;
|
||||||
|
sourceElementIndex = leftOverCurrentSourceChunk;
|
||||||
|
destinationElementIndex = (int) (needNewDestinationChunk ? 0 : numberToCopy);
|
||||||
|
|
||||||
} while (leftOver > 0);
|
} while (leftOverTotal > 0);
|
||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user