in-place algorithm and fix of perf bug where we not early exited in spsort after insertion sorting small buckets so they were sorted again by us too :-)

This commit is contained in:
Richard Thier 2022-08-16 18:06:46 +02:00
parent b1ab4f2f87
commit 36ea38940b

View File

@ -134,55 +134,39 @@ inline void spsort(uint32_t *t, int n, int m = 32);
/** Helper function that puts elements higher then mid to the top of the array and lower to the bottom. Returns number of bottoms */
inline int internal_array_separate(uint32_t *t, int n, uint32_t mid) {
/*
// Init left-right "write head" indices
int left = 0;
int right = n - 1;
uint32_t current = t[left];
bool current_is_left = true;
// Separate to the ends of the array (in-place)
for(int i = 0; i < n; ++i) {
if(current < mid) {
const auto tmp = t[left];
t[left++] = current;
current = current_is_left ? t[left] : tmp;
current_is_left = true;
} else {
const auto tmp = t[right];
t[right--] = current;
current = tmp;
current = !current_is_left ? t[right] : tmp;
current_is_left = false;
if(n > 0) {
// Two heads that also read & write (both)
int left = 0;
int right = n - 1;
while(left < right) {
bool lok = (t[left] < mid);
bool rok = (t[right] >= mid);
if(lok || rok) {
// HOT PATH
// Move heads until both in wrong location
left += lok;
right -= rok;
} else {
// REGULAR PATH
// Both in wrong location - xchg them!
auto tmp = t[right];
t[right] = t[left];
t[left] = tmp;
++left;
--right;
}
}
// Edge-case increment if single elem happens in middle in the end
left += ((left == right) && (t[left] < mid));
return left;
}
return left;
*/
// FIXME: bad quality debug code to remove
std::vector<uint32_t> v(n);
int left = 0;
int right = n - 1;
auto current = t[0];
for(int i = 0; i < n; ++i) {
if(current < mid) {
v[left++] = current;
current = t[i + 1];
} else {
v[right--] = current;
current = t[i + 1];
}
}
for(int i = 0; i < n; ++i) {
t[i] = v[i];
}
return left;
return 0;
}
// TODO: [spsort] In-place variant that looks like a quicksort-kind-of-thing:
// ALGO: [spsort] In-place variant that looks like a quicksort-kind-of-thing:
// - I realized that in-placing make this similar to quicksort actually
// - We check if the thing is small enough for insertion sorting in-place
// - If not, we calculate low-mid-high
@ -205,6 +189,7 @@ inline void internal_spsort(uint32_t *t, int n, int m, uint32_t low, uint32_t mi
// Makes small arrays sort fast otherwise we need to go down m == 2 or such!
if(n < m) {
binsertion_sort(t, n);
return;
}
auto left = internal_array_separate(t, n, mid);