mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 20:11:17 +00:00
209 lines
4.6 KiB
C
209 lines
4.6 KiB
C
module std::math;
|
|
|
|
// Move ODD_PHI into a shared module
|
|
const ODD_PHI128 @local = 0x9e3779b97f4a7c15f39cc0605cedc835;
|
|
const ODD_PHI64 @local = 0x9e3779b97f4a7c15;
|
|
const ODD_PHI32 @local = 0x9e3779b9;
|
|
const ODD_PHI16 @local = 0x9e37;
|
|
|
|
const MUL_LCG128 @local = 0xdb36357734e34abb0050d0761fcdfc15;
|
|
const MUL_LCG64 @local = 0xd1342543de82ef95;
|
|
const MUL_LCG32 @local = 0x915f77f5;
|
|
const MUL_LCG16 @local = 0x915d; // TODO: Find good constant
|
|
|
|
|
|
// -------------------------------- Pcg128_64 --------------------------------
|
|
|
|
struct Pcg128Random
|
|
{
|
|
inline Random random;
|
|
Pcg128RandomState state;
|
|
}
|
|
|
|
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)
|
|
{
|
|
const ROT_SHIFT = 64 - 6;
|
|
uint128* s = (uint128*)self;
|
|
uint128 xor = *s ^ *s >> ((128 - ROT_SHIFT) / 2);
|
|
char rot = (char)(*s >> (128 - 6));
|
|
*s = *s * MUL_LCG128 + ODD_PHI128;
|
|
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)
|
|
{
|
|
@random_value_to_bytes(self.state.next_int, bytes);
|
|
}
|
|
|
|
fn void Pcg64RandomState.set_seed(&self, ulong seed)
|
|
{
|
|
*self = (Pcg64RandomState)seed;
|
|
}
|
|
|
|
fn uint Pcg64RandomState.next_int(&self)
|
|
{
|
|
const ROT_SHIFT = 32 - 5;
|
|
ulong* s = (ulong*)self;
|
|
ulong xor = *s ^ *s >> ((64 - ROT_SHIFT) / 2);
|
|
char rot = (char)(*s >> (64 - 5));
|
|
*s = *s * MUL_LCG64 + ODD_PHI64;
|
|
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)
|
|
{
|
|
@random_value_to_bytes(self.state.next_short, bytes);
|
|
}
|
|
|
|
fn void Pcg32RandomState.set_seed(&self, uint seed)
|
|
{
|
|
*self = (Pcg32RandomState)seed;
|
|
}
|
|
|
|
fn ushort Pcg32RandomState.next_short(&self)
|
|
{
|
|
const ROT_SHIFT = 16 - 4;
|
|
uint* s = (uint*)self;
|
|
uint xor = *s ^ *s >> ((32 - ROT_SHIFT) / 2);
|
|
char rot = (char)(*s >> (32 - 4));
|
|
*s = *s * MUL_LCG32 + ODD_PHI32;
|
|
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)
|
|
{
|
|
@random_value_to_bytes(self.state.next_byte, bytes);
|
|
}
|
|
|
|
fn void Pcg16RandomState.set_seed(&self, ushort seed)
|
|
{
|
|
*self = (Pcg16RandomState)seed;
|
|
}
|
|
|
|
fn char Pcg16RandomState.next_byte(&self)
|
|
{
|
|
const ROT_SHIFT = 8 - 3;
|
|
ushort* s = (ushort*)self;
|
|
ushort xor = *s ^ *s >> ((16 - ROT_SHIFT) / 2);
|
|
char rot = (char)(*s >> (16 - 3));
|
|
*s = *s * MUL_LCG16 + ODD_PHI16;
|
|
return ((char)(xor >> ROT_SHIFT)).rotr(rot);
|
|
}
|