kernel: replace random number generator with mersenne twister
This commit is contained in:
@@ -61,6 +61,7 @@ extern uint64_t host_to_little_u64(uint64_t v);
|
|||||||
extern uint64_t big_to_host_u64(uint64_t v);
|
extern uint64_t big_to_host_u64(uint64_t v);
|
||||||
extern uint64_t little_to_host_u64(uint64_t v);
|
extern uint64_t little_to_host_u64(uint64_t v);
|
||||||
|
|
||||||
|
extern void init_random(uint64_t seed);
|
||||||
extern bool fill_random(void *buffer, unsigned int size);
|
extern bool fill_random(void *buffer, unsigned int size);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|||||||
@@ -1,35 +1,81 @@
|
|||||||
#include <kernel/util.h>
|
#include <kernel/util.h>
|
||||||
|
|
||||||
static unsigned int random_seed = 53455346;
|
typedef uint64_t word_t;
|
||||||
|
#define STATE_SIZE 312
|
||||||
|
#define MIDDLE 156
|
||||||
|
#define INIT_SHIFT 62
|
||||||
|
#define TWIST_MASK 0xb5026f5aa96619e9
|
||||||
|
#define INIT_FACT 6364136223846793005
|
||||||
|
#define SHIFT1 29
|
||||||
|
#define MASK1 0x5555555555555555
|
||||||
|
#define SHIFT2 17
|
||||||
|
#define MASK2 0x71d67fffeda60000
|
||||||
|
#define SHIFT3 37
|
||||||
|
#define MASK3 0xfff7eee000000000
|
||||||
|
#define SHIFT4 43
|
||||||
|
|
||||||
|
#define LOWER_MASK 0x7fffffff
|
||||||
|
#define UPPER_MASK (~(word_t)LOWER_MASK)
|
||||||
|
static word_t state[STATE_SIZE];
|
||||||
|
static size_t index = STATE_SIZE + 1;
|
||||||
|
|
||||||
|
static void seed(word_t s)
|
||||||
|
{
|
||||||
|
index = STATE_SIZE;
|
||||||
|
state[0] = s;
|
||||||
|
for (size_t i = 1; i < STATE_SIZE; i++) {
|
||||||
|
state[i] = (INIT_FACT
|
||||||
|
* (state[i - 1] ^ (state[i - 1] >> INIT_SHIFT)))
|
||||||
|
+ i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void twist(void)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < STATE_SIZE; i++) {
|
||||||
|
word_t x = (state[i] & UPPER_MASK)
|
||||||
|
| (state[(i + 1) % STATE_SIZE] & LOWER_MASK);
|
||||||
|
x = (x >> 1) ^ (x & 1 ? TWIST_MASK : 0);
|
||||||
|
state[i] = state[(i + MIDDLE) % STATE_SIZE] ^ x;
|
||||||
|
}
|
||||||
|
|
||||||
|
index = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static word_t mt_random(void)
|
||||||
|
{
|
||||||
|
if (index >= STATE_SIZE) {
|
||||||
|
twist();
|
||||||
|
}
|
||||||
|
|
||||||
|
word_t y = state[index];
|
||||||
|
y ^= (y >> SHIFT1) & MASK1;
|
||||||
|
y ^= (y << SHIFT2) & MASK2;
|
||||||
|
y ^= (y << SHIFT3) & MASK3;
|
||||||
|
y ^= y >> SHIFT4;
|
||||||
|
|
||||||
|
index++;
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_random(uint64_t seedvalue)
|
||||||
|
{
|
||||||
|
seed(seedvalue);
|
||||||
|
}
|
||||||
|
|
||||||
bool fill_random(void *p, unsigned int size)
|
bool fill_random(void *p, unsigned int size)
|
||||||
{
|
{
|
||||||
unsigned char *buffer = p;
|
unsigned char *dst = p;
|
||||||
|
uint64_t w = mt_random();
|
||||||
|
unsigned char *src = (unsigned char *)&w;
|
||||||
|
|
||||||
if (!buffer || !size) {
|
for (size_t i = 0, j = 0; i < size; i++, j++) {
|
||||||
return false;
|
dst[i] = src[j];
|
||||||
}
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < size; i++) {
|
if (j == (sizeof w) - 1) {
|
||||||
uint32_t next = random_seed;
|
w = mt_random();
|
||||||
uint32_t result;
|
j = 0;
|
||||||
|
}
|
||||||
next *= 1103515245;
|
|
||||||
next += 12345;
|
|
||||||
result = (uint32_t)(next / 65536) % 2048;
|
|
||||||
|
|
||||||
next *= 1103515245;
|
|
||||||
next += 12345;
|
|
||||||
result <<= 10;
|
|
||||||
result ^= (uint32_t)(next / 65536) % 1024;
|
|
||||||
|
|
||||||
next *= 1103515245;
|
|
||||||
next += 12345;
|
|
||||||
result <<= 10;
|
|
||||||
result ^= (uint32_t)(next / 65536) % 1024;
|
|
||||||
random_seed = next;
|
|
||||||
|
|
||||||
buffer[i] = (uint8_t)(result % 256);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
Reference in New Issue
Block a user