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:
parent
b1ab4f2f87
commit
36ea38940b
@ -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);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user