Files
Espresso/lib/math/random.c
2026-03-20 16:57:08 -05:00

80 lines
1.4 KiB
C

#include <types.h>
#include <math/random.h>
/*
This code uses Xorshift (high speed, small) and PCG (Permuted Congruential Generator).
PCG may or may not be slightly slower than Xorshift.
*/
static uint32_t xorshift_state = 2463534242;
static void srand_xorshift(uint32_t seed)
{
xorshift_state = seed;
}
static inline uint32_t rand_xorshift(void)
{
uint32_t x = xorshift_state;
x ^= x << 13;
x ^= x >> 17;
x ^= x << 5;
return xorshift_state = x;
}
static uint64_t state = 0x853c49e6748fea9bULL;
static uint64_t inc = 0xda3e39cb94b95bdbULL;
static inline uint32_t rand_pcg32(void)
{
uint64_t oldstate = state;
state = oldstate * 6364136223846793005ULL + (inc | 1);
uint32_t xorshifted = ((oldstate >> 18u) ^ oldstate) >> 27u;
uint32_t rot = oldstate >> 59u;
return (xorshifted >> rot) | (xorshifted << ((-rot) & 31));
}
void seed_rand(uint32_t seed)
{
srand_xorshift(seed);
state = seed * 6364136223846793005ULL + (seed | 1);
}
uint32_t uirand(void)
{
return rand_pcg32() ^ rand_xorshift();
}
/* get a number between 0 and max-1 */
uint32_t uirand_range(uint32_t max)
{
if (max == 0)
{
return 0;
}
return uirand() % max;
}
uint64_t ulrand(void)
{
uint64_t hi = uirand();
uint64_t lo = uirand();
return (hi << 32) | lo;
}
/* get a number between 0 and max-1 */
uint64_t ulrand_range(uint64_t max)
{
if (max == 0)
{
return 0;
}
return ulrand() % max;
}