mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 20:11:17 +00:00
191 lines
5.4 KiB
Plaintext
191 lines
5.4 KiB
Plaintext
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());
|