magyarsort/randominus.h

50 lines
1.8 KiB
C

#ifndef RANDOMINUS_H
#define RANDOMINUS_H
/* To randomize an array - hopefully as fast as possible */
#include "fastrand/fastrand.h"
#define RD_REL_WIDTH 16
/** swap */
static void inline rd_swap(uint32_t *a, uint32_t *b) {
uint32_t tmp = *a;
*a = *b;
*b = tmp;
}
/** This is by no means "cryptographically correct" or stuff, but fast */
static inline void randominus(uint32_t *a, int n, uint32_t seed) {
/** Initialized ILP random generator */
uint32_t ilp_seeds[8];
rand_ilp_state rsi;
rand_state rs = init_rand();
for(int i = 0; i < 8; ++i) {
uint32_t choice = rand_between(&rs, 0, n);
ilp_seeds[i] = choice;
}
/** Go over the array and randomly swap stuff - hand unrolled with ILP random get! */
#pragma GCC unroll 16
for(int i = (RD_REL_WIDTH/2 + 1); i < (n - 8 - (RD_REL_WIDTH/2 + 1)); i += 8) {
uint32_t to = fastmodlike(lcg_ilp(&rsi, A), n);
uint32_t relto1 = fastmodlike(lcg_ilp(&rsi, B), RD_REL_WIDTH) - (RD_REL_WIDTH / 2);
uint32_t relto2 = fastmodlike(lcg_ilp(&rsi, C), RD_REL_WIDTH) - (RD_REL_WIDTH / 2);
uint32_t relto3 = fastmodlike(lcg_ilp(&rsi, D), RD_REL_WIDTH) - (RD_REL_WIDTH / 2);
uint32_t relto4 = fastmodlike(lcg_ilp(&rsi, E), RD_REL_WIDTH) - (RD_REL_WIDTH / 2);
uint32_t relto5 = fastmodlike(lcg_ilp(&rsi, F), RD_REL_WIDTH) - (RD_REL_WIDTH / 2);
uint32_t relto6 = fastmodlike(lcg_ilp(&rsi, G), RD_REL_WIDTH) - (RD_REL_WIDTH / 2);
uint32_t relto7 = fastmodlike(lcg_ilp(&rsi, H), RD_REL_WIDTH) - (RD_REL_WIDTH / 2);
rd_swap(&a[i], &a[to]);
rd_swap(&a[i + 1], &a[i + relto1]);
rd_swap(&a[i + 2], &a[i + relto2]);
rd_swap(&a[i + 3], &a[i + relto3]);
rd_swap(&a[i + 4], &a[i + relto4]);
rd_swap(&a[i + 5], &a[i + relto5]);
rd_swap(&a[i + 6], &a[i + relto6]);
rd_swap(&a[i + 7], &a[i + relto7]);
}
}
#endif /* RANDOMINUS_H */