mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Remove abs from libc. Create abstract random.
This commit is contained in:
@@ -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
119
lib/std/math/math.random.c3
Normal 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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
38
lib/std/math/random/math.simple_random.c3
Normal file
38
lib/std/math/random/math.simple_random.c3
Normal 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));
|
||||
}
|
||||
Reference in New Issue
Block a user