libluna: Add a sort() function
This commit is contained in:
parent
6beea7f817
commit
dcd93cce3a
@ -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
|
||||
|
26
libluna/include/luna/Sort.h
Normal file
26
libluna/include/luna/Sort.h
Normal 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
53
libluna/src/Sort.cpp
Normal 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);
|
||||
}
|
Loading…
Reference in New Issue
Block a user