add basic quicksort support (#816)

* lib/std/sort: refactor binarysearch namespace to prepare for sorting

Signed-off-by: Pierre Curto <pierre.curto@gmail.com>

* std/lib/sort: add basic quicksort support

Signed-off-by: Pierre Curto <pierre.curto@gmail.com>

* lib/std/hash: use method first parameter inferred type

Signed-off-by: Pierre Curto <pierre.curto@gmail.com>

* lib/std/hash: add fnv64a support

Signed-off-by: Pierre Curto <pierre.curto@gmail.com>

---------

Signed-off-by: Pierre Curto <pierre.curto@gmail.com>
This commit is contained in:
Pierre Curto
2023-07-04 20:15:03 +02:00
committed by GitHub
parent 6231cc83d9
commit f8a3e4f6f0
10 changed files with 255 additions and 57 deletions

View File

@@ -1,12 +1,12 @@
module std::sort::binarysearch;
module std::sort;
/**
* Perform a binary search over the sorted array and return the smallest index
* in [0, array.len) where cmp(i) is true and cmp(j) is true for j in [i, array.len).
* @require is_searchable(list) "The list must be indexable and support .len or .len()"
* @require is_comparer(cmp, list) "Expeced a comparison function which compares values"
* @require is_comparer(cmp, list) "Expected a comparison function which compares values"
**/
macro usz cmp_search(list, x, cmp)
macro usz binarysearch_with(list, x, cmp)
{
usz i;
usz len = @len_from_list(list);
@@ -34,7 +34,7 @@ macro usz cmp_search(list, x, cmp)
* @require is_searchable(list) "The list must be indexable and support .len or .len()"
* @checked less(list[0], x) "The values must be comparable"
**/
macro usz search(list, x)
macro usz binarysearch(list, x)
{
usz i;
usz len = @len_from_list(list);
@@ -48,24 +48,4 @@ macro usz search(list, x)
}
}
return i;
}
macro bool is_searchable(list) @local
{
return $checks(list[0]) && ($checks(list.len) || $checks(list.len()));
}
macro usz @len_from_list(&list) @local
{
$if $checks(list.len()):
return list.len();
$else
return list.len;
$endif
}
macro bool is_comparer(cmp, list)
{
return $checks(int i = cmp(list[0], list[0]))
|| $checks(int i = cmp(&list[0], &list[0]));
}
}

66
lib/std/sort/quicksort.c3 Normal file
View File

@@ -0,0 +1,66 @@
module std::sort;
/**
* @require is_searchable(list) "The list must be indexable and support .len or .len()"
**/
macro quicksort(list, $Type)
{
(($Type)(list)).sort(null);
}
/**
* @require is_searchable(list) "The list must be indexable and support .len or .len()"
* @require is_comparer(cmp, list) "Expected a comparison function which compares values"
**/
macro quicksort_with(list, $Type, cmp)
{
(($Type)(list)).sort(cmp);
}
module std::sort::quicksort<Type, Comparer>;
import std::sort;
def Quicksort = distinct Type[];
fn void Quicksort.sort(qs, Comparer cmp)
{
usz len = sort::@len_from_list(qs);
qs.qsort(0, (isz)len - 1, cmp);
}
fn void Quicksort.qsort(Quicksort qs, isz low, isz high, Comparer cmp) @private
{
if (low < high)
{
isz p = qs.partition(low, high, cmp);
qs.qsort(low, p - 1, cmp);
qs.qsort(p + 1, high, cmp);
}
}
fn isz Quicksort.partition(qs, isz low, isz high, Comparer cmp) @inline @private
{
Type pivot = qs[high];
isz i = low - 1;
for (isz j = low; j < high; j++)
{
$if $checks(cmp(qs[0], qs[0])):
int res = cmp(qs[j], pivot);
$else
$if $checks(cmp(&qs[0], &qs[0])):
int res = cmp(&qs[j], &pivot);
$else
int res;
if (greater(qs[j], pivot)) res = 1;
$endif
$endif
if (res <= 0)
{
i++;
@swap(qs[i], qs[j]);
}
}
i++;
@swap(qs[i], qs[high]);
return i;
}

21
lib/std/sort/sort.c3 Normal file
View File

@@ -0,0 +1,21 @@
module std::sort;
macro bool is_searchable(list)
{
return $checks(list[0]) && ($checks(list.len) || $checks(list.len()));
}
macro usz @len_from_list(&list)
{
$if $checks(list.len()):
return list.len();
$else
return list.len;
$endif
}
macro bool is_comparer(cmp, list)
{
return $checks(int i = cmp(list[0], list[0]))
|| $checks(int i = cmp(&list[0], &list[0]));
}