Remove abs from libc. Create abstract random.

This commit is contained in:
Christoffer Lerno
2023-02-24 00:00:36 +01:00
parent 2a6339a25e
commit fc0cad2894
4 changed files with 157 additions and 48 deletions

View File

@@ -52,7 +52,6 @@ extern fn int unsetenv(ZString name);
extern fn int system(char* str);
extern fn void bsearch(void* key, void *base, usz items, usz size, CompareFunction compare);
extern fn void qsort(void* base, usz items, usz size, CompareFunction compare);
extern fn int abs(int x);
extern fn DivResult div(int numer, int denom);
extern fn long labs(long x);
extern fn LongDivResult ldiv(long number, long denom);

119
lib/std/math/math.random.c3 Normal file
View File

@@ -0,0 +1,119 @@
module std::math;
struct Random
{
RandomInterface fns;
void* state;
}
typedef RandomSeedFn = fn void(Random*, char[] seed);
typedef RandomNextBytesFn = fn void(Random*, char[] buffer);
typedef 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;
}

View File

@@ -1,47 +0,0 @@
module std::math;
struct SimpleRandom
{
long seed;
}
const long SIMPLE_RANDOM_MULTIPLIER @private = 0x5DEECE66D;
const long SIMPLE_RANDOM_ADDEND @private = 0xB;
const long SIMPLE_RANDOM_MASK @private = (1i64 << 48) - 1;
fn long simple_random_initial_scramble(long seed) @private
{
return (seed ^ SIMPLE_RANDOM_MULTIPLIER) & SIMPLE_RANDOM_MASK;
}
fn int SimpleRandom.next(SimpleRandom* r, int bits) @private
{
long nextseed = (r.seed * SIMPLE_RANDOM_MULTIPLIER + SIMPLE_RANDOM_ADDEND) & SIMPLE_RANDOM_MASK;
r.seed = nextseed;
return (int)nextseed >> (48 - bits);
}
fn void SimpleRandom.set_seed(SimpleRandom* r, long seed)
{
r.seed = simple_random_initial_scramble(seed);
}
fn int SimpleRandom.next_int(SimpleRandom* r)
{
return r.next(32) @inline;
}
fn bool SimpleRandom.next_bool(SimpleRandom* r)
{
return r.next(1) != 0;
}
fn float SimpleRandom.next_float(SimpleRandom* r)
{
return r.next(24) / (float)(1 << 24);
}
fn double SimpleRandom.next_double(SimpleRandom* r)
{
return (((long)(r.next(26)) << 27) + r.next(27)) * 0x1.0p-53;
}

View File

@@ -0,0 +1,38 @@
module std::math;
typedef SimpleRandom = distinct ulong;
const long SIMPLE_RANDOM_MULTIPLIER @local = 0x5DEECE66D;
const long SIMPLE_RANDOM_ADDEND @local = 0xB;
const long SIMPLE_RANDOM_MASK @local = (1u64 << 48) - 1;
RandomInterface simple_random_interface = {
.seed_fn = fn (random, seed) => ((SimpleRandom*)random.state).set_seeds(seed),
.next_fn = fn (random, bits) => ((SimpleRandom*)random.state).next(bits)
};
fn Random SimpleRandom.as_random(SimpleRandom* random)
{
return { .fns = simple_random_interface, .state = random };
}
fn uint SimpleRandom.next(SimpleRandom* r, int bits)
{
ulong nextseed = ((ulong)*r * SIMPLE_RANDOM_MULTIPLIER + SIMPLE_RANDOM_ADDEND) & SIMPLE_RANDOM_MASK;
*r = (SimpleRandom)nextseed;
return (uint)(nextseed >> (48 - bits));
}
fn void SimpleRandom.set_seed(SimpleRandom* r, ulong seed)
{
*r = (SimpleRandom)((seed ^ SIMPLE_RANDOM_MULTIPLIER) & SIMPLE_RANDOM_MASK);
}
fn void SimpleRandom.set_seeds(SimpleRandom* r, char[] seed)
{
char[8] full;
foreach (i, c : seed)
{
full[i % 8] ^= c;
}
r.set_seed(bitcast(full, ulong));
}