summaryrefslogtreecommitdiff
path: root/xorshift.c
blob: 9291b90acc56f8e775d6f1ff45b62a85935eeb01 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
/*	“An experimental exploration of Marsaglia’s xorshift generators,
 *	scrambled”, Sebastiano Vigna */

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <assert.h>
#include <unistd.h>

#include "xorshift.h"

uint64_t xorshift_step (randctx * const st) {
	uint64_t s0 = st->s[ st->p ];
	uint64_t s1 = st->s[ st->p = ( st->p + 1 ) & (XORSHIFT_S-1) ];
	s1 ^= s1 << 31; // a
	s1 ^= s1 >> 11; // b
	s0 ^= s0 >> 30; // c
	return ( st->s[ st->p ] = s0 ^ s1 ) * 1181783497276652981LL;
}

static uint64_t rand64 () {
	unsigned long long rand;
	while (!__builtin_ia32_rdrand64_step (&rand));
	return rand;
}

void xorshift_seed (randctx * const st) {
	/* seed with high-quality randomness */
	for (unsigned char i = 0; i < XORSHIFT_S; i++) {
		st->s[i] = rand64 ();
	}
}

#if 0
uint64_t xorshift_step (randctx * const st) {
	uint64_t x = st->s[0];
	x ^= x >> 12; // a
	x ^= x << 25; // b
	x ^= x >> 27; // c
	st->s[0] = x;
	return x * 2685821657736338717LL;
}
#endif