From 796394712d0535cb61ddf9ee6dd2423303a4ffcb Mon Sep 17 00:00:00 2001 From: Brendan Hansen Date: Mon, 13 Feb 2023 12:42:50 -0600 Subject: [PATCH] refactored and documented random.onyx --- core/random/random.onyx | 126 +++++++++++++++++++++++++++++++--------- 1 file changed, 97 insertions(+), 29 deletions(-) diff --git a/core/random/random.onyx b/core/random/random.onyx index 527fb16f..20c7ccdd 100644 --- a/core/random/random.onyx +++ b/core/random/random.onyx @@ -1,42 +1,110 @@ package core.random -#local seed : i64 = 8675309 +// +// The state of a random number generator. +Random :: struct { + seed: i64; +} -#local RANDOM_MULTIPLIER :: 25214903917 -#local RANDOM_INCREMENT :: cast(i64) 11 -// #local RANDOM_MODULUS :: 1 << 32 +#inject Random { + // + // Creates a new random number generator. + // An initial seed can be passed in, otherwise the + // current UNIX time is used. + make :: (seed: i64 = core.os.time()) -> Random { + return .{ seed }; + } -set_seed :: #match { - (s: u32) do seed = ~~s; , - (s: u64) do seed = s; , -} + // + // Sets the seed of the random number generator + set_seed :: #match { + (self: ^Random, s: u32) { self.seed = ~~s; }, + (self: ^Random, s: u64) { self.seed = s; }, + } -int :: (s := ^seed) -> u32 { - *s = *s * RANDOM_MULTIPLIER + RANDOM_INCREMENT; - return cast(u32) ((*s >> 16) & ~~0xffffffff); -} + // + // Generates a random 32-bit integer. + int :: (self: ^Random) -> u32 { + s := self.seed * RANDOM_MULTIPLIER + RANDOM_INCREMENT; + defer self.seed = s; + return cast(u32) ((s >> 16) & ~~0xffffffff); + } -between :: (lo: i32, hi: i32) -> i32 do return int () % (hi + 1 - lo) + lo; + // + // Generates a random 32-bit integer between `lo` and `hi`. + between :: (self: ^Random, lo: i32, hi: i32) -> i32 { + return self->int() % (hi + 1 - lo) + lo; + } -float :: (lo := 0.0f, hi := 1.0f) -> f32 { - return (cast(f32) (int() % (1 << 20)) / cast(f32) (1 << 20)) * (hi - lo) + lo; -} + // + // Generates a random floating point number between `lo` and `hi`. + float :: (self: ^Random, lo := 0.0f, hi := 1.0f) -> f32 { + return (cast(f32) (self->int() % (1 << 20)) / cast(f32) (1 << 20)) * (hi - lo) + lo; + } -choice :: (a: [] $T) -> T { - return a[between(0, a.count - 1)]; -} + // + // Returns a random element from a slice. + choice :: (self: ^Random, a: [] $T) -> T { + return a[self->between(0, a.count - 1)]; + } -string :: (bytes_long: u32, alpha_numeric := false, allocator := context.allocator) -> str { - memory :: package core.memory + // + // Returns a random string of length `bytes_long`. If `alpha_numeric` is + // true, then the string will only consist of alpha-numeric characters. + string :: (self: ^Random, bytes_long: u32, alpha_numeric := false, allocator := context.allocator) -> str { + memory :: package core.memory - s := memory.make_slice(u8, bytes_long, allocator=allocator); - for^ s { - if alpha_numeric { - #persist alpha_numeral := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; - *it = choice(alpha_numeral); - } else { - *it = ~~between(32, 127); + s := memory.make_slice(u8, bytes_long, allocator=allocator); + for^ s { + if alpha_numeric { + #persist alpha_numeral := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + *it = self->choice(alpha_numeral); + } else { + *it = ~~(self->between(32, 127)); + } } + return s; } - return s; } + +// +// Below are procedures that use a global random number +// generator for quick random number generation. +// + + +// +// The global random state. +global_random := Random.{ 8675309 }; + +set_seed :: #match { + (s: u32) { global_random->set_seed(~~s); }, + (s: u64) { global_random->set_seed(s); }, +} + +int :: () => + global_random->int(); + +between :: (lo: i32, hi: i32) => + global_random->between(lo, hi); + +float :: (lo := 0.0f, hi := 1.0f) => + global_random->float(lo, hi); + +choice :: (a: [] $T) => + global_random->choice(a); + +string :: (bytes_long: u32, alpha_numeric := false, allocator := context.allocator) => + global_random->string(bytes_long, alpha_numeric, allocator); + + + +// +// Internal implementation details +// + +#package { + RANDOM_MULTIPLIER :: 25214903917 + RANDOM_INCREMENT :: cast(i64) 11 +} + -- 2.25.1