Files
mango/util/random.c

83 lines
1.6 KiB
C
Raw Normal View History

#include <kernel/util.h>
2026-02-08 12:06:50 +00:00
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
2026-02-08 12:06:50 +00:00
#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)
2026-02-08 12:06:50 +00:00
{
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;
}
2026-02-08 12:06:50 +00:00
static word_t mt_random(void)
{
if (index >= STATE_SIZE) {
twist();
2026-02-08 12:06:50 +00:00
}
word_t y = state[index];
y ^= (y >> SHIFT1) & MASK1;
y ^= (y << SHIFT2) & MASK2;
y ^= (y << SHIFT3) & MASK3;
y ^= y >> SHIFT4;
index++;
return y;
}
2026-02-08 12:06:50 +00:00
void init_random(uint64_t seedvalue)
{
seed(seedvalue);
}
2026-02-08 12:06:50 +00:00
bool fill_random(void *p, unsigned int size)
{
unsigned char *dst = p;
uint64_t w = mt_random();
unsigned char *src = (unsigned char *)&w;
2026-02-08 12:06:50 +00:00
for (size_t i = 0, j = 0; i < size; i++, j++) {
dst[i] = src[j];
2026-02-08 12:06:50 +00:00
if (j == (sizeof w) - 1) {
w = mt_random();
j = 0;
}
2026-02-08 12:06:50 +00:00
}
return true;
}