Compare commits

...

10 Commits

Author SHA1 Message Date
Richard Thier
0b974f6242 Revert "added better test by rlblaster / ypsu / kbalazs"
This reverts commit cc96941dca32c222cbdb12808e8abb2dec78b5e6.
2021-12-13 02:29:33 +01:00
Richard Thier
cc96941dca added better test by rlblaster / ypsu / kbalazs 2021-12-13 02:28:22 +01:00
Richard Thier
1d0ba81e49 tried if it works with nibbles too: seems like easier to debug actually in this mode 2021-03-11 23:20:03 +01:00
Richard Thier
151b8f398b Likely better ILP and no manual digit counts in code 2021-03-11 23:13:53 +01:00
Richard Thier
22e80d4cd5 indent 2021-03-11 22:40:37 +01:00
Richard Thier
f30b5056cc noexcept 2021-03-11 22:39:53 +01:00
Richard Thier
83ae455c34 rename 2021-03-11 22:38:23 +01:00
Richard Thier
cfc9a050e4 removed manual digit usage by recursive template trickz 2021-03-11 22:34:44 +01:00
Richard Thier
c7fe2f0507 little refactor to maybe avoid manual digit misery 2021-03-11 22:19:29 +01:00
Richard Thier
e076ab662b prefix sum 2021-03-11 22:06:50 +01:00

View File

@ -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; }
/** 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 {}
};
// Calculate occurences of digits
static inline void countOccurences(uint32_t arr[], size_t size, size_t *radicsOut) noexcept {
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];
// Creates no object, struct is empty
OccurenceMagic<DIGITS - 1>(arr, i, radicsOut);
}
}
// TODO: remove debug stuffz
/** 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