rand: document all functions, document range notation form, fix copy-pasta (#7619)

pull/7634/head
Larpon 2020-12-27 19:06:17 +01:00 committed by GitHub
parent b9df7aae4d
commit ed6ba0a2b8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 169 additions and 154 deletions

View File

@ -59,3 +59,10 @@ A workaround (if you _must_ use the libc RNG) is to:
3. Seed the second instance. 3. Seed the second instance.
4. Generate all values required. 4. Generate all values required.
5. And so on... 5. And so on...
# Notes
Please note that [math interval](https://en.wikipedia.org/wiki/Interval_(mathematics)#Including_or_excluding_endpoints) notation is used throughout
the function documentation to denote what numbers ranges include.
An example of `[0, max)` thus denotes a range with all posible values
between `0` and `max` **including** 0 but **excluding** `max`.

View File

@ -56,7 +56,7 @@ const (
inv_f64_limit = 1.0 / 9007199254740992.0 inv_f64_limit = 1.0 / 9007199254740992.0
) )
// A generator that uses the Mersenne Twister algorithm with period 2^19937 // MT19937RNG is generator that uses the Mersenne Twister algorithm with period 2^19937.
pub struct MT19937RNG { pub struct MT19937RNG {
mut: mut:
state []u64 = calculate_state(util.time_seed_array(2), mut []u64{len: nn}) state []u64 = calculate_state(util.time_seed_array(2), mut []u64{len: nn})
@ -65,6 +65,7 @@ mut:
has_next bool has_next bool
} }
// calculate_state returns a random state array calculated from the `seed_data`.
fn calculate_state(seed_data []u32, mut state []u64) []u64 { fn calculate_state(seed_data []u32, mut state []u64) []u64 {
lo := u64(seed_data[0]) lo := u64(seed_data[0])
hi := u64(seed_data[1]) hi := u64(seed_data[1])
@ -75,7 +76,8 @@ fn calculate_state(seed_data []u32, mut state []u64) []u64 {
return *state return *state
} }
// seed() - Set the seed, needs only two u32s in little endian format as [lower, higher] // seed sets the current random state based on `seed_data`.
// seed expects `seed_data` to be only two `u32`s in little-endian format as [lower, higher].
pub fn (mut rng MT19937RNG) seed(seed_data []u32) { pub fn (mut rng MT19937RNG) seed(seed_data []u32) {
if seed_data.len != 2 { if seed_data.len != 2 {
eprintln('mt19937 needs only two 32bit integers as seed: [lower, higher]') eprintln('mt19937 needs only two 32bit integers as seed: [lower, higher]')
@ -87,7 +89,7 @@ pub fn (mut rng MT19937RNG) seed(seed_data []u32) {
rng.has_next = false rng.has_next = false
} }
// rng.u32() - return a pseudorandom 32bit int in [0, 2**32) // u32 returns a pseudorandom 32bit int in range `[0, 2³²)`.
[inline] [inline]
pub fn (mut rng MT19937RNG) u32() u32 { pub fn (mut rng MT19937RNG) u32() u32 {
if rng.has_next { if rng.has_next {
@ -100,7 +102,7 @@ pub fn (mut rng MT19937RNG) u32() u32 {
return u32(ans & 0xffffffff) return u32(ans & 0xffffffff)
} }
// rng.u64() - return a pseudorandom 64bit int in [0, 2**64) // u64 returns a pseudorandom 64bit int in range `[0, 2⁶⁴)`.
[inline] [inline]
pub fn (mut rng MT19937RNG) u64() u64 { pub fn (mut rng MT19937RNG) u64() u64 {
mag01 := [u64(0), u64(matrix_a)] mag01 := [u64(0), u64(matrix_a)]
@ -129,35 +131,35 @@ pub fn (mut rng MT19937RNG) u64() u64 {
return x return x
} }
// rng.int() - return a 32-bit signed (possibly negative) int // int returns a 32-bit signed (possibly negative) `int`.
[inline] [inline]
pub fn (mut rng MT19937RNG) int() int { pub fn (mut rng MT19937RNG) int() int {
return int(rng.u32()) return int(rng.u32())
} }
// rng.i64() - return a 64-bit signed (possibly negative) i64 // i64 returns a 64-bit signed (possibly negative) `i64`.
[inline] [inline]
pub fn (mut rng MT19937RNG) i64() i64 { pub fn (mut rng MT19937RNG) i64() i64 {
return i64(rng.u64()) return i64(rng.u64())
} }
// rng.int31() - return a 31bit positive pseudorandom integer // int31 returns a 31bit positive pseudorandom `int`.
[inline] [inline]
pub fn (mut rng MT19937RNG) int31() int { pub fn (mut rng MT19937RNG) int31() int {
return int(rng.u32() >> 1) return int(rng.u32() >> 1)
} }
// rng.int63() - return a 63bit positive pseudorandom integer // int63 returns a 63bit positive pseudorandom `i64`.
[inline] [inline]
pub fn (mut rng MT19937RNG) int63() i64 { pub fn (mut rng MT19937RNG) int63() i64 {
return i64(rng.u64() >> 1) return i64(rng.u64() >> 1)
} }
// rng.u32n(max) - return a 32bit u32 in [0, max) // u32n returns a 32bit `u32` in range `[0, max)`.
[inline] [inline]
pub fn (mut rng MT19937RNG) u32n(max u32) u32 { pub fn (mut rng MT19937RNG) u32n(max u32) u32 {
if max == 0 { if max == 0 {
eprintln('max must be positive integer') eprintln('max must be positive integer.')
exit(1) exit(1)
} }
// Check SysRNG in system_rng.c.v for explanation // Check SysRNG in system_rng.c.v for explanation
@ -181,11 +183,11 @@ pub fn (mut rng MT19937RNG) u32n(max u32) u32 {
return u32(0) return u32(0)
} }
// rng.u64n(max) - return a 64bit u64 in [0, max) // u64n returns a 64bit `u64` in range `[0, max)`.
[inline] [inline]
pub fn (mut rng MT19937RNG) u64n(max u64) u64 { pub fn (mut rng MT19937RNG) u64n(max u64) u64 {
if max == 0 { if max == 0 {
eprintln('max must be positive integer') eprintln('max must be positive integer.')
exit(1) exit(1)
} }
bit_len := bits.len_64(max) bit_len := bits.len_64(max)
@ -208,27 +210,27 @@ pub fn (mut rng MT19937RNG) u64n(max u64) u64 {
return u64(0) return u64(0)
} }
// rng.u32n(min, max) returns a pseudorandom u32 value that is guaranteed to be in [min, max) // u32n returns a pseudorandom `u32` value that is guaranteed to be in range `[min, max)`.
[inline] [inline]
pub fn (mut rng MT19937RNG) u32_in_range(min u32, max u32) u32 { pub fn (mut rng MT19937RNG) u32_in_range(min u32, max u32) u32 {
if max <= min { if max <= min {
eprintln('max must be greater than min') eprintln('max must be greater than min.')
exit(1) exit(1)
} }
return min + rng.u32n(max - min) return min + rng.u32n(max - min)
} }
// rng.u64n(min, max) returns a pseudorandom u64 value that is guaranteed to be in [min, max) // u64n returns a pseudorandom `u64` value that is guaranteed to be in range `[min, max)`.
[inline] [inline]
pub fn (mut rng MT19937RNG) u64_in_range(min u64, max u64) u64 { pub fn (mut rng MT19937RNG) u64_in_range(min u64, max u64) u64 {
if max <= min { if max <= min {
eprintln('max must be greater than min') eprintln('max must be greater than min.')
exit(1) exit(1)
} }
return min + rng.u64n(max - min) return min + rng.u64n(max - min)
} }
// rng.intn(max) - return a 32bit positive int in [0, max) // intn returns a 32bit positive `int` in range `[0, max)`.
[inline] [inline]
pub fn (mut rng MT19937RNG) intn(max int) int { pub fn (mut rng MT19937RNG) intn(max int) int {
if max <= 0 { if max <= 0 {
@ -238,7 +240,7 @@ pub fn (mut rng MT19937RNG) intn(max int) int {
return int(rng.u32n(u32(max))) return int(rng.u32n(u32(max)))
} }
// rng.i64n(max) - return a 64bit positive i64 in [0, max) // i64n returns a 64bit positive `i64` in range `[0, max)`.
[inline] [inline]
pub fn (mut rng MT19937RNG) i64n(max i64) i64 { pub fn (mut rng MT19937RNG) i64n(max i64) i64 {
if max <= 0 { if max <= 0 {
@ -248,7 +250,7 @@ pub fn (mut rng MT19937RNG) i64n(max i64) i64 {
return i64(rng.u64n(u64(max))) return i64(rng.u64n(u64(max)))
} }
// rng.int_in_range(min, max) - return a 32bit positive int in [0, max) // int_in_range returns a 32bit positive `int` in range `[min, max)`.
[inline] [inline]
pub fn (mut rng MT19937RNG) int_in_range(min int, max int) int { pub fn (mut rng MT19937RNG) int_in_range(min int, max int) int {
if max <= min { if max <= min {
@ -258,7 +260,7 @@ pub fn (mut rng MT19937RNG) int_in_range(min int, max int) int {
return min + rng.intn(max - min) return min + rng.intn(max - min)
} }
// rng.i64_in_range(min, max) - return a 64bit positive i64 in [0, max) // i64_in_range returns a 64bit positive `i64` in range `[min, max)`.
[inline] [inline]
pub fn (mut rng MT19937RNG) i64_in_range(min i64, max i64) i64 { pub fn (mut rng MT19937RNG) i64_in_range(min i64, max i64) i64 {
if max <= min { if max <= min {
@ -268,19 +270,19 @@ pub fn (mut rng MT19937RNG) i64_in_range(min i64, max i64) i64 {
return min + rng.i64n(max - min) return min + rng.i64n(max - min)
} }
// rng.f32() - return a 32bit real in [0, 1) // f32 returns a 32bit real (`f32`) in range `[0, 1)`.
[inline] [inline]
pub fn (mut rng MT19937RNG) f32() f32 { pub fn (mut rng MT19937RNG) f32() f32 {
return f32(rng.f64()) return f32(rng.f64())
} }
// rng.f64() - return 64bit real in [0, 1) // f64 returns 64bit real (`f64`) in range `[0, 1)`.
[inline] [inline]
pub fn (mut rng MT19937RNG) f64() f64 { pub fn (mut rng MT19937RNG) f64() f64 {
return f64(rng.u64() >> 11) * inv_f64_limit return f64(rng.u64() >> 11) * inv_f64_limit
} }
// rng.f32n(max) - return 64bit real in [0, max) // f32n returns a 32bit real (`f32`) in range [0, max)`.
[inline] [inline]
pub fn (mut rng MT19937RNG) f32n(max f32) f32 { pub fn (mut rng MT19937RNG) f32n(max f32) f32 {
if max <= 0 { if max <= 0 {
@ -290,7 +292,7 @@ pub fn (mut rng MT19937RNG) f32n(max f32) f32 {
return rng.f32() * max return rng.f32() * max
} }
// rng.f64n(max) - return 64bit real in [0, max) // f64n returns a 64bit real (`f64`) in range `[0, max)`.
[inline] [inline]
pub fn (mut rng MT19937RNG) f64n(max f64) f64 { pub fn (mut rng MT19937RNG) f64n(max f64) f64 {
if max <= 0 { if max <= 0 {
@ -300,21 +302,21 @@ pub fn (mut rng MT19937RNG) f64n(max f64) f64 {
return rng.f64() * max return rng.f64() * max
} }
// rng.f32_in_range(min, max) returns a pseudorandom f32 that lies in [min, max) // f32_in_range returns a pseudorandom `f32` that lies in range `[min, max)`.
[inline] [inline]
pub fn (mut rng MT19937RNG) f32_in_range(min f32, max f32) f32 { pub fn (mut rng MT19937RNG) f32_in_range(min f32, max f32) f32 {
if max <= min { if max <= min {
eprintln('max must be greater than min') eprintln('max must be greater than min.')
exit(1) exit(1)
} }
return min + rng.f32n(max - min) return min + rng.f32n(max - min)
} }
// rng.i64_in_range(min, max) returns a pseudorandom i64 that lies in [min, max) // i64_in_range returns a pseudorandom `i64` that lies in range `[min, max)`.
[inline] [inline]
pub fn (mut rng MT19937RNG) f64_in_range(min f64, max f64) f64 { pub fn (mut rng MT19937RNG) f64_in_range(min f64, max f64) f64 {
if max <= min { if max <= min {
eprintln('max must be greater than min') eprintln('max must be greater than min.')
exit(1) exit(1)
} }
return min + rng.f64n(max - min) return min + rng.f64n(max - min)

View File

@ -6,20 +6,23 @@ module musl
import math.bits import math.bits
import rand.util import rand.util
// Ported from https://git.musl-libc.org/cgit/musl/tree/src/prng/rand_r.c // MuslRNG ported from https://git.musl-libc.org/cgit/musl/tree/src/prng/rand_r.c
pub struct MuslRNG { pub struct MuslRNG {
mut: mut:
state u32 = util.time_seed_32() state u32 = util.time_seed_32()
} }
// seed sets the current random state based on `seed_data`.
// seed expects `seed_data` to be only one `u32`.
pub fn (mut rng MuslRNG) seed(seed_data []u32) { pub fn (mut rng MuslRNG) seed(seed_data []u32) {
if seed_data.len != 1 { if seed_data.len != 1 {
eprintln('MuslRNG needs only one unsigned 32 bit integer as a seed.') eprintln('MuslRNG needs only one unsigned 32-bit integer as a seed.')
exit(1) exit(1)
} }
rng.state = seed_data[0] rng.state = seed_data[0]
} }
// temper returns a tempered value based on `prev` value.
[inline] [inline]
fn temper(prev u32) u32 { fn temper(prev u32) u32 {
mut x := prev mut x := prev
@ -30,7 +33,7 @@ fn temper(prev u32) u32 {
return x return x
} }
// rng.u32() - return a pseudorandom 32 bit unsigned u32 // u32 returns a pseudorandom 32-bit unsigned integer (`u32`).
[inline] [inline]
pub fn (mut rng MuslRNG) u32() u32 { pub fn (mut rng MuslRNG) u32() u32 {
rng.state = rng.state * 1103515245 + 12345 rng.state = rng.state * 1103515245 + 12345
@ -39,17 +42,17 @@ pub fn (mut rng MuslRNG) u32() u32 {
return temper(rng.state) return temper(rng.state)
} }
// rng.u64() - return a pseudorandom 64 bit unsigned u64 // u64 returns a pseudorandom 64-bit unsigned integer (`u64`).
[inline] [inline]
pub fn (mut rng MuslRNG) u64() u64 { pub fn (mut rng MuslRNG) u64() u64 {
return u64(rng.u32()) | (u64(rng.u32()) << 32) return u64(rng.u32()) | (u64(rng.u32()) << 32)
} }
// rn.u32n(max) - return a pseudorandom 32 bit unsigned u32 in [0, max) // u32n returns a pseudorandom 32-bit unsigned integer `u32` in range `[0, max)`.
[inline] [inline]
pub fn (mut rng MuslRNG) u32n(max u32) u32 { pub fn (mut rng MuslRNG) u32n(max u32) u32 {
if max == 0 { if max == 0 {
eprintln('max must be positive integer') eprintln('max must be positive integer.')
exit(1) exit(1)
} }
// Check SysRNG in system_rng.c.v for explanation // Check SysRNG in system_rng.c.v for explanation
@ -73,11 +76,11 @@ pub fn (mut rng MuslRNG) u32n(max u32) u32 {
return u32(0) return u32(0)
} }
// rn.u64n(max) - return a pseudorandom 64 bit unsigned u64 in [0, max) // u64n returns a pseudorandom 64-bit unsigned integer (`u64`) in range `[0, max)`.
[inline] [inline]
pub fn (mut rng MuslRNG) u64n(max u64) u64 { pub fn (mut rng MuslRNG) u64n(max u64) u64 {
if max == 0 { if max == 0 {
eprintln('max must be positive integer') eprintln('max must be positive integer.')
exit(1) exit(1)
} }
bit_len := bits.len_64(max) bit_len := bits.len_64(max)
@ -100,51 +103,51 @@ pub fn (mut rng MuslRNG) u64n(max u64) u64 {
return u64(0) return u64(0)
} }
// rn.u32_in_range(min, max) - return a pseudorandom 32 bit unsigned u32 in [min, max) // u32_in_range returns a pseudorandom 32-bit unsigned integer (`u32`) in range `[min, max)`.
[inline] [inline]
pub fn (mut rng MuslRNG) u32_in_range(min u64, max u64) u64 { pub fn (mut rng MuslRNG) u32_in_range(min u64, max u64) u64 {
if max <= min { if max <= min {
eprintln('max must be greater than min') eprintln('max must be greater than min.')
exit(1) exit(1)
} }
return min + rng.u32n(u32(max - min)) return min + rng.u32n(u32(max - min))
} }
// rn.u64_in_range(min, max) - return a pseudorandom 64 bit unsigned u64 in [min, max) // u64_in_range returns a pseudorandom 64-bit unsigned integer (`u64`) in range `[min, max)`.
[inline] [inline]
pub fn (mut rng MuslRNG) u64_in_range(min u64, max u64) u64 { pub fn (mut rng MuslRNG) u64_in_range(min u64, max u64) u64 {
if max <= min { if max <= min {
eprintln('max must be greater than min') eprintln('max must be greater than min.')
exit(1) exit(1)
} }
return min + rng.u64n(max - min) return min + rng.u64n(max - min)
} }
// rng.int() - return a 32-bit signed (possibly negative) int // int returns a 32-bit signed (possibly negative) integer (`int`).
[inline] [inline]
pub fn (mut rng MuslRNG) int() int { pub fn (mut rng MuslRNG) int() int {
return int(rng.u32()) return int(rng.u32())
} }
// rng.i64() - return a 64-bit signed (possibly negative) i64 // i64 returns a 64-bit signed (possibly negative) integer (`i64`).
[inline] [inline]
pub fn (mut rng MuslRNG) i64() i64 { pub fn (mut rng MuslRNG) i64() i64 {
return i64(rng.u64()) return i64(rng.u64())
} }
// rng.int31() - return a 31bit positive pseudorandom integer // int31 returns a 31-bit positive pseudorandom integer (`int`).
[inline] [inline]
pub fn (mut rng MuslRNG) int31() int { pub fn (mut rng MuslRNG) int31() int {
return int(rng.u32() >> 1) return int(rng.u32() >> 1)
} }
// rng.int63() - return a 63bit positive pseudorandom integer // int63 returns a 63-bit positive pseudorandom integer (`i64`).
[inline] [inline]
pub fn (mut rng MuslRNG) int63() i64 { pub fn (mut rng MuslRNG) int63() i64 {
return i64(rng.u64() >> 1) return i64(rng.u64() >> 1)
} }
// rng.intn(max) - return a 32bit positive int in [0, max) // intn returns a 32-bit positive int in range `[0, max)`.
[inline] [inline]
pub fn (mut rng MuslRNG) intn(max int) int { pub fn (mut rng MuslRNG) intn(max int) int {
if max <= 0 { if max <= 0 {
@ -154,7 +157,7 @@ pub fn (mut rng MuslRNG) intn(max int) int {
return int(rng.u32n(u32(max))) return int(rng.u32n(u32(max)))
} }
// rng.i64n(max) - return a 64bit positive i64 in [0, max) // i64n returns a 64-bit positive integer `i64` in range `[0, max)`.
[inline] [inline]
pub fn (mut rng MuslRNG) i64n(max i64) i64 { pub fn (mut rng MuslRNG) i64n(max i64) i64 {
if max <= 0 { if max <= 0 {
@ -164,7 +167,7 @@ pub fn (mut rng MuslRNG) i64n(max i64) i64 {
return i64(rng.u64n(u64(max))) return i64(rng.u64n(u64(max)))
} }
// rng.int_in_range(min, max) - return a 32bit positive int in [0, max) // int_in_range returns a 32-bit positive integer `int` in range `[0, max)`.
[inline] [inline]
pub fn (mut rng MuslRNG) int_in_range(min int, max int) int { pub fn (mut rng MuslRNG) int_in_range(min int, max int) int {
if max <= min { if max <= min {
@ -174,7 +177,7 @@ pub fn (mut rng MuslRNG) int_in_range(min int, max int) int {
return min + rng.intn(max - min) return min + rng.intn(max - min)
} }
// rng.i64_in_range(min, max) - return a 64bit positive i64 in [0, max) // i64_in_range returns a 64-bit positive integer `i64` in range `[0, max)`.
[inline] [inline]
pub fn (mut rng MuslRNG) i64_in_range(min i64, max i64) i64 { pub fn (mut rng MuslRNG) i64_in_range(min i64, max i64) i64 {
if max <= min { if max <= min {
@ -184,19 +187,19 @@ pub fn (mut rng MuslRNG) i64_in_range(min i64, max i64) i64 {
return min + rng.i64n(max - min) return min + rng.i64n(max - min)
} }
// rng.f32() returns a pseudorandom f32 value between 0.0 (inclusive) and 1.0 (exclusive) i.e [0, 1) // f32 returns a pseudorandom `f32` value in range `[0, 1)`.
[inline] [inline]
pub fn (mut rng MuslRNG) f32() f32 { pub fn (mut rng MuslRNG) f32() f32 {
return f32(rng.u32()) / util.max_u32_as_f32 return f32(rng.u32()) / util.max_u32_as_f32
} }
// rng.f64() returns a pseudorandom f64 value between 0.0 (inclusive) and 1.0 (exclusive) i.e [0, 1) // f64 returns a pseudorandom `f64` value in range `[0, 1)`.
[inline] [inline]
pub fn (mut rng MuslRNG) f64() f64 { pub fn (mut rng MuslRNG) f64() f64 {
return f64(rng.u64()) / util.max_u64_as_f64 return f64(rng.u64()) / util.max_u64_as_f64
} }
// rng.f32n() returns a pseudorandom f32 value in [0, max) // f32n returns a pseudorandom `f32` value in range `[0, max)`.
[inline] [inline]
pub fn (mut rng MuslRNG) f32n(max f32) f32 { pub fn (mut rng MuslRNG) f32n(max f32) f32 {
if max <= 0 { if max <= 0 {
@ -206,7 +209,7 @@ pub fn (mut rng MuslRNG) f32n(max f32) f32 {
return rng.f32() * max return rng.f32() * max
} }
// rng.f64n() returns a pseudorandom f64 value in [0, max) // f64n returns a pseudorandom `f64` value in range `[0, max)`.
[inline] [inline]
pub fn (mut rng MuslRNG) f64n(max f64) f64 { pub fn (mut rng MuslRNG) f64n(max f64) f64 {
if max <= 0 { if max <= 0 {
@ -216,21 +219,21 @@ pub fn (mut rng MuslRNG) f64n(max f64) f64 {
return rng.f64() * max return rng.f64() * max
} }
// rng.f32_in_range(min, max) returns a pseudorandom f32 that lies in [min, max) // f32_in_range returns a pseudorandom `f32` in range `[min, max)`.
[inline] [inline]
pub fn (mut rng MuslRNG) f32_in_range(min f32, max f32) f32 { pub fn (mut rng MuslRNG) f32_in_range(min f32, max f32) f32 {
if max <= min { if max <= min {
eprintln('max must be greater than min') eprintln('max must be greater than min.')
exit(1) exit(1)
} }
return min + rng.f32n(max - min) return min + rng.f32n(max - min)
} }
// rng.i64_in_range(min, max) returns a pseudorandom i64 that lies in [min, max) // i64_in_range returns a pseudorandom `i64` in range `[min, max)`.
[inline] [inline]
pub fn (mut rng MuslRNG) f64_in_range(min f64, max f64) f64 { pub fn (mut rng MuslRNG) f64_in_range(min f64, max f64) f64 {
if max <= min { if max <= min {
eprintln('max must be greater than min') eprintln('max must be greater than min.')
exit(1) exit(1)
} }
return min + rng.f64n(max - min) return min + rng.f64n(max - min)

View File

@ -5,7 +5,7 @@ module pcg32
import rand.util import rand.util
// Ported from http://www.pcg-random.org/download.html, // PCG32RNG ported from http://www.pcg-random.org/download.html,
// https://github.com/imneme/pcg-c-basic/blob/master/pcg_basic.c, and // https://github.com/imneme/pcg-c-basic/blob/master/pcg_basic.c, and
// https://github.com/imneme/pcg-c-basic/blob/master/pcg_basic.h // https://github.com/imneme/pcg-c-basic/blob/master/pcg_basic.h
pub struct PCG32RNG { pub struct PCG32RNG {
@ -14,12 +14,12 @@ mut:
inc u64 = u64(0xda3e39cb94b95bdb) ^ util.time_seed_64() inc u64 = u64(0xda3e39cb94b95bdb) ^ util.time_seed_64()
} }
// rng.seed(seed_data) - seed the PCG32RNG with 4 u32 values. // seed seeds the PCG32RNG with 4 `u32` values.
// The first 2 represent the 64-bit initial state as [lower 32 bits, higher 32 bits] // The first 2 represent the 64-bit initial state as `[lower 32 bits, higher 32 bits]`
// The last 2 represent the 64-bit stream/step of the PRNG. // The last 2 represent the 64-bit stream/step of the PRNG.
pub fn (mut rng PCG32RNG) seed(seed_data []u32) { pub fn (mut rng PCG32RNG) seed(seed_data []u32) {
if seed_data.len != 4 { if seed_data.len != 4 {
eprintln('PCG32RNG needs 4 u32s to be seeded. First two the initial state and the last two the stream/step. Both in little endian format: [lower, higher]') eprintln('PCG32RNG needs 4 u32s to be seeded. First two the initial state and the last two the stream/step. Both in little endian format: [lower, higher].')
exit(1) exit(1)
} }
init_state := u64(seed_data[0]) | (u64(seed_data[1]) << 32) init_state := u64(seed_data[0]) | (u64(seed_data[1]) << 32)
@ -31,7 +31,7 @@ pub fn (mut rng PCG32RNG) seed(seed_data []u32) {
rng.u32() rng.u32()
} }
// rng.u32() - return a pseudorandom 32 bit unsigned u32 // u32 returns a pseudorandom unsigned `u32`.
[inline] [inline]
pub fn (mut rng PCG32RNG) u32() u32 { pub fn (mut rng PCG32RNG) u32() u32 {
oldstate := rng.state oldstate := rng.state
@ -41,13 +41,13 @@ pub fn (mut rng PCG32RNG) u32() u32 {
return ((xorshifted >> rot) | (xorshifted << ((-rot) & u32(31)))) return ((xorshifted >> rot) | (xorshifted << ((-rot) & u32(31))))
} }
// rng.u64() - return a pseudorandom 64 bit unsigned u64 // u64 returns a pseudorandom 64-bit unsigned `u64`.
[inline] [inline]
pub fn (mut rng PCG32RNG) u64() u64 { pub fn (mut rng PCG32RNG) u64() u64 {
return u64(rng.u32()) | (u64(rng.u32()) << 32) return u64(rng.u32()) | (u64(rng.u32()) << 32)
} }
// rn.u32n(max) - return a pseudorandom 32 bit unsigned u32 in [0, max) // u32n returns a pseudorandom 32-bit unsigned `u32` in range `[0, max)`.
[inline] [inline]
pub fn (mut rng PCG32RNG) u32n(max u32) u32 { pub fn (mut rng PCG32RNG) u32n(max u32) u32 {
if max == 0 { if max == 0 {
@ -71,7 +71,7 @@ pub fn (mut rng PCG32RNG) u32n(max u32) u32 {
return u32(0) return u32(0)
} }
// rn.u64n(max) - return a pseudorandom 64 bit unsigned u64 in [0, max) // u64n returns a pseudorandom 64-bit unsigned `u64` in range `[0, max)`.
[inline] [inline]
pub fn (mut rng PCG32RNG) u64n(max u64) u64 { pub fn (mut rng PCG32RNG) u64n(max u64) u64 {
if max == 0 { if max == 0 {
@ -88,7 +88,7 @@ pub fn (mut rng PCG32RNG) u64n(max u64) u64 {
return u64(0) return u64(0)
} }
// rn.u32_in_range(min, max) - return a pseudorandom 32 bit unsigned u32 in [min, max) // u32_in_range returns a pseudorandom 32-bit unsigned `u32` in range `[min, max)`.
[inline] [inline]
pub fn (mut rng PCG32RNG) u32_in_range(min u64, max u64) u64 { pub fn (mut rng PCG32RNG) u32_in_range(min u64, max u64) u64 {
if max <= min { if max <= min {
@ -98,7 +98,7 @@ pub fn (mut rng PCG32RNG) u32_in_range(min u64, max u64) u64 {
return min + rng.u32n(u32(max - min)) return min + rng.u32n(u32(max - min))
} }
// rn.u64_in_range(min, max) - return a pseudorandom 64 bit unsigned u64 in [min, max) // u64_in_range returns a pseudorandom 64-bit unsigned `u64` in range `[min, max)`.
[inline] [inline]
pub fn (mut rng PCG32RNG) u64_in_range(min u64, max u64) u64 { pub fn (mut rng PCG32RNG) u64_in_range(min u64, max u64) u64 {
if max <= min { if max <= min {
@ -108,31 +108,31 @@ pub fn (mut rng PCG32RNG) u64_in_range(min u64, max u64) u64 {
return min + rng.u64n(max - min) return min + rng.u64n(max - min)
} }
// rng.int() - return a 32-bit signed (possibly negative) int // int returns a 32-bit signed (possibly negative) `int`.
[inline] [inline]
pub fn (mut rng PCG32RNG) int() int { pub fn (mut rng PCG32RNG) int() int {
return int(rng.u32()) return int(rng.u32())
} }
// rng.i64() - return a 64-bit signed (possibly negative) i64 // i64 returns a 64-bit signed (possibly negative) `i64`.
[inline] [inline]
pub fn (mut rng PCG32RNG) i64() i64 { pub fn (mut rng PCG32RNG) i64() i64 {
return i64(rng.u64()) return i64(rng.u64())
} }
// rng.int31() - return a 31bit positive pseudorandom integer // int31 returns a 31-bit positive pseudorandom `int`.
[inline] [inline]
pub fn (mut rng PCG32RNG) int31() int { pub fn (mut rng PCG32RNG) int31() int {
return int(rng.u32() >> 1) return int(rng.u32() >> 1)
} }
// rng.int63() - return a 63bit positive pseudorandom integer // int63 returns a 63-bit positive pseudorandom `i64`.
[inline] [inline]
pub fn (mut rng PCG32RNG) int63() i64 { pub fn (mut rng PCG32RNG) int63() i64 {
return i64(rng.u64() >> 1) return i64(rng.u64() >> 1)
} }
// rng.intn(max) - return a 32bit positive int in [0, max) // intn returns a 32-bit positive `int` in range `[0, max)`.
[inline] [inline]
pub fn (mut rng PCG32RNG) intn(max int) int { pub fn (mut rng PCG32RNG) intn(max int) int {
if max <= 0 { if max <= 0 {
@ -142,7 +142,7 @@ pub fn (mut rng PCG32RNG) intn(max int) int {
return int(rng.u32n(u32(max))) return int(rng.u32n(u32(max)))
} }
// rng.i64n(max) - return a 64bit positive i64 in [0, max) // i64n returns a 64-bit positive `i64` in range `[0, max)`.
[inline] [inline]
pub fn (mut rng PCG32RNG) i64n(max i64) i64 { pub fn (mut rng PCG32RNG) i64n(max i64) i64 {
if max <= 0 { if max <= 0 {
@ -152,7 +152,7 @@ pub fn (mut rng PCG32RNG) i64n(max i64) i64 {
return i64(rng.u64n(u64(max))) return i64(rng.u64n(u64(max)))
} }
// rng.int_in_range(min, max) - return a 32bit positive int in [0, max) // int_in_range returns a 32-bit positive `int` in range `[0, max)`.
[inline] [inline]
pub fn (mut rng PCG32RNG) int_in_range(min int, max int) int { pub fn (mut rng PCG32RNG) int_in_range(min int, max int) int {
if max <= min { if max <= min {
@ -162,7 +162,7 @@ pub fn (mut rng PCG32RNG) int_in_range(min int, max int) int {
return min + rng.intn(max - min) return min + rng.intn(max - min)
} }
// rng.i64_in_range(min, max) - return a 64bit positive i64 in [0, max) // i64_in_range returns a 64-bit positive `i64` in range `[0, max)`.
[inline] [inline]
pub fn (mut rng PCG32RNG) i64_in_range(min i64, max i64) i64 { pub fn (mut rng PCG32RNG) i64_in_range(min i64, max i64) i64 {
if max <= min { if max <= min {
@ -172,19 +172,19 @@ pub fn (mut rng PCG32RNG) i64_in_range(min i64, max i64) i64 {
return min + rng.i64n(max - min) return min + rng.i64n(max - min)
} }
// rng.f32() returns a pseudorandom f32 value between 0.0 (inclusive) and 1.0 (exclusive) i.e [0, 1) // f32 returns a pseudorandom `f32` value in range `[0, 1)`.
[inline] [inline]
pub fn (mut rng PCG32RNG) f32() f32 { pub fn (mut rng PCG32RNG) f32() f32 {
return f32(rng.u32()) / util.max_u32_as_f32 return f32(rng.u32()) / util.max_u32_as_f32
} }
// rng.f64() returns a pseudorandom f64 value between 0.0 (inclusive) and 1.0 (exclusive) i.e [0, 1) // f64 returns a pseudorandom `f64` value in range `[0, 1)`.
[inline] [inline]
pub fn (mut rng PCG32RNG) f64() f64 { pub fn (mut rng PCG32RNG) f64() f64 {
return f64(rng.u64()) / util.max_u64_as_f64 return f64(rng.u64()) / util.max_u64_as_f64
} }
// rng.f32n() returns a pseudorandom f32 value in [0, max) // f32n returns a pseudorandom `f32` value in range `[0, max)`.
[inline] [inline]
pub fn (mut rng PCG32RNG) f32n(max f32) f32 { pub fn (mut rng PCG32RNG) f32n(max f32) f32 {
if max <= 0 { if max <= 0 {
@ -194,7 +194,7 @@ pub fn (mut rng PCG32RNG) f32n(max f32) f32 {
return rng.f32() * max return rng.f32() * max
} }
// rng.f64n() returns a pseudorandom f64 value in [0, max) // f64n returns a pseudorandom `f64` value in range `[0, max)`.
[inline] [inline]
pub fn (mut rng PCG32RNG) f64n(max f64) f64 { pub fn (mut rng PCG32RNG) f64n(max f64) f64 {
if max <= 0 { if max <= 0 {
@ -204,7 +204,7 @@ pub fn (mut rng PCG32RNG) f64n(max f64) f64 {
return rng.f64() * max return rng.f64() * max
} }
// rng.f32_in_range(min, max) returns a pseudorandom f32 that lies in [min, max) // f32_in_range returns a pseudorandom `f32` in range `[min, max)`.
[inline] [inline]
pub fn (mut rng PCG32RNG) f32_in_range(min f32, max f32) f32 { pub fn (mut rng PCG32RNG) f32_in_range(min f32, max f32) f32 {
if max <= min { if max <= min {
@ -214,7 +214,7 @@ pub fn (mut rng PCG32RNG) f32_in_range(min f32, max f32) f32 {
return min + rng.f32n(max - min) return min + rng.f32n(max - min)
} }
// rng.i64_in_range(min, max) returns a pseudorandom i64 that lies in [min, max) // i64_in_range returns a pseudorandom `i64` in range `[min, max)`.
[inline] [inline]
pub fn (mut rng PCG32RNG) f64_in_range(min f64, max f64) f64 { pub fn (mut rng PCG32RNG) f64_in_range(min f64, max f64) f64 {
if max <= min { if max <= min {

View File

@ -7,13 +7,14 @@ import rand.util
import rand.wyrand import rand.wyrand
import time import time
// Configuration struct for creating a new instance of the default RNG. // PRNGConfigStruct is a configuration struct for creating a new instance of the default RNG.
pub struct PRNGConfigStruct { pub struct PRNGConfigStruct {
seed []u32 = util.time_seed_array(2) seed []u32 = util.time_seed_array(2)
} }
__global ( default_rng &wyrand.WyRandRNG ) __global ( default_rng &wyrand.WyRandRNG )
// init initializes the default RNG.
fn init() { fn init() {
default_rng = new_default({}) default_rng = new_default({})
} }
@ -30,103 +31,103 @@ pub fn seed(seed []u32) {
default_rng.seed(seed) default_rng.seed(seed)
} }
// u32() returns a uniformly distributed u32 in _[0, 2<sup>32</sup>)_ // u32 returns a uniformly distributed `u32` in range `[0, 2³²)`.
pub fn u32() u32 { pub fn u32() u32 {
return default_rng.u32() return default_rng.u32()
} }
// u64() returns a uniformly distributed u64 in _[0, 2<sup>64</sup>)_ // u64 returns a uniformly distributed `u64` in range `[0, 2⁶⁴)`.
pub fn u64() u64 { pub fn u64() u64 {
return default_rng.u64() return default_rng.u64()
} }
// u32n(max) returns a uniformly distributed pseudorandom 32-bit signed positive u32 in _[0, max)_ // u32n returns a uniformly distributed pseudorandom 32-bit signed positive `u32` in range `[0, max)`.
pub fn u32n(max u32) u32 { pub fn u32n(max u32) u32 {
return default_rng.u32n(max) return default_rng.u32n(max)
} }
// u64n(max) returns a uniformly distributed pseudorandom 64-bit signed positive u64 in _[0, max)_ // u64n returns a uniformly distributed pseudorandom 64-bit signed positive `u64` in range `[0, max)`.
pub fn u64n(max u64) u64 { pub fn u64n(max u64) u64 {
return default_rng.u64n(max) return default_rng.u64n(max)
} }
// u32_in_range(min, max) returns a uniformly distributed pseudorandom 32-bit unsigned u32 in _[min, max)_ // u32_in_range returns a uniformly distributed pseudorandom 32-bit unsigned `u32` in range `[min, max)`.
pub fn u32_in_range(min u32, max u32) u32 { pub fn u32_in_range(min u32, max u32) u32 {
return default_rng.u32_in_range(min, max) return default_rng.u32_in_range(min, max)
} }
// u64_in_range(min, max) returns a uniformly distributed pseudorandom 64-bit unsigned u64 in _[min, max)_ // u64_in_range returns a uniformly distributed pseudorandom 64-bit unsigned `u64` in range `[min, max)`.
pub fn u64_in_range(min u64, max u64) u64 { pub fn u64_in_range(min u64, max u64) u64 {
return default_rng.u64_in_range(min, max) return default_rng.u64_in_range(min, max)
} }
// int() returns a uniformly distributed pseudorandom 32-bit signed (possibly negative) int // int returns a uniformly distributed pseudorandom 32-bit signed (possibly negative) `int`.
pub fn int() int { pub fn int() int {
return default_rng.int() return default_rng.int()
} }
// intn(max) returns a uniformly distributed pseudorandom 32-bit signed positive int in _[0, max)_ // intn returns a uniformly distributed pseudorandom 32-bit signed positive `int` in range `[0, max)`.
pub fn intn(max int) int { pub fn intn(max int) int {
return default_rng.intn(max) return default_rng.intn(max)
} }
// int_in_range(min, max) returns a uniformly distributed pseudorandom // int_in_range returns a uniformly distributed pseudorandom 32-bit signed int in range `[min, max)`.
// 32-bit signed int in [min, max). Both min and max can be negative, but we must have _min < max_. // Both `min` and `max` can be negative, but we must have `min < max`.
pub fn int_in_range(min int, max int) int { pub fn int_in_range(min int, max int) int {
return default_rng.int_in_range(min, max) return default_rng.int_in_range(min, max)
} }
// int31() returns a uniformly distributed pseudorandom 31-bit signed positive int // int31 returns a uniformly distributed pseudorandom 31-bit signed positive `int`.
pub fn int31() int { pub fn int31() int {
return default_rng.int31() return default_rng.int31()
} }
// i64() returns a uniformly distributed pseudorandom 64-bit signed (possibly negative) i64 // i64 returns a uniformly distributed pseudorandom 64-bit signed (possibly negative) `i64`.
pub fn i64() i64 { pub fn i64() i64 {
return default_rng.i64() return default_rng.i64()
} }
// i64n(max) returns a uniformly distributed pseudorandom 64-bit signed positive i64 in _[0, max)_ // i64n returns a uniformly distributed pseudorandom 64-bit signed positive `i64` in range `[0, max)`.
pub fn i64n(max i64) i64 { pub fn i64n(max i64) i64 {
return default_rng.i64n(max) return default_rng.i64n(max)
} }
// i64_in_range(min, max) returns a uniformly distributed pseudorandom 64-bit signed int in _[min, max)_ // i64_in_range returns a uniformly distributed pseudorandom 64-bit signed `i64` in range `[min, max)`.
pub fn i64_in_range(min i64, max i64) i64 { pub fn i64_in_range(min i64, max i64) i64 {
return default_rng.i64_in_range(min, max) return default_rng.i64_in_range(min, max)
} }
// int63() returns a uniformly distributed pseudorandom 63-bit signed positive int // int63 returns a uniformly distributed pseudorandom 63-bit signed positive `i64`.
pub fn int63() i64 { pub fn int63() i64 {
return default_rng.int63() return default_rng.int63()
} }
// f32() returns a uniformly distributed 32-bit floating point in _[0, 1)_ // f32 returns a uniformly distributed 32-bit floating point in range `[0, 1)`.
pub fn f32() f32 { pub fn f32() f32 {
return default_rng.f32() return default_rng.f32()
} }
// f64() returns a uniformly distributed 64-bit floating point in _[0, 1)_ // f64 returns a uniformly distributed 64-bit floating point in range `[0, 1)`.
pub fn f64() f64 { pub fn f64() f64 {
return default_rng.f64() return default_rng.f64()
} }
// f32n() returns a uniformly distributed 32-bit floating point in _[0, max)_ // f32n returns a uniformly distributed 32-bit floating point in range `[0, max)`.
pub fn f32n(max f32) f32 { pub fn f32n(max f32) f32 {
return default_rng.f32n(max) return default_rng.f32n(max)
} }
// f64n() returns a uniformly distributed 64-bit floating point in _[0, max)_ // f64n returns a uniformly distributed 64-bit floating point in range `[0, max)`.
pub fn f64n(max f64) f64 { pub fn f64n(max f64) f64 {
return default_rng.f64n(max) return default_rng.f64n(max)
} }
// f32_in_range(min, max) returns a uniformly distributed 32-bit floating point in _[min, max)_ // f32_in_range returns a uniformly distributed 32-bit floating point in range `[min, max)`.
pub fn f32_in_range(min f32, max f32) f32 { pub fn f32_in_range(min f32, max f32) f32 {
return default_rng.f32_in_range(min, max) return default_rng.f32_in_range(min, max)
} }
// f64_in_range(min, max) returns a uniformly distributed 64-bit floating point in _[min, max)_ // f64_in_range returns a uniformly distributed 64-bit floating point in range `[min, max)`.
pub fn f64_in_range(min f64, max f64) f64 { pub fn f64_in_range(min f64, max f64) f64 {
return default_rng.f64_in_range(min, max) return default_rng.f64_in_range(min, max)
} }
@ -135,6 +136,7 @@ const (
chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
) )
// string returns a string of length `len` containing random characters in range `[a-zA-Z]`.
pub fn string(len int) string { pub fn string(len int) string {
mut buf := malloc(len) mut buf := malloc(len)
for i in 0 .. len { for i in 0 .. len {
@ -145,7 +147,7 @@ pub fn string(len int) string {
return unsafe {buf.vstring_with_len(len)} return unsafe {buf.vstring_with_len(len)}
} }
// rand.uuid_v4 generate a completely random UUID (v4) // uuid_v4 generates a random (v4) UUID
// See https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random) // See https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random)
pub fn uuid_v4() string { pub fn uuid_v4() string {
buflen := 36 buflen := 36
@ -189,7 +191,7 @@ const (
ulid_encoding = '0123456789ABCDEFGHJKMNPQRSTVWXYZ' ulid_encoding = '0123456789ABCDEFGHJKMNPQRSTVWXYZ'
) )
// rand.ulid generates an Unique Lexicographically sortable IDentifier. // ulid generates an Unique Lexicographically sortable IDentifier.
// See https://github.com/ulid/spec . // See https://github.com/ulid/spec .
// NB: ULIDs can leak timing information, if you make them public, because // NB: ULIDs can leak timing information, if you make them public, because
// you can infer the rate at which some resource is being created, like // you can infer the rate at which some resource is being created, like
@ -199,6 +201,7 @@ pub fn ulid() string {
return ulid_at_millisecond(time.utc().unix_time_milli()) return ulid_at_millisecond(time.utc().unix_time_milli())
} }
// ulid_at_millisecond does the same as `ulid` but takes a custom Unix millisecond timestamp via `unix_time_milli`.
pub fn ulid_at_millisecond(unix_time_milli u64) string { pub fn ulid_at_millisecond(unix_time_milli u64) string {
buflen := 26 buflen := 26
mut buf := malloc(27) mut buf := malloc(27)

View File

@ -5,7 +5,7 @@ module splitmix64
import rand.util import rand.util
// Ported from http://xoshiro.di.unimi.it/splitmix64.c // SplitMix64RNG ported from http://xoshiro.di.unimi.it/splitmix64.c
pub struct SplitMix64RNG { pub struct SplitMix64RNG {
mut: mut:
state u64 = util.time_seed_64() state u64 = util.time_seed_64()
@ -13,7 +13,7 @@ mut:
extra u32 extra u32
} }
// rng.seed(seed_data) sets the seed of the accepting SplitMix64RNG to the given data // seed sets the seed of the accepting SplitMix64RNG to the given data
// in little-endian format (i.e. lower 32 bits are in [0] and higher 32 bits in [1]). // in little-endian format (i.e. lower 32 bits are in [0] and higher 32 bits in [1]).
pub fn (mut rng SplitMix64RNG) seed(seed_data []u32) { pub fn (mut rng SplitMix64RNG) seed(seed_data []u32) {
if seed_data.len != 2 { if seed_data.len != 2 {
@ -24,7 +24,7 @@ pub fn (mut rng SplitMix64RNG) seed(seed_data []u32) {
rng.has_extra = false rng.has_extra = false
} }
// rng.u32() updates the PRNG state and returns the next pseudorandom u32 // u32 updates the PRNG state and returns the next pseudorandom `u32`.
[inline] [inline]
pub fn (mut rng SplitMix64RNG) u32() u32 { pub fn (mut rng SplitMix64RNG) u32() u32 {
if rng.has_extra { if rng.has_extra {
@ -39,7 +39,7 @@ pub fn (mut rng SplitMix64RNG) u32() u32 {
return lower return lower
} }
// rng.u64() updates the PRNG state and returns the next pseudorandom u64 // u64 updates the PRNG state and returns the next pseudorandom `u64`.
[inline] [inline]
pub fn (mut rng SplitMix64RNG) u64() u64 { pub fn (mut rng SplitMix64RNG) u64() u64 {
rng.state += (0x9e3779b97f4a7c15) rng.state += (0x9e3779b97f4a7c15)
@ -49,7 +49,7 @@ pub fn (mut rng SplitMix64RNG) u64() u64 {
return z ^ (z >> (31)) return z ^ (z >> (31))
} }
// rng.u32n(bound) returns a pseudorandom u32 less than the bound // u32n returns a pseudorandom `u32` less than `bound`.
[inline] [inline]
pub fn (mut rng SplitMix64RNG) u32n(bound u32) u32 { pub fn (mut rng SplitMix64RNG) u32n(bound u32) u32 {
// This function is kept similar to the u64 version // This function is kept similar to the u64 version
@ -67,7 +67,7 @@ pub fn (mut rng SplitMix64RNG) u32n(bound u32) u32 {
return u32(0) return u32(0)
} }
// rng.u64n(bound) returns a pseudorandom u64 less than the bound // u64n returns a pseudorandom `u64` less than `bound`.
[inline] [inline]
pub fn (mut rng SplitMix64RNG) u64n(bound u64) u64 { pub fn (mut rng SplitMix64RNG) u64n(bound u64) u64 {
// See pcg32.v for explanation of comment. This algorithm // See pcg32.v for explanation of comment. This algorithm
@ -86,7 +86,7 @@ pub fn (mut rng SplitMix64RNG) u64n(bound u64) u64 {
return u64(0) return u64(0)
} }
// rng.u32n(min, max) returns a pseudorandom u32 value that is guaranteed to be in [min, max) // u32n returns a pseudorandom `u32` value that is guaranteed to be in range `[min, max)`.
[inline] [inline]
pub fn (mut rng SplitMix64RNG) u32_in_range(min u32, max u32) u32 { pub fn (mut rng SplitMix64RNG) u32_in_range(min u32, max u32) u32 {
if max <= min { if max <= min {
@ -96,7 +96,7 @@ pub fn (mut rng SplitMix64RNG) u32_in_range(min u32, max u32) u32 {
return min + rng.u32n(max - min) return min + rng.u32n(max - min)
} }
// rng.u64n(min, max) returns a pseudorandom u64 value that is guaranteed to be in [min, max) // u64n returns a pseudorandom `u64` value that is guaranteed to be in range `[min, max)`.
[inline] [inline]
pub fn (mut rng SplitMix64RNG) u64_in_range(min u64, max u64) u64 { pub fn (mut rng SplitMix64RNG) u64_in_range(min u64, max u64) u64 {
if max <= min { if max <= min {
@ -106,31 +106,31 @@ pub fn (mut rng SplitMix64RNG) u64_in_range(min u64, max u64) u64 {
return min + rng.u64n(max - min) return min + rng.u64n(max - min)
} }
// rng.int() returns a pseudorandom 32-bit int (which may be negative) // int returns a pseudorandom 32-bit (possibly negative) `int`.
[inline] [inline]
pub fn (mut rng SplitMix64RNG) int() int { pub fn (mut rng SplitMix64RNG) int() int {
return int(rng.u32()) return int(rng.u32())
} }
// rng.i64() returns a pseudorandom 64-bit i64 (which may be negative) // i64 returns a pseudorandom 64-bit (possibly negative) `i64`.
[inline] [inline]
pub fn (mut rng SplitMix64RNG) i64() i64 { pub fn (mut rng SplitMix64RNG) i64() i64 {
return i64(rng.u64()) return i64(rng.u64())
} }
// rng.int31() returns a pseudorandom 31-bit int which is non-negative // int31 returns a positive pseudorandom 31-bit `int`.
[inline] [inline]
pub fn (mut rng SplitMix64RNG) int31() int { pub fn (mut rng SplitMix64RNG) int31() int {
return int(rng.u32() & util.u31_mask) // Set the 32nd bit to 0. return int(rng.u32() & util.u31_mask) // Set the 32nd bit to 0.
} }
// rng.int63() returns a pseudorandom 63-bit int which is non-negative // int63 returns a positive pseudorandom 63-bit `i64`.
[inline] [inline]
pub fn (mut rng SplitMix64RNG) int63() i64 { pub fn (mut rng SplitMix64RNG) int63() i64 {
return i64(rng.u64() & util.u63_mask) // Set the 64th bit to 0. return i64(rng.u64() & util.u63_mask) // Set the 64th bit to 0.
} }
// rng.intn(max) returns a pseudorandom int that lies in [0, max) // intn returns a pseudorandom `int` in range `[0, max)`.
[inline] [inline]
pub fn (mut rng SplitMix64RNG) intn(max int) int { pub fn (mut rng SplitMix64RNG) intn(max int) int {
if max <= 0 { if max <= 0 {
@ -140,7 +140,7 @@ pub fn (mut rng SplitMix64RNG) intn(max int) int {
return int(rng.u32n(u32(max))) return int(rng.u32n(u32(max)))
} }
// rng.i64n(max) returns a pseudorandom int that lies in [0, max) // i64n returns a pseudorandom `i64` in range `[0, max)`.
[inline] [inline]
pub fn (mut rng SplitMix64RNG) i64n(max i64) i64 { pub fn (mut rng SplitMix64RNG) i64n(max i64) i64 {
if max <= 0 { if max <= 0 {
@ -150,7 +150,7 @@ pub fn (mut rng SplitMix64RNG) i64n(max i64) i64 {
return i64(rng.u64n(u64(max))) return i64(rng.u64n(u64(max)))
} }
// rng.int_in_range(min, max) returns a pseudorandom int that lies in [min, max) // int_in_range returns a pseudorandom `int` in range `[min, max)`.
[inline] [inline]
pub fn (mut rng SplitMix64RNG) int_in_range(min int, max int) int { pub fn (mut rng SplitMix64RNG) int_in_range(min int, max int) int {
if max <= min { if max <= min {
@ -161,7 +161,7 @@ pub fn (mut rng SplitMix64RNG) int_in_range(min int, max int) int {
return min + rng.intn(max - min) return min + rng.intn(max - min)
} }
// rng.i64_in_range(min, max) returns a pseudorandom i64 that lies in [min, max) // i64_in_range returns a pseudorandom `i64` in range `[min, max)`.
[inline] [inline]
pub fn (mut rng SplitMix64RNG) i64_in_range(min i64, max i64) i64 { pub fn (mut rng SplitMix64RNG) i64_in_range(min i64, max i64) i64 {
if max <= min { if max <= min {
@ -171,19 +171,19 @@ pub fn (mut rng SplitMix64RNG) i64_in_range(min i64, max i64) i64 {
return min + rng.i64n(max - min) return min + rng.i64n(max - min)
} }
// rng.f32() returns a pseudorandom f32 value between 0.0 (inclusive) and 1.0 (exclusive) i.e [0, 1) // f32 returns a pseudorandom `f32` value in range `[0, 1)`.
[inline] [inline]
pub fn (mut rng SplitMix64RNG) f32() f32 { pub fn (mut rng SplitMix64RNG) f32() f32 {
return f32(rng.u32()) / util.max_u32_as_f32 return f32(rng.u32()) / util.max_u32_as_f32
} }
// rng.f64() returns a pseudorandom f64 value between 0.0 (inclusive) and 1.0 (exclusive) i.e [0, 1) // f64 returns a pseudorandom `f64` value in range `[0, 1)`.
[inline] [inline]
pub fn (mut rng SplitMix64RNG) f64() f64 { pub fn (mut rng SplitMix64RNG) f64() f64 {
return f64(rng.u64()) / util.max_u64_as_f64 return f64(rng.u64()) / util.max_u64_as_f64
} }
// rng.f32n() returns a pseudorandom f32 value in [0, max) // f32n returns a pseudorandom `f32` value in range `[0, max)`.
[inline] [inline]
pub fn (mut rng SplitMix64RNG) f32n(max f32) f32 { pub fn (mut rng SplitMix64RNG) f32n(max f32) f32 {
if max <= 0 { if max <= 0 {
@ -193,7 +193,7 @@ pub fn (mut rng SplitMix64RNG) f32n(max f32) f32 {
return rng.f32() * max return rng.f32() * max
} }
// rng.f64n() returns a pseudorandom f64 value in [0, max) // f64n returns a pseudorandom `f64` value in range `[0, max)`.
[inline] [inline]
pub fn (mut rng SplitMix64RNG) f64n(max f64) f64 { pub fn (mut rng SplitMix64RNG) f64n(max f64) f64 {
if max <= 0 { if max <= 0 {
@ -203,7 +203,7 @@ pub fn (mut rng SplitMix64RNG) f64n(max f64) f64 {
return rng.f64() * max return rng.f64() * max
} }
// rng.f32_in_range(min, max) returns a pseudorandom f32 that lies in [min, max) // f32_in_range returns a pseudorandom `f32` in range `[min, max)`.
[inline] [inline]
pub fn (mut rng SplitMix64RNG) f32_in_range(min f32, max f32) f32 { pub fn (mut rng SplitMix64RNG) f32_in_range(min f32, max f32) f32 {
if max <= min { if max <= min {
@ -213,7 +213,7 @@ pub fn (mut rng SplitMix64RNG) f32_in_range(min f32, max f32) f32 {
return min + rng.f32n(max - min) return min + rng.f32n(max - min)
} }
// rng.i64_in_range(min, max) returns a pseudorandom i64 that lies in [min, max) // i64_in_range returns a pseudorandom `i64` in range `[min, max)`.
[inline] [inline]
pub fn (mut rng SplitMix64RNG) f64_in_range(min f64, max f64) f64 { pub fn (mut rng SplitMix64RNG) f64_in_range(min f64, max f64) f64 {
if max <= min { if max <= min {

View File

@ -5,7 +5,7 @@ module util
import time import time
// Commonly used constants across RNGs // Commonly used constants across RNGs - some taken from "Numerical Recipes".
pub const ( pub const (
lower_mask = u64(0x00000000FFFFFFFF) lower_mask = u64(0x00000000FFFFFFFF)
max_u32 = 0xFFFFFFFF max_u32 = 0xFFFFFFFF
@ -16,13 +16,13 @@ pub const (
u63_mask = u64(0x7FFFFFFFFFFFFFFF) u63_mask = u64(0x7FFFFFFFFFFFFFFF)
) )
// Constants taken from Numerical Recipes // nr_next returns a next value based on the previous value `prev`.
[inline] [inline]
fn nr_next(prev u32) u32 { fn nr_next(prev u32) u32 {
return prev * 1664525 + 1013904223 return prev * 1664525 + 1013904223
} }
// time_seed_array is a utility function that returns the required number of u32s generated from system time // time_seed_array returns the required number of u32s generated from system time.
[inline] [inline]
pub fn time_seed_array(count int) []u32 { pub fn time_seed_array(count int) []u32 {
ctime := time.now() ctime := time.now()
@ -35,13 +35,13 @@ pub fn time_seed_array(count int) []u32 {
return seed_data return seed_data
} }
// time_seed_32 returns a 32-bit seed geenrated from system time // time_seed_32 returns a 32-bit seed generated from system time.
[inline] [inline]
pub fn time_seed_32() u32 { pub fn time_seed_32() u32 {
return time_seed_array(1)[0] return time_seed_array(1)[0]
} }
// time_seed_64 returns a 64-bit seed geenrated from system time // time_seed_64 returns a 64-bit seed generated from system time.
[inline] [inline]
pub fn time_seed_64() u64 { pub fn time_seed_64() u64 {
seed_data := time_seed_array(2) seed_data := time_seed_array(2)

View File

@ -7,13 +7,13 @@ import math.bits
import rand.util import rand.util
import hash as wyhash import hash as wyhash
// Redefinition of some constants that we will need for pseudorandom number generation // Redefinition of some constants that we will need for pseudorandom number generation.
const ( const (
wyp0 = u64(0xa0761d6478bd642f) wyp0 = u64(0xa0761d6478bd642f)
wyp1 = u64(0xe7037ed1a0b428db) wyp1 = u64(0xe7037ed1a0b428db)
) )
// RNG based on the WyHash hashing algorithm // WyRandRNG is a RNG based on the WyHash hashing algorithm.
pub struct WyRandRNG { pub struct WyRandRNG {
mut: mut:
state u64 = util.time_seed_64() state u64 = util.time_seed_64()
@ -21,7 +21,7 @@ mut:
extra u32 extra u32
} }
// seed() - Set the seed, needs only two u32s in little endian format as [lower, higher] // seed sets the seed, needs only two `u32`s in little-endian format as [lower, higher].
pub fn (mut rng WyRandRNG) seed(seed_data []u32) { pub fn (mut rng WyRandRNG) seed(seed_data []u32) {
if seed_data.len != 2 { if seed_data.len != 2 {
eprintln('WyRandRNG needs 2 32-bit unsigned integers as the seed.') eprintln('WyRandRNG needs 2 32-bit unsigned integers as the seed.')
@ -31,7 +31,7 @@ pub fn (mut rng WyRandRNG) seed(seed_data []u32) {
rng.has_extra = false rng.has_extra = false
} }
// rng.u32() updates the PRNG state and returns the next pseudorandom u32 // u32 updates the PRNG state and returns the next pseudorandom `u32`.
[inline] [inline]
pub fn (mut rng WyRandRNG) u32() u32 { pub fn (mut rng WyRandRNG) u32() u32 {
if rng.has_extra { if rng.has_extra {
@ -46,7 +46,7 @@ pub fn (mut rng WyRandRNG) u32() u32 {
return lower return lower
} }
// rng.u64() updates the PRNG state and returns the next pseudorandom u64 // u64 updates the PRNG state and returns the next pseudorandom `u64`.
[inline] [inline]
pub fn (mut rng WyRandRNG) u64() u64 { pub fn (mut rng WyRandRNG) u64() u64 {
unsafe { unsafe {
@ -58,7 +58,7 @@ pub fn (mut rng WyRandRNG) u64() u64 {
return 0 return 0
} }
// rng.u32n(max) returns a pseudorandom u32 less than the max // u32n returns a pseudorandom `u32` less than `max`.
[inline] [inline]
pub fn (mut rng WyRandRNG) u32n(max u32) u32 { pub fn (mut rng WyRandRNG) u32n(max u32) u32 {
if max == 0 { if max == 0 {
@ -86,7 +86,7 @@ pub fn (mut rng WyRandRNG) u32n(max u32) u32 {
return u32(0) return u32(0)
} }
// rng.u64n(max) returns a pseudorandom u64 less than the max // u64n returns a pseudorandom `u64` less than `max`.
[inline] [inline]
pub fn (mut rng WyRandRNG) u64n(max u64) u64 { pub fn (mut rng WyRandRNG) u64n(max u64) u64 {
if max == 0 { if max == 0 {
@ -113,7 +113,7 @@ pub fn (mut rng WyRandRNG) u64n(max u64) u64 {
return u64(0) return u64(0)
} }
// rng.u32n(min, max) returns a pseudorandom u32 value that is guaranteed to be in [min, max) // u32n returns a pseudorandom `u32` value that is guaranteed to be in range `[min, max)`.
[inline] [inline]
pub fn (mut rng WyRandRNG) u32_in_range(min u32, max u32) u32 { pub fn (mut rng WyRandRNG) u32_in_range(min u32, max u32) u32 {
if max <= min { if max <= min {
@ -123,7 +123,7 @@ pub fn (mut rng WyRandRNG) u32_in_range(min u32, max u32) u32 {
return min + rng.u32n(max - min) return min + rng.u32n(max - min)
} }
// rng.u64n(min, max) returns a pseudorandom u64 value that is guaranteed to be in [min, max) // u64n returns a pseudorandom `u64` value that is guaranteed to be in range `[min, max)`.
[inline] [inline]
pub fn (mut rng WyRandRNG) u64_in_range(min u64, max u64) u64 { pub fn (mut rng WyRandRNG) u64_in_range(min u64, max u64) u64 {
if max <= min { if max <= min {
@ -133,31 +133,31 @@ pub fn (mut rng WyRandRNG) u64_in_range(min u64, max u64) u64 {
return min + rng.u64n(max - min) return min + rng.u64n(max - min)
} }
// rng.int() returns a pseudorandom 32-bit int (which may be negative) // int returns a (possibly negative) pseudorandom 32-bit `int`.
[inline] [inline]
pub fn (mut rng WyRandRNG) int() int { pub fn (mut rng WyRandRNG) int() int {
return int(rng.u32()) return int(rng.u32())
} }
// rng.i64() returns a pseudorandom 64-bit i64 (which may be negative) // i64 returns a (possibly negative) pseudorandom 64-bit `i64`.
[inline] [inline]
pub fn (mut rng WyRandRNG) i64() i64 { pub fn (mut rng WyRandRNG) i64() i64 {
return i64(rng.u64()) return i64(rng.u64())
} }
// rng.int31() returns a pseudorandom 31-bit int which is non-negative // int31 returns a positive pseudorandom 31-bit `int`.
[inline] [inline]
pub fn (mut rng WyRandRNG) int31() int { pub fn (mut rng WyRandRNG) int31() int {
return int(rng.u32() & util.u31_mask) // Set the 32nd bit to 0. return int(rng.u32() & util.u31_mask) // Set the 32nd bit to 0.
} }
// rng.int63() returns a pseudorandom 63-bit int which is non-negative // int63 returns a positive pseudorandom 63-bit `i64`.
[inline] [inline]
pub fn (mut rng WyRandRNG) int63() i64 { pub fn (mut rng WyRandRNG) int63() i64 {
return i64(rng.u64() & util.u63_mask) // Set the 64th bit to 0. return i64(rng.u64() & util.u63_mask) // Set the 64th bit to 0.
} }
// rng.intn(max) returns a pseudorandom int that lies in [0, max) // intn returns a pseudorandom `int` in range `[0, max)`.
[inline] [inline]
pub fn (mut rng WyRandRNG) intn(max int) int { pub fn (mut rng WyRandRNG) intn(max int) int {
if max <= 0 { if max <= 0 {
@ -167,7 +167,7 @@ pub fn (mut rng WyRandRNG) intn(max int) int {
return int(rng.u32n(u32(max))) return int(rng.u32n(u32(max)))
} }
// rng.i64n(max) returns a pseudorandom int that lies in [0, max) // i64n returns a pseudorandom int that lies in `[0, max)`.
[inline] [inline]
pub fn (mut rng WyRandRNG) i64n(max i64) i64 { pub fn (mut rng WyRandRNG) i64n(max i64) i64 {
if max <= 0 { if max <= 0 {
@ -177,7 +177,7 @@ pub fn (mut rng WyRandRNG) i64n(max i64) i64 {
return i64(rng.u64n(u64(max))) return i64(rng.u64n(u64(max)))
} }
// rng.int_in_range(min, max) returns a pseudorandom int that lies in [min, max) // int_in_range returns a pseudorandom `int` in range `[min, max)`.
[inline] [inline]
pub fn (mut rng WyRandRNG) int_in_range(min int, max int) int { pub fn (mut rng WyRandRNG) int_in_range(min int, max int) int {
if max <= min { if max <= min {
@ -188,7 +188,7 @@ pub fn (mut rng WyRandRNG) int_in_range(min int, max int) int {
return min + rng.intn(max - min) return min + rng.intn(max - min)
} }
// rng.i64_in_range(min, max) returns a pseudorandom i64 that lies in [min, max) // i64_in_range returns a pseudorandom `i64` in range `[min, max)`.
[inline] [inline]
pub fn (mut rng WyRandRNG) i64_in_range(min i64, max i64) i64 { pub fn (mut rng WyRandRNG) i64_in_range(min i64, max i64) i64 {
if max <= min { if max <= min {
@ -198,19 +198,19 @@ pub fn (mut rng WyRandRNG) i64_in_range(min i64, max i64) i64 {
return min + rng.i64n(max - min) return min + rng.i64n(max - min)
} }
// rng.f32() returns a pseudorandom f32 value between 0.0 (inclusive) and 1.0 (exclusive) i.e [0, 1) // f32 returns a pseudorandom `f32` value in range `[0, 1)`.
[inline] [inline]
pub fn (mut rng WyRandRNG) f32() f32 { pub fn (mut rng WyRandRNG) f32() f32 {
return f32(rng.u32()) / util.max_u32_as_f32 return f32(rng.u32()) / util.max_u32_as_f32
} }
// rng.f64() returns a pseudorandom f64 value between 0.0 (inclusive) and 1.0 (exclusive) i.e [0, 1) // f64 returns a pseudorandom `f64` value in range `[0, 1)`.
[inline] [inline]
pub fn (mut rng WyRandRNG) f64() f64 { pub fn (mut rng WyRandRNG) f64() f64 {
return f64(rng.u64()) / util.max_u64_as_f64 return f64(rng.u64()) / util.max_u64_as_f64
} }
// rng.f32n() returns a pseudorandom f32 value in [0, max) // f32n returns a pseudorandom `f32` value in range `[0, max)`.
[inline] [inline]
pub fn (mut rng WyRandRNG) f32n(max f32) f32 { pub fn (mut rng WyRandRNG) f32n(max f32) f32 {
if max <= 0 { if max <= 0 {
@ -220,7 +220,7 @@ pub fn (mut rng WyRandRNG) f32n(max f32) f32 {
return rng.f32() * max return rng.f32() * max
} }
// rng.f64n() returns a pseudorandom f64 value in [0, max) // f64n returns a pseudorandom `f64` value in range `[0, max)`.
[inline] [inline]
pub fn (mut rng WyRandRNG) f64n(max f64) f64 { pub fn (mut rng WyRandRNG) f64n(max f64) f64 {
if max <= 0 { if max <= 0 {
@ -230,7 +230,7 @@ pub fn (mut rng WyRandRNG) f64n(max f64) f64 {
return rng.f64() * max return rng.f64() * max
} }
// rng.f32_in_range(min, max) returns a pseudorandom f32 that lies in [min, max) // f32_in_range returns a pseudorandom `f32` in range `[min, max)`.
[inline] [inline]
pub fn (mut rng WyRandRNG) f32_in_range(min f32, max f32) f32 { pub fn (mut rng WyRandRNG) f32_in_range(min f32, max f32) f32 {
if max <= min { if max <= min {
@ -240,7 +240,7 @@ pub fn (mut rng WyRandRNG) f32_in_range(min f32, max f32) f32 {
return min + rng.f32n(max - min) return min + rng.f32n(max - min)
} }
// rng.i64_in_range(min, max) returns a pseudorandom i64 that lies in [min, max) // i64_in_range returns a pseudorandom `i64` in range `[min, max)`.
[inline] [inline]
pub fn (mut rng WyRandRNG) f64_in_range(min f64, max f64) f64 { pub fn (mut rng WyRandRNG) f64_in_range(min f64, max f64) f64 {
if max <= min { if max <= min {