Add memory-based AddRange overloads

This commit is contained in:
Marek Lemańczyk committed 2025-09-16 14:20:11 +02:00
1 parent f6640deaf1
commit b0e7f96496
2 files changed
+126

No files matched your search

@@ -232,6 +232,100 @@ namespace Recyclable.Collections
}
}
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
internal static void AddRange<T>(this RecyclablePriorityQueue<T> queue, ReadOnlyMemory<T> items)
{
ReadOnlySpan<T> span = items.Span;
int count = span.Length;
if (count == 0)
{
return;
}
int startIndex = queue._size;
int newCount = startIndex + count;
EnsureCapacity(queue, newCount);
for (int i = 0; i < count; i++)
{
queue._heap[startIndex + i] = span[i];
}
queue._size = newCount;
int half = newCount >> 1;
for (int i = half - 1; i >= 0; i--)
{
int index = i;
T item = queue._heap[index];
while (index < half)
{
int child = (index << 1) + 1;
int right = child + 1;
if (right < newCount && queue._comparer.Compare(queue._heap[right], queue._heap[child]) < 0)
{
child = right;
}
if (queue._comparer.Compare(queue._heap[child], item) >= 0)
{
break;
}
queue._heap[index] = queue._heap[child];
index = child;
}
queue._heap[index] = item;
}
}
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
internal static void AddRange<T>(this RecyclablePriorityQueue<T> queue, Memory<T> items)
{
Span<T> span = items.Span;
int count = span.Length;
if (count == 0)
{
return;
}
int startIndex = queue._size;
int newCount = startIndex + count;
EnsureCapacity(queue, newCount);
for (int i = 0; i < count; i++)
{
queue._heap[startIndex + i] = span[i];
}
queue._size = newCount;
int half = newCount >> 1;
for (int i = half - 1; i >= 0; i--)
{
int index = i;
T item = queue._heap[index];
while (index < half)
{
int child = (index << 1) + 1;
int right = child + 1;
if (right < newCount && queue._comparer.Compare(queue._heap[right], queue._heap[child]) < 0)
{
child = right;
}
if (queue._comparer.Compare(queue._heap[child], item) >= 0)
{
break;
}
queue._heap[index] = queue._heap[child];
index = child;
}
queue._heap[index] = item;
}
}
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
internal static void AddRange<T>(this RecyclablePriorityQueue<T> queue, T[] items)
{
@@ -124,6 +124,38 @@ namespace Recyclable.CollectionsTests
_ = result.Should().Equal(_testData.Order());
}
[Fact]
public void AddRangeReadOnlyMemoryShouldAddItemsInSortedOrder()
{
using var queue = new RecyclablePriorityQueue<int>();
queue.AddRange((ReadOnlyMemory<int>)_testData);
var result = new List<int>();
while (queue.LongCount > 0)
{
result.Add(queue.Dequeue());
}
_ = result.Should().Equal(_testData.Order());
}
[Fact]
public void AddRangeMemoryShouldNotOverrideItems()
{
using var queue = new RecyclablePriorityQueue<int>();
queue.AddRange(_testData.AsMemory());
queue.AddRange(_testData.AsMemory());
var expected = _testData.Concat(_testData).Order().ToArray();
var result = new List<int>();
while (queue.LongCount > 0)
{
result.Add(queue.Dequeue());
}
_ = result.Should().Equal(expected);
}
[Fact]
public void AddRangeArrayShouldNotOverrideItems()
{