From 6d80b36d7042c63b218c56bbd3b06ee3117dec6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Lema=C5=84czyk?= Date: Tue, 16 Sep 2025 13:52:15 +0200 Subject: [PATCH] Implement standalone AddRange overloads --- .../RecyclablePriorityQueue.AddRange.cs | 222 +++++++++++++++++- 1 file changed, 217 insertions(+), 5 deletions(-) diff --git a/Recyclable.Collections/RecyclablePriorityQueue.AddRange.cs b/Recyclable.Collections/RecyclablePriorityQueue.AddRange.cs index c91513e..3346bc5 100644 --- a/Recyclable.Collections/RecyclablePriorityQueue.AddRange.cs +++ b/Recyclable.Collections/RecyclablePriorityQueue.AddRange.cs @@ -96,11 +96,95 @@ namespace Recyclable.Collections [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)] internal static void AddRange(this RecyclablePriorityQueue queue, Span items) - => AddRange(queue, (ReadOnlySpan)items); + { + int count = items.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] = items[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(this RecyclablePriorityQueue queue, T[] items) - => AddRange(queue, (ReadOnlySpan)items); + { + int count = items.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] = items[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(this RecyclablePriorityQueue queue, in Array items) @@ -147,7 +231,49 @@ namespace Recyclable.Collections [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)] internal static void AddRange(this RecyclablePriorityQueue queue, List items) - => AddRange(queue, CollectionsMarshal.AsSpan(items)); + { + int count = items.Count; + 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] = items[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(this RecyclablePriorityQueue queue, ICollection items) @@ -257,11 +383,97 @@ namespace Recyclable.Collections [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)] internal static void AddRange(this RecyclablePriorityQueue queue, RecyclableList items) - => AddRange(queue, new ReadOnlySpan(items._memoryBlock, 0, items._count)); + { + int count = items._count; + if (count == 0) + { + return; + } + + int startIndex = queue._size; + int newCount = startIndex + count; + EnsureCapacity(queue, newCount); + + T[] source = items._memoryBlock; + for (int i = 0; i < count; i++) + { + queue._heap[startIndex + i] = source[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(this RecyclablePriorityQueue queue, RecyclablePriorityQueue items) - => AddRange(queue, new ReadOnlySpan(items._heap, 0, items._size)); + { + int count = items._size; + if (count == 0) + { + return; + } + + int startIndex = queue._size; + int newCount = startIndex + count; + EnsureCapacity(queue, newCount); + + T[] source = items._heap; + for (int i = 0; i < count; i++) + { + queue._heap[startIndex + i] = source[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(this RecyclablePriorityQueue queue, IReadOnlyList items)