diff --git a/.vscode/settings.json b/.vscode/settings.json index 672190d..4cd077c 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,6 +1,76 @@ { "C_Cpp.default.compilerPath": "/usr/bin/gcc", "files.associations": { - "span": "cpp" + "span": "cpp", + "any": "cpp", + "array": "cpp", + "atomic": "cpp", + "bit": "cpp", + "cctype": "cpp", + "charconv": "cpp", + "chrono": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "codecvt": "cpp", + "compare": "cpp", + "concepts": "cpp", + "condition_variable": "cpp", + "cstdarg": "cpp", + "cstddef": "cpp", + "cstdint": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cstring": "cpp", + "ctime": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "deque": "cpp", + "list": "cpp", + "map": "cpp", + "set": "cpp", + "string": "cpp", + "unordered_map": "cpp", + "unordered_set": "cpp", + "vector": "cpp", + "exception": "cpp", + "algorithm": "cpp", + "functional": "cpp", + "iterator": "cpp", + "memory": "cpp", + "memory_resource": "cpp", + "numeric": "cpp", + "optional": "cpp", + "random": "cpp", + "ratio": "cpp", + "string_view": "cpp", + "system_error": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "utility": "cpp", + "format": "cpp", + "fstream": "cpp", + "initializer_list": "cpp", + "iomanip": "cpp", + "iosfwd": "cpp", + "iostream": "cpp", + "istream": "cpp", + "limits": "cpp", + "mutex": "cpp", + "new": "cpp", + "numbers": "cpp", + "ostream": "cpp", + "queue": "cpp", + "ranges": "cpp", + "semaphore": "cpp", + "sstream": "cpp", + "stdexcept": "cpp", + "stdfloat": "cpp", + "stop_token": "cpp", + "streambuf": "cpp", + "text_encoding": "cpp", + "thread": "cpp", + "cinttypes": "cpp", + "typeinfo": "cpp", + "variant": "cpp" } } \ No newline at end of file diff --git a/result.txt b/result.txt deleted file mode 100644 index 7cdbe28..0000000 --- a/result.txt +++ /dev/null @@ -1,6 +0,0 @@ -RESULT name=sort n=100 t=1 iterations=1530 durationNanoseconds=653 totalDurationNanoseconds=1000022 constructorNanoseconds=233 totalConstructorNanoseconds=356900 -RESULT name=sort n=1000 t=1 iterations=76 durationNanoseconds=13288 totalDurationNanoseconds=1009961 constructorNanoseconds=598 totalConstructorNanoseconds=45480 -RESULT name=sort n=10001 t=1 iterations=3 durationNanoseconds=465803 totalDurationNanoseconds=1397411 constructorNanoseconds=26923 totalConstructorNanoseconds=80770 -RESULT name=sort n=100000 t=1 iterations=1 durationNanoseconds=6197415 totalDurationNanoseconds=6197415 constructorNanoseconds=790010 totalConstructorNanoseconds=790010 -RESULT name=sort n=999999 t=1 iterations=1 durationNanoseconds=67456368 totalDurationNanoseconds=67456368 constructorNanoseconds=5975124 totalConstructorNanoseconds=5975124 -RESULT name=sort n=10000000 t=1 iterations=1 durationNanoseconds=756668481 totalDurationNanoseconds=756668481 constructorNanoseconds=55741740 totalConstructorNanoseconds=55741740 diff --git a/src/sorter.cpp b/src/sorter.cpp index 9ef5d00..4c33d60 100755 --- a/src/sorter.cpp +++ b/src/sorter.cpp @@ -2,6 +2,8 @@ #include #include +#include +#include namespace ae { @@ -11,11 +13,17 @@ void sorter::sort(container& data) { std::ranges::copy(data.placeholder_[i], std::back_inserter(data.placeholder_[0])); data.placeholder_[i].clear(); } - std::ranges::sort(data.placeholder_[0]); + sorter::msd_inplace_radix_sort(data.placeholder_[0], 0, [&](auto span) {sorter::robin_hood_sort(span);}); } -void sorter::msd_inplace_radix_sort(std::span range, size_t passes, size_t digit) { - if (digit == passes) { +void sorter::msd_inplace_radix_sort( + std::span range, + size_t passes, + const std::function bucket)>& bucket_sort +) { + std::cerr << "passes: " << passes << std::endl; + if (sorter::RADIX_ITERATIONS == passes) { + bucket_sort(range); return; } @@ -23,12 +31,57 @@ void sorter::msd_inplace_radix_sort(std::span range, si auto upper = std::end(range); for (auto element = lower; element < std::end(range);) { - // Mask out the -last bit and check if it is set - if ((*element & (1uz << sizeof(container::element_type) * 8 - digit))) { - + std::cerr << *element << " " << &*element << " " << &*lower << " " << &*upper << std::endl; + // Mask out the -last bit and check if it is set + if ((*element & (1uz << sizeof(container::element_type) * 8 - passes))) { + // The bit is set, so move to the beginning of the end section and decrement the upper iterator + std::swap(upper, element); + --upper; } else { - + // The bit is unset, so move to the end of the beginning section and increment the upper iterator + std::swap(lower, element); + ++lower; } + if (element < lower) { + ++element; + } else if (element > upper) { + --element; + } + } + assert(lower == upper); + sorter::msd_inplace_radix_sort(std::span (std::begin(range), lower), passes + 1, bucket_sort); + sorter::msd_inplace_radix_sort(std::span (upper, std::end(range)), passes + 1, bucket_sort); +} + +void sorter::robin_hood_sort(std::span bucket) { + const auto size = bucket.size() + sorter::OVERHEAD_SIZE; + const size_t mask = ~(-1 >> sorter::RADIX_ITERATIONS); + container::element_type space[size]; + + for (auto element : bucket) { + auto masked_element = (element & mask); + auto index = masked_element * size/ mask; + if (space[index] == -1) { + space[index] = masked_element; + } else { + auto i = index; + while (i < size && space[index] != -1) {++i;}; + space[i] = masked_element; + } + } + + // 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]); + } + } + + // copy data back into original range + auto i = 0; + for (auto element = std::begin(bucket); element < std::end(bucket); ++element) { + *element = space[i]; } } diff --git a/src/sorter.hpp b/src/sorter.hpp index b2d4268..d8096d9 100755 --- a/src/sorter.hpp +++ b/src/sorter.hpp @@ -1,6 +1,7 @@ #pragma once #include "container.hpp" +#include "functional" namespace ae { @@ -9,7 +10,16 @@ class sorter { void sort(container& data); // TODO You may add additional functions or data members to the sorter. - void msd_inplace_radix_sort(std::span range, size_t passes, size_t digit = 0); + void msd_inplace_radix_sort( + std::span range, + size_t passes, + const std::function bucket)>& bucket_sort + ); + + const size_t OVERHEAD_SIZE = 100L; + const size_t RADIX_ITERATIONS = 32; + + void robin_hood_sort(std::span range); }; } // namespace ae