diff options
| author | stderr64 <stderr64@null.net> | 2026-09-24 20:49:27 +0300 |
|---|---|---|
| committer | stderr64 <stderr64@null.net> | 2026-09-24 20:49:27 +0300 |
| commit | f54963e1364568d8f4f6e1a5be1646d4c5e7a94e (patch) | |
| tree | 447191762cf030afce72724b8374b06348feab2d /xorshift.c | |
| download | libxorshift-f54963e1364568d8f4f6e1a5be1646d4c5e7a94e.tar.gz libxorshift-f54963e1364568d8f4f6e1a5be1646d4c5e7a94e.tar.zst | |
First commit
Diffstat (limited to 'xorshift.c')
| -rw-r--r-- | xorshift.c | 64 |
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; +} |
