Compare commits
10 Commits
f8d4f597c6
...
0b974f6242
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0b974f6242 | ||
|
|
cc96941dca | ||
|
|
1d0ba81e49 | ||
|
|
151b8f398b | ||
|
|
22e80d4cd5 | ||
|
|
f30b5056cc | ||
|
|
83ae455c34 | ||
|
|
cfc9a050e4 | ||
|
|
c7fe2f0507 | ||
|
|
e076ab662b |
101
magyarsort.h
101
magyarsort.h
@ -9,9 +9,9 @@
|
||||
* LICENCE: CC3 - look it up, you need to mention me but that is all
|
||||
*/
|
||||
|
||||
#include <vector>
|
||||
#include <cstdio>
|
||||
#include <cstdint>
|
||||
#include <cstring> // memset
|
||||
|
||||
namespace MagyarSort {
|
||||
|
||||
@ -23,44 +23,67 @@ namespace MagyarSort {
|
||||
// - 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"
|
||||
static constexpr int DIGITS = 8; // "helyiérték"
|
||||
static constexpr int BITS_PER_DIGIT = 4; // "bit / helyiérték"
|
||||
static constexpr int DIGIT_RANGE = 16; // "helyiérték állapottér"
|
||||
|
||||
template<int digitChoice>
|
||||
template<int DIGIT_CHOICE>
|
||||
static inline uint32_t getDigit(uint32_t num) noexcept {
|
||||
static constexpr int SHIFT = digitChoice * BITS_PER_DIGIT;
|
||||
static constexpr int SHIFT = DIGIT_CHOICE * BITS_PER_DIGIT;
|
||||
|
||||
uint32_t shifted = num >> SHIFT;
|
||||
return shifted & (DIGIT_RANGE - 1);
|
||||
}
|
||||
|
||||
/** 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]);
|
||||
|
||||
printf("d0:%u, arr[i]: %u\n", d0, arr[i]);
|
||||
printf("d1:%u, arr[i]: %u\n", d1, arr[i]);
|
||||
printf("d2:%u, arr[i]: %u\n", d2, arr[i]);
|
||||
printf("d3:%u, arr[i]: %u\n", d3, arr[i]);
|
||||
|
||||
++radics[d0];
|
||||
++radics[d1 + DIGIT_RANGE * 1];
|
||||
++radics[d2 + DIGIT_RANGE * 2];
|
||||
++radics[d3 + DIGIT_RANGE * 3];
|
||||
/** Recursive Functor: no class should be generated I think (compiler should be smart) */
|
||||
template<int DIGIT>
|
||||
struct OccurenceMagic : public OccurenceMagic<DIGIT - 1> {
|
||||
inline OccurenceMagic(uint32_t arr[], size_t i, size_t *radicsOut) noexcept
|
||||
: OccurenceMagic<DIGIT -1 >(arr, i, radicsOut) {
|
||||
// Parents run first so template recursion runs DIGIT=0 first...
|
||||
++radicsOut[getDigit<DIGIT>(arr[i]) + DIGIT_RANGE * DIGIT];
|
||||
}
|
||||
};
|
||||
/** Ends template recursion */
|
||||
template<>
|
||||
struct OccurenceMagic<-1> {
|
||||
inline OccurenceMagic(uint32_t arr[], size_t i, size_t *radicsOut) noexcept {}
|
||||
};
|
||||
|
||||
// TODO: remove debug stuffz
|
||||
static inline void countOccurences(uint32_t arr[], size_t size, size_t *radicsOut) noexcept {
|
||||
for(size_t i = 0; i < size; ++i) {
|
||||
// Creates no object, struct is empty
|
||||
OccurenceMagic<DIGITS - 1>(arr, i, radicsOut);
|
||||
}
|
||||
}
|
||||
|
||||
/** Recursive Functor: no class should be generated I think (compiler should be smart) */
|
||||
template<int DIGIT>
|
||||
struct PrefixMagic : public PrefixMagic<DIGIT - 1> {
|
||||
inline PrefixMagic(size_t *radics, size_t *prev, int i) noexcept
|
||||
: PrefixMagic<DIGIT - 1>(radics, prev, i) {
|
||||
static constexpr int DSTART = (DIGIT * DIGIT_RANGE);
|
||||
radics[DSTART + i] += prev[DIGIT];
|
||||
prev[DIGIT] = radics[DSTART + i];
|
||||
}
|
||||
};
|
||||
/** Ends template recursion */
|
||||
template<>
|
||||
struct PrefixMagic<-1> {
|
||||
inline PrefixMagic(size_t *radics, size_t *prev, int i) noexcept {}
|
||||
};
|
||||
|
||||
static inline void calcPrefixSums(size_t *radics) noexcept {
|
||||
static thread_local size_t prev[DIGITS];
|
||||
memset(prev, 0, sizeof(prev));
|
||||
|
||||
for(int i = 0; i < DIGIT_RANGE; ++i) {
|
||||
// This is a template-unrolled loop too
|
||||
PrefixMagic<DIGITS - 1>(radics, prev, i);
|
||||
}
|
||||
}
|
||||
|
||||
void debugIt(size_t *radics) {
|
||||
for(size_t j = 0; j < DIGITS; ++j) {
|
||||
printf("d%d: ", j);
|
||||
for(size_t i = 0; i < DIGIT_RANGE; ++i) {
|
||||
@ -69,6 +92,24 @@ namespace MagyarSort {
|
||||
printf("\n\n");
|
||||
}
|
||||
}
|
||||
|
||||
/** 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];
|
||||
memset(radics, 0, sizeof(radics));
|
||||
|
||||
// Calculate occurences of digits
|
||||
countOccurences(arr, size, radics);
|
||||
|
||||
debugIt(radics);
|
||||
|
||||
// Calculate prefix sums
|
||||
calcPrefixSums(radics);
|
||||
|
||||
debugIt(radics);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user