LibC: Implement qsort_r
This is not really required by anything but i've seen few ports optionally use it if available. This was trivial to implement so why not add it :^)
This commit is contained in:
@@ -84,6 +84,7 @@ int posix_openpt(int oflag);
|
|||||||
char* ptsname(int fildes);
|
char* ptsname(int fildes);
|
||||||
int putenv(char* string);
|
int putenv(char* string);
|
||||||
void qsort(void* base, size_t nel, size_t width, int (*compar)(const void*, const void*));
|
void qsort(void* base, size_t nel, size_t width, int (*compar)(const void*, const void*));
|
||||||
|
void qsort_r(void* base, size_t nel, size_t width, int (*compar)(const void*, const void*, void*), void* arg);
|
||||||
int rand(void);
|
int rand(void);
|
||||||
int rand_r(unsigned* seed);
|
int rand_r(unsigned* seed);
|
||||||
long random(void);
|
long random(void);
|
||||||
|
|||||||
@@ -566,7 +566,8 @@ struct qsort_pair
|
|||||||
uint8_t* gt;
|
uint8_t* gt;
|
||||||
};
|
};
|
||||||
|
|
||||||
static qsort_pair qsort_partition(uint8_t* pbegin, uint8_t* pend, size_t width, int (*compar)(const void*, const void*))
|
template<typename... Args>
|
||||||
|
static qsort_pair qsort_partition(uint8_t* pbegin, uint8_t* pend, size_t width, int (*compar)(const void*, const void*, Args...), Args... args)
|
||||||
{
|
{
|
||||||
uint8_t* pivot = pbegin + (pend - pbegin) / width / 2 * width;
|
uint8_t* pivot = pbegin + (pend - pbegin) / width / 2 * width;
|
||||||
|
|
||||||
@@ -576,7 +577,7 @@ static qsort_pair qsort_partition(uint8_t* pbegin, uint8_t* pend, size_t width,
|
|||||||
|
|
||||||
while (eq < gt)
|
while (eq < gt)
|
||||||
{
|
{
|
||||||
const int comp = (eq == pivot) ? 0 : compar(eq, pivot);
|
const int comp = (eq == pivot) ? 0 : compar(eq, pivot, args...);
|
||||||
|
|
||||||
if (comp < 0)
|
if (comp < 0)
|
||||||
{
|
{
|
||||||
@@ -602,13 +603,14 @@ static qsort_pair qsort_partition(uint8_t* pbegin, uint8_t* pend, size_t width,
|
|||||||
return { lt, gt };
|
return { lt, gt };
|
||||||
}
|
}
|
||||||
|
|
||||||
static void qsort_impl(uint8_t* pbegin, uint8_t* pend, size_t width, int (*compar)(const void*, const void*))
|
template<typename... Args>
|
||||||
|
static void qsort_impl(uint8_t* pbegin, uint8_t* pend, size_t width, int (*compar)(const void*, const void*, Args...), Args... args)
|
||||||
{
|
{
|
||||||
if (pbegin + width >= pend)
|
if (pbegin + width >= pend)
|
||||||
return;
|
return;
|
||||||
auto [lt, gt] = qsort_partition(pbegin, pend, width, compar);
|
auto [lt, gt] = qsort_partition(pbegin, pend, width, compar, args...);
|
||||||
qsort_impl(pbegin, lt, width, compar);
|
qsort_impl(pbegin, lt, width, compar, args...);
|
||||||
qsort_impl(gt, pend, width, compar);
|
qsort_impl(gt, pend, width, compar, args...);
|
||||||
}
|
}
|
||||||
|
|
||||||
void qsort(void* base, size_t nel, size_t width, int (*compar)(const void*, const void*))
|
void qsort(void* base, size_t nel, size_t width, int (*compar)(const void*, const void*))
|
||||||
@@ -619,6 +621,14 @@ void qsort(void* base, size_t nel, size_t width, int (*compar)(const void*, cons
|
|||||||
qsort_impl(pbegin, pbegin + nel * width, width, compar);
|
qsort_impl(pbegin, pbegin + nel * width, width, compar);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void qsort_r(void* base, size_t nel, size_t width, int (*compar)(const void*, const void*, void*), void* arg)
|
||||||
|
{
|
||||||
|
if (width == 0 || nel <= 1)
|
||||||
|
return;
|
||||||
|
uint8_t* pbegin = static_cast<uint8_t*>(base);
|
||||||
|
qsort_impl(pbegin, pbegin + nel * width, width, compar, arg);
|
||||||
|
}
|
||||||
|
|
||||||
// Constants and algorithm from https://en.wikipedia.org/wiki/Permuted_congruential_generator
|
// Constants and algorithm from https://en.wikipedia.org/wiki/Permuted_congruential_generator
|
||||||
|
|
||||||
static constexpr uint64_t s_rand_multiplier = 6364136223846793005;
|
static constexpr uint64_t s_rand_multiplier = 6364136223846793005;
|
||||||
|
|||||||
Reference in New Issue
Block a user