mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Make Random use protocols.
This commit is contained in:
committed by
Christoffer Lerno
parent
a1bce81ed0
commit
f3e3aa231d
@@ -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());
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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());
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user