This can be nice if user has memory for a the temporary buffer and doesnt want the sorting to allocate or be able to fail. Also counts are now stack allocated, there isn't really any reason to allocate them on the heap as 256x 64 bit values only adds up to 2 KiB
104 lines
3.4 KiB
C++
104 lines
3.4 KiB
C++
#include <BAN/Vector.h>
|
|
#include <BAN/Sort.h>
|
|
|
|
#include <inttypes.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
template<typename T>
|
|
bool is_sorted(BAN::Vector<T>& vec)
|
|
{
|
|
for (size_t i = 0; i < vec.size() - 1; i++)
|
|
if (vec[i] > vec[i + 1])
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
#define CURRENT_NS() ({ timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); ts.tv_sec * 1'000'000'000 + ts.tv_nsec; })
|
|
|
|
#define TEST_ALGORITHM(ms, function) do { \
|
|
uint64_t duration_us = 0; \
|
|
printf(#function "\n"); \
|
|
for (size_t size = 100; duration_us < ms * 1000; size *= 10) { \
|
|
BAN::Vector<unsigned> data(size, 0); \
|
|
for (auto& val : data) \
|
|
val = rand() % 100; \
|
|
uint64_t start_ns = CURRENT_NS(); \
|
|
(void)function(data.begin(), data.end()); \
|
|
uint64_t stop_ns = CURRENT_NS(); \
|
|
if (!is_sorted(data)) { \
|
|
printf(" \e[31mFAILED!\e[m\n"); \
|
|
break; \
|
|
} \
|
|
duration_us = (stop_ns - start_ns) / 1'000; \
|
|
printf(" %5d.%03d ms (%zu)\n", \
|
|
(int)(duration_us / 1000), \
|
|
(int)(duration_us % 1000), \
|
|
size \
|
|
); \
|
|
} \
|
|
} while (0)
|
|
|
|
|
|
#define TEST_ALGORITHM_RADIX(ms) do { \
|
|
uint64_t duration_us = 0; \
|
|
printf("radix with preallocated buffer\n"); \
|
|
for (size_t size = 100; duration_us < ms * 1000; size *= 10) { \
|
|
BAN::Vector<unsigned> data(size, 0); \
|
|
for (auto& val : data) \
|
|
val = rand() % 100; \
|
|
BAN::Vector<unsigned> temp(size); \
|
|
uint64_t start_ns = CURRENT_NS(); \
|
|
BAN::sort::radix_sort(data.begin(), data.end(), temp.span()); \
|
|
uint64_t stop_ns = CURRENT_NS(); \
|
|
if (!is_sorted(data)) { \
|
|
printf(" \e[31mFAILED!\e[m\n"); \
|
|
break; \
|
|
} \
|
|
duration_us = (stop_ns - start_ns) / 1'000; \
|
|
printf(" %5d.%03d ms (%zu)\n", \
|
|
(int)(duration_us / 1000), \
|
|
(int)(duration_us % 1000), \
|
|
size \
|
|
); \
|
|
} \
|
|
} while (0)
|
|
|
|
|
|
#define TEST_ALGORITHM_QSORT(ms) do { \
|
|
uint64_t duration_us = 0; \
|
|
printf("qsort\n"); \
|
|
for (size_t size = 100; duration_us < ms * 1000; size *= 10) { \
|
|
BAN::Vector<unsigned> data(size, 0); \
|
|
for (auto& val : data) \
|
|
val = rand() % 100; \
|
|
uint64_t start_ns = CURRENT_NS(); \
|
|
qsort(data.data(), data.size(), sizeof(unsigned), [](const void* a, const void* b) -> int { return *(unsigned*)a - *(unsigned*)b; }); \
|
|
uint64_t stop_ns = CURRENT_NS(); \
|
|
if (!is_sorted(data)) { \
|
|
printf(" \e[31mFAILED!\e[m\n"); \
|
|
break; \
|
|
} \
|
|
duration_us = (stop_ns - start_ns) / 1'000; \
|
|
printf(" %5d.%03d ms (%zu)\n", \
|
|
(int)(duration_us / 1000), \
|
|
(int)(duration_us % 1000), \
|
|
size \
|
|
); \
|
|
} \
|
|
} while (0)
|
|
|
|
int main()
|
|
{
|
|
srand(time(0));
|
|
TEST_ALGORITHM(100, BAN::sort::exchange_sort);
|
|
TEST_ALGORITHM(100, BAN::sort::quick_sort);
|
|
TEST_ALGORITHM(100, BAN::sort::insertion_sort);
|
|
TEST_ALGORITHM(100, BAN::sort::heap_sort);
|
|
TEST_ALGORITHM(100, BAN::sort::intro_sort);
|
|
TEST_ALGORITHM(1000, BAN::sort::sort);
|
|
TEST_ALGORITHM(1000, BAN::sort::radix_sort);
|
|
TEST_ALGORITHM_RADIX(1000);
|
|
TEST_ALGORITHM_QSORT(100);
|
|
}
|