mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
120 lines
2.2 KiB
C
120 lines
2.2 KiB
C
module std::math;
|
|
|
|
struct Random
|
|
{
|
|
RandomInterface fns;
|
|
void* state;
|
|
}
|
|
|
|
def RandomSeedFn = fn void(Random*, char[] seed);
|
|
def RandomNextBytesFn = fn void(Random*, char[] buffer);
|
|
def RandomNextFn = fn uint(Random*, int bits);
|
|
|
|
struct RandomInterface
|
|
{
|
|
RandomSeedFn seed_fn;
|
|
RandomNextBytesFn next_bytes_fn;
|
|
RandomNextFn next_fn;
|
|
}
|
|
|
|
/**
|
|
* @param [&inout] random
|
|
* @param [inout] buffer
|
|
**/
|
|
fn void Random.next_bytes(Random* random, char[] buffer)
|
|
{
|
|
if (!buffer.len) return;
|
|
if (RandomNextBytesFn func = random.fns.next_bytes_fn)
|
|
{
|
|
func(random, buffer);
|
|
return;
|
|
}
|
|
if (RandomNextFn func = random.fns.next_fn)
|
|
{
|
|
usz current = 0;
|
|
while (current < buffer.len)
|
|
{
|
|
char[4] res = bitcast(func(random, 32), char[4]);
|
|
foreach (c : res)
|
|
{
|
|
buffer[current++] = c;
|
|
if (current == buffer.len) return;
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
unreachable("Invalid Random type.");
|
|
}
|
|
|
|
/**
|
|
* @param [&inout] random
|
|
* @require bits >= 0 && bits <= 32
|
|
**/
|
|
fn uint Random.next(Random* random, int bits)
|
|
{
|
|
if (bits == 0) return 0;
|
|
if (RandomNextFn func = random.fns.next_fn) return func(random, bits);
|
|
int bytes = (bits + 7) / 8;
|
|
char[4] buffer;
|
|
char[] b = buffer[:bytes];
|
|
assert(random.fns.next_bytes_fn, "Invalid Random");
|
|
random.fns.next_bytes_fn(random, b) @inline;
|
|
uint next = 0;
|
|
foreach (char c : b)
|
|
{
|
|
next = next << 8 + c;
|
|
}
|
|
if (bits < 32) next >>= bytes * 8 - bits;
|
|
return next;
|
|
}
|
|
|
|
/**
|
|
* @param [&inout] random
|
|
**/
|
|
fn ulong Random.next_long(Random* random)
|
|
{
|
|
char[8] buffer;
|
|
random.next_bytes(&buffer);
|
|
return bitcast(buffer, ulong);
|
|
}
|
|
|
|
/**
|
|
* @param [&inout] random
|
|
**/
|
|
fn void Random.set_seed(Random* random, long seed)
|
|
{
|
|
random.fns.seed_fn(random, &&bitcast(seed, char[8])) @inline;
|
|
}
|
|
|
|
/**
|
|
* @param [&inout] random
|
|
* @param [in] seed
|
|
**/
|
|
fn void Random.set_seeds(Random* random, char[] seed)
|
|
{
|
|
random.fns.seed_fn(random, seed);
|
|
}
|
|
|
|
/**
|
|
* @param [&inout] random
|
|
**/
|
|
fn bool Random.next_bool(Random* random)
|
|
{
|
|
return random.next(1) != 0;
|
|
}
|
|
|
|
fn float Random.next_float(Random* r)
|
|
{
|
|
return r.next(24) / (float)(1 << 24);
|
|
}
|
|
|
|
fn double Random.next_double(Random* r)
|
|
{
|
|
return (((long)(r.next(26)) << 27) + r.next(27)) * 0x1.0p-53;
|
|
}
|
|
|
|
fn uint Random.next_int(Random* r)
|
|
{
|
|
return r.next(32) @inline;
|
|
}
|