Make Random use protocols.

This commit is contained in:
Christoffer Lerno
2023-10-06 09:05:34 +02:00
committed by Christoffer Lerno
parent a1bce81ed0
commit f3e3aa231d
8 changed files with 308 additions and 748 deletions

View File

@@ -1,95 +1,19 @@
module std::math;
module std::math::random;
struct Random
protocol Random
{
RandomInterface* fns;
fn void set_seed(&self, char[] input);
fn char next_byte(&self);
fn ushort next_short(&self);
fn uint next_int(&self);
fn ulong next_long(&self);
fn uint128 next_int128(&self);
fn void next_bytes(&self, char[] buffer);
}
def RandomSeedFn = fn void(Random*, char[] seed);
def RandomNextBytesFn = fn void(Random*, char[] buffer);
struct RandomInterface
macro Random.seed(&self, seed)
{
RandomSeedFn seed_fn;
RandomNextBytesFn next_bytes_fn;
}
/**
* @param [&inout] random
* @param [inout] buffer
**/
fn void Random.next_bytes(&random, char[] buffer)
{
if (!buffer.len) return;
random.fns.next_bytes_fn(random, buffer);
}
/**
* @param [&inout] self
**/
fn char Random.next_byte(&self)
{
char result @noinit;
self.next_bytes(((char*)&result)[:1]);
return result;
}
/**
* @param [&inout] self
**/
fn ushort Random.next_short(&self)
{
ushort result @noinit;
self.next_bytes(((char*)&result)[:2]);
return result;
}
/**
* @param [&inout] self
**/
fn uint Random.next_int(&self)
{
uint result @noinit;
self.next_bytes(((char*)&result)[:4]);
return result;
}
/**
* @param [&inout] self
**/
fn ulong Random.next_long(&self)
{
ulong result @noinit;
self.next_bytes(((char*)&result)[:8]);
return result;
}
/**
* @param [&inout] self
**/
fn uint128 Random.next_uint128(&self)
{
uint128 result @noinit;
self.next_bytes(((char*)&result)[:16]);
return result;
}
/**
* @param [&inout] self
* @require types::is_numerical($typeof(seed))
**/
macro void Random.seed_random(&self, seed)
{
self.fns.seed_fn(self, @as_char_view(seed)) @inline;
}
/**
* @param [&inout] random
* @param [in] seed
**/
fn void Random.set_seed(&random, char[] seed)
{
random.fns.seed_fn(random, seed);
self.set_seed(@as_char_view(seed));
}
fn int Random.next(&random, int max)
@@ -97,9 +21,6 @@ fn int Random.next(&random, int max)
return (int)(random.next_double() * max);
}
/**
* @param [&inout] self
**/
fn bool Random.next_bool(&self)
{
return self.next_byte() & 1 == 0;
@@ -117,6 +38,11 @@ fn double Random.next_double(&self)
return val * 0x1.0p-53;
}
macro uint128 @long_to_int128(#function) => (uint128)#function << 64 + #function;
macro ulong @int_to_long(#function) => (ulong)#function << 32 + #function;
macro uint @short_to_int(#function) => (uint)#function << 16 + #function;
macro ushort @char_to_short(#function) => (ushort)#function << 8 + #function;
macro @random_value_to_bytes(#function, char[] bytes)
{
var $byte_size = $sizeof(#function());

View File

@@ -1,4 +1,4 @@
module std::math;
module std::math::random;
// Move ODD_PHI into a shared module
const ODD_PHI128 @local = 0x9e3779b97f4a7c15f39cc0605cedc835;
@@ -12,45 +12,16 @@ const MUL_LCG32 @local = 0x915f77f5;
const MUL_LCG16 @local = 0x915d; // TODO: Find good constant
// -------------------------------- Lcg128_64 --------------------------------
// Lcg128_64
def Lcg128Random = distinct uint128;
struct Lcg128Random
fn void Lcg128Random.set_seed(&self, char[] input) : Random
{
inline Random random;
Lcg128RandomState state;
*self = (Lcg128Random)random::make_seed(uint128, input);
}
def Lcg128RandomState = distinct uint128;
const RandomInterface LCG_128_RANDOM_INTERFACE @local = {
.seed_fn = (RandomSeedFn)&Lcg128Random.set_seed,
.next_bytes_fn = (RandomNextBytesFn)&Lcg128Random.next_bytes,
};
fn void Lcg128Random.init(&self)
{
self.random.fns = &LCG_128_RANDOM_INTERFACE;
}
fn void Lcg128Random.set_seed(&self, char[] input)
{
self.state.set_seed(random::make_seed(uint128, input));
}
/**
* @require bytes.len > 0
**/
fn void Lcg128Random.next_bytes(&self, char[] bytes)
{
@random_value_to_bytes(self.state.next_long, bytes);
}
fn void Lcg128RandomState.set_seed(&self, uint128 seed) @inline
{
*self = (Lcg128RandomState)seed;
}
fn ulong Lcg128RandomState.next_long(&self)
fn ulong Lcg128Random.next_long(&self) : Random
{
uint128* s = (uint128*)self;
ulong result = (ulong)(*s >> 64);
@@ -58,46 +29,26 @@ fn ulong Lcg128RandomState.next_long(&self)
return result;
}
// -------------------------------- Lcg64_32 --------------------------------
struct Lcg64Random
{
inline Random random;
Lcg64RandomState state;
}
def Lcg64RandomState = distinct ulong;
const RandomInterface LCG_64_RANDOM_INTERFACE @local = {
.seed_fn = (RandomSeedFn)&Lcg64Random.set_seed,
.next_bytes_fn = (RandomNextBytesFn)&Lcg64Random.next_bytes,
};
fn void Lcg64Random.init(&self)
{
self.random.fns = &LCG_64_RANDOM_INTERFACE;
}
fn void Lcg64Random.set_seed(&self, char[] seed)
{
self.state.set_seed(random::make_seed(ulong, seed));
}
/**
* @require bytes.len > 0
**/
fn void Lcg64Random.next_bytes(&self, char[] bytes)
fn void Lcg128Random.next_bytes(&self, char[] bytes) : Random => @random_value_to_bytes(self.next_long, bytes);
fn uint128 Lcg128Random.next_int128(&self) : Random => @long_to_int128(self.next_long());
fn uint Lcg128Random.next_int(&self) : Random => (uint)self.next_long();
fn ushort Lcg128Random.next_short(&self) : Random => (ushort)self.next_long();
fn char Lcg128Random.next_byte(&self) : Random => (char)self.next_long();
// -------------------------------- Lcg64_32 --------------------------------
def Lcg64Random = distinct ulong;
fn void Lcg64Random.set_seed(&self, char[] seed) : Random
{
@random_value_to_bytes(self.state.next_int, bytes);
*self = (Lcg64Random)random::make_seed(ulong, seed);
}
fn void Lcg64RandomState.set_seed(&self, ulong seed)
{
*self = (Lcg64RandomState)seed;
}
fn uint Lcg64RandomState.next_int(&self)
fn uint Lcg64Random.next_int(&self) : Random
{
ulong* s = (ulong*)self;
uint result = (uint)(*s >> 32);
@@ -105,17 +56,25 @@ fn uint Lcg64RandomState.next_int(&self)
return result;
}
/**
* @require bytes.len > 0
**/
fn void Lcg64Random.next_bytes(&self, char[] bytes) : Random => @random_value_to_bytes(self.next_int, bytes);
fn uint128 Lcg64Random.next_int128(&self) : Random => @long_to_int128(self.next_long());
fn ulong Lcg64Random.next_long(&self) : Random => @int_to_long(self.next_int());
fn ushort Lcg64Random.next_short(&self) : Random => (ushort)self.next_int();
fn char Lcg64Random.next_byte(&self) : Random => (char)self.next_int();
// -------------------------------- Lcg32_16 --------------------------------
def Lcg32RandomState = distinct uint;
def Lcg32Random = distinct uint;
fn void Lcg32RandomState.set_seed(&self, uint seed)
fn void Lcg32Random.set_seed(&self, char[] seed) : Random
{
*self = (Lcg32RandomState)seed;
*self = (Lcg32Random)random::make_seed(uint, seed);
}
fn ushort Lcg32RandomState.next_short(&self)
fn ushort Lcg32Random.next_short(&self) : Random
{
uint* s = (uint*)self;
ushort result = (ushort)(*s >> 16);
@@ -123,20 +82,31 @@ fn ushort Lcg32RandomState.next_short(&self)
return result;
}
fn void Lcg32Random.next_bytes(&self, char[] bytes) : Random => @random_value_to_bytes(self.next_short, bytes);
fn uint128 Lcg32Random.next_int128(&self) : Random => @long_to_int128(self.next_long());
fn ulong Lcg32Random.next_long(&self) : Random => @int_to_long(self.next_int());
fn uint Lcg32Random.next_int(&self) : Random => @short_to_int(self.next_short());
fn char Lcg32Random.next_byte(&self) : Random => (char)self.next_short();
// -------------------------------- Lcg16_8 --------------------------------
def Lcg16Random = distinct ushort;
def Lcg16RandomState = distinct ushort;
fn void Lcg16RandomState.set_seed(&self, ushort seed)
fn void Lcg16Random.set_seed(&self, char[] seed) : Random
{
*self = (Lcg16RandomState)seed;
*self = (Lcg16Random)random::make_seed(ushort, seed);
}
fn char Lcg16RandomState.next_byte(&self)
fn char Lcg16Random.next_byte(&self) : Random
{
ushort* s = (ushort*)self;
char result = (char)(*s >> 8);
*s = *s * MUL_LCG16 + ODD_PHI16;
return result;
}
fn void Lcg16Random.next_bytes(&self, char[] bytes) : Random => @random_value_to_bytes(self.next_byte, bytes);
fn uint128 Lcg16Random.next_int128(&self) : Random => @long_to_int128(self.next_long());
fn ulong Lcg16Random.next_long(&self) : Random => @int_to_long(self.next_int());
fn uint Lcg16Random.next_int(&self) : Random => @short_to_int(self.next_short());
fn ushort Lcg16Random.next_short(&self) : Random => @char_to_short(self.next_byte());

View File

@@ -1,49 +1,28 @@
module std::math;
module std::math::random;
const MUL_MCG128 @local = 0x9e3779b97f4a7c15f39cc0605cedc835;
const MUL_MCG64 @local = 0xf1357aea2e62a9c5;
const MUL_MCG32 @local = 0x93d765dd;
const MUL_MCG16 @local = 0x93d5; // TODO: Find good constant
// -------------------------------- Mcg128_64 --------------------------------
// Mcg128_64
struct Mcg128Random
def Mcg128Random = distinct uint128;
fn void Mcg128Random.set_seed(&self, char[] seed) : Random
{
inline Random random;
Mcg128RandomState state;
}
def Mcg128RandomState = distinct uint128;
const RandomInterface MCG_128_RANDOM_INTERFACE @local = {
.seed_fn = (RandomSeedFn)&Mcg128Random.set_seed,
.next_bytes_fn = (RandomNextBytesFn)&Mcg128Random.next_bytes,
};
fn void Mcg128Random.init(&self)
{
self.random.fns = &MCG_64_RANDOM_INTERFACE;
}
fn void Mcg128Random.set_seed(&self, char[] seed)
{
self.state.set_seed(random::make_seed(uint128, seed));
*self = (Mcg128Random)(random::make_seed(uint128, seed) | 1);
}
/**
* @require bytes.len > 0
**/
fn void Mcg128Random.next_bytes(&self, char[] bytes)
fn void Mcg128Random.next_bytes(&self, char[] bytes) : Random
{
@random_value_to_bytes(self.state.next_long, bytes);
@random_value_to_bytes(self.next_long, bytes);
}
fn void Mcg128RandomState.set_seed(&self, uint128 seed)
{
*self = (Mcg128RandomState)seed | 1;
}
fn ulong Mcg128RandomState.next_long(&self)
fn ulong Mcg128Random.next_long(&self) : Random
{
uint128* s = (uint128*)self;
ulong result = (ulong)(*s >> 64);
@@ -51,48 +30,32 @@ fn ulong Mcg128RandomState.next_long(&self)
return result;
}
fn uint128 Mcg128Random.next_int128(&self) : Random => @long_to_int128(self.next_long());
fn uint Mcg128Random.next_int(&self) : Random => (uint)self.next_long();
fn ushort Mcg128Random.next_short(&self) : Random => (ushort)self.next_long();
fn char Mcg128Random.next_byte(&self) : Random => (char)self.next_long();
// -------------------------------- Mcg64RandomState --------------------------------
struct Mcg64Random
// Mcg64RandomState
def Mcg64Random = distinct ulong;
fn void Mcg64Random.set_seed(&self, char[] seed) : Random
{
inline Random random;
Mcg64RandomState state;
}
const RandomInterface MCG_64_RANDOM_INTERFACE @local = {
.seed_fn = (RandomSeedFn)&Mcg64Random.set_seed,
.next_bytes_fn = (RandomNextBytesFn)&Mcg64Random.next_bytes,
};
def Mcg64RandomState = distinct ulong;
fn void Mcg64Random.init(&self)
{
self.random.fns = &MCG_64_RANDOM_INTERFACE;
}
fn void Mcg64Random.set_seed(&self, char[] seed)
{
self.state.set_seed(random::make_seed(ulong, seed));
*self = (Mcg64Random)random::make_seed(ulong, seed) | 1;
}
/**
* @require bytes.len > 0
**/
fn void Mcg64Random.next_bytes(&self, char[] bytes)
fn void Mcg64Random.next_bytes(&self, char[] bytes) : Random
{
@random_value_to_bytes(self.state.next_int, bytes);
@random_value_to_bytes(self.next_int, bytes);
}
fn void Mcg64RandomState.set_seed(&self, ulong seed)
{
*self = (Mcg64RandomState)self | 1;
}
fn uint Mcg64RandomState.next_int(&self)
fn uint Mcg64Random.next_int(&self) : Random
{
ulong* s = (ulong*)self;
uint result = (uint)(*s >> 32);
@@ -100,17 +63,22 @@ fn uint Mcg64RandomState.next_int(&self)
return result;
}
fn uint128 Mcg64Random.next_int128(&self) : Random => @long_to_int128(self.next_long());
fn ulong Mcg64Random.next_long(&self) : Random => @int_to_long(self.next_int());
fn ushort Mcg64Random.next_short(&self) : Random => (ushort)self.next_int();
fn char Mcg64Random.next_byte(&self) : Random => (char)self.next_int();
// -------------------------------- Mcg32RandomState --------------------------------
def Mcg32RandomState = distinct uint;
// Mcg32Random
fn void Mcg32RandomState.set_seed(&self, uint seed)
def Mcg32Random = distinct uint;
fn void Mcg32Random.set_seed(&self, char[] seed) : Random
{
*self = (Mcg32RandomState)seed | 1;
*self = (Mcg32Random)random::make_seed(uint, seed) | 1;
}
fn ushort Mcg32RandomState.next_short(&self)
fn ushort Mcg32Random.next_short(&self)
{
uint* s = (uint*)self;
ushort result = (ushort)(*s >> 16);
@@ -118,20 +86,34 @@ fn ushort Mcg32RandomState.next_short(&self)
return result;
}
/**
* @require bytes.len > 0
**/
fn void Mcg32Random.next_bytes(&self, char[] bytes) : Random => @random_value_to_bytes(self.next_short, bytes);
fn uint128 Mcg32Random.next_int128(&self) : Random => @long_to_int128(self.next_long());
fn ulong Mcg32Random.next_long(&self) : Random => @int_to_long(self.next_int());
fn uint Mcg32Random.next_int(&self) : Random => @short_to_int(self.next_short());
fn char Mcg32Random.next_byte(&self) : Random => (char)self.next_short();
// -------------------------------- Mcg16RandomState --------------------------------
def Mcg16RandomState = distinct ushort;
def Mcg16Random = distinct ushort;
fn void Mcg16RandomState.set_seed(&self, ushort seed)
fn void Mcg16Random.set_seed(&self, char[] seed) : Random
{
*self = (Mcg16RandomState)seed | 1;
*self = (Mcg16Random)random::make_seed(ushort, seed) | 1;
}
fn char Mcg16RandomState.next_byte(&self)
fn char Mcg16Random.next_byte(&self) : Random
{
ushort* s = (ushort*)self;
char result = (char)(*s >> 8);
*s *= MUL_MCG16;
return result;
}
fn void Mcg16Random.next_bytes(&self, char[] bytes) : Random => @random_value_to_bytes(self.next_byte, bytes);
fn uint128 Mcg16Random.next_int128(&self) : Random => @long_to_int128(self.next_long());
fn ulong Mcg16Random.next_long(&self) : Random => @int_to_long(self.next_int());
fn uint Mcg16Random.next_int(&self) : Random => @short_to_int(self.next_short());
fn ushort Mcg16Random.next_short(&self) : Random => @char_to_short(self.next_byte());

View File

@@ -1,4 +1,4 @@
module std::math;
module std::math::random;
// Move ODD_PHI into a shared module
const ODD_PHI128 @local = 0x9e3779b97f4a7c15f39cc0605cedc835;
@@ -7,50 +7,20 @@ const ODD_PHI32 @local = 0x9e3779b9;
const ODD_PHI16 @local = 0x9e37;
const ODD_PHI8 @local = 0x9f;
// -------------------------------- Msws128 --------------------------------
// 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)
fn void Msws128Random.set_seed(&self, char[] input) : Random
{
self.random.fns = &MSWS_128_RANDOM_INTERFACE;
*self = bitcast(random::make_seed(uint128[4], input), Msws128Random);
}
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)
fn uint128 Msws128Random.next_int128(&self)
{
uint128 s0 = self.state0;
self.state0 = self.state0 * self.state0 + self.weyl0;
@@ -65,50 +35,29 @@ fn uint128 Msws128RandomState.next_int128(&self)
return s0 + s1;
}
/**
* @require bytes.len > 0
**/
fn void Msws128Random.next_bytes(&self, char[] bytes) : Random => @random_value_to_bytes(self.next_int128, bytes);
fn ulong Msws128Random.next_long(&self) : Random => (ulong)self.next_int128();
fn uint Msws128Random.next_int(&self) : Random => (uint)self.next_int128();
fn ushort Msws128Random.next_short(&self) : Random => (ushort)self.next_int128();
fn char Msws128Random.next_byte(&self) : Random => (char)self.next_int128();
// -------------------------------- Msws64 --------------------------------
// 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)
fn void Msws64Random.set_seed(&self, char[] input) : Random
{
self.random.fns = &MSWS_64_RANDOM_INTERFACE;
*self = bitcast(random::make_seed(ulong[4], input), Msws64Random);
}
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)
fn ulong Msws64Random.next_long(&self) : Random
{
ulong s0 = self.state0;
self.state0 = self.state0 * self.state0 + self.weyl0;
@@ -123,50 +72,29 @@ fn ulong Msws64RandomState.next_long(&self)
return s0 + s1;
}
/**
* @require bytes.len > 0
**/
fn void Msws64Random.next_bytes(&self, char[] bytes) : Random => @random_value_to_bytes(self.next_long, bytes);
fn uint128 Msws64Random.next_int128(&self) : Random => @long_to_int128(self.next_long());
fn uint Msws64Random.next_int(&self) : Random => (uint)self.next_long();
fn ushort Msws64Random.next_short(&self) : Random => (ushort)self.next_long();
fn char Msws64Random.next_byte(&self) : Random => (char)self.next_long();
// -------------------------------- Msws32 --------------------------------
// 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)
fn void Msws32Random.set_seed(&self, char[] input) : Random
{
self.random.fns = &MSWS_32_RANDOM_INTERFACE;
*self = bitcast(random::make_seed(uint[4], input), Msws32Random);
}
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)
fn uint Msws32Random.next_int(&self) : Random
{
uint s0 = self.state0;
self.state0 = self.state0 * self.state0 + self.weyl0;
@@ -181,51 +109,30 @@ fn uint Msws32RandomState.next_int(&self)
return s0 + s1;
}
/**
* @require bytes.len > 0
**/
fn void Msws32Random.next_bytes(&self, char[] bytes) : Random => @random_value_to_bytes(self.next_int, bytes);
fn uint128 Msws32Random.next_int128(&self) : Random => @long_to_int128(self.next_long());
fn ulong Msws32Random.next_long(&self) : Random => @int_to_long(self.next_int());
fn ushort Msws32Random.next_short(&self) : Random => (ushort)self.next_int();
fn char Msws32Random.next_byte(&self) : Random => (char)self.next_int();
// -------------------------------- Msws16 --------------------------------
// 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)
fn void Msws16Random.set_seed(&self, char[] input) : Random
{
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);
*self = bitcast(random::make_seed(ushort[4], input), Msws16Random);
}
fn void Msws16RandomState.set_seed(&self, ushort[4] seed)
{
*self = bitcast(seed, Msws16RandomState);
}
fn ushort Msws16RandomState.next_short(&self)
fn ushort Msws16Random.next_short(&self) : Random
{
ushort s0 = self.state0;
self.state0 = self.state0 * self.state0 + self.weyl0;
@@ -240,50 +147,28 @@ fn ushort Msws16RandomState.next_short(&self)
return s0 + s1;
}
/**
* @require bytes.len > 0
**/
fn void Msws16Random.next_bytes(&self, char[] bytes) : Random => @random_value_to_bytes(self.next_short, bytes);
fn uint128 Msws16Random.next_int128(&self) : Random => @long_to_int128(self.next_long());
fn ulong Msws16Random.next_long(&self) : Random => @int_to_long(self.next_int());
fn uint Msws16Random.next_int(&self) : Random => @short_to_int(self.next_short());
fn char Msws16Random.next_byte(&self) : Random => (char)self.next_short();
// -------------------------------- Msws8 --------------------------------
// 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)
fn void Msws8Random.set_seed(&self, char[] input) : Random
{
self.random.fns = &MSWS_8_RANDOM_INTERFACE;
*self = bitcast(random::make_seed(char[4], input), Msws8Random);
}
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)
fn char Msws8Random.next_byte(&self) : Random
{
char s0 = self.state0;
self.state0 = self.state0 * self.state0 + self.weyl0;
@@ -297,3 +182,9 @@ fn char Msws8RandomState.next_byte(&self)
return s0 + s1;
}
fn void Msws8Random.next_bytes(&self, char[] bytes) : Random => @random_value_to_bytes(self.next_byte, bytes);
fn uint128 Msws8Random.next_int128(&self) : Random => @long_to_int128(self.next_long());
fn ulong Msws8Random.next_long(&self) : Random => @int_to_long(self.next_int());
fn uint Msws8Random.next_int(&self) : Random => @short_to_int(self.next_short());
fn ushort Msws8Random.next_short(&self) : Random => @char_to_short(self.next_byte());

View File

@@ -1,4 +1,4 @@
module std::math;
module std::math::random;
// Move ODD_PHI into a shared module
const ODD_PHI128 @local = 0x9e3779b97f4a7c15f39cc0605cedc835;
@@ -14,43 +14,16 @@ const MUL_LCG16 @local = 0x915d; // TODO: Find good constant
// -------------------------------- Pcg128_64 --------------------------------
struct Pcg128Random
def Pcg128Random = distinct uint128;
fn void Pcg128Random.set_seed(&self, char[] input) : Random
{
inline Random random;
Pcg128RandomState state;
*self = (Pcg128Random)random::make_seed(uint128, input);
}
def Pcg128RandomState = distinct uint128;
const RandomInterface PCG_128_RANDOM_INTERFACE @local = {
.seed_fn = (RandomSeedFn)&Pcg128Random.set_seed,
.next_bytes_fn = (RandomNextBytesFn)&Pcg128Random.next_bytes,
};
fn void Pcg128Random.init(&self)
{
self.random.fns = &PCG_128_RANDOM_INTERFACE;
}
fn void Pcg128Random.set_seed(&self, char[] input)
{
self.state.set_seed(random::make_seed(uint128, input));
}
/**
* @require bytes.len > 0
**/
fn void Pcg128Random.next_bytes(&self, char[] bytes)
{
@random_value_to_bytes(self.state.next_long, bytes);
}
fn void Pcg128RandomState.set_seed(&self, uint128 seed)
{
*self = (Pcg128RandomState)seed;
}
fn ulong Pcg128RandomState.next_long(&self)
fn ulong Pcg128Random.next_long(&self)
{
const ROT_SHIFT = 64 - 6;
uint128* s = (uint128*)self;
@@ -60,46 +33,25 @@ fn ulong Pcg128RandomState.next_long(&self)
return ((ulong)(xor >> ROT_SHIFT)).rotr(rot);
}
// -------------------------------- Pcg64_32 --------------------------------
struct Pcg64Random
{
inline Random random;
Pcg64RandomState state;
}
def Pcg64RandomState = distinct ulong;
const RandomInterface PCG_64_RANDOM_INTERFACE @local = {
.seed_fn = (RandomSeedFn)&Pcg64Random.set_seed,
.next_bytes_fn = (RandomNextBytesFn)&Pcg64Random.next_bytes,
};
fn void Pcg64Random.init(&self)
{
self.random.fns = &PCG_64_RANDOM_INTERFACE;
}
fn void Pcg64Random.set_seed(&self, char[] input)
{
self.state.set_seed(random::make_seed(ulong, input));
}
/**
* @require bytes.len > 0
**/
fn void Pcg64Random.next_bytes(&self, char[] bytes)
fn void Pcg128Random.next_bytes(&self, char[] bytes) : Random => @random_value_to_bytes(self.next_long, bytes);
fn uint128 Pcg128Random.next_int128(&self) : Random => @long_to_int128(self.next_long());
fn uint Pcg128Random.next_int(&self) : Random => (uint)self.next_long();
fn ushort Pcg128Random.next_short(&self) : Random => (ushort)self.next_long();
fn char Pcg128Random.next_byte(&self) : Random => (char)self.next_long();
// -------------------------------- Pcg64_32 --------------------------------
def Pcg64Random = distinct ulong;
fn void Pcg64Random.set_seed(&self, char[] input) : Random
{
@random_value_to_bytes(self.state.next_int, bytes);
*self = (Pcg64Random)random::make_seed(ulong, input);
}
fn void Pcg64RandomState.set_seed(&self, ulong seed)
{
*self = (Pcg64RandomState)seed;
}
fn uint Pcg64RandomState.next_int(&self)
fn uint Pcg64Random.next_int(&self) : Random
{
const ROT_SHIFT = 32 - 5;
ulong* s = (ulong*)self;
@@ -109,46 +61,26 @@ fn uint Pcg64RandomState.next_int(&self)
return ((uint)(xor >> ROT_SHIFT)).rotr(rot);
}
// -------------------------------- Pcg32_16 --------------------------------
struct Pcg32Random
{
inline Random random;
Pcg32RandomState state;
}
def Pcg32RandomState = distinct uint;
const RandomInterface PCG_32_RANDOM_INTERFACE @local = {
.seed_fn = (RandomSeedFn)&Pcg32Random.set_seed,
.next_bytes_fn = (RandomNextBytesFn)&Pcg32Random.next_bytes,
};
fn void Pcg32Random.init(&self)
{
self.random.fns = &PCG_32_RANDOM_INTERFACE;
}
fn void Pcg32Random.set_seed(&self, char[] input)
{
self.state.set_seed(random::make_seed(uint, input));
}
/**
* @require bytes.len > 0
**/
fn void Pcg32Random.next_bytes(&self, char[] bytes)
fn void Pcg64Random.next_bytes(&self, char[] bytes) : Random => @random_value_to_bytes(self.next_int, bytes);
fn uint128 Pcg64Random.next_int128(&self) : Random => @long_to_int128(self.next_long());
fn ulong Pcg64Random.next_long(&self) : Random => @int_to_long(self.next_int());
fn ushort Pcg64Random.next_short(&self) : Random => (ushort)self.next_int();
fn char Pcg64Random.next_byte(&self) : Random => (char)self.next_int();
// -------------------------------- Pcg32_16 --------------------------------
def Pcg32Random = distinct uint;
fn void Pcg32Random.set_seed(&self, char[] input) : Random
{
@random_value_to_bytes(self.state.next_short, bytes);
*self = (Pcg32Random)random::make_seed(uint, input);
}
fn void Pcg32RandomState.set_seed(&self, uint seed)
{
*self = (Pcg32RandomState)seed;
}
fn ushort Pcg32RandomState.next_short(&self)
fn ushort Pcg32Random.next_short(&self) : Random
{
const ROT_SHIFT = 16 - 4;
uint* s = (uint*)self;
@@ -158,46 +90,25 @@ fn ushort Pcg32RandomState.next_short(&self)
return ((ushort)(xor >> ROT_SHIFT)).rotr(rot);
}
// -------------------------------- Pcg16_8 --------------------------------
struct Pcg16Random
{
inline Random random;
Pcg16RandomState state;
}
def Pcg16RandomState = distinct ushort;
const RandomInterface PCG_16_RANDOM_INTERFACE @local = {
.seed_fn = (RandomSeedFn)&Pcg16Random.set_seed,
.next_bytes_fn = (RandomNextBytesFn)&Pcg16Random.next_bytes,
};
fn void Pcg16Random.init(&self)
{
self.random.fns = &PCG_16_RANDOM_INTERFACE;
}
fn void Pcg16Random.set_seed(&self, char[] input)
{
self.state.set_seed(random::make_seed(ushort, input));
}
/**
* @require bytes.len > 0
**/
fn void Pcg16Random.next_bytes(&self, char[] bytes)
fn void Pcg32Random.next_bytes(&self, char[] bytes) : Random => @random_value_to_bytes(self.next_short, bytes);
fn uint128 Pcg32Random.next_int128(&self) : Random => @long_to_int128(self.next_long());
fn ulong Pcg32Random.next_long(&self) : Random => @int_to_long(self.next_int());
fn uint Pcg32Random.next_int(&self) : Random => @short_to_int(self.next_short());
fn char Pcg32Random.next_byte(&self) : Random => (char)self.next_short();
// -------------------------------- Pcg16_8 --------------------------------
def Pcg16Random = distinct ushort;
fn void Pcg16Random.set_seed(&self, char[] input) : Random
{
@random_value_to_bytes(self.state.next_byte, bytes);
*self = (Pcg16Random)random::make_seed(ushort, input);
}
fn void Pcg16RandomState.set_seed(&self, ushort seed)
{
*self = (Pcg16RandomState)seed;
}
fn char Pcg16RandomState.next_byte(&self)
fn char Pcg16Random.next_byte(&self) : Random
{
const ROT_SHIFT = 8 - 3;
ushort* s = (ushort*)self;
@@ -206,3 +117,9 @@ fn char Pcg16RandomState.next_byte(&self)
*s = *s * MUL_LCG16 + ODD_PHI16;
return ((char)(xor >> ROT_SHIFT)).rotr(rot);
}
fn void Pcg16Random.next_bytes(&self, char[] bytes) : Random => @random_value_to_bytes(self.next_byte, bytes);
fn uint128 Pcg16Random.next_int128(&self) : Random => @long_to_int128(self.next_long());
fn ulong Pcg16Random.next_long(&self) : Random => @int_to_long(self.next_int());
fn uint Pcg16Random.next_int(&self) : Random => @short_to_int(self.next_short());
fn ushort Pcg16Random.next_short(&self) : Random => @char_to_short(self.next_byte());

View File

@@ -1,4 +1,4 @@
module std::math;
module std::math::random;
// Move ODD_PHI into a shared module
const ODD_PHI128 @local = 0x9e3779b97f4a7c15f39cc0605cedc835;
@@ -8,46 +8,16 @@ const ODD_PHI16 @local = 0x9e37;
const ODD_PHI8 @local = 0x9f;
// -------------------------------- Sfc128 --------------------------------
// Sfc128
struct Sfc128Random
def Sfc128Random = distinct uint128[4];
fn void Sfc128Random.set_seed(&self, char[] input) : Random
{
inline Random random;
Sfc128RandomState state;
*self = (Sfc128Random)random::make_seed(uint128[4], input);
}
def Sfc128RandomState = distinct uint128[4];
const RandomInterface SFC_128_RANDOM_INTERFACE @local = {
.seed_fn = (RandomSeedFn)&Sfc128Random.set_seed,
.next_bytes_fn = (RandomNextBytesFn)&Sfc128Random.next_bytes,
};
fn void Sfc128Random.init(&self)
{
self.random.fns = &SFC_128_RANDOM_INTERFACE;
}
fn void Sfc128Random.set_seed(&self, char[] input)
{
self.state.set_seed(random::make_seed(uint128[4], input));
}
/**
* @require bytes.len > 0
**/
fn void Sfc128Random.next_bytes(&self, char[] bytes)
{
@random_value_to_bytes(self.state.next_int128, bytes);
}
fn void Sfc128RandomState.set_seed(&self, uint128[4] seed)
{
*self = (Sfc128RandomState)seed;
}
fn uint128 Sfc128RandomState.next_int128(&self) // TODO: Find good constant
fn uint128 Sfc128Random.next_int128(&self) : Random // TODO: Find good constant
{
uint128* s = (uint128[4]*)self;
uint128 result = s[0] + s[1] + s[3];
@@ -58,47 +28,26 @@ fn uint128 Sfc128RandomState.next_int128(&self) // TODO: Find good constant
return result;
}
// -------------------------------- Sfc64 --------------------------------
struct Sfc64Random
{
inline Random random;
Sfc64RandomState state;
}
def Sfc64RandomState = distinct ulong[4];
const RandomInterface SFC_64_RANDOM_INTERFACE @local = {
.seed_fn = (RandomSeedFn)&Sfc64Random.set_seed,
.next_bytes_fn = (RandomNextBytesFn)&Sfc64Random.next_bytes,
};
fn void Sfc64Random.init(&self)
{
self.random.fns = &SFC_64_RANDOM_INTERFACE;
}
fn void Sfc64Random.set_seed(&self, char[] input)
{
self.state.set_seed(random::make_seed(ulong[4], input));
}
/**
* @require bytes.len > 0
**/
fn void Sfc64Random.next_bytes(&self, char[] bytes)
fn void Sfc128Random.next_bytes(&self, char[] bytes) : Random => @random_value_to_bytes(self.next_int128, bytes);
fn ulong Sfc128Random.next_long(&self) : Random => (uint)self.next_int128();
fn uint Sfc128Random.next_int(&self) : Random => (uint)self.next_int128();
fn ushort Sfc128Random.next_short(&self) : Random => (ushort)self.next_int128();
fn char Sfc128Random.next_byte(&self) : Random => (char)self.next_int128();
// -------------------------------- Sfc64 --------------------------------
def Sfc64Random = distinct ulong[4];
fn void Sfc64Random.set_seed(&self, char[] input) : Random
{
@random_value_to_bytes(self.state.next_long, bytes);
*self = (Sfc64Random)random::make_seed(ulong[4], input);
}
fn void Sfc64RandomState.set_seed(&self, ulong[4] seed)
{
*self = (Sfc64RandomState)seed;
}
fn ulong Sfc64RandomState.next_long(&self)
fn ulong Sfc64Random.next_long(&self) : Random
{
ulong* s = (ulong[4]*)self;
ulong result = s[0] + s[1] + s[3];
@@ -109,47 +58,25 @@ fn ulong Sfc64RandomState.next_long(&self)
return result;
}
// -------------------------------- Sfc32 --------------------------------
struct Sfc32Random
{
inline Random random;
Sfc32RandomState state;
}
def Sfc32RandomState = distinct uint[4];
const RandomInterface SFC_32_RANDOM_INTERFACE @local = {
.seed_fn = (RandomSeedFn)&Sfc32Random.set_seed,
.next_bytes_fn = (RandomNextBytesFn)&Sfc32Random.next_bytes,
};
fn void Sfc32Random.init(&self)
{
self.random.fns = &SFC_32_RANDOM_INTERFACE;
}
fn void Sfc32Random.set_seed(&self, char[] input)
{
self.state.set_seed(random::make_seed(uint[4], input));
}
/**
* @require bytes.len > 0
**/
fn void Sfc32Random.next_bytes(&self, char[] bytes)
fn void Sfc64Random.next_bytes(&self, char[] bytes) : Random => @random_value_to_bytes(self.next_long, bytes);
fn uint128 Sfc64Random.next_int128(&self) : Random => @long_to_int128(self.next_long());
fn uint Sfc64Random.next_int(&self) : Random => (uint)self.next_long();
fn ushort Sfc64Random.next_short(&self) : Random => (ushort)self.next_long();
fn char Sfc64Random.next_byte(&self) : Random => (char)self.next_long();
// -------------------------------- Sfc32 --------------------------------
def Sfc32Random = distinct uint[4];
fn void Sfc32Random.set_seed(&self, char[] input) : Random
{
@random_value_to_bytes(self.state.next_int, bytes);
*self = (Sfc32Random)random::make_seed(uint[4], input);
}
fn void Sfc32RandomState.set_seed(&self, uint[4] seed)
{
*self = (Sfc32RandomState)seed;
}
fn uint Sfc32RandomState.next_int(&sfc)
fn uint Sfc32Random.next_int(&sfc) : Random
{
uint* s = (uint[4]*)sfc;
uint result = s[0] + s[1] + s[3];
@@ -160,46 +87,26 @@ fn uint Sfc32RandomState.next_int(&sfc)
return result;
}
// -------------------------------- Sfc16 --------------------------------
struct Sfc16Random
{
inline Random random;
Sfc16RandomState state;
}
def Sfc16RandomState = distinct ushort[4];
const RandomInterface SFC_16_RANDOM_INTERFACE @local = {
.seed_fn = (RandomSeedFn)&Sfc16Random.set_seed,
.next_bytes_fn = (RandomNextBytesFn)&Sfc16Random.next_bytes,
};
fn void Sfc16Random.init(&self)
{
self.random.fns = &SFC_16_RANDOM_INTERFACE;
}
fn void Sfc16Random.set_seed(&self, char[] input)
{
self.state.set_seed(random::make_seed(ushort[4], input));
}
/**
* @require bytes.len > 0
**/
fn void Sfc16Random.next_bytes(&self, char[] bytes)
fn void Sfc32Random.next_bytes(&self, char[] bytes) : Random => @random_value_to_bytes(self.next_int, bytes);
fn uint128 Sfc32Random.next_int128(&self) : Random => @long_to_int128(self.next_long());
fn ulong Sfc32Random.next_long(&self) : Random => @int_to_long(self.next_int());
fn ushort Sfc32Random.next_short(&self) : Random => (ushort)self.next_int();
fn char Sfc32Random.next_byte(&self) : Random => (char)self.next_int();
// -------------------------------- Sfc16 --------------------------------
def Sfc16Random = distinct ushort[4];
fn void Sfc16Random.set_seed(&self, char[] input) : Random
{
@random_value_to_bytes(self.state.next_short, bytes);
*self = (Sfc16Random)random::make_seed(ushort[4], input);
}
fn void Sfc16RandomState.set_seed(&self, ushort[4] seed)
{
*self = (Sfc16RandomState)seed;
}
fn ushort Sfc16RandomState.next_short(&seed)
fn ushort Sfc16Random.next_short(&seed) : Random
{
ushort* s = (ushort[4]*)seed;
ushort result = s[0] + s[1] + s[3];
@@ -210,46 +117,26 @@ fn ushort Sfc16RandomState.next_short(&seed)
return result;
}
// -------------------------------- Sfc8 --------------------------------
struct Sfc8Random
{
inline Random random;
Sfc8RandomState state;
}
def Sfc8RandomState = distinct char[4];
const RandomInterface SFC_8_RANDOM_INTERFACE @local = {
.seed_fn = (RandomSeedFn)&Sfc8Random.set_seed,
.next_bytes_fn = (RandomNextBytesFn)&Sfc8Random.next_bytes,
};
fn void Sfc8Random.init(&self)
{
self.random.fns = &SFC_8_RANDOM_INTERFACE;
}
fn void Sfc8Random.set_seed(&self, char[] input)
{
self.state.set_seed(random::make_seed(char[4], input));
}
/**
* @require bytes.len > 0
**/
fn void Sfc8Random.next_bytes(&self, char[] bytes)
fn void Sfc16Random.next_bytes(&self, char[] bytes) : Random => @random_value_to_bytes(self.next_short, bytes);
fn uint128 Sfc16Random.next_int128(&self) : Random => @long_to_int128(self.next_long());
fn ulong Sfc16Random.next_long(&self) : Random => @int_to_long(self.next_int());
fn uint Sfc16Random.next_int(&self) : Random => @short_to_int(self.next_short());
fn char Sfc16Random.next_byte(&self) : Random => (char)self.next_short();
// -------------------------------- Sfc8 --------------------------------
def Sfc8Random = distinct char[4];
fn void Sfc8Random.set_seed(&self, char[] input) : Random
{
@random_value_to_bytes(self.state.next_byte, bytes);
*self = (Sfc8Random)random::make_seed(char[4], input);
}
fn void Sfc8RandomState.set_seed(&self, char[4] seed)
{
*self = (Sfc8RandomState)seed;
}
fn char Sfc8RandomState.next_byte(&self) // TODO: Find better constants
fn char Sfc8Random.next_byte(&self) : Random // TODO: Find better constants
{
char* s = (char[4]*)self;
char result = s[0] + s[1] + s[3];
@@ -259,3 +146,9 @@ fn char Sfc8RandomState.next_byte(&self) // TODO: Find better constants
s[3] += ODD_PHI8;
return result;
}
fn void Sfc8Random.next_bytes(&self, char[] bytes) : Random => @random_value_to_bytes(self.next_byte, bytes);
fn uint128 Sfc8Random.next_int128(&self) : Random => @long_to_int128(self.next_long());
fn ulong Sfc8Random.next_long(&self) : Random => @int_to_long(self.next_int());
fn uint Sfc8Random.next_int(&self) : Random => @short_to_int(self.next_short());
fn ushort Sfc8Random.next_short(&self) : Random => @char_to_short(self.next_byte());

View File

@@ -1,53 +1,34 @@
module std::math;
module std::math::random;
struct SimpleRandom
{
inline Random random;
SimpleRandomState state;
}
def SimpleRandom = distinct ulong;
def SimpleRandomState = distinct ulong;
const RandomInterface SIMPLE_RANDOM_INTERFACE @local = {
.seed_fn = (RandomSeedFn)&SimpleRandom.set_seed,
.next_bytes_fn = (RandomNextBytesFn)&SimpleRandom.next_bytes,
};
fn void SimpleRandom.init(&self)
{
self.random.fns = &SIMPLE_RANDOM_INTERFACE;
}
/**
* @require bytes.len > 0
**/
fn void SimpleRandom.next_bytes(&self, char[] bytes)
{
@random_value_to_bytes(self.state.next_int, bytes);
}
fn void SimpleRandom.set_seed(&self, char[] seed)
fn void SimpleRandom.set_seed(&self, char[] seed) : Random
{
char[8] full;
foreach (i, c : seed)
{
full[i % 8] ^= c;
}
self.state.set_seed(bitcast(full, ulong));
*self = (SimpleRandom)(bitcast(full, ulong) ^ SIMPLE_RANDOM_MULTIPLIER) & SIMPLE_RANDOM_MASK;
}
fn void SimpleRandomState.set_seed(&self, ulong seed)
{
*self = (SimpleRandomState)(seed ^ SIMPLE_RANDOM_MULTIPLIER) & SIMPLE_RANDOM_MASK;
}
fn uint SimpleRandomState.next_int(&self)
fn uint SimpleRandom.next_int(&self) : Random
{
ulong nextseed = ((ulong)*self * SIMPLE_RANDOM_MULTIPLIER + SIMPLE_RANDOM_ADDEND) & SIMPLE_RANDOM_MASK;
*self = (SimpleRandomState)nextseed;
*self = (SimpleRandom)nextseed;
return (uint)(nextseed >> (48 - 32));
}
/**
* @require bytes.len > 0
**/
fn void SimpleRandom.next_bytes(&self, char[] bytes) : Random => @random_value_to_bytes(self.next_int, bytes);
fn uint128 SimpleRandom.next_int128(&self) : Random => @long_to_int128(self.next_long());
fn ulong SimpleRandom.next_long(&self) : Random => @int_to_long(self.next_int());
fn ushort SimpleRandom.next_short(&self) : Random => (ushort)self.next_int();
fn char SimpleRandom.next_byte(&self) : Random => (char)self.next_int();
const long SIMPLE_RANDOM_MULTIPLIER @local = 0x5DEECE66D;
const long SIMPLE_RANDOM_ADDEND @local = 0xB;
const long SIMPLE_RANDOM_MASK @local = (1u64 << 48) - 1;