aboutsummaryrefslogtreecommitdiff
path: root/examples/random
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2025-04-06 21:43:19 -0400
committerBruce Hill <bruce@bruce-hill.com>2025-04-06 21:43:19 -0400
commitd8afa73368cdff38125fa1f7d17ad5ce54c84def (patch)
treeac4e54673da6ac32df1e351b913b7c1ddd1118b9 /examples/random
parentf4020db2f0d772481ba71edf78fbb65575badc00 (diff)
Improved inline C code: now uses `C_code` keyword and supports
interpolation with @
Diffstat (limited to 'examples/random')
-rw-r--r--examples/random/random.tm191
1 files changed, 92 insertions, 99 deletions
diff --git a/examples/random/random.tm b/examples/random/random.tm
index 94528dd7..13600b47 100644
--- a/examples/random/random.tm
+++ b/examples/random/random.tm
@@ -5,77 +5,72 @@ use ./chacha.h
struct chacha_ctx(j0,j1,j2,j3,j4,j5,j6,j7,j8,j9,j10,j11,j12,j13,j14,j15:Int32; extern, secret)
func from_seed(seed:[Byte]=[] -> chacha_ctx)
- return inline C : chacha_ctx {
+ return C_code:chacha_ctx(
chacha_ctx ctx;
uint8_t seed_bytes[KEYSZ + IVSZ] = {};
for (int64_t i = 0; i < (int64_t)sizeof(seed_bytes); i++)
- seed_bytes[i] = i < _$seed.length ? *(uint8_t*)(_$seed.data + i*_$seed.stride) : 0;
+ seed_bytes[i] = i < @seed.length ? *(uint8_t*)(@seed.data + i*@seed.stride) : 0;
chacha_keysetup(&ctx, seed_bytes);
chacha_ivsetup(&ctx, seed_bytes + KEYSZ);
- ctx;
- }
+ ctx
+ )
random := RandomNumberGenerator.new()
func _os_random_bytes(count:Int64 -> [Byte])
- return inline C : [Byte] {
- uint8_t *random_bytes = GC_MALLOC_ATOMIC(_$count);
- getrandom(random_bytes, _$count, 0);
- (Array_t){.length=_$count, .data=random_bytes, .stride=1, .atomic=1};
- }
-
+ return C_code:[Byte](
+ uint8_t *random_bytes = GC_MALLOC_ATOMIC(@count);
+ getrandom(random_bytes, @count, 0);
+ (Array_t){.length=@count, .data=random_bytes, .stride=1, .atomic=1}
+ )
struct RandomNumberGenerator(_chacha:chacha_ctx, _random_bytes:[Byte]=[]; secret)
func new(seed:[Byte]?=none, -> @RandomNumberGenerator)
ctx := chacha_ctx.from_seed(seed or _os_random_bytes(40))
return @RandomNumberGenerator(ctx, [])
func _rekey(rng:&RandomNumberGenerator)
- rng._random_bytes = inline C : [Byte] {
+ rng._random_bytes = C_code:[Byte](
Byte_t new_keystream[KEYSZ + IVSZ] = {};
// Fill the buffer with the keystream
- chacha_encrypt_bytes(&_$rng->_chacha, new_keystream, new_keystream, sizeof(new_keystream));
+ chacha_encrypt_bytes(&@rng->_chacha, new_keystream, new_keystream, sizeof(new_keystream));
// Immediately reinitialize for backtracking resistance
- chacha_keysetup(&_$rng->_chacha, new_keystream);
- chacha_ivsetup(&_$rng->_chacha, new_keystream + KEYSZ);
+ chacha_keysetup(&@rng->_chacha, new_keystream);
+ chacha_ivsetup(&@rng->_chacha, new_keystream + KEYSZ);
Array_t new_bytes = (Array_t){.data=GC_MALLOC_ATOMIC(1024), .length=1024, .stride=1, .atomic=1};
memset(new_bytes.data, 0, new_bytes.length);
- chacha_encrypt_bytes(&_$rng->_chacha, new_bytes.data, new_bytes.data, new_bytes.length);
- new_bytes;
- }
+ chacha_encrypt_bytes(&@rng->_chacha, new_bytes.data, new_bytes.data, new_bytes.length);
+ new_bytes
+ )
func _fill_bytes(rng:&RandomNumberGenerator, dest:&Memory, needed:Int64)
- inline C {
- while (_$needed > 0) {
- if (_$rng->_random_bytes.length == 0)
- _$random$RandomNumberGenerator$_rekey(_$rng);
+ C_code {
+ while (@needed > 0) {
+ if (@rng->_random_bytes.length == 0)
+ @(rng._rekey());
- assert(_$rng->_random_bytes.stride == 1);
+ assert(@rng->_random_bytes.stride == 1);
- int64_t batch_size = MIN(_$needed, _$rng->_random_bytes.length);
- uint8_t *batch_src = _$rng->_random_bytes.data;
- memcpy(_$dest, batch_src, batch_size);
+ int64_t batch_size = MIN(@needed, @rng->_random_bytes.length);
+ uint8_t *batch_src = @rng->_random_bytes.data;
+ memcpy(@dest, batch_src, batch_size);
memset(batch_src, 0, batch_size);
- _$rng->_random_bytes.data += batch_size;
- _$rng->_random_bytes.length -= batch_size;
- _$dest += batch_size;
- _$needed -= batch_size;
+ @rng->_random_bytes.data += batch_size;
+ @rng->_random_bytes.length -= batch_size;
+ @dest += batch_size;
+ @needed -= batch_size;
}
}
func bytes(rng:&RandomNumberGenerator, count:Int -> [Byte])
- return inline C : [Byte] {
- int64_t count64 = Int64$from_int(_$count, false);
- Array_t ret = {.data=GC_MALLOC_ATOMIC(count64), .stride=1, .atomic=1, .length=count64};
- _$random$RandomNumberGenerator$_fill_bytes(_$rng, ret.data, count64);
- ret;
- }
+ count64 := Int64(count)
+ buf := C_code:@Memory(GC_MALLOC_ATOMIC(@count64))
+ rng._fill_bytes(buf, count64)
+ return C_code:[Byte]((Array_t){.data=@buf, .stride=1, .atomic=1, .length=@count64})
func byte(rng:&RandomNumberGenerator -> Byte)
- return inline C : Byte {
- Byte_t b;
- _$random$RandomNumberGenerator$_fill_bytes(_$rng, &b, sizeof(b));
- b;
- }
+ byte : &Byte
+ rng._fill_bytes(byte, 1)
+ return byte[]
func bool(rng:&RandomNumberGenerator, probability=0.5 -> Bool)
if probability == 0.5
@@ -86,97 +81,95 @@ struct RandomNumberGenerator(_chacha:chacha_ctx, _random_bytes:[Byte]=[]; secret
func int64(rng:&RandomNumberGenerator, min=Int64.min, max=Int64.max -> Int64)
fail("Random minimum value $min is larger than the maximum value $max") if min > max
return min if min == max
+ random_int64 : &Int64
+ rng._fill_bytes(random_int64, 8)
if min == Int64.min and max == Int64.max
- return inline C : Int64 {
- int64_t i;
- _$random$RandomNumberGenerator$_fill_bytes(_$rng, &i, sizeof(i));
- i;
- }
+ return random_int64
- return inline C : Int64 {
- uint64_t range = (uint64_t)_$max - (uint64_t)_$min + 1;
+ return C_code:Int64(
+ uint64_t range = (uint64_t)@max - (uint64_t)@min + 1;
uint64_t min_r = -range % range;
uint64_t r;
+ @random_int64 = &r;
for (;;) {
- _$random$RandomNumberGenerator$_fill_bytes(_$rng, (uint8_t*)&r, sizeof(r));
+ @(rng._fill_bytes(random_int64, 8));
if (r >= min_r) break;
}
- (int64_t)((uint64_t)_$min + (r % range));
- }
+ (int64_t)((uint64_t)@min + (r % range))
+ )
func int32(rng:&RandomNumberGenerator, min=Int32.min, max=Int32.max -> Int32)
fail("Random minimum value $min is larger than the maximum value $max") if min > max
return min if min == max
+ random_int32 : &Int32
+ rng._fill_bytes(random_int32, 8)
if min == Int32.min and max == Int32.max
- return inline C : Int32 {
- int32_t i;
- _$random$RandomNumberGenerator$_fill_bytes(_$rng, &i, sizeof(i));
- i;
- }
+ return random_int32
- return inline C : Int32 {
- uint32_t range = (uint32_t)_$max - (uint32_t)_$min + 1;
+ return C_code:Int32(
+ uint32_t range = (uint32_t)@max - (uint32_t)@min + 1;
uint32_t min_r = -range % range;
uint32_t r;
+ @random_int32 = &r;
for (;;) {
- _$random$RandomNumberGenerator$_fill_bytes(_$rng, (uint8_t*)&r, sizeof(r));
+ @(rng._fill_bytes(random_int32, 8));
if (r >= min_r) break;
}
- (int32_t)((uint32_t)_$min + (r % range));
- }
+ (int32_t)((uint32_t)@min + (r % range))
+ )
func int16(rng:&RandomNumberGenerator, min=Int16.min, max=Int16.max -> Int16)
fail("Random minimum value $min is larger than the maximum value $max") if min > max
return min if min == max
+ random_int16 : &Int16
+ rng._fill_bytes(random_int16, 8)
if min == Int16.min and max == Int16.max
- return inline C : Int16 {
- int16_t i;
- _$random$RandomNumberGenerator$_fill_bytes(_$rng, &i, sizeof(i));
- i;
- }
+ return random_int16
- return inline C : Int16 {
- uint16_t range = (uint16_t)_$max - (uint16_t)_$min + 1;
+ return C_code:Int16(
+ uint16_t range = (uint16_t)@max - (uint16_t)@min + 1;
uint16_t min_r = -range % range;
uint16_t r;
+ @random_int16 = &r;
for (;;) {
- _$random$RandomNumberGenerator$_fill_bytes(_$rng, (uint8_t*)&r, sizeof(r));
+ @(rng._fill_bytes(random_int16, 8));
if (r >= min_r) break;
}
- (int16_t)((uint16_t)_$min + (r % range));
- }
+ (int16_t)((uint16_t)@min + (r % range))
+ )
func int8(rng:&RandomNumberGenerator, min=Int8.min, max=Int8.max -> Int8)
fail("Random minimum value $min is larger than the maximum value $max") if min > max
return min if min == max
+ random_int8 : &Int8
+ rng._fill_bytes(random_int8, 8)
if min == Int8.min and max == Int8.max
- return inline C : Int8 {
- int8_t i;
- _$random$RandomNumberGenerator$_fill_bytes(_$rng, &i, sizeof(i));
- i;
- }
+ return random_int8
- return inline C : Int8 {
- uint8_t range = (uint8_t)_$max - (uint8_t)_$min + 1;
+ return C_code:Int8(
+ uint8_t range = (uint8_t)@max - (uint8_t)@min + 1;
uint8_t min_r = -range % range;
uint8_t r;
+ @random_int8 = &r;
for (;;) {
- _$random$RandomNumberGenerator$_fill_bytes(_$rng, (uint8_t*)&r, sizeof(r));
+ @(rng._fill_bytes(random_int8, 8));
if (r >= min_r) break;
}
- (int8_t)((uint8_t)_$min + (r % range));
- }
+ (int8_t)((uint8_t)@min + (r % range))
+ )
func num(rng:&RandomNumberGenerator, min=0., max=1. -> Num)
- return inline C : Num {
- if (_$min > _$max) fail("Random minimum value (", _$min, ") is larger than the maximum value (", _$max, ")");
- if (_$min == _$max) return _$min;
+ num_buf : &Num
+ return C_code:Num(
+ if (@min > @max) fail("Random minimum value (", @min, ") is larger than the maximum value (", @max, ")");
+ if (@min == @max) return @min;
union {
Num_t num;
uint64_t bits;
} r = {.bits=0}, one = {.num=1.0};
- _$random$RandomNumberGenerator$_fill_bytes(_$rng, (uint8_t*)&r, sizeof(r));
+ @num_buf = &r.num;
+ @(rng._fill_bytes(num_buf, 8));
// Set r.num to 1.<random-bits>
r.bits &= ~(0xFFFULL << 52);
@@ -184,37 +177,37 @@ struct RandomNumberGenerator(_chacha:chacha_ctx, _random_bytes:[Byte]=[]; secret
r.num -= 1.0;
- (_$min == 0.0 && _$max == 1.0) ? r.num : ((1.0-r.num)*_$min + r.num*_$max);
- }
+ (@min == 0.0 && @max == 1.0) ? r.num : ((1.0-r.num)*@min + r.num*@max)
+ )
func num32(rng:&RandomNumberGenerator, min=Num32(0.), max=Num32(1.) -> Num32)
return Num32(rng.num(Num(min), Num(max)))
func int(rng:&RandomNumberGenerator, min:Int, max:Int -> Int)
- return inline C : Int {
- if (likely(((_$min.small & _$max.small) & 1) != 0)) {
- int32_t r = _$random$RandomNumberGenerator$int32(_$rng, (int32_t)(_$min.small >> 2), (int32_t)(_$max.small >> 2));
+ return C_code:Int(
+ if (likely(((@min.small & @max.small) & 1) != 0)) {
+ int32_t r = @(rng.int32(Int32(min), Int32(max)));
return I_small(r);
}
- int32_t cmp = Int$compare_value(_$min, _$max);
+ int32_t cmp = @(min <> max);
if (cmp > 0)
- fail("Random minimum value (", _$min, ") is larger than the maximum value (", _$max, ")");
- if (cmp == 0) return _$min;
+ fail("Random minimum value (", @min, ") is larger than the maximum value (", @max, ")");
+ if (cmp == 0) return @min;
mpz_t range_size;
- mpz_init_set_int(range_size, _$max);
- if (_$min.small & 1) {
+ mpz_init_set_int(range_size, @max);
+ if (@min.small & 1) {
mpz_t min_mpz;
- mpz_init_set_si(min_mpz, _$min.small >> 2);
+ mpz_init_set_si(min_mpz, @min.small >> 2);
mpz_sub(range_size, range_size, min_mpz);
} else {
- mpz_sub(range_size, range_size, *_$min.big);
+ mpz_sub(range_size, range_size, *@min.big);
}
gmp_randstate_t gmp_rng;
gmp_randinit_default(gmp_rng);
- int64_t seed = _$random$RandomNumberGenerator$int64(_$rng, INT64_MIN, INT64_MAX);
+ int64_t seed = @(rng.int64());
gmp_randseed_ui(gmp_rng, (unsigned long)seed);
mpz_t r;
@@ -222,8 +215,8 @@ struct RandomNumberGenerator(_chacha:chacha_ctx, _random_bytes:[Byte]=[]; secret
mpz_urandomm(r, gmp_rng, range_size);
gmp_randclear(gmp_rng);
- Int$plus(_$min, Int$from_mpz(r));
- }
+ Int$plus(@min, Int$from_mpz(r))
+ )
func main()