2025-07-28 22:25:26 +02:00
|
|
|
#include "sorter.hpp"
|
|
|
|
|
|
|
|
|
|
#include <algorithm>
|
|
|
|
|
#include <iterator>
|
2025-07-29 21:45:53 +02:00
|
|
|
#include <cassert>
|
|
|
|
|
#include <iostream>
|
2025-07-30 15:05:52 +02:00
|
|
|
#include <bitset>
|
|
|
|
|
#include <climits>
|
2025-07-28 22:25:26 +02:00
|
|
|
|
|
|
|
|
namespace ae {
|
|
|
|
|
|
|
|
|
|
void sorter::sort(container& data) {
|
|
|
|
|
// TODO Implement your sorting algorithm
|
|
|
|
|
for (auto i = 1uz; i < data.placeholder_.size(); ++i) {
|
|
|
|
|
std::ranges::copy(data.placeholder_[i], std::back_inserter(data.placeholder_[0]));
|
|
|
|
|
data.placeholder_[i].clear();
|
|
|
|
|
}
|
2025-07-29 21:45:53 +02:00
|
|
|
sorter::msd_inplace_radix_sort(data.placeholder_[0], 0, [&](auto span) {sorter::robin_hood_sort(span);});
|
2025-07-28 22:25:26 +02:00
|
|
|
}
|
|
|
|
|
|
2025-07-29 21:45:53 +02:00
|
|
|
void sorter::msd_inplace_radix_sort(
|
|
|
|
|
std::span<container::element_type> range,
|
|
|
|
|
size_t passes,
|
|
|
|
|
const std::function<void(std::span<container::element_type> bucket)>& bucket_sort
|
|
|
|
|
) {
|
2025-07-30 15:05:52 +02:00
|
|
|
std::cerr << "passes: " << passes << "size: " << range.size() << std::endl;
|
2025-07-29 21:45:53 +02:00
|
|
|
if (sorter::RADIX_ITERATIONS == passes) {
|
2025-07-30 15:05:52 +02:00
|
|
|
std::cerr << "going to robin " << *std::begin(range) << std::endl;
|
|
|
|
|
if (std::begin(range) + 1 < std::end(range)) {
|
|
|
|
|
bucket_sort(range);
|
|
|
|
|
}
|
2025-07-28 22:25:26 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto lower = std::begin(range);
|
|
|
|
|
auto upper = std::end(range);
|
|
|
|
|
|
2025-07-30 15:05:52 +02:00
|
|
|
for (auto element = lower; element < upper;) {
|
2025-07-29 21:45:53 +02:00
|
|
|
std::cerr << *element << " " << &*element << " " << &*lower << " " << &*upper << std::endl;
|
|
|
|
|
// Mask out the <sorter::RADIX_ITERATIONS>-last bit and check if it is set
|
2025-07-30 15:05:52 +02:00
|
|
|
// std::cerr << std::bitset<64>((1L << (sizeof(container::element_type) * CHAR_BIT - passes - 1))) << std::endl;
|
|
|
|
|
// fprintf(stderr, "%lx\n", (1L << (sizeof(container::element_type) * CHAR_BIT - passes - 1)));
|
|
|
|
|
if ((*element & (1L << (sizeof(container::element_type) * CHAR_BIT - passes - 1)))) {
|
2025-07-29 21:45:53 +02:00
|
|
|
// The <passes> bit is set, so move to the beginning of the end section and decrement the upper iterator
|
2025-07-30 15:05:52 +02:00
|
|
|
std::swap(*upper, *element);
|
2025-07-29 21:45:53 +02:00
|
|
|
--upper;
|
|
|
|
|
} else {
|
|
|
|
|
// The <passes> bit is unset, so move to the end of the beginning section and increment the upper iterator
|
2025-07-30 15:05:52 +02:00
|
|
|
std::swap(*lower, *element);
|
2025-07-29 21:45:53 +02:00
|
|
|
++lower;
|
|
|
|
|
++element;
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-07-30 15:05:52 +02:00
|
|
|
// assert(lower == upper);
|
2025-07-29 21:45:53 +02:00
|
|
|
sorter::msd_inplace_radix_sort(std::span<container::element_type> (std::begin(range), lower), passes + 1, bucket_sort);
|
|
|
|
|
sorter::msd_inplace_radix_sort(std::span<container::element_type> (upper, std::end(range)), passes + 1, bucket_sort);
|
|
|
|
|
}
|
|
|
|
|
void sorter::robin_hood_sort(std::span<container::element_type> bucket) {
|
2025-07-30 15:05:52 +02:00
|
|
|
std::cerr << "robin hood lol" << std::endl;
|
2025-07-29 21:45:53 +02:00
|
|
|
const auto size = bucket.size() + sorter::OVERHEAD_SIZE;
|
2025-07-30 15:05:52 +02:00
|
|
|
const auto mask = ((1L) << (sizeof(container::element_type) * CHAR_BIT - sorter::RADIX_ITERATIONS)) - 1;
|
2025-07-29 21:45:53 +02:00
|
|
|
container::element_type space[size];
|
2025-07-30 15:05:52 +02:00
|
|
|
std::cerr << "robin hood before loop" << std::endl;
|
2025-07-29 21:45:53 +02:00
|
|
|
for (auto element : bucket) {
|
|
|
|
|
auto masked_element = (element & mask);
|
2025-07-30 15:05:52 +02:00
|
|
|
std::cerr << "robin hood elements " << element << " " << masked_element << " " << size << " " << mask << std::endl;
|
|
|
|
|
auto index = (masked_element * size) / mask;
|
|
|
|
|
std::cerr << "robin hood index " << index << " " << size << std::endl;
|
2025-07-29 21:45:53 +02:00
|
|
|
if (space[index] == -1) {
|
|
|
|
|
space[index] = masked_element;
|
2025-07-28 22:25:26 +02:00
|
|
|
} else {
|
2025-07-29 21:45:53 +02:00
|
|
|
auto i = index;
|
|
|
|
|
while (i < size && space[index] != -1) {++i;};
|
|
|
|
|
space[i] = masked_element;
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-07-30 15:05:52 +02:00
|
|
|
std::cerr << "robin hood after loop" << std::endl;
|
2025-07-28 22:25:26 +02:00
|
|
|
|
2025-07-29 21:45:53 +02:00
|
|
|
// One final pass to correct linear probing errors
|
|
|
|
|
for (auto i = 1; i < size; ++i) {
|
|
|
|
|
auto j = i;
|
|
|
|
|
while (space[j-1] > space[j] && j > 0) {
|
|
|
|
|
std::swap((space[j]),space[j-1]);
|
2025-07-28 22:25:26 +02:00
|
|
|
}
|
|
|
|
|
}
|
2025-07-29 21:45:53 +02:00
|
|
|
|
|
|
|
|
// copy data back into original range
|
|
|
|
|
auto i = 0;
|
|
|
|
|
for (auto element = std::begin(bucket); element < std::end(bucket); ++element) {
|
|
|
|
|
*element = space[i];
|
|
|
|
|
}
|
2025-07-28 22:25:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace ae
|