blob: 6fdd5fb687e3ccc5a0a0a01b8f1dbfd1d6e7c1f8 (
about) (
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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
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;
}
|