rand: separate rand.util and rand.seed submodules (#8353)

pull/8357/head
Subhomoy Haldar 2021-01-26 19:25:09 +05:30 committed by GitHub
parent 5f2b2df546
commit 97103f680a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 107 additions and 104 deletions

View File

@ -3,7 +3,7 @@ module util
import os import os
import rand import rand
import rand.wyrand import rand.wyrand
import rand.util as rutil import rand.seed as rseed
const ( const (
retries = 10000 retries = 10000
@ -26,9 +26,7 @@ pub fn temp_file(tfo TempFileOptions) ?(os.File, string) {
} }
d = d.trim_right(os.path_separator) d = d.trim_right(os.path_separator)
mut rng := rand.new_default(rand.PRNGConfigStruct{}) mut rng := rand.new_default(rand.PRNGConfigStruct{})
prefix, suffix := prefix_and_suffix(tfo.pattern) or { prefix, suffix := prefix_and_suffix(tfo.pattern) or { return error(@FN + ' ' + err) }
return error(@FN + ' ' + err)
}
for retry := 0; retry < retries; retry++ { for retry := 0; retry < retries; retry++ {
path := os.join_path(d, prefix + random_number(mut rng) + suffix) path := os.join_path(d, prefix + random_number(mut rng) + suffix)
mut mode := 'rw+' mut mode := 'rw+'
@ -36,7 +34,7 @@ pub fn temp_file(tfo TempFileOptions) ?(os.File, string) {
mode = 'w+' mode = 'w+'
} }
mut file := os.open_file(path, mode, 0o600) or { mut file := os.open_file(path, mode, 0o600) or {
rng.seed(rutil.time_seed_array(2)) rng.seed(rseed.time_seed_array(2))
continue continue
} }
if os.exists(path) && os.is_file(path) { if os.exists(path) && os.is_file(path) {
@ -64,13 +62,11 @@ pub fn temp_dir(tdo TempFileOptions) ?string {
} }
d = d.trim_right(os.path_separator) d = d.trim_right(os.path_separator)
mut rng := rand.new_default(rand.PRNGConfigStruct{}) mut rng := rand.new_default(rand.PRNGConfigStruct{})
prefix, suffix := prefix_and_suffix(tdo.pattern) or { prefix, suffix := prefix_and_suffix(tdo.pattern) or { return error(@FN + ' ' + err) }
return error(@FN + ' ' + err)
}
for retry := 0; retry < retries; retry++ { for retry := 0; retry < retries; retry++ {
path := os.join_path(d, prefix + random_number(mut rng) + suffix) path := os.join_path(d, prefix + random_number(mut rng) + suffix)
os.mkdir_all(path) or { os.mkdir_all(path) or {
rng.seed(rutil.time_seed_array(2)) rng.seed(rseed.time_seed_array(2))
continue continue
} }
if os.is_dir(path) && os.exists(path) { if os.is_dir(path) && os.exists(path) {
@ -96,9 +92,7 @@ fn prefix_and_suffix(pattern string) ?(string, string) {
if pat.contains(os.path_separator) { if pat.contains(os.path_separator) {
return error('pattern cannot contain path separators ($os.path_separator).') return error('pattern cannot contain path separators ($os.path_separator).')
} }
pos := pat.last_index('*') or { pos := pat.last_index('*') or { -1 }
-1
}
mut prefix := '' mut prefix := ''
mut suffix := '' mut suffix := ''
if pos != -1 { if pos != -1 {

View File

@ -4,7 +4,7 @@
module mt19937 module mt19937
import math.bits import math.bits
import rand.util import rand.seed
/* /*
C++ functions for MT19937, with initialization improved 2002/2/10. C++ functions for MT19937, with initialization improved 2002/2/10.
@ -59,8 +59,8 @@ const (
// MT19937RNG is 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(seed.time_seed_array(2), mut []u64{len: mt19937.nn})
mti int = nn mti int = mt19937.nn
next_rnd u32 next_rnd u32
has_next bool has_next bool
} }
@ -70,7 +70,7 @@ 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])
state[0] = u64((hi << 32) | lo) state[0] = u64((hi << 32) | lo)
for j := 1; j < nn; j++ { for j := 1; j < mt19937.nn; j++ {
state[j] = u64(6364136223846793005) * (state[j - 1] ^ (state[j - 1] >> 62)) + u64(j) state[j] = u64(6364136223846793005) * (state[j - 1] ^ (state[j - 1] >> 62)) + u64(j)
} }
return *state return *state
@ -84,7 +84,7 @@ pub fn (mut rng MT19937RNG) seed(seed_data []u32) {
exit(1) exit(1)
} }
rng.state = calculate_state(seed_data, mut rng.state) rng.state = calculate_state(seed_data, mut rng.state)
rng.mti = nn rng.mti = mt19937.nn
rng.next_rnd = 0 rng.next_rnd = 0
rng.has_next = false rng.has_next = false
} }
@ -105,21 +105,21 @@ pub fn (mut rng MT19937RNG) u32() u32 {
// u64 returns a pseudorandom 64bit int in range `[0, 2⁶⁴)`. // 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(mt19937.matrix_a)]
mut x := u64(0) mut x := u64(0)
mut i := int(0) mut i := int(0)
if rng.mti >= nn { if rng.mti >= mt19937.nn {
for i = 0; i < nn - mm; i++ { for i = 0; i < mt19937.nn - mt19937.mm; i++ {
x = (rng.state[i] & um) | (rng.state[i + 1] & lm) x = (rng.state[i] & mt19937.um) | (rng.state[i + 1] & mt19937.lm)
rng.state[i] = rng.state[i + mm] ^ (x >> 1) ^ mag01[int(x & 1)] rng.state[i] = rng.state[i + mt19937.mm] ^ (x >> 1) ^ mag01[int(x & 1)]
} }
for i < nn - 1 { for i < mt19937.nn - 1 {
x = (rng.state[i] & um) | (rng.state[i + 1] & lm) x = (rng.state[i] & mt19937.um) | (rng.state[i + 1] & mt19937.lm)
rng.state[i] = rng.state[i + (mm - nn)] ^ (x >> 1) ^ mag01[int(x & 1)] rng.state[i] = rng.state[i + (mt19937.mm - mt19937.nn)] ^ (x >> 1) ^ mag01[int(x & 1)]
i++ i++
} }
x = (rng.state[nn - 1] & um) | (rng.state[0] & lm) x = (rng.state[mt19937.nn - 1] & mt19937.um) | (rng.state[0] & mt19937.lm)
rng.state[nn - 1] = rng.state[mm - 1] ^ (x >> 1) ^ mag01[int(x & 1)] rng.state[mt19937.nn - 1] = rng.state[mt19937.mm - 1] ^ (x >> 1) ^ mag01[int(x & 1)]
rng.mti = 0 rng.mti = 0
} }
x = rng.state[rng.mti] x = rng.state[rng.mti]
@ -279,7 +279,7 @@ pub fn (mut rng MT19937RNG) f32() f32 {
// f64 returns 64bit real (`f64`) in range `[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) * mt19937.inv_f64_limit
} }
// f32n returns a 32bit real (`f32`) in range [0, max)`. // f32n returns a 32bit real (`f32`) in range [0, max)`.

View File

@ -1,6 +1,6 @@
import math import math
import rand.mt19937 import rand.mt19937
import rand.util import rand.seed
const ( const (
range_limit = 40 range_limit = 40
@ -26,7 +26,7 @@ fn mt19937_basic_test() {
fn gen_randoms(seed_data []u32, bound int) []u64 { fn gen_randoms(seed_data []u32, bound int) []u64 {
bound_u64 := u64(bound) bound_u64 := u64(bound)
mut randoms := []u64{len:(20)} mut randoms := []u64{len: (20)}
mut rnd := mt19937.MT19937RNG{} mut rnd := mt19937.MT19937RNG{}
rnd.seed(seed_data) rnd.seed(seed_data)
for i in 0 .. 20 { for i in 0 .. 20 {
@ -36,7 +36,7 @@ fn gen_randoms(seed_data []u32, bound int) []u64 {
} }
fn test_mt19937_reproducibility() { fn test_mt19937_reproducibility() {
seed_data := util.time_seed_array(2) seed_data := seed.time_seed_array(2)
randoms1 := gen_randoms(seed_data, 1000) randoms1 := gen_randoms(seed_data, 1000)
randoms2 := gen_randoms(seed_data, 1000) randoms2 := gen_randoms(seed_data, 1000)
assert randoms1.len == randoms2.len assert randoms1.len == randoms2.len

View File

@ -4,12 +4,13 @@
module musl module musl
import math.bits import math.bits
import rand.seed
import rand.util import rand.util
// MuslRNG 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 = seed.time_seed_32()
} }
// seed sets the current random state based on `seed_data`. // seed sets the current random state based on `seed_data`.

View File

@ -1,6 +1,6 @@
import math import math
import rand.musl import rand.musl
import rand.util import rand.seed
const ( const (
range_limit = 40 range_limit = 40
@ -16,7 +16,7 @@ const (
fn gen_randoms(seed_data []u32, bound int) []u64 { fn gen_randoms(seed_data []u32, bound int) []u64 {
bound_u64 := u64(bound) bound_u64 := u64(bound)
mut randoms := []u64{len:(20)} mut randoms := []u64{len: (20)}
mut rnd := musl.MuslRNG{} mut rnd := musl.MuslRNG{}
rnd.seed(seed_data) rnd.seed(seed_data)
for i in 0 .. 20 { for i in 0 .. 20 {
@ -26,7 +26,7 @@ fn gen_randoms(seed_data []u32, bound int) []u64 {
} }
fn test_musl_reproducibility() { fn test_musl_reproducibility() {
seed_data := util.time_seed_array(1) seed_data := seed.time_seed_array(1)
randoms1 := gen_randoms(seed_data, 1000) randoms1 := gen_randoms(seed_data, 1000)
randoms2 := gen_randoms(seed_data, 1000) randoms2 := gen_randoms(seed_data, 1000)
assert randoms1.len == randoms2.len assert randoms1.len == randoms2.len

View File

@ -3,6 +3,7 @@
// that can be found in the LICENSE file. // that can be found in the LICENSE file.
module pcg32 module pcg32
import rand.seed
import rand.util import rand.util
// PCG32RNG ported from http://www.pcg-random.org/download.html, // PCG32RNG ported from http://www.pcg-random.org/download.html,
@ -10,8 +11,8 @@ import rand.util
// 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 {
mut: mut:
state u64 = u64(0x853c49e6748fea9b) ^ util.time_seed_64() state u64 = u64(0x853c49e6748fea9b) ^ seed.time_seed_64()
inc u64 = u64(0xda3e39cb94b95bdb) ^ util.time_seed_64() inc u64 = u64(0xda3e39cb94b95bdb) ^ seed.time_seed_64()
} }
// seed seeds the PCG32RNG with 4 `u32` values. // seed seeds the PCG32RNG with 4 `u32` values.

View File

@ -1,6 +1,6 @@
import math import math
import rand.pcg32 import rand.pcg32
import rand.util import rand.seed
const ( const (
range_limit = 40 range_limit = 40
@ -25,7 +25,7 @@ fn gen_randoms(seed_data []u32, bound int) []u32 {
} }
fn test_pcg32_reproducibility() { fn test_pcg32_reproducibility() {
seed_data := util.time_seed_array(4) seed_data := seed.time_seed_array(4)
randoms1 := gen_randoms(seed_data, 1000) randoms1 := gen_randoms(seed_data, 1000)
randoms2 := gen_randoms(seed_data, 1000) randoms2 := gen_randoms(seed_data, 1000)
assert randoms1.len == randoms2.len assert randoms1.len == randoms2.len

View File

@ -3,13 +3,13 @@
// that can be found in the LICENSE file. // that can be found in the LICENSE file.
module rand module rand
import rand.util import rand.seed
import rand.wyrand import rand.wyrand
import time import time
// PRNGConfigStruct is a 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 = seed.time_seed_array(2)
} }
__global ( default_rng &wyrand.WyRandRNG ) __global ( default_rng &wyrand.WyRandRNG )
@ -141,10 +141,10 @@ pub fn string(len int) string {
mut buf := malloc(len) mut buf := malloc(len)
for i in 0 .. len { for i in 0 .. len {
unsafe { unsafe {
buf[i] = chars[intn(chars.len)] buf[i] = rand.chars[intn(rand.chars.len)]
} }
} }
return unsafe {buf.vstring_with_len(len)} return unsafe { buf.vstring_with_len(len) }
} }
// uuid_v4 generates a random (v4) UUID // uuid_v4 generates a random (v4) UUID
@ -184,7 +184,7 @@ pub fn uuid_v4() string {
buf[14] = `4` buf[14] = `4`
buf[buflen] = 0 buf[buflen] = 0
} }
return unsafe {buf.vstring_with_len(buflen)} return unsafe { buf.vstring_with_len(buflen) }
} }
const ( const (
@ -209,7 +209,7 @@ pub fn ulid_at_millisecond(unix_time_milli u64) string {
mut i := 9 mut i := 9
for i >= 0 { for i >= 0 {
unsafe { unsafe {
buf[i] = ulid_encoding[t & 0x1F] buf[i] = rand.ulid_encoding[t & 0x1F]
} }
t = t >> 5 t = t >> 5
i-- i--
@ -219,7 +219,7 @@ pub fn ulid_at_millisecond(unix_time_milli u64) string {
i = 10 i = 10
for i < 19 { for i < 19 {
unsafe { unsafe {
buf[i] = ulid_encoding[x & 0x1F] buf[i] = rand.ulid_encoding[x & 0x1F]
} }
x = x >> 5 x = x >> 5
i++ i++
@ -228,7 +228,7 @@ pub fn ulid_at_millisecond(unix_time_milli u64) string {
x = default_rng.u64() x = default_rng.u64()
for i < 26 { for i < 26 {
unsafe { unsafe {
buf[i] = ulid_encoding[x & 0x1F] buf[i] = rand.ulid_encoding[x & 0x1F]
} }
x = x >> 5 x = x >> 5
i++ i++
@ -236,5 +236,5 @@ pub fn ulid_at_millisecond(unix_time_milli u64) string {
unsafe { unsafe {
buf[26] = 0 buf[26] = 0
} }
return unsafe {buf.vstring_with_len(buflen)} return unsafe { buf.vstring_with_len(buflen) }
} }

View File

@ -40,7 +40,7 @@ fn test_ulids_generated_in_the_same_millisecond_have_the_same_prefix() {
t := time.utc().unix_time_milli() t := time.utc().unix_time_milli()
mut ulid1 := '' mut ulid1 := ''
mut ulid2 := '' mut ulid2 := ''
mut ulid3 := '' mut ulid3 := ''
ulid1 = rand.ulid_at_millisecond(t) ulid1 = rand.ulid_at_millisecond(t)
ulid2 = rand.ulid_at_millisecond(t) ulid2 = rand.ulid_at_millisecond(t)
ulid3 = rand.ulid_at_millisecond(t) ulid3 = rand.ulid_at_millisecond(t)

View File

@ -0,0 +1,40 @@
// Copyright (c) 2019-2021 Alexander Medvednikov. All rights reserved.
// Use of this source code is governed by an MIT license
// that can be found in the LICENSE file.
module seed
import time
// nr_next returns a next value based on the previous value `prev`.
[inline]
fn nr_next(prev u32) u32 {
return prev * 1664525 + 1013904223
}
// time_seed_array returns the required number of u32s generated from system time.
[inline]
pub fn time_seed_array(count int) []u32 {
ctime := time.now()
mut seed := u32(ctime.unix_time() ^ ctime.microsecond)
mut seed_data := []u32{cap: count}
for _ in 0 .. count {
seed = nr_next(seed)
seed_data << nr_next(seed)
}
return seed_data
}
// time_seed_32 returns a 32-bit seed generated from system time.
[inline]
pub fn time_seed_32() u32 {
return time_seed_array(1)[0]
}
// time_seed_64 returns a 64-bit seed generated from system time.
[inline]
pub fn time_seed_64() u64 {
seed_data := time_seed_array(2)
lower := u64(seed_data[0])
upper := u64(seed_data[1])
return lower | (upper << 32)
}

View File

@ -3,12 +3,13 @@
// that can be found in the LICENSE file. // that can be found in the LICENSE file.
module splitmix64 module splitmix64
import rand.seed
import rand.util import rand.util
// SplitMix64RNG 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 = seed.time_seed_64()
has_extra bool has_extra bool
extra u32 extra u32
} }

View File

@ -1,6 +1,6 @@
import math import math
import rand.splitmix64 import rand.splitmix64
import rand.util import rand.seed
const ( const (
range_limit = 40 range_limit = 40
@ -16,7 +16,7 @@ const (
fn gen_randoms(seed_data []u32, bound int) []u64 { fn gen_randoms(seed_data []u32, bound int) []u64 {
bound_u64 := u64(bound) bound_u64 := u64(bound)
mut randoms := []u64{len:(20)} mut randoms := []u64{len: (20)}
mut rnd := splitmix64.SplitMix64RNG{} mut rnd := splitmix64.SplitMix64RNG{}
rnd.seed(seed_data) rnd.seed(seed_data)
for i in 0 .. 20 { for i in 0 .. 20 {
@ -26,7 +26,7 @@ fn gen_randoms(seed_data []u32, bound int) []u64 {
} }
fn test_splitmix64_reproducibility() { fn test_splitmix64_reproducibility() {
seed_data := util.time_seed_array(2) seed_data := seed.time_seed_array(2)
randoms1 := gen_randoms(seed_data, 1000) randoms1 := gen_randoms(seed_data, 1000)
randoms2 := gen_randoms(seed_data, 1000) randoms2 := gen_randoms(seed_data, 1000)
assert randoms1.len == randoms2.len assert randoms1.len == randoms2.len

View File

@ -4,6 +4,7 @@
module sys module sys
import math.bits import math.bits
import rand.seed
import rand.util import rand.util
// Implementation note: // Implementation note:
@ -23,8 +24,8 @@ const (
) )
fn calculate_iterations_for(bits int) int { fn calculate_iterations_for(bits int) int {
base := bits / rand_bitsize base := bits / sys.rand_bitsize
extra := if bits % rand_bitsize == 0 { 0 } else { 1 } extra := if bits % sys.rand_bitsize == 0 { 0 } else { 1 }
return base + extra return base + extra
} }
@ -36,7 +37,7 @@ fn C.rand() int
// SysRNG is the PRNG provided by default in the libc implementiation that V uses. // SysRNG is the PRNG provided by default in the libc implementiation that V uses.
pub struct SysRNG { pub struct SysRNG {
mut: mut:
seed u32 = util.time_seed_32() seed u32 = seed.time_seed_32()
} }
// r.seed() sets the seed of the accepting SysRNG to the given data. // r.seed() sets the seed of the accepting SysRNG to the given data.
@ -46,7 +47,7 @@ pub fn (mut r SysRNG) seed(seed_data []u32) {
exit(1) exit(1)
} }
r.seed = seed_data[0] r.seed = seed_data[0]
unsafe {C.srand(int(r.seed))} unsafe { C.srand(int(r.seed)) }
} }
// r.default_rand() exposes the default behavior of the system's RNG // r.default_rand() exposes the default behavior of the system's RNG
@ -63,8 +64,8 @@ pub fn (r SysRNG) default_rand() int {
[inline] [inline]
pub fn (r SysRNG) u32() u32 { pub fn (r SysRNG) u32() u32 {
mut result := u32(C.rand()) mut result := u32(C.rand())
for i in 1 .. u32_iter_count { for i in 1 .. sys.u32_iter_count {
result = result ^ (u32(C.rand()) << (rand_bitsize * i)) result = result ^ (u32(C.rand()) << (sys.rand_bitsize * i))
} }
return result return result
} }
@ -73,8 +74,8 @@ pub fn (r SysRNG) u32() u32 {
[inline] [inline]
pub fn (r SysRNG) u64() u64 { pub fn (r SysRNG) u64() u64 {
mut result := u64(C.rand()) mut result := u64(C.rand())
for i in 1 .. u64_iter_count { for i in 1 .. sys.u64_iter_count {
result = result ^ (u64(C.rand()) << (rand_bitsize * i)) result = result ^ (u64(C.rand()) << (sys.rand_bitsize * i))
} }
return result return result
} }

View File

@ -3,8 +3,6 @@
// that can be found in the LICENSE file. // that can be found in the LICENSE file.
module util module util
import time
// Commonly used constants across RNGs - some taken from "Numerical Recipes". // Commonly used constants across RNGs - some taken from "Numerical Recipes".
pub const ( pub const (
lower_mask = u64(0x00000000FFFFFFFF) lower_mask = u64(0x00000000FFFFFFFF)
@ -15,37 +13,3 @@ pub const (
u31_mask = u32(0x7FFFFFFF) u31_mask = u32(0x7FFFFFFF)
u63_mask = u64(0x7FFFFFFFFFFFFFFF) u63_mask = u64(0x7FFFFFFFFFFFFFFF)
) )
// nr_next returns a next value based on the previous value `prev`.
[inline]
fn nr_next(prev u32) u32 {
return prev * 1664525 + 1013904223
}
// time_seed_array returns the required number of u32s generated from system time.
[inline]
pub fn time_seed_array(count int) []u32 {
ctime := time.now()
mut seed := u32(ctime.unix_time() ^ ctime.microsecond)
mut seed_data := []u32{cap: count}
for _ in 0 .. count {
seed = nr_next(seed)
seed_data << nr_next(seed)
}
return seed_data
}
// time_seed_32 returns a 32-bit seed generated from system time.
[inline]
pub fn time_seed_32() u32 {
return time_seed_array(1)[0]
}
// time_seed_64 returns a 64-bit seed generated from system time.
[inline]
pub fn time_seed_64() u64 {
seed_data := time_seed_array(2)
lower := u64(seed_data[0])
upper := u64(seed_data[1])
return lower | (upper << 32)
}

View File

@ -4,8 +4,9 @@
module wyrand module wyrand
import math.bits import math.bits
import rand.seed
import rand.util import rand.util
import hash as wyhash import hash
// 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 (
@ -16,7 +17,7 @@ const (
// WyRandRNG is a 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 = seed.time_seed_64()
has_extra bool has_extra bool
extra u32 extra u32
} }
@ -51,9 +52,9 @@ pub fn (mut rng WyRandRNG) u32() u32 {
pub fn (mut rng WyRandRNG) u64() u64 { pub fn (mut rng WyRandRNG) u64() u64 {
unsafe { unsafe {
mut seed1 := rng.state mut seed1 := rng.state
seed1 += wyp0 seed1 += wyrand.wyp0
rng.state = seed1 rng.state = seed1
return wyhash.wymum(seed1 ^ wyp1, seed1) return hash.wymum(seed1 ^ wyrand.wyp1, seed1)
} }
return 0 return 0
} }

View File

@ -1,5 +1,5 @@
import math import math
import rand.util import rand.seed
import rand.wyrand import rand.wyrand
const ( const (
@ -16,7 +16,7 @@ const (
fn gen_randoms(seed_data []u32, bound int) []u64 { fn gen_randoms(seed_data []u32, bound int) []u64 {
bound_u64 := u64(bound) bound_u64 := u64(bound)
mut randoms := []u64{len:(20)} mut randoms := []u64{len: (20)}
mut rnd := wyrand.WyRandRNG{} mut rnd := wyrand.WyRandRNG{}
rnd.seed(seed_data) rnd.seed(seed_data)
for i in 0 .. 20 { for i in 0 .. 20 {
@ -26,7 +26,7 @@ fn gen_randoms(seed_data []u32, bound int) []u64 {
} }
fn test_wyrand_reproducibility() { fn test_wyrand_reproducibility() {
seed_data := util.time_seed_array(2) seed_data := seed.time_seed_array(2)
randoms1 := gen_randoms(seed_data, 1000) randoms1 := gen_randoms(seed_data, 1000)
randoms2 := gen_randoms(seed_data, 1000) randoms2 := gen_randoms(seed_data, 1000)
assert randoms1.len == randoms2.len assert randoms1.len == randoms2.len