Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 57 additions & 12 deletions src/core/IronPython.Modules/_heapq.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,24 @@ public static void heapify(CodeContext/*!*/ context, [NotNone] PythonList list)
}
}

[Documentation("Maxheap variant of heapify.")]
public static void _heapify_max(CodeContext context, [NotNone] PythonList list) {
lock (list) {
DoHeapifyMax(context, list);
}
}

[Documentation("Pop the smallest item off the heap, maintaining the heap invariant.")]
public static object? heappop(CodeContext/*!*/ context, [NotNone] PythonList list) {
lock (list) {
int last = list._size - 1;
if (last < 0) {
throw PythonOps.IndexError("index out of range");
}
list.FastSwap(0, last);
list._size--;
SiftDown(context, list, 0, last - 1);
return list._data[list._size];
return DoHeapPop(context, list, max: false);
}
}

[Documentation("Maxheap variant of heappop.")]
public static object? _heappop_max(CodeContext context, [NotNone] PythonList list) {
lock (list) {
return DoHeapPop(context, list, max: true);
}
}

Expand Down Expand Up @@ -70,10 +77,14 @@ public static void heappush(CodeContext/*!*/ context, [NotNone] PythonList list,
)]
public static object? heapreplace(CodeContext/*!*/ context, [NotNone] PythonList list, object? item) {
lock (list) {
object? ret = list._data[0];
list._data[0] = item;
SiftDown(context, list, 0, list._size - 1);
return ret;
return DoHeapReplace(context, list, item, max: false);
}
}

[Documentation("Maxheap variant of heapreplace.")]
public static object? _heapreplace_max(CodeContext context, [NotNone] PythonList list, object? item) {
lock (list) {
return DoHeapReplace(context, list, item, max: true);
}
}

Expand Down Expand Up @@ -160,6 +171,7 @@ private static bool IsLessThan(CodeContext/*!*/ context, object? x, object? y) {
}
}

#if PYTHON_34
private static void HeapSort(CodeContext/*!*/ context, PythonList list) {
HeapSort(context, list, false);
}
Expand All @@ -186,6 +198,7 @@ private static void HeapSort(CodeContext/*!*/ context, PythonList list, bool rev
}
}
}
#endif

private static void DoHeapify(CodeContext/*!*/ context, PythonList list) {
int last = list._size - 1;
Expand All @@ -207,6 +220,35 @@ private static void DoHeapifyMax(CodeContext/*!*/ context, PythonList list) {
}
}

private static object? DoHeapPop(CodeContext context, PythonList list, bool max) {
int last = list._size - 1;
if (last < 0) {
throw PythonOps.IndexError("index out of range");
}
list.FastSwap(0, last);
list._size--;
if (max) {
SiftDownMax(context, list, 0, last - 1);
} else {
SiftDown(context, list, 0, last - 1);
}
return list._data[list._size];
}

private static object? DoHeapReplace(CodeContext context, PythonList list, object? item, bool max) {
if (list._size == 0) {
throw PythonOps.IndexError("index out of range");
}
object? ret = list._data[0];
list._data[0] = item;
if (max) {
SiftDownMax(context, list, 0, list._size - 1);
} else {
SiftDown(context, list, 0, list._size - 1);
}
return ret;
}

private static object? DoPushPop(CodeContext/*!*/ context, PythonList heap, object? item) {
object? first;
if (heap._size == 0 || !IsLessThan(context, first = heap._data[0], item)) {
Expand All @@ -217,6 +259,7 @@ private static void DoHeapifyMax(CodeContext/*!*/ context, PythonList list) {
return first;
}

#if PYTHON_34
private static object? DoPushPopMax(CodeContext/*!*/ context, PythonList heap, object? item) {
object? first;
if (heap._size == 0 || !IsLessThan(context, item, first = heap._data[0])) {
Expand All @@ -226,6 +269,7 @@ private static void DoHeapifyMax(CodeContext/*!*/ context, PythonList list) {
SiftDownMax(context, heap, 0, heap._size - 1);
return first;
}
#endif

private static void SiftDown(CodeContext/*!*/ context, PythonList heap, int start, int stop) {
int parent = start;
Expand Down Expand Up @@ -275,6 +319,7 @@ private static void SiftUp(CodeContext/*!*/ context, PythonList heap, int index)
}
}

// TODO: this will get used in 3.14 (for heappush_max)
private static void SiftUpMax(CodeContext/*!*/ context, PythonList heap, int index) {
while (index > 0) {
int parent = (index - 1) / 2;
Expand Down
1 change: 0 additions & 1 deletion tests/suite/stdlib/test_heapq.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ def load_tests(loader, standard_tests, pattern):
test.test_heapq.TestErrorHandlingC('test_comparison_operator_modifiying_heap'), # TypeError: '<' not supported between instances of 'EvilClass' and 'int'
test.test_heapq.TestErrorHandlingC('test_comparison_operator_modifiying_heap_two_heaps'), # AssertionError: (<class 'IndexError'>, <class 'RuntimeError'>) not raised by heappush
test.test_heapq.TestErrorHandlingPython('test_comparison_operator_modifiying_heap'), # TypeError: '<' not supported between instances of 'EvilClass' and 'int'
test.test_heapq.TestModules('test_c_functions'), # AssertionError: 'heapq' != '_heapq'
]

skip_tests = []
Expand Down
Loading