rand: document all functions, document range notation form, fix copy-pasta (#7619)
parent
b9df7aae4d
commit
ed6ba0a2b8
|
@ -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`.
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
Loading…
Reference in New Issue