Fix of accidentally printing "prev" when using $checks. Updated binary search.

This commit is contained in:
Christoffer Lerno
2023-07-04 02:29:02 +02:00
parent 55d17ec990
commit c249c3f3b6
5 changed files with 70 additions and 53 deletions

View File

@@ -1,26 +1,25 @@
module std::sort::binarysearch;
/*
* Compare x and y and return one of the following values:
* -1 if x < y
* 0 if x == y
* 1 if x > y
*/
def Comparer = fn int (void *x, void *y);
/**
* 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_array_or_subarray(array) "array must be an array or subarray"
* @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"
**/
macro usz cmp_search(array, x, Comparer cmp)
macro usz cmp_search(list, x, cmp)
{
usz i;
for (usz j = array.len; i < j;)
usz len = @len_from_list(list);
for (usz j = len; i < j;)
{
usz half = (i + j) / 2;
int res = cmp(&array[half], &x);
switch {
$if $checks(cmp(list[0], list[0])):
int res = cmp(list[half], x);
$else
int res = cmp(&list[half], &x);
$endif
switch
{
case res > 0: j = half;
case res < 0: i = half + 1;
default: return half;
@@ -32,35 +31,41 @@ macro usz cmp_search(array, x, Comparer cmp)
/**
* Perform a binary search over the sorted array and return the index
* in [0, array.len) where x would be inserted.
* @require is_array_or_subarray(array) "array must be an array or subarray"
* @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(array, x)
macro usz search(list, x)
{
usz i;
for (usz j = array.len; i < j;)
usz len = @len_from_list(list);
for (usz j = len; i < j;)
{
usz half = (i + j) / 2;
switch {
case greater(array[half], x): j = half;
case less(array[half], x): i = half + 1;
case greater(list[half], x): j = half;
case less(list[half], x): i = half + 1;
default: return half;
}
}
return i;
}
macro bool is_array_or_subarray(slice) @private
macro bool is_searchable(list) @local
{
$switch ($typeof(slice).kindof)
$case POINTER:
var $Inner = $typefrom($typeof(bytes).inner);
$if $Inner.kindof == ARRAY:
return true;
$endif
$case ARRAY:
$case SUBARRAY:
return true;
$default:
return false;
$endswitch
}
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]));
}