codon/stdlib/internal/sort.codon

85 lines
2.6 KiB
Python

# Copyright (C) 2022-2023 Exaloop Inc. <https://exaloop.io>
from algorithms.pdqsort import pdq_sort_inplace
from algorithms.insertionsort import insertion_sort_inplace
from algorithms.heapsort import heap_sort_inplace
from algorithms.qsort import qsort_inplace
from algorithms.timsort import tim_sort_inplace
def sorted(
v: Generator[T],
key=Optional[int](),
reverse: bool = False,
algorithm: Static[str] = "auto",
T: type,
) -> List[T]:
"""
Return a sorted list of the elements in v
"""
newlist = [a for a in v]
if not isinstance(key, Optional):
newlist.sort(key, reverse, algorithm)
else:
newlist.sort(reverse=reverse, algorithm=algorithm)
return newlist
def _is_pdq_compatible(x):
if (isinstance(x, int) or
isinstance(x, float) or
isinstance(x, bool) or
isinstance(x, byte) or
isinstance(x, str) or
isinstance(x, Int) or
isinstance(x, UInt)):
return True
elif isinstance(x, Tuple):
for a in x:
if not _is_pdq_compatible(a):
return False
return True
else:
return False
def _sort_list(
self: List[T], key: Callable[[T], S], algorithm: Static[str], T: type, S: type
):
if algorithm == "tim" or algorithm == "auto":
tim_sort_inplace(self, key)
elif algorithm == "pdq":
pdq_sort_inplace(self, key)
elif algorithm == "insertion":
insertion_sort_inplace(self, key)
elif algorithm == "heap":
heap_sort_inplace(self, key)
elif algorithm == "quick":
qsort_inplace(self, key)
else:
compile_error("invalid sort algorithm")
@extend
class List:
def sort(
self,
key=Optional[int](),
reverse: bool = False,
algorithm: Static[str] = "auto",
):
if isinstance(key, Optional):
if algorithm == "auto":
# Python uses Timsort in all cases, but if we
# know stability does not matter (i.e. sorting
# primitive type with no key), we will use
# faster PDQ instead. PDQ is ~50% faster than
# Timsort for sorting 1B 64-bit ints.
if self:
if _is_pdq_compatible(self[0]):
pdq_sort_inplace(self, lambda x: x)
else:
tim_sort_inplace(self, lambda x: x)
else:
_sort_list(self, lambda x: x, algorithm)
else:
_sort_list(self, key, algorithm)
if reverse:
self.reverse()