From c7c77c90fb4165786c91771e3396cc49ea95eaf3 Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Sat, 1 Aug 2020 14:06:01 +0200 Subject: [PATCH] WIP: Range creation --- ExaArray/ExaArray1D.Factories.cs | 106 +++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) diff --git a/ExaArray/ExaArray1D.Factories.cs b/ExaArray/ExaArray1D.Factories.cs index 2fe257e..2e4f576 100644 --- a/ExaArray/ExaArray1D.Factories.cs +++ b/ExaArray/ExaArray1D.Factories.cs @@ -31,5 +31,111 @@ namespace Exa return next; } + + public static ExaArray1D CreateFrom(ExaArray1D 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."); + + int sourceChunkIndexTo = -1; + int sourceElementIndexTo = -1; + switch (other.OptimizationStrategy) + { + case Strategy.MAX_PERFORMANCE: + sourceChunkIndexTo = (int) (indexTo / MAX_CAPACITY_ARRAY_PERFORMANCE); + sourceElementIndexTo = (int) (indexTo - (ulong) sourceChunkIndexTo * MAX_CAPACITY_ARRAY_PERFORMANCE); + break; + case Strategy.MAX_ELEMENTS: + sourceChunkIndexTo = (int) (indexTo / MAX_CAPACITY_ARRAY); + sourceElementIndexTo = (int) (indexTo - (ulong) sourceChunkIndexTo * MAX_CAPACITY_ARRAY); + break; + } + + int sourceChunkIndexFrom = -1; + int sourceElementIndexFrom = -1; + switch (other.OptimizationStrategy) + { + case Strategy.MAX_PERFORMANCE: + sourceChunkIndexFrom = (int) (indexFrom / MAX_CAPACITY_ARRAY_PERFORMANCE); + sourceElementIndexFrom = (int) (indexFrom - (ulong) sourceChunkIndexFrom * MAX_CAPACITY_ARRAY_PERFORMANCE); + break; + case Strategy.MAX_ELEMENTS: + sourceChunkIndexFrom = (int) (indexFrom / MAX_CAPACITY_ARRAY); + sourceElementIndexFrom = (int) (indexFrom - (ulong) sourceChunkIndexFrom * MAX_CAPACITY_ARRAY); + break; + } + + ulong newRange = indexTo - indexFrom + 1; + int destChunks = -1; + switch (other.OptimizationStrategy) + { + case Strategy.MAX_PERFORMANCE: + destChunks = (int) ((newRange - 1) / MAX_CAPACITY_ARRAY_PERFORMANCE) + 1; + break; + case Strategy.MAX_ELEMENTS: + destChunks = (int) ((newRange - 1) / MAX_CAPACITY_ARRAY) + 1; + break; + } + + var next = new ExaArray1D(other.OptimizationStrategy) + { + Length = newRange, + chunks = new T[destChunks][], + }; + + int sourceChunkIndex = sourceChunkIndexFrom; + int destinChunkIndex = 0; + int sourceElementIndex = sourceElementIndexFrom; + int destinElementIndex = 0; + ulong leftOver = newRange; + + do + { + uint numberToCopy = 0; + + // Case: small number of elements from first chunk only + if (sourceChunkIndexFrom == sourceChunkIndexTo) + numberToCopy = (uint) (sourceElementIndexTo - sourceElementIndexFrom + 1); + + // Case: this is first chunk of multiple chunks + start somewhere in the middle + else if (sourceElementIndex > 0) + 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) + 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); + + // Case: multiple chunks + this seems to be the last chunk + else if (sourceElementIndex == 0 && leftOver < other.maxArrayCapacity) + numberToCopy = (uint) leftOver; + + if(next.chunks[destinChunkIndex] == null) + next.chunks[destinChunkIndex] = 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; + } + + Array.Copy(other.chunks[sourceChunkIndex], sourceElementIndex, next.chunks[destinChunkIndex], destinElementIndex, numberToCopy); + + var needNewChunk = next.chunks[destinChunkIndex].Length == next.maxArrayCapacity; + leftOver -= numberToCopy; + sourceChunkIndex++; + destinChunkIndex = needNewChunk ? destinChunkIndex + 1 : destinChunkIndex; + sourceElementIndex = 0; + destinElementIndex = (int) (needNewChunk ? 0 : numberToCopy); + + } while (leftOver > 0); + return next; + } } } \ No newline at end of file