69 lines
2.0 KiB
C
69 lines
2.0 KiB
C
|
|
#ifndef MAGYAR_SORT_H
|
||
|
|
#define MAGYAR_SORT_H
|
||
|
|
/**
|
||
|
|
* single header lib: In-place, fast heavily modified and optimized radix sort.
|
||
|
|
*
|
||
|
|
* Only unsigned ints for now, but should be able to modify for int and float...
|
||
|
|
* This is the counting variant with smart changes (not per-bit).
|
||
|
|
*
|
||
|
|
* LICENCE: CC3 - look it up, you need to mention me but that is all
|
||
|
|
*/
|
||
|
|
|
||
|
|
#include <vector>
|
||
|
|
#include <cstdint>
|
||
|
|
|
||
|
|
namespace MagyarSort {
|
||
|
|
|
||
|
|
// Only change these if you know what you are doing
|
||
|
|
// I use these because I want to see if nibbles are
|
||
|
|
// better or something...
|
||
|
|
//
|
||
|
|
// Bytes of nibbles only:
|
||
|
|
// - DIGIT_RANGE and BITS_PER_DIGIT should correspond
|
||
|
|
// - DIGITS should also correspond with the uint32_t
|
||
|
|
// - and DIGIT_RANGE should be 2^n value (16 or 256)
|
||
|
|
static constexpr int DIGITS = 4; // "helyiérték"
|
||
|
|
static constexpr int BITS_PER_DIGIT = 8; // "bit / helyiérték"
|
||
|
|
static constexpr int DIGIT_RANGE = 256; // "helyiérték állapottér"
|
||
|
|
|
||
|
|
template<int digitChoice>
|
||
|
|
static inline uint32_t getDigit(uint32_t num) noexcept {
|
||
|
|
static constexpr int SHIFT = digitChoice * BITS_PER_DIGIT;
|
||
|
|
|
||
|
|
uint32_t shifted = num >> SHIFT;
|
||
|
|
return shifted & DIGIT_RANGE;
|
||
|
|
}
|
||
|
|
|
||
|
|
/** Sort the given array (in-place sorting) with the given size */
|
||
|
|
inline void sort(uint32_t arr[], size_t size) noexcept {
|
||
|
|
// Holds "digit" occurences, prefix sums, whatevers
|
||
|
|
// First "DIGIT_RANGE" elem is for MSB "DIGITS", last is for LSB
|
||
|
|
static thread_local size_t radics[DIGITS * DIGIT_RANGE];
|
||
|
|
for(int i = 0; i < (DIGITS * DIGIT_RANGE); ++i) { radics[i] = 0; }
|
||
|
|
|
||
|
|
// Calculate occurences of digits
|
||
|
|
for(size_t i = 0; i < size; ++i) {
|
||
|
|
auto d0 = getDigit<0>(arr[i]);
|
||
|
|
auto d1 = getDigit<1>(arr[i]);
|
||
|
|
auto d2 = getDigit<2>(arr[i]);
|
||
|
|
auto d3 = getDigit<3>(arr[i]);
|
||
|
|
|
||
|
|
++radics[d0];
|
||
|
|
++radics[d1 + DIGIT_RANGE * 1];
|
||
|
|
++radics[d2 + DIGIT_RANGE * 2];
|
||
|
|
++radics[d3 + DIGIT_RANGE * 3];
|
||
|
|
}
|
||
|
|
|
||
|
|
// TODO: remove debug stuffz
|
||
|
|
for(size_t j = 0; j < DIGITS; ++j) {
|
||
|
|
printf("d%d: ", j);
|
||
|
|
for(size_t i = 0; i < DIGIT_RANGE; ++i) {
|
||
|
|
printf("%d,");
|
||
|
|
}
|
||
|
|
printf("\n");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
#endif
|