Files
c3c/lib/std/math/random/math.msws.c3
2023-08-26 12:58:57 +02:00

300 lines
6.2 KiB
C

module std::math;
// Move ODD_PHI into a shared module
const ODD_PHI128 @local = 0x9e3779b97f4a7c15f39cc0605cedc835;
const ODD_PHI64 @local = 0x9e3779b97f4a7c15;
const ODD_PHI32 @local = 0x9e3779b9;
const ODD_PHI16 @local = 0x9e37;
const ODD_PHI8 @local = 0x9f;
// -------------------------------- Msws128 --------------------------------
struct Msws128Random
{
inline Random random;
Msws128RandomState state;
}
struct Msws128RandomState
{
uint128 state0, state1;
uint128 weyl0, weyl1;
}
const RandomInterface MSWS_128_RANDOM_INTERFACE @local = {
.seed_fn = (RandomSeedFn)&Msws128Random.set_seed,
.next_bytes_fn = (RandomNextBytesFn)&Msws128Random.next_bytes,
};
fn void Msws128Random.init(&self)
{
self.random.fns = &MSWS_128_RANDOM_INTERFACE;
}
fn void Msws128Random.set_seed(&self, char[] input)
{
self.state.set_seed(random::make_seed(uint128[4], input));
}
/**
* @require bytes.len > 0
**/
fn void Msws128Random.next_bytes(&self, char[] bytes)
{
@random_value_to_bytes(self.state.next_int128, bytes);
}
fn void Msws128RandomState.set_seed(&self, uint128[4] seed)
{
*self = bitcast(seed, Msws128RandomState);
}
fn uint128 Msws128RandomState.next_int128(&self)
{
uint128 s0 = self.state0;
self.state0 = self.state0 * self.state0 + self.weyl0;
self.state0 = self.state0.rotr(64);
self.weyl0 += ODD_PHI128;
self.state1 = self.state1 * self.state1 + self.weyl1;
uint128 s1 = self.state1;
self.state1 = self.state1.rotr(64);
self.weyl1 -= ODD_PHI128;
return s0 + s1;
}
// -------------------------------- Msws64 --------------------------------
struct Msws64Random
{
inline Random random;
Msws64RandomState state;
}
struct Msws64RandomState
{
ulong state0, state1;
ulong weyl0, weyl1;
}
const RandomInterface MSWS_64_RANDOM_INTERFACE @local = {
.seed_fn = (RandomSeedFn)&Msws64Random.set_seed,
.next_bytes_fn = (RandomNextBytesFn)&Msws64Random.next_bytes,
};
fn void Msws64Random.init(&self)
{
self.random.fns = &MSWS_64_RANDOM_INTERFACE;
}
fn void Msws64Random.set_seed(&self, char[] input)
{
self.state.set_seed(random::make_seed(ulong[4], input));
}
/**
* @require bytes.len > 0
**/
fn void Msws64Random.next_bytes(&self, char[] bytes)
{
@random_value_to_bytes(self.state.next_long, bytes);
}
fn void Msws64RandomState.set_seed(&self, ulong[4] seed)
{
*self = bitcast(seed, Msws64RandomState);
}
fn ulong Msws64RandomState.next_long(&self)
{
ulong s0 = self.state0;
self.state0 = self.state0 * self.state0 + self.weyl0;
self.state0 = self.state0.rotr(32);
self.weyl0 += ODD_PHI64;
self.state1 = self.state1 * self.state1 + self.weyl1;
ulong s1 = self.state1;
self.state1 = self.state1.rotr(32);
self.weyl1 -= ODD_PHI64;
return s0 + s1;
}
// -------------------------------- Msws32 --------------------------------
struct Msws32Random
{
inline Random random;
Msws32RandomState state;
}
struct Msws32RandomState
{
uint state0, state1;
uint weyl0, weyl1;
}
const RandomInterface MSWS_32_RANDOM_INTERFACE @local = {
.seed_fn = (RandomSeedFn)&Msws32Random.set_seed,
.next_bytes_fn = (RandomNextBytesFn)&Msws32Random.next_bytes,
};
fn void Msws32Random.init(&self)
{
self.random.fns = &MSWS_32_RANDOM_INTERFACE;
}
fn void Msws32Random.set_seed(&self, char[] input)
{
self.state.set_seed(random::make_seed(uint[4], input));
}
/**
* @require bytes.len > 0
**/
fn void Msws32Random.next_bytes(&self, char[] bytes)
{
@random_value_to_bytes(self.state.next_int, bytes);
}
fn void Msws32RandomState.set_seed(&self, uint[4] seed)
{
*self = bitcast(seed, Msws32RandomState);
}
fn uint Msws32RandomState.next_int(&self)
{
uint s0 = self.state0;
self.state0 = self.state0 * self.state0 + self.weyl0;
self.state0 = self.state0.rotr(16);
self.weyl0 += ODD_PHI32;
self.state1 = self.state1 * self.state1 + self.weyl1;
uint s1 = self.state1;
self.state1 = self.state1.rotr(16);
self.weyl1 -= ODD_PHI32;
return s0 + s1;
}
// -------------------------------- Msws16 --------------------------------
struct Msws16Random
{
inline Random random;
Msws16RandomState state;
}
struct Msws16RandomState
{
ushort state0, state1;
ushort weyl0, weyl1;
}
const RandomInterface MSWS_16_RANDOM_INTERFACE @local = {
.seed_fn = (RandomSeedFn)&Msws16Random.set_seed,
.next_bytes_fn = (RandomNextBytesFn)&Msws16Random.next_bytes,
};
fn void Msws16Random.init(&self)
{
self.random.fns = &MSWS_16_RANDOM_INTERFACE;
}
fn void Msws16Random.set_seed(&self, char[] input)
{
self.state.set_seed(random::make_seed(ushort[4], input));
}
/**
* @require bytes.len > 0
**/
fn void Msws16Random.next_bytes(&self, char[] bytes)
{
@random_value_to_bytes(self.state.next_short, bytes);
}
fn void Msws16RandomState.set_seed(&self, ushort[4] seed)
{
*self = bitcast(seed, Msws16RandomState);
}
fn ushort Msws16RandomState.next_short(&self)
{
ushort s0 = self.state0;
self.state0 = self.state0 * self.state0 + self.weyl0;
self.state0 = self.state0.rotr(8);
self.weyl0 += ODD_PHI16;
self.state1 = self.state1 * self.state1 + self.weyl1;
ushort s1 = self.state1;
self.state1 = self.state1.rotr(8);
self.weyl1 -= ODD_PHI16;
return s0 + s1;
}
// -------------------------------- Msws8 --------------------------------
struct Msws8Random
{
inline Random random;
Msws8RandomState state;
}
struct Msws8RandomState
{
char state0, state1;
char weyl0, weyl1;
}
const RandomInterface MSWS_8_RANDOM_INTERFACE @local = {
.seed_fn = (RandomSeedFn)&Msws8Random.set_seed,
.next_bytes_fn = (RandomNextBytesFn)&Msws8Random.next_bytes,
};
fn void Msws8Random.init(&self)
{
self.random.fns = &MSWS_8_RANDOM_INTERFACE;
}
fn void Msws8Random.set_seed(&self, char[] input)
{
self.state.set_seed(random::make_seed(char[4], input));
}
/**
* @require bytes.len > 0
**/
fn void Msws8Random.next_bytes(&self, char[] bytes)
{
@random_value_to_bytes(self.state.next_byte, bytes);
}
fn void Msws8RandomState.set_seed(&msws, char[4] seed)
{
*msws = bitcast(seed, Msws8RandomState);
}
fn char Msws8RandomState.next_byte(&self)
{
char s0 = self.state0;
self.state0 = self.state0 * self.state0 + self.weyl0;
self.state0 = self.state0.rotr(4);
self.weyl0 += ODD_PHI8;
self.state1 = self.state1 * self.state1 + self.weyl1;
char s1 = self.state1;
self.state1 = self.state1.rotr(4);
self.weyl1 -= ODD_PHI8;
return s0 + s1;
}