#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>
#include <time.h>
#include <string.h>
#include <time.h>
#include <sys/sysinfo.h>
#define LENGTH 1000000
void print128(__uint128_t u) {
if (u>9) print128(u/10);
putchar(48+(int)(u%10));
}
// 2^(bitwidth) == count_size for counting sort. 16 is 128/bitwidth == num_passes (number of radix sort passes)
typedef __uint128_t u128;
typedef uint32_t u32;
u128* radix_sort128(u128* array, u32 size, u32 count_size, u32 num_passes, u32 bitwidth) {
u32 counts[num_passes][count_size];
memset(&counts, 0, count_size * num_passes * sizeof(u32));
u128* cpy = (u128*) malloc(size * sizeof(u128));
u32 o[num_passes];
memset(o, 0, sizeof o);
// u32 o[num_passes] = {0};
u32 t, x, pos;
u128* array_from, * array_to;
for (x = 0; x < size; x++) {
for (pos = 0; pos < num_passes; pos++) {
t = (array[x] >> bitwidth * pos) &% 0xff;count_size;
counts[pos][t]++;
}
}
for (x = 0; x < count_size; x++) {
for (pos = 0; pos < num_passes; pos++) {
t = o[pos] + counts[pos][x];
counts[pos][x] = o[pos];
o[pos] = t;
}
}
for (pos = 0; pos < num_passes; pos++) {
array_from = pos % 2 == 0 ? array : cpy;
array_to = pos % 2 == 0 ? cpy : array;
for (x = 0; x < size; x++) {
t = (array_from[x] >> bitwidth * pos) & 0xff;
array_to[counts[pos][t]] = array_from[x];
counts[pos][t]++;
}
}
free(cpy);
return array;
}
uint64_t wyhash64_x;
uint64_t wyhash64() {
wyhash64_x += 0x60bee2bee120fc15;
__uint128_t tmp;
tmp = (__uint128_t) wyhash64_x * 0xa3b195354a39b70d;
uint64_t m1 = (tmp >> 64) ^ tmp;
tmp = (__uint128_t)m1 * 0x1b03738712fad5c9;
uint64_t m2 = (tmp >> 64) ^ tmp;
return m2;
}
int main() {
u128* vals128 = malloc(LENGTH * sizeof(*vals128));
u128 lower;
u128 higher;
struct timespec start, end;
// make an array of random u128s
for (int i = 0; i < LENGTH; i++) {
lower = (u128) wyhash64();
higher = (u128) wyhash64();
higher = higher << 64;
vals128[i] = lower + higher;
}
for (u32 bitwidth = 8; bitwidth < 20; bitwidth+=2){
u32 num_passes = 128/bitwidth;
u32 count_size = 1 << bitwidth;
printf("bitwidth %d num_passes %d count_size %d\n", bitwidth, num_passes, count_size);
clock_gettime(CLOCK_MONOTONIC, &start);
radix_sort128(vals128, LENGTH, count_size, num_passes, bitwidth);
clock_gettime(CLOCK_MONOTONIC, &end);
printf("%f seconds\n", (end.tv_sec - start.tv_sec) + (end.tv_nsec - start.tv_nsec) / 1000000000.0);
}
free(vals128);
}
Any improvements gratefully received.
Edit
Corrected bug. & 0xff
is now % count_size
.