Files
c3c/lib/std/math/random/math.msws.c3
Christoffer Lerno 99cfaa1583 Refactor protocols.
2023-10-06 22:31:41 +02:00

191 lines
5.4 KiB
C

module std::math::random;
// 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 (Random)
{
uint128 state0, state1;
uint128 weyl0, weyl1;
}
fn void Msws128Random.set_seed(&self, char[] input) @dynamic
{
*self = bitcast(random::make_seed(uint128[4], input), Msws128Random);
}
fn uint128 Msws128Random.next_int128(&self) @dynamic
{
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;
}
/**
* @require bytes.len > 0
**/
fn void Msws128Random.next_bytes(&self, char[] bytes) @dynamic => @random_value_to_bytes(self.next_int128, bytes);
fn ulong Msws128Random.next_long(&self) @dynamic => (ulong)self.next_int128();
fn uint Msws128Random.next_int(&self) @dynamic => (uint)self.next_int128();
fn ushort Msws128Random.next_short(&self) @dynamic => (ushort)self.next_int128();
fn char Msws128Random.next_byte(&self) @dynamic => (char)self.next_int128();
// Msws64
struct Msws64Random (Random)
{
ulong state0, state1;
ulong weyl0, weyl1;
}
fn void Msws64Random.set_seed(&self, char[] input) @dynamic
{
*self = bitcast(random::make_seed(ulong[4], input), Msws64Random);
}
fn ulong Msws64Random.next_long(&self) @dynamic
{
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;
}
/**
* @require bytes.len > 0
**/
fn void Msws64Random.next_bytes(&self, char[] bytes) @dynamic => @random_value_to_bytes(self.next_long, bytes);
fn uint128 Msws64Random.next_int128(&self) @dynamic => @long_to_int128(self.next_long());
fn uint Msws64Random.next_int(&self) @dynamic => (uint)self.next_long();
fn ushort Msws64Random.next_short(&self) @dynamic => (ushort)self.next_long();
fn char Msws64Random.next_byte(&self) @dynamic => (char)self.next_long();
// Msws32
struct Msws32Random (Random)
{
uint state0, state1;
uint weyl0, weyl1;
}
fn void Msws32Random.set_seed(&self, char[] input) @dynamic
{
*self = bitcast(random::make_seed(uint[4], input), Msws32Random);
}
fn uint Msws32Random.next_int(&self) @dynamic
{
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;
}
/**
* @require bytes.len > 0
**/
fn void Msws32Random.next_bytes(&self, char[] bytes) @dynamic => @random_value_to_bytes(self.next_int, bytes);
fn uint128 Msws32Random.next_int128(&self) @dynamic => @long_to_int128(self.next_long());
fn ulong Msws32Random.next_long(&self) @dynamic => @int_to_long(self.next_int());
fn ushort Msws32Random.next_short(&self) @dynamic => (ushort)self.next_int();
fn char Msws32Random.next_byte(&self) @dynamic => (char)self.next_int();
// Msws16
struct Msws16Random (Random)
{
ushort state0, state1;
ushort weyl0, weyl1;
}
fn void Msws16Random.set_seed(&self, char[] input) @dynamic
{
*self = bitcast(random::make_seed(ushort[4], input), Msws16Random);
}
fn ushort Msws16Random.next_short(&self) @dynamic
{
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;
}
/**
* @require bytes.len > 0
**/
fn void Msws16Random.next_bytes(&self, char[] bytes) @dynamic => @random_value_to_bytes(self.next_short, bytes);
fn uint128 Msws16Random.next_int128(&self) @dynamic => @long_to_int128(self.next_long());
fn ulong Msws16Random.next_long(&self) @dynamic => @int_to_long(self.next_int());
fn uint Msws16Random.next_int(&self) @dynamic => @short_to_int(self.next_short());
fn char Msws16Random.next_byte(&self) @dynamic => (char)self.next_short();
// Msws8
struct Msws8Random (Random)
{
char state0, state1;
char weyl0, weyl1;
}
fn void Msws8Random.set_seed(&self, char[] input) @dynamic
{
*self = bitcast(random::make_seed(char[4], input), Msws8Random);
}
fn char Msws8Random.next_byte(&self) @dynamic
{
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;
}
fn void Msws8Random.next_bytes(&self, char[] bytes) @dynamic => @random_value_to_bytes(self.next_byte, bytes);
fn uint128 Msws8Random.next_int128(&self) @dynamic => @long_to_int128(self.next_long());
fn ulong Msws8Random.next_long(&self) @dynamic => @int_to_long(self.next_int());
fn uint Msws8Random.next_int(&self) @dynamic => @short_to_int(self.next_short());
fn ushort Msws8Random.next_short(&self) @dynamic => @char_to_short(self.next_byte());