libluna: Add a sort() function

This commit is contained in:
apio 2023-05-02 20:42:48 +02:00
parent 6beea7f817
commit dcd93cce3a
Signed by: apio
GPG Key ID: B8A7D06E42258954
3 changed files with 80 additions and 0 deletions

View File

@ -5,6 +5,7 @@ file(GLOB HEADERS include/luna/*.h)
set(FREESTANDING_SOURCES
${HEADERS}
src/Format.cpp
src/Sort.cpp
src/NumberParsing.cpp
src/CString.cpp
src/CPath.cpp

View File

@ -0,0 +1,26 @@
#pragma once
#include <luna/Types.h>
typedef int (*compar_t)(const void*, const void*);
void c_quicksort(void* base, usize nmemb, usize size, compar_t compar);
template <typename T> void sort(T* base, usize nmemb, int (*compar)(const T*, const T*))
{
return c_quicksort(base, nmemb, sizeof(T), (compar_t)compar);
}
template <typename T> void sort(T* base, usize nmemb, compar_t compar)
{
return c_quicksort(base, nmemb, sizeof(T), compar);
}
template <typename T> void sort(T* begin, T* end, int (*compar)(const T*, const T*))
{
return c_quicksort(begin, end - begin, sizeof(T), (compar_t)compar);
}
template <typename T> void sort(T* begin, T* end, compar_t compar)
{
return c_quicksort(begin, end - begin, sizeof(T), compar);
}

53
libluna/src/Sort.cpp Normal file
View File

@ -0,0 +1,53 @@
#include <luna/Alignment.h>
#include <luna/Sort.h>
static void swap_sized(void* ptr1, void* ptr2, usize size)
{
char* x = (char*)ptr1;
char* y = (char*)ptr2;
while (size--)
{
char t = *x;
*x = *y;
*y = t;
x += 1;
y += 1;
}
}
static usize partition(void* base, usize start, usize end, usize size, compar_t compar)
{
auto atindex = [&base, &size](usize index) { return offset_ptr(base, index * size); };
void* pivot = atindex(end);
usize i = (start - 1);
for (usize j = start; j <= end - 1; j++)
{
if (compar(atindex(j), pivot) < 0)
{
i++;
swap_sized(atindex(i), atindex(j), size);
}
}
swap_sized(atindex(i + 1), pivot, size);
return i + 1;
}
static void quicksort_impl(void* base, usize start, usize end, usize size, compar_t compar)
{
if (start < end)
{
usize pivot = partition(base, start, end, size, compar);
if ((end - start) < 2) return;
quicksort_impl(base, start, pivot - 1, size, compar);
quicksort_impl(base, pivot + 1, end, size, compar);
}
}
void c_quicksort(void* base, usize nmemb, usize size, compar_t compar)
{
quicksort_impl(base, 0, nmemb - 1, size, compar);
}