inplace quicksort fixes - but thier_apply seems like not doing anything?

This commit is contained in:
Richard Thier 2023-07-01 03:48:42 +02:00
parent 79b95bf905
commit 873c17f658

View File

@ -421,17 +421,17 @@ static inline void thiersort_apply(
TSU32 elemsize, TSU32 elemsize,
void *tmp, void *tmp,
void (*free)(void *ptr)) { void (*free)(void *ptr)) {
// Replace all positions /* Replace all positions */
for(TSU32 i = 0; i < length; ++i) { for(TSU32 i = 0; i < length; ++i) {
// Replace the whole chain starting at i (j for chain index) /* Replace the whole chain starting at i (j for chain index) */
// This works because we can easily check what does'nt need moves anymore. /* This works because we can easily check what does'nt need moves anymore. */
TSU32 j = i; TSU32 j = i;
TSU32 ni = sortres[j].i; TSU32 ni = sortres[j].i;
// Until would move to its own position, chain /* Until would move to its own position, chain */
// This also solves "already at right place" originals. /* This also solves "already at right place" originals. */
while(ni != j) { while(ni != j) {
// xchg j and ni /* xchg j and ni */
memcpy(tmp, &((TSU8*)arr)[(size_t)j * elemsize], elemsize); memcpy(tmp, &((TSU8*)arr)[(size_t)j * elemsize], elemsize);
memcpy( memcpy(
&((TSU8*)arr)[(size_t)j * elemsize], &((TSU8*)arr)[(size_t)j * elemsize],
@ -439,14 +439,14 @@ static inline void thiersort_apply(
elemsize); elemsize);
memcpy(&((TSU8*)arr)[(size_t)ni * elemsize], tmp, elemsize); memcpy(&((TSU8*)arr)[(size_t)ni * elemsize], tmp, elemsize);
// Mark j index as done in sortres for outer loop. /* Mark j index as done in sortres for outer loop. */
// This is necessary for inner loop stopping early /* This is necessary for inner loop stopping early */
// and outer catch up on already processed location. /* and outer catch up on already processed location. */
sortres[j].i = j; sortres[j].i = j;
// Update j and ni /* Update j and ni */
// Now we must find what should be at new location j /* Now we must find what should be at new location j */
// instead of what we swap in there from old j loc. /* instead of what we swap in there from old j loc. */
j = ni; j = ni;
ni = sortres[j].i; ni = sortres[j].i;
} }
@ -518,7 +518,8 @@ static inline TSU8 ts_radixi(
return ts_floatsigntrick((TSU8)k.u); return ts_floatsigntrick((TSU8)k.u);
} }
assert(false); // should never happen /* Should never happen */
assert(false);
} }
/** Simple inplace quicksort for tselems */ /** Simple inplace quicksort for tselems */
@ -533,8 +534,10 @@ static inline void ts_quicksort_inplace(
const TSU32 bi, const TSU32 bi,
void *reent_data), void *reent_data),
void *reent_data) { void *reent_data) {
// Must do this early exit! /* Must do this early exit! */
if(from >= to) return; // TODO: TS_UNLIKELY
if(to == 0) return;
if(from >= to - 1) return;
TSU32 len = (to - from); TSU32 len = (to - from);
TSU32 mid = from + len / 2; TSU32 mid = from + len / 2;
@ -544,7 +547,7 @@ static inline void ts_quicksort_inplace(
TSU32 left = from; TSU32 left = from;
TSU32 right = to - 1; TSU32 right = to - 1;
while(left < right) { while(left < right) {
// Step over rightly positioned elems from left /* Step over rightly positioned elems from left */
union tskey leftkey = arr[left].key; union tskey leftkey = arr[left].key;
TSU32 lefti = arr[left].i; TSU32 lefti = arr[left].i;
while((left < right) && lt(leftkey, pivotkey, lefti, pivoti, reent_data)) { while((left < right) && lt(leftkey, pivotkey, lefti, pivoti, reent_data)) {
@ -553,16 +556,16 @@ static inline void ts_quicksort_inplace(
lefti = arr[left].i; lefti = arr[left].i;
} }
// Step over rightly positioned elems from right /* Step over rightly positioned elems from right */
union tskey rightkey = arr[right].key; union tskey rightkey = arr[right].key;
TSU32 righti = arr[right].i; TSU32 righti = arr[right].i;
while((left < right) && lt(pivotkey, rightkey, pivoti, righti, reent_data)) { while((left < right) && !lt(rightkey, pivotkey, righti, pivoti, reent_data)) {
--right; --right;
rightkey = arr[right].key; rightkey = arr[right].key;
righti = arr[right].i; righti = arr[right].i;
} }
// Swap wrongly positioned element /* Swap wrongly positioned element */
if(left < right) { if(left < right) {
const struct tselem tmp = arr[left]; const struct tselem tmp = arr[left];
arr[left] = arr[right]; arr[left] = arr[right];
@ -579,9 +582,31 @@ static inline void ts_quicksort_inplace(
left += (lt(leftkey, pivotkey, lefti, pivoti, reent_data)); left += (lt(leftkey, pivotkey, lefti, pivoti, reent_data));
} }
/* Just simple recursion for now */ /* Check edge-case when left got empty. */
ts_quicksort_inplace(arr, from, left, lt, reent_data); /* Rem.: Right moves over the pivot invariably as left cannot pass over if! */
ts_quicksort_inplace(arr, left, to, lt, reent_data); /* This means that right subset can never be empty, but left can! */
/* This also means that if left is empty, all invariants were just */
/* stepped over (from right) and not moved from its original position! */
// TODO: TS_UNLIKELY
if(from < left) {
/** Good case: Somewhere cutting the array in around half */
ts_quicksort_inplace(arr, from, left, lt, reent_data);
ts_quicksort_inplace(arr, left, to, lt, reent_data);
} else {
/* Left sub-array got to be empty - but to step with recursion */
/* we need to shrink sizes, which is possible by moving the pivot */
/* to the start of the right (because we know its a minimal elem!) */
/* XXX: If we collect up all pivots, we can move all here if want.. */
/* Swap */
const struct tselem tmp = arr[left];
arr[left] = arr[mid];
arr[mid] = tmp;
/* Bad case: could shrink the array by one element only */
ts_quicksort_inplace(arr, left + 1, to, lt, reent_data);
}
} }
/** /**
@ -601,7 +626,7 @@ static inline void ts_quicksort_fromto(
const TSU32 bi, const TSU32 bi,
void *reent_data), void *reent_data),
void *reent_data) { void *reent_data) {
// Must do this early exit! // FIXME: Code is rotten here - see above variant pls!
if(from >= to) return; if(from >= to) return;
TSU32 len = (to - from); TSU32 len = (to - from);
@ -650,7 +675,7 @@ static inline void thiersort8_internal(
/* Step 1) Bucketing */ /* Step 1) Bucketing */
#ifdef TS_SSE2 #ifdef TS_SSE2
// TODO: implement with SSE2 /* TODO: implement with SSE2 */
#else #else
/* TODO: We can go both down and upwards here to increase ILP! */ /* TODO: We can go both down and upwards here to increase ILP! */
/* Occurence counting O(n) */ /* Occurence counting O(n) */