stdlib: add qsort (TEST)

This commit is contained in:
Lephenixnoir 2021-06-28 15:49:47 +02:00
parent a6dbcfb227
commit ea35c18c41
Signed by: Lephenixnoir
GPG Key ID: 1BBA026E13FC0495
3 changed files with 48 additions and 1 deletions

View File

@ -149,6 +149,7 @@ set(SOURCES
src/libc/stdlib/ldiv.c
src/libc/stdlib/llabs.c
src/libc/stdlib/lldiv.c
src/libc/stdlib/qsort.c
src/libc/stdlib/reallocarray.c
src/libc/stdlib/strto_fp.c
src/libc/stdlib/strto_int.c

3
STATUS
View File

@ -115,7 +115,8 @@ DONE: Function/symbol/macro is defined, builds, links, and is tested
7.20.4.4 _Exit: DONE (gint only)
! 7.20.4.5 getenv: TODO
! 7.20.4.6 system: TODO
! 7.20.5 Searching and sorting utilities: TODO
! 7.20.5.1 bsearch: TODO
! 7.20.5.2 qsort: TEST
7.20.6.1 abs, labs, llabs: DONE
7.20.6.2 div, ldiv, lldiv: DONE
! 7.20.7 Multibyte/wide character conversion functions: TODO

45
src/libc/stdlib/qsort.c Normal file
View File

@ -0,0 +1,45 @@
#include <stdlib.h>
#include <string.h>
typedef int comp_func(void const *left, void const *right);
static int partition(void *base, size_t size, comp_func *compare,
int low, int high)
{
#define AT(n) (base + size * (n))
__attribute__((aligned(4))) char tmp[size], pivot[size];
memcpy(pivot, AT((low + high) >> 1), size);
int i = low - 1;
int j = high + 1;
while(1) {
do i++;
while(compare(AT(i), pivot) < 0);
do j--;
while(compare(AT(j), pivot) > 0);
if(i >= j) return j;
memcpy(tmp, AT(i), size);
memcpy(AT(i), AT(j), size);
memcpy(AT(j), tmp, size);
}
}
static void sort(void *base, size_t size, comp_func *compare,
int low, int high)
{
if(low >= high) return;
int p = partition(base, size, compare, low, high);
sort(base, size, compare, low, p);
sort(base, size, compare, p+1, high);
}
void qsort(void *base, size_t n, size_t size, comp_func *compare)
{
sort(base, size, compare, 0, n-1);
}