Implement reverse in radix sort, fix style, fix build

This commit is contained in:
g-arslan 2020-05-18 16:13:59 +03:00
parent 95668def24
commit c01a7ef0e2
2 changed files with 20 additions and 14 deletions

View File

@ -124,10 +124,11 @@ namespace
}
template <typename T>
void inplacePartialSwapHelper(T& arr, size_t bound, bool reverse) {
void inplacePartialSwapHelper(T& arr, size_t bound)
{
std::reverse(std::begin(arr), std::begin(arr) + bound);
std::reverse(std::begin(arr) + bound, std::end(arr));
if (!reverse) std::reverse(std::begin(arr), std::end(arr));
std::reverse(std::begin(arr), std::end(arr));
}
template <typename T>
@ -188,28 +189,27 @@ void ColumnVector<T>::getPermutation(bool reverse, size_t limit, int nan_directi
for (UInt32 i = 0; i < UInt32(s); ++i)
pairs[i] = {data[i], i};
RadixSort<RadixSortTraits<T>>::executeLSD(pairs.data(), s, res.data());
RadixSort<RadixSortTraits<T>>::executeLSD(pairs.data(), s, reverse, res.data());
/// Radix sort treats all NaNs to be greater than all numbers.
/// If the user needs the opposite, we must move them accordingly.
size_t nans_to_move = 0;
if (std::is_floating_point_v<T> && nan_direction_hint < 0)
{
for (ssize_t i = s - 1; i >= 0; --i)
size_t nans_to_move = 0;
for (size_t i = 0; i < s; ++i)
{
if (isNaN(data[res[i]]))
if (isNaN(data[res[reverse ? i : s - 1 - i]]))
++nans_to_move;
else
break;
}
}
if (nans_to_move) {
inplacePartialSwapHelper(res, s - nans_to_move, reverse);
} else if (reverse) {
std::reverse(std::begin(res), std::end(res));
if (nans_to_move)
{
inplacePartialSwapHelper(res, reverse ? nans_to_move : s - nans_to_move);
}
}
return;
}
}

View File

@ -313,7 +313,7 @@ private:
public:
/// Least significant digit radix sort (stable)
static void executeLSD(Element * arr, size_t size, Index * destination = NULL)
static void executeLSD(Element * arr, size_t size, bool reverse = false, Index * destination = nullptr)
{
/// If the array is smaller than 256, then it is better to use another algorithm.
@ -386,13 +386,19 @@ public:
size_t pos = getPart(pass, keyToBits(Traits::extractKey(reader[i])));
/// Place the element on the next free position.
writer[++histograms[pass * HISTOGRAM_SIZE + pos]] = Traits::extractIndex(reader[i]);
if (reverse)
writer[size - 1 - (++histograms[pass * HISTOGRAM_SIZE + pos])] = Traits::extractIndex(reader[i]);
else
writer[++histograms[pass * HISTOGRAM_SIZE + pos]] = Traits::extractIndex(reader[i]);
}
} else if (NUM_PASSES % 2)
{
/// If the number of passes is odd, the result array is in a temporary buffer. Copy it to the place of the original array.
/// NOTE Sometimes it will be more optimal to provide non-destructive interface, that will not modify original array.
memcpy(arr, swap_buffer, size * sizeof(Element));
} else if (reverse)
{
std::reverse(arr, arr + size);
}
allocator.deallocate(swap_buffer, size * sizeof(Element));