diff --git a/qsort.h b/qsort.h index 177e9b4..dc32535 100644 --- a/qsort.h +++ b/qsort.h @@ -102,12 +102,16 @@ static inline pret3 partition3(uint32_t array[], int low, int high, uint32_t piv /* index until smaller or eq elements lay */ int i = (low - 1); + uint32_t pc = 0; /* traverse each element of the array */ /* compare them with the pivot */ #pragma GCC unroll 4 - for (int j = low; j < high; ++j) { - if (array[j] < pivot) { + for (int j = low; j <= high; ++j) { + /* Branchless pivot-count */ + pc += (array[j] == pivot); + + if(array[j] < pivot) { /* if element smaller than pivot is found */ /* swap it with the greater element pointed by i */ ++i; @@ -117,6 +121,14 @@ static inline pret3 partition3(uint32_t array[], int low, int high, uint32_t piv } } + /* Can spare out the second loop in these cases */ + if(pc < 2) { + pret3 ret; + ret.leftend = i; + ret.rightend = i + 1; + return ret; + } + /* index until smaller or eq elements lay */ int i2 = (high + 1); diff --git a/zssort.h b/zssort.h index 5386ac4..4ef2029 100644 --- a/zssort.h +++ b/zssort.h @@ -37,7 +37,7 @@ static inline void zssort(uint32_t array[], int low, int high) { } } -/* ZSSORT */ +/* ZSSORTR */ /** Always at most log(n) space needing randomized quicksort variant */ static inline void zssort_rand(uint32_t array[], int low, int high, rpivotstate *state) { @@ -63,6 +63,32 @@ static inline void zssort_rand(uint32_t array[], int low, int high, rpivotstate } } +/* THREEWAY_ZS */ + +/** Always at most log(n) space needing randomized quicksort variant */ +static inline void zssort_rand3(uint32_t array[], int low, int high, rpivotstate *state) { + while (low < high) { + int pi = pick_pivot(state, (high + 1) - low) + low; + pret3 res = partition3(array, low, high, array[pi]); + + /* If we recurse only the smaller part */ + /* That ensures at most n/2 elements can */ + /* be on any given level of the recursion */ + /* tree: that is we ensure log2(N) memuse! */ + if((res.leftend - low) < (high - res.rightend)) { + // Left smaller: recurse left of pivot + zssort_rand3(array, low, res.leftend, state); + // (*) Update partitioning loop for remaining part + low = res.rightend; + } else { + // Right smaller: recurse right of pivot + zssort_rand3(array, res.rightend, high, state); + // (*) Update partitioning loop for remaining part + high = res.leftend; /* high inclusive! */ + } + } +} + /* ZSSORTC */ /** Always at most log(n) space needing randomized quicksort variant - with checking for sameconst-arrays */