summaryrefslogtreecommitdiff
path: root/xorshift.c
diff options
context:
space:
mode:
authorstderr64 <stderr64@null.net>2026-09-24 20:49:27 +0300
committerstderr64 <stderr64@null.net>2026-09-24 20:49:27 +0300
commitf54963e1364568d8f4f6e1a5be1646d4c5e7a94e (patch)
tree447191762cf030afce72724b8374b06348feab2d /xorshift.c
downloadlibxorshift-f54963e1364568d8f4f6e1a5be1646d4c5e7a94e.tar.gz
libxorshift-f54963e1364568d8f4f6e1a5be1646d4c5e7a94e.tar.zst
First commit
Diffstat (limited to 'xorshift.c')
-rw-r--r--xorshift.c64
1 files changed, 64 insertions, 0 deletions
diff --git a/xorshift.c b/xorshift.c
new file mode 100644
index 0000000..6fdd5fb
--- /dev/null
+++ b/xorshift.c
@@ -0,0 +1,64 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <errno.h>
+#include <unistd.h>
+#include <assert.h>
+#include <limits.h>
+#include <sys/random.h>
+#include <string.h>
+#include "structs.h"
+
+struct rng_state global_rng_state;
+
+__attribute__((visibility("default"))) bool initialize_states(){
+ assert( (sizeof(uint32_t) * CHAR_BIT) == 32 );
+ memset( (void*)&global_rng_state, 0, sizeof(struct rng_state) );
+ ssize_t state_bytes_read = 0;
+ if ( (state_bytes_read = getrandom((void*)&global_rng_state.states, 16 * sizeof(uint32_t), GRND_NONBLOCK)) == -1 )
+ return false;
+ if ( (size_t)state_bytes_read < (16 * sizeof(uint32_t)) ){
+ errno = EIO;
+ return false;
+ }
+ global_rng_state.state_idx = global_rng_state.states[7] & 0x0f;
+ errno = 0;
+ return true;
+}
+
+__attribute__((visibility("default"))) uint32_t get_random_output(){
+ size_t use_state = global_rng_state.state_idx;
+ global_rng_state.state_idx = global_rng_state.states[use_state] & 0x0f;
+ if ( global_rng_state.gen_period_ctr >= 0xffffffff ){
+ global_rng_state.period_end_ctr++;
+ if ( global_rng_state.period_end_ctr >= 16 ){
+ assert( initialize_states() == true );
+ global_rng_state.period_end_ctr = 0;
+ }
+ global_rng_state.gen_period_ctr = 0;
+ }
+ global_rng_state.gen_period_ctr++;
+ global_rng_state.states[use_state] ^= global_rng_state.states[use_state] >> 11;
+ global_rng_state.states[use_state] ^= global_rng_state.states[use_state] << 7;
+ global_rng_state.states[use_state] ^= global_rng_state.states[use_state] >> 16;
+ return global_rng_state.states[use_state] * OUTPUT_MULTIPLIER;
+}
+
+__attribute__((visibility("default"))) uint32_t get_uniform_uint( uint32_t min, uint32_t max ){
+ if ( max <= min )
+ return min;
+ uint32_t ncount = (max - min) + 1;
+ uint32_t upper_bound = 0xffffffff - (0xffffffff % ncount);
+ uint32_t gen_output = get_random_output();
+ if ( gen_output > upper_bound ){
+ while ( gen_output > upper_bound )
+ gen_output = get_random_output();
+ }
+ return (gen_output % max) + min;
+}
+
+__attribute__((visibility("default"))) void clear_rng_state(){
+ memset( (void*)&global_rng_state, 0, sizeof(struct rng_state) );
+ return;
+}