80 lines
1.4 KiB
C
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;
|
|
}
|