rand: reorganize: phase 2
parent
67fcce2d46
commit
e649cf84e3
|
@ -12,11 +12,11 @@ fn main() {
|
||||||
println('Generating $sample_size strings between $min_str_len - $max_str_len chars long...')
|
println('Generating $sample_size strings between $min_str_len - $max_str_len chars long...')
|
||||||
mut bytepile := []byte{}
|
mut bytepile := []byte{}
|
||||||
for _ in 0 .. sample_size * max_str_len {
|
for _ in 0 .. sample_size * max_str_len {
|
||||||
bytepile << byte(40 + rand.next(125 - 40))
|
bytepile << byte(rand.int_in_range(40, 125))
|
||||||
}
|
}
|
||||||
mut str_lens := []int{}
|
mut str_lens := []int{}
|
||||||
for _ in 0 .. sample_size {
|
for _ in 0 .. sample_size {
|
||||||
str_lens << min_str_len + rand.next(max_str_len - min_str_len)
|
str_lens << rand.int_in_range(min_str_len, max_str_len)
|
||||||
}
|
}
|
||||||
println('Hashing each of the generated strings...')
|
println('Hashing each of the generated strings...')
|
||||||
t0 := time.ticks()
|
t0 := time.ticks()
|
||||||
|
|
|
@ -22,6 +22,7 @@ const (
|
||||||
]
|
]
|
||||||
skip_on_windows = [
|
skip_on_windows = [
|
||||||
'vlib/orm/orm_test.v',
|
'vlib/orm/orm_test.v',
|
||||||
|
'vlib/net/websocket/ws_test.v',
|
||||||
]
|
]
|
||||||
skip_on_non_windows = []string{}
|
skip_on_non_windows = []string{}
|
||||||
skip_on_macos = []string{}
|
skip_on_macos = []string{}
|
||||||
|
|
|
@ -236,7 +236,7 @@ fn intersect(r Ray, spheres &Sphere, nspheres int) (bool, f64, int){
|
||||||
|
|
||||||
// some casual random function, try to avoid the 0
|
// some casual random function, try to avoid the 0
|
||||||
fn rand_f64() f64 {
|
fn rand_f64() f64 {
|
||||||
x := (C.rand()+1) & 0x3FFF_FFFF
|
x := (rand.intn(cache_len)+1) & 0x3FFF_FFFF
|
||||||
return f64(x)/f64(0x3FFF_FFFF)
|
return f64(x)/f64(0x3FFF_FFFF)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -318,7 +318,7 @@ fn radiance(r Ray, depthi int, scene_id int) Vec {
|
||||||
//r1 := f64(2.0 * math.pi) * rand_f64()
|
//r1 := f64(2.0 * math.pi) * rand_f64()
|
||||||
|
|
||||||
// tabbed speed-up
|
// tabbed speed-up
|
||||||
r1 := C.rand() & cache_mask
|
r1 := rand.intn(cache_len) & cache_mask
|
||||||
|
|
||||||
r2 := rand_f64()
|
r2 := rand_f64()
|
||||||
r2s := math.sqrt(r2)
|
r2s := math.sqrt(r2)
|
||||||
|
@ -465,9 +465,8 @@ fn main() {
|
||||||
height = os.args[5].int()
|
height = os.args[5].int()
|
||||||
}
|
}
|
||||||
|
|
||||||
// init the rand, using the same seed allows to obtain the same result in different runs
|
// change the seed for a different result
|
||||||
// change the seed from 2020 for different results
|
rand.seed([u32(2020), 0])
|
||||||
rand.seed(2020)
|
|
||||||
|
|
||||||
t1:=time.ticks()
|
t1:=time.ticks()
|
||||||
|
|
||||||
|
|
|
@ -7,11 +7,10 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
rand.seed(int(time.now().unix))
|
rand.intn(gen_max) // skip the first
|
||||||
rand.next(gen_max) // skip the first
|
|
||||||
mut arr := []int{}
|
mut arr := []int{}
|
||||||
for _ in 0..gen_len {
|
for _ in 0..gen_len {
|
||||||
arr << rand.next(gen_max)
|
arr << rand.intn(gen_max)
|
||||||
}
|
}
|
||||||
println('length of random array is $arr.len')
|
println('length of random array is $arr.len')
|
||||||
println('before quick sort whether array is sorted: ${is_sorted(arr)}')
|
println('before quick sort whether array is sorted: ${is_sorted(arr)}')
|
||||||
|
|
|
@ -2,9 +2,7 @@ import rand
|
||||||
import time
|
import time
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
rand.seed(int(time.now().unix))
|
|
||||||
|
|
||||||
for _ in 0..10 {
|
for _ in 0..10 {
|
||||||
println('${rand.next(255)}.${rand.next(255)}.${rand.next(255)}.${rand.next(255)}')
|
println('${rand.intn(255)}.${rand.intn(255)}.${rand.intn(255)}.${rand.intn(255)}')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -193,7 +193,6 @@ fn main() {
|
||||||
|
|
||||||
fn (mut g Game) init_game() {
|
fn (mut g Game) init_game() {
|
||||||
g.parse_tetros()
|
g.parse_tetros()
|
||||||
rand.seed(int(time.now().unix))
|
|
||||||
g.generate_tetro()
|
g.generate_tetro()
|
||||||
g.field = []
|
g.field = []
|
||||||
// Generate the field, fill it with 0's, add -1's on each edge
|
// Generate the field, fill it with 0's, add -1's on each edge
|
||||||
|
@ -300,7 +299,7 @@ fn (mut g Game) delete_completed_line(y int) {
|
||||||
fn (mut g Game) generate_tetro() {
|
fn (mut g Game) generate_tetro() {
|
||||||
g.pos_y = 0
|
g.pos_y = 0
|
||||||
g.pos_x = field_width / 2 - tetro_size / 2
|
g.pos_x = field_width / 2 - tetro_size / 2
|
||||||
g.tetro_idx = rand.next(b_tetros.len)
|
g.tetro_idx = rand.intn(b_tetros.len)
|
||||||
g.rotation_idx = 0
|
g.rotation_idx = 0
|
||||||
g.get_tetro()
|
g.get_tetro()
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,7 +81,7 @@ fn get_bet(money int) int {
|
||||||
}
|
}
|
||||||
bet = line.int()
|
bet = line.int()
|
||||||
if bet <= 0 {
|
if bet <= 0 {
|
||||||
println('error: $line is not heigher than 1.')
|
println('error: $line is not higher than 1.')
|
||||||
continue
|
continue
|
||||||
} else if bet > money {
|
} else if bet > money {
|
||||||
println('error: $line is more money than you have.')
|
println('error: $line is more money than you have.')
|
||||||
|
@ -92,8 +92,7 @@ fn get_bet(money int) int {
|
||||||
|
|
||||||
fn run_wheel(bet_nbr int, _bet int) int {
|
fn run_wheel(bet_nbr int, _bet int) int {
|
||||||
mut bet := _bet
|
mut bet := _bet
|
||||||
rand.seed(int(time.now().unix))
|
winning_nbr := rand.intn(50)
|
||||||
winning_nbr := rand.next(50)
|
|
||||||
print('Roulette Wheel spinning... and stops on the number $winning_nbr which is a ')
|
print('Roulette Wheel spinning... and stops on the number $winning_nbr which is a ')
|
||||||
if winning_nbr % 2 == 1 {
|
if winning_nbr % 2 == 1 {
|
||||||
println(odd)
|
println(odd)
|
||||||
|
@ -115,7 +114,7 @@ fn run_wheel(bet_nbr int, _bet int) int {
|
||||||
|
|
||||||
fn is_broke(money int) bool {
|
fn is_broke(money int) bool {
|
||||||
if money <= 0 {
|
if money <= 0 {
|
||||||
println('You\'broke, the game is over..')
|
println('You\'re broke, the game is over..')
|
||||||
return false
|
return false
|
||||||
} else {
|
} else {
|
||||||
quit := Options{'yes', 'y'}
|
quit := Options{'yes', 'y'}
|
||||||
|
|
|
@ -19,16 +19,15 @@ fn test_bf_set_clear_toggle_get() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_bf_and_not_or_xor() {
|
fn test_bf_and_not_or_xor() {
|
||||||
rand.seed(int(time.now().unix))
|
|
||||||
len := 80
|
len := 80
|
||||||
mut input1 := bitfield.new(len)
|
mut input1 := bitfield.new(len)
|
||||||
mut input2 := bitfield.new(len)
|
mut input2 := bitfield.new(len)
|
||||||
mut i := 0
|
mut i := 0
|
||||||
for i < len {
|
for i < len {
|
||||||
if rand.next(2) == 1 {
|
if rand.intn(2) == 1 {
|
||||||
input1.set_bit(i)
|
input1.set_bit(i)
|
||||||
}
|
}
|
||||||
if rand.next(2) == 1{
|
if rand.intn(2) == 1{
|
||||||
input2.set_bit(i)
|
input2.set_bit(i)
|
||||||
}
|
}
|
||||||
i++
|
i++
|
||||||
|
@ -46,11 +45,10 @@ fn test_bf_and_not_or_xor() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_clone_cmp() {
|
fn test_clone_cmp() {
|
||||||
rand.seed(int(time.now().unix))
|
|
||||||
len := 80
|
len := 80
|
||||||
mut input := bitfield.new(len)
|
mut input := bitfield.new(len)
|
||||||
for i in 0..len {
|
for i in 0..len {
|
||||||
if rand.next(2) == 1 {
|
if rand.intn(2) == 1 {
|
||||||
input.set_bit(i)
|
input.set_bit(i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -60,11 +58,10 @@ fn test_clone_cmp() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_slice_join() {
|
fn test_slice_join() {
|
||||||
rand.seed(int(time.now().unix))
|
|
||||||
len := 80
|
len := 80
|
||||||
mut input := bitfield.new(len)
|
mut input := bitfield.new(len)
|
||||||
for i in 0..len {
|
for i in 0..len {
|
||||||
if rand.next(2) == 1 {
|
if rand.intn(2) == 1 {
|
||||||
input.set_bit(i)
|
input.set_bit(i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -83,12 +80,11 @@ fn test_slice_join() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_pop_count() {
|
fn test_pop_count() {
|
||||||
rand.seed(int(time.now().unix))
|
|
||||||
len := 80
|
len := 80
|
||||||
mut count0 := 0
|
mut count0 := 0
|
||||||
mut input := bitfield.new(len)
|
mut input := bitfield.new(len)
|
||||||
for i in 0..len {
|
for i in 0..len {
|
||||||
if rand.next(2) == 1 {
|
if rand.intn(2) == 1 {
|
||||||
input.set_bit(i)
|
input.set_bit(i)
|
||||||
count0++
|
count0++
|
||||||
}
|
}
|
||||||
|
@ -98,13 +94,12 @@ fn test_pop_count() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_hamming() {
|
fn test_hamming() {
|
||||||
rand.seed(int(time.now().unix))
|
|
||||||
len := 80
|
len := 80
|
||||||
mut count := 0
|
mut count := 0
|
||||||
mut input1 := bitfield.new(len)
|
mut input1 := bitfield.new(len)
|
||||||
mut input2 := bitfield.new(len)
|
mut input2 := bitfield.new(len)
|
||||||
for i in 0..len {
|
for i in 0..len {
|
||||||
match rand.next(4) {
|
match rand.intn(4) {
|
||||||
0, 1 {
|
0, 1 {
|
||||||
input1.set_bit(i)
|
input1.set_bit(i)
|
||||||
count++
|
count++
|
||||||
|
@ -138,11 +133,10 @@ fn test_bf_from_bytes() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_bf_from_str() {
|
fn test_bf_from_str() {
|
||||||
rand.seed(int(time.now().unix))
|
|
||||||
len := 80
|
len := 80
|
||||||
mut input := ''
|
mut input := ''
|
||||||
for _ in 0..len {
|
for _ in 0..len {
|
||||||
if rand.next(2) == 1 {
|
if rand.intn(2) == 1 {
|
||||||
input = input + '1'
|
input = input + '1'
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -160,11 +154,10 @@ fn test_bf_from_str() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_bf_bf2str() {
|
fn test_bf_bf2str() {
|
||||||
rand.seed(int(time.now().unix))
|
|
||||||
len := 80
|
len := 80
|
||||||
mut input := bitfield.new(len)
|
mut input := bitfield.new(len)
|
||||||
for i in 0..len {
|
for i in 0..len {
|
||||||
if rand.next(2) == 1 {
|
if rand.intn(2) == 1 {
|
||||||
input.set_bit(i)
|
input.set_bit(i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -188,7 +181,6 @@ fn test_bf_bf2str() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_bf_set_all() {
|
fn test_bf_set_all() {
|
||||||
rand.seed(int(time.now().unix))
|
|
||||||
len := 80
|
len := 80
|
||||||
mut input := bitfield.new(len)
|
mut input := bitfield.new(len)
|
||||||
input.set_all()
|
input.set_all()
|
||||||
|
@ -202,11 +194,10 @@ fn test_bf_set_all() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_bf_clear_all() {
|
fn test_bf_clear_all() {
|
||||||
rand.seed(int(time.now().unix))
|
|
||||||
len := 80
|
len := 80
|
||||||
mut input := bitfield.new(len)
|
mut input := bitfield.new(len)
|
||||||
for i in 0..len {
|
for i in 0..len {
|
||||||
if rand.next(2) == 1 {
|
if rand.intn(2) == 1 {
|
||||||
input.set_bit(i)
|
input.set_bit(i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -221,11 +212,10 @@ fn test_bf_clear_all() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_bf_reverse() {
|
fn test_bf_reverse() {
|
||||||
rand.seed(int(time.now().unix))
|
|
||||||
len := 80
|
len := 80
|
||||||
mut input := bitfield.new(len)
|
mut input := bitfield.new(len)
|
||||||
for i in 0..len {
|
for i in 0..len {
|
||||||
if rand.next(2) == 1 {
|
if rand.intn(2) == 1 {
|
||||||
input.set_bit(i)
|
input.set_bit(i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -241,11 +231,10 @@ fn test_bf_reverse() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_bf_resize() {
|
fn test_bf_resize() {
|
||||||
rand.seed(int(time.now().unix))
|
|
||||||
len := 80
|
len := 80
|
||||||
mut input := bitfield.new(rand.next(len) + 1)
|
mut input := bitfield.new(rand.intn(len) + 1)
|
||||||
for _ in 0..100 {
|
for _ in 0..100 {
|
||||||
input.resize(rand.next(len) + 1)
|
input.resize(rand.intn(len) + 1)
|
||||||
input.set_bit(input.get_size() - 1)
|
input.set_bit(input.get_size() - 1)
|
||||||
}
|
}
|
||||||
assert input.get_bit(input.get_size() - 1) == 1
|
assert input.get_bit(input.get_size() - 1) == 1
|
||||||
|
@ -259,7 +248,6 @@ fn test_bf_pos() {
|
||||||
* all haystacks here contain exactly one instanse of needle,
|
* all haystacks here contain exactly one instanse of needle,
|
||||||
* so search should return non-negative-values
|
* so search should return non-negative-values
|
||||||
**/
|
**/
|
||||||
rand.seed(int(time.now().unix))
|
|
||||||
len := 80
|
len := 80
|
||||||
mut result := 1
|
mut result := 1
|
||||||
for i := 1; i < len; i++ { // needle size
|
for i := 1; i < len; i++ { // needle size
|
||||||
|
@ -269,13 +257,13 @@ fn test_bf_pos() {
|
||||||
|
|
||||||
// fill the needle with random values
|
// fill the needle with random values
|
||||||
for k in 0..i {
|
for k in 0..i {
|
||||||
if rand.next(2) == 1 {
|
if rand.intn(2) == 1 {
|
||||||
needle.set_bit(k)
|
needle.set_bit(k)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure the needle contains at least one set bit, selected randomly
|
// make sure the needle contains at least one set bit, selected randomly
|
||||||
r := rand.next(i)
|
r := rand.intn(i)
|
||||||
needle.set_bit(r)
|
needle.set_bit(r)
|
||||||
|
|
||||||
// create the haystack, make sure it contains the needle
|
// create the haystack, make sure it contains the needle
|
||||||
|
@ -322,11 +310,10 @@ fn test_bf_rotate() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_bf_printing(){
|
fn test_bf_printing(){
|
||||||
rand.seed(int(time.now().unix))
|
|
||||||
len := 80
|
len := 80
|
||||||
mut input := bitfield.new(len)
|
mut input := bitfield.new(len)
|
||||||
for i in 0..len {
|
for i in 0..len {
|
||||||
if rand.next(2) == 0 {
|
if rand.intn(2) == 0 {
|
||||||
input.set_bit(i)
|
input.set_bit(i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
module websocket
|
module websocket
|
||||||
|
|
||||||
import time
|
|
||||||
import rand
|
import rand
|
||||||
import math
|
|
||||||
import crypto.sha1
|
import crypto.sha1
|
||||||
import encoding.base64
|
import encoding.base64
|
||||||
|
|
||||||
|
@ -20,10 +18,7 @@ fn htonl64(payload_len u64) byteptr {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_masking_key() []byte {
|
fn create_masking_key() []byte {
|
||||||
t := time.ticks()
|
mask_bit := byte(rand.intn(255))
|
||||||
tseq := t % 23237671
|
|
||||||
mut rnd := rand.new_pcg32(u64(t), u64(tseq))
|
|
||||||
mask_bit := byte(rnd.bounded_next(u32(math.max_i32)))
|
|
||||||
buf := [`0`].repeat(4)
|
buf := [`0`].repeat(4)
|
||||||
C.memcpy(buf.data, &mask_bit, 4)
|
C.memcpy(buf.data, &mask_bit, 4)
|
||||||
return buf
|
return buf
|
||||||
|
@ -46,7 +41,7 @@ fn get_nonce(nonce_size int) string {
|
||||||
mut nonce := []byte{len: nonce_size, cap: nonce_size}
|
mut nonce := []byte{len: nonce_size, cap: nonce_size}
|
||||||
alphanum := '0123456789ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvwxyz'
|
alphanum := '0123456789ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvwxyz'
|
||||||
for i in 0 .. nonce_size {
|
for i in 0 .. nonce_size {
|
||||||
nonce[i] = alphanum[rand.next(61)]
|
nonce[i] = alphanum[rand.intn(alphanum.len)]
|
||||||
}
|
}
|
||||||
return tos(nonce.data, nonce.len).clone()
|
return tos(nonce.data, nonce.len).clone()
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
# Quickstart
|
||||||
|
|
||||||
|
The V `rand` module provides two main ways in which users can generate pseudorandom numbers:
|
||||||
|
|
||||||
|
1. Through top-level functions in the `rand` module.
|
||||||
|
- `import rand` - Import the `rand` module.
|
||||||
|
- `rand.seed(seed_data)` to seed (optional).
|
||||||
|
- Use `rand.int()`, `rand.u32n(max)`, etc.
|
||||||
|
2. Through a generator of choice. The PRNGs are included in their respective submodules.
|
||||||
|
- `import rand.pcg32` - Import the module of the PRNG required.
|
||||||
|
- `mut rng := pcg32.PCG32RNG{}` - Initialize the struct. Note that the **`mut`** is important.
|
||||||
|
- `rng.seed(seed_data)` - optionally seed it with an array of `u32` values.
|
||||||
|
- Use `rng.int()`, `rng.u32n(max)`, etc.
|
||||||
|
|
||||||
|
# General Background
|
||||||
|
|
||||||
|
A PRNG is a Pseudo Random Number Generator. Computers cannot generate truly random numbers without an external source of noise or entropy. We can use algorithms to generate sequences of seemingly random numbers, but their outputs will always be deterministic. This is often useful for simulations that need the same starting seed.
|
||||||
|
|
||||||
|
If you need truly random numbers that are going to be used for cryptography, use the `crypto.rand` module.
|
||||||
|
|
||||||
|
# Guaranteed functions
|
||||||
|
|
||||||
|
The following 21 functions are guaranteed to be supported by `rand` as well as the individual PRNGs.
|
||||||
|
|
||||||
|
- `seed(seed_data)` where `seed_data` is an array of `u32` values. Different generators require different number of bits as the initial seed. The smallest is 32-bits, required by `sys.SysRNG`. Most others require 64-bits or 2 `u32` values.
|
||||||
|
- `u32()`, `u64()`, `int()`, `i64()`, `f32()`, `f64()`
|
||||||
|
- `u32n(max)`, `u64n(max)`, `intn(max)`, `i64n(max)`, `f32n(max)`, `f64n(max)`
|
||||||
|
- `u32_in_range(min, max)`, `u64_in_range(min, max)`, `int_in_range(min, max)`, `i64_in_range(min, max)`, `f32_in_range(min, max)`, `f64_in_range(min, max)`
|
||||||
|
- `int31()`, `int63()`
|
||||||
|
|
||||||
|
# Utility Functions
|
||||||
|
|
||||||
|
All the generators are time-seeded. The helper functions publicly available in `rand.util` module are:
|
||||||
|
|
||||||
|
1. `time_seed_array()` - returns a `[]u32` that can be directly plugged into the `seed()` functions.
|
||||||
|
2. `time_seed_32()` and `time_seed_64()` - 32-bit and 64-bit values respectively that are generated from the current time.
|
||||||
|
|
||||||
|
# Caveats
|
||||||
|
|
||||||
|
Note that the `sys.SysRNG` struct (in the C backend) uses `C.srand()` which sets the seed globally. Consequently, all instances of the RNG will be affected. This problem does not arise for the other RNGs. A workaround (if you _must_ use the libc RNG) is to:
|
||||||
|
|
||||||
|
1. Seed the first instance.
|
||||||
|
2. Generate all values required.
|
||||||
|
3. Seed the second instance.
|
||||||
|
4. Generate all values required.
|
||||||
|
5. And so on...
|
|
@ -1,9 +1,10 @@
|
||||||
// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved.
|
// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved.
|
||||||
// Use of this source code is governed by an MIT license
|
// Use of this source code is governed by an MIT license
|
||||||
// that can be found in the LICENSE file.
|
// that can be found in the LICENSE file.
|
||||||
module rand
|
module mt19937
|
||||||
|
|
||||||
import math.bits
|
import math.bits
|
||||||
|
import rand.util
|
||||||
|
|
||||||
/*
|
/*
|
||||||
C++ functions for MT19937, with initialization improved 2002/2/10.
|
C++ functions for MT19937, with initialization improved 2002/2/10.
|
||||||
|
@ -58,7 +59,7 @@ const (
|
||||||
// A generator that uses the Mersenne Twister algorithm with period 2^19937
|
// A generator that uses the Mersenne Twister algorithm with period 2^19937
|
||||||
pub struct MT19937RNG {
|
pub struct MT19937RNG {
|
||||||
mut:
|
mut:
|
||||||
state []u64 = calculate_state(time_seed_array(2), mut []u64{len: nn})
|
state []u64 = calculate_state(util.time_seed_array(2), mut []u64{len: nn})
|
||||||
mti int = nn
|
mti int = nn
|
||||||
next_rnd u32 = 0
|
next_rnd u32 = 0
|
||||||
has_next bool = false
|
has_next bool = false
|
|
@ -1,5 +1,6 @@
|
||||||
import rand
|
import mt19937
|
||||||
import math
|
import math
|
||||||
|
import rand.util
|
||||||
|
|
||||||
const (
|
const (
|
||||||
range_limit = 40
|
range_limit = 40
|
||||||
|
@ -14,7 +15,7 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
fn mt19937_basic_test() {
|
fn mt19937_basic_test() {
|
||||||
mut rng := rand.MT19937RNG{}
|
mut rng := mt19937.MT19937RNG{}
|
||||||
rng.seed([u32(0xdeadbeef)])
|
rng.seed([u32(0xdeadbeef)])
|
||||||
target := [956529277, 3842322136, 3319553134, 1843186657, 2704993644, 595827513, 938518626,
|
target := [956529277, 3842322136, 3319553134, 1843186657, 2704993644, 595827513, 938518626,
|
||||||
1676224337, 3221315650, 1819026461]
|
1676224337, 3221315650, 1819026461]
|
||||||
|
@ -26,7 +27,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(0)].repeat(20)
|
mut randoms := [u64(0)].repeat(20)
|
||||||
mut rnd := rand.MT19937RNG{}
|
mut rnd := mt19937.MT19937RNG{}
|
||||||
rnd.seed(seed_data)
|
rnd.seed(seed_data)
|
||||||
for i in 0 .. 20 {
|
for i in 0 .. 20 {
|
||||||
randoms[i] = rnd.u64n(bound_u64)
|
randoms[i] = rnd.u64n(bound_u64)
|
||||||
|
@ -35,7 +36,7 @@ fn gen_randoms(seed_data []u32, bound int) []u64 {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_mt19937_reproducibility() {
|
fn test_mt19937_reproducibility() {
|
||||||
seed_data := rand.time_seed_array(2)
|
seed_data := util.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
|
||||||
|
@ -61,7 +62,7 @@ fn test_mt19937_variability() {
|
||||||
// at fault, try changing the seed values. Repeated values are
|
// at fault, try changing the seed values. Repeated values are
|
||||||
// improbable but not impossible.
|
// improbable but not impossible.
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.MT19937RNG{}
|
mut rng := mt19937.MT19937RNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
mut values := []u64{cap: value_count}
|
mut values := []u64{cap: value_count}
|
||||||
for i in 0 .. value_count {
|
for i in 0 .. value_count {
|
||||||
|
@ -73,7 +74,7 @@ fn test_mt19937_variability() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_uniformity_u64(mut rng rand.MT19937RNG, range u64) {
|
fn check_uniformity_u64(mut rng mt19937.MT19937RNG, range u64) {
|
||||||
range_f64 := f64(range)
|
range_f64 := f64(range)
|
||||||
expected_mean := range_f64 / 2.0
|
expected_mean := range_f64 / 2.0
|
||||||
mut variance := 0.0
|
mut variance := 0.0
|
||||||
|
@ -91,7 +92,7 @@ fn check_uniformity_u64(mut rng rand.MT19937RNG, range u64) {
|
||||||
fn test_mt19937_uniformity_u64() {
|
fn test_mt19937_uniformity_u64() {
|
||||||
ranges := [14019545, 80240, 130]
|
ranges := [14019545, 80240, 130]
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.MT19937RNG{}
|
mut rng := mt19937.MT19937RNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for range in ranges {
|
for range in ranges {
|
||||||
check_uniformity_u64(mut rng, u64(range))
|
check_uniformity_u64(mut rng, u64(range))
|
||||||
|
@ -99,7 +100,7 @@ fn test_mt19937_uniformity_u64() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_uniformity_f64(mut rng rand.MT19937RNG) {
|
fn check_uniformity_f64(mut rng mt19937.MT19937RNG) {
|
||||||
expected_mean := 0.5
|
expected_mean := 0.5
|
||||||
mut variance := 0.0
|
mut variance := 0.0
|
||||||
for _ in 0 .. sample_size {
|
for _ in 0 .. sample_size {
|
||||||
|
@ -116,19 +117,19 @@ fn check_uniformity_f64(mut rng rand.MT19937RNG) {
|
||||||
fn test_mt19937_uniformity_f64() {
|
fn test_mt19937_uniformity_f64() {
|
||||||
// The f64 version
|
// The f64 version
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.MT19937RNG{}
|
mut rng := mt19937.MT19937RNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
check_uniformity_f64(mut rng)
|
check_uniformity_f64(mut rng)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_mt19937_u32n() {
|
fn test_mt19937_u32n() {
|
||||||
max := 16384
|
max := u32(16384)
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.MT19937RNG{}
|
mut rng := mt19937.MT19937RNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.u32n(u32(max))
|
value := rng.u32n(max)
|
||||||
assert value >= 0
|
assert value >= 0
|
||||||
assert value < max
|
assert value < max
|
||||||
}
|
}
|
||||||
|
@ -138,7 +139,7 @@ fn test_mt19937_u32n() {
|
||||||
fn test_mt19937_u64n() {
|
fn test_mt19937_u64n() {
|
||||||
max := u64(379091181005)
|
max := u64(379091181005)
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.MT19937RNG{}
|
mut rng := mt19937.MT19937RNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.u64n(max)
|
value := rng.u64n(max)
|
||||||
|
@ -149,13 +150,13 @@ fn test_mt19937_u64n() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_mt19937_u32_in_range() {
|
fn test_mt19937_u32_in_range() {
|
||||||
max := 484468466
|
max := u32(484468466)
|
||||||
min := 316846
|
min := u32(316846)
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.MT19937RNG{}
|
mut rng := mt19937.MT19937RNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.u32_in_range(u32(min), u32(max))
|
value := rng.u32_in_range(min, max)
|
||||||
assert value >= min
|
assert value >= min
|
||||||
assert value < max
|
assert value < max
|
||||||
}
|
}
|
||||||
|
@ -166,7 +167,7 @@ fn test_mt19937_u64_in_range() {
|
||||||
max := u64(216468454685163)
|
max := u64(216468454685163)
|
||||||
min := u64(6848646868)
|
min := u64(6848646868)
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.MT19937RNG{}
|
mut rng := mt19937.MT19937RNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.u64_in_range(min, max)
|
value := rng.u64_in_range(min, max)
|
||||||
|
@ -180,7 +181,7 @@ fn test_mt19937_int31() {
|
||||||
max_u31 := 0x7FFFFFFF
|
max_u31 := 0x7FFFFFFF
|
||||||
sign_mask := 0x80000000
|
sign_mask := 0x80000000
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.MT19937RNG{}
|
mut rng := mt19937.MT19937RNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.int31()
|
value := rng.int31()
|
||||||
|
@ -196,7 +197,7 @@ fn test_mt19937_int63() {
|
||||||
max_u63 := i64(0x7FFFFFFFFFFFFFFF)
|
max_u63 := i64(0x7FFFFFFFFFFFFFFF)
|
||||||
sign_mask := i64(0x8000000000000000)
|
sign_mask := i64(0x8000000000000000)
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.MT19937RNG{}
|
mut rng := mt19937.MT19937RNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.int63()
|
value := rng.int63()
|
||||||
|
@ -210,7 +211,7 @@ fn test_mt19937_int63() {
|
||||||
fn test_mt19937_intn() {
|
fn test_mt19937_intn() {
|
||||||
max := 2525642
|
max := 2525642
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.MT19937RNG{}
|
mut rng := mt19937.MT19937RNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.intn(max)
|
value := rng.intn(max)
|
||||||
|
@ -223,7 +224,7 @@ fn test_mt19937_intn() {
|
||||||
fn test_mt19937_i64n() {
|
fn test_mt19937_i64n() {
|
||||||
max := i64(3246727724653636)
|
max := i64(3246727724653636)
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.MT19937RNG{}
|
mut rng := mt19937.MT19937RNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.i64n(max)
|
value := rng.i64n(max)
|
||||||
|
@ -237,7 +238,7 @@ fn test_mt19937_int_in_range() {
|
||||||
min := -4252
|
min := -4252
|
||||||
max := 1034
|
max := 1034
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.MT19937RNG{}
|
mut rng := mt19937.MT19937RNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.int_in_range(min, max)
|
value := rng.int_in_range(min, max)
|
||||||
|
@ -251,7 +252,7 @@ fn test_mt19937_i64_in_range() {
|
||||||
min := i64(-24095)
|
min := i64(-24095)
|
||||||
max := i64(324058)
|
max := i64(324058)
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.MT19937RNG{}
|
mut rng := mt19937.MT19937RNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.i64_in_range(min, max)
|
value := rng.i64_in_range(min, max)
|
||||||
|
@ -263,7 +264,7 @@ fn test_mt19937_i64_in_range() {
|
||||||
|
|
||||||
fn test_mt19937_f32() {
|
fn test_mt19937_f32() {
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.MT19937RNG{}
|
mut rng := mt19937.MT19937RNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.f32()
|
value := rng.f32()
|
||||||
|
@ -275,7 +276,7 @@ fn test_mt19937_f32() {
|
||||||
|
|
||||||
fn test_mt19937_f64() {
|
fn test_mt19937_f64() {
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.MT19937RNG{}
|
mut rng := mt19937.MT19937RNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.f64()
|
value := rng.f64()
|
||||||
|
@ -288,7 +289,7 @@ fn test_mt19937_f64() {
|
||||||
fn test_mt19937_f32n() {
|
fn test_mt19937_f32n() {
|
||||||
max := f32(357.0)
|
max := f32(357.0)
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.MT19937RNG{}
|
mut rng := mt19937.MT19937RNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.f32n(max)
|
value := rng.f32n(max)
|
||||||
|
@ -301,7 +302,7 @@ fn test_mt19937_f32n() {
|
||||||
fn test_mt19937_f64n() {
|
fn test_mt19937_f64n() {
|
||||||
max := 1.52e6
|
max := 1.52e6
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.MT19937RNG{}
|
mut rng := mt19937.MT19937RNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.f64n(max)
|
value := rng.f64n(max)
|
||||||
|
@ -315,7 +316,7 @@ fn test_mt19937_f32_in_range() {
|
||||||
min := f32(-24.0)
|
min := f32(-24.0)
|
||||||
max := f32(125.0)
|
max := f32(125.0)
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.MT19937RNG{}
|
mut rng := mt19937.MT19937RNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.f32_in_range(min, max)
|
value := rng.f32_in_range(min, max)
|
||||||
|
@ -329,7 +330,7 @@ fn test_mt19937_f64_in_range() {
|
||||||
min := -548.7
|
min := -548.7
|
||||||
max := 5015.2
|
max := 5015.2
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.MT19937RNG{}
|
mut rng := mt19937.MT19937RNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.f64_in_range(min, max)
|
value := rng.f64_in_range(min, max)
|
|
@ -1,14 +1,15 @@
|
||||||
// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved.
|
// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved.
|
||||||
// Use of this source code is governed by an MIT license
|
// Use of this source code is governed by an MIT license
|
||||||
// that can be found in the LICENSE file.
|
// that can be found in the LICENSE file.
|
||||||
module rand
|
module musl
|
||||||
|
|
||||||
import math.bits
|
import math.bits
|
||||||
|
import rand.util
|
||||||
|
|
||||||
// Ported from https://git.musl-libc.org/cgit/musl/tree/src/prng/rand_r.c
|
// 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 = time_seed_32()
|
state u32 = util.time_seed_32()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut rng MuslRNG) seed(seed_data []u32) {
|
pub fn (mut rng MuslRNG) seed(seed_data []u32) {
|
||||||
|
@ -186,13 +187,13 @@ pub fn (mut rng MuslRNG) i64_in_range(min, max i64) i64 {
|
||||||
// rng.f32() returns a pseudorandom f32 value between 0.0 (inclusive) and 1.0 (exclusive) i.e [0, 1)
|
// rng.f32() returns a pseudorandom f32 value between 0.0 (inclusive) and 1.0 (exclusive) i.e [0, 1)
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (mut rng MuslRNG) f32() f32 {
|
pub fn (mut rng MuslRNG) f32() f32 {
|
||||||
return f32(rng.u32()) / 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)
|
// rng.f64() returns a pseudorandom f64 value between 0.0 (inclusive) and 1.0 (exclusive) i.e [0, 1)
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (mut rng MuslRNG) f64() f64 {
|
pub fn (mut rng MuslRNG) f64() f64 {
|
||||||
return f64(rng.u64()) / max_u64_as_f64
|
return f64(rng.u64()) / util.max_u64_as_f64
|
||||||
}
|
}
|
||||||
|
|
||||||
// rng.f32n() returns a pseudorandom f32 value in [0, max)
|
// rng.f32n() returns a pseudorandom f32 value in [0, max)
|
|
@ -1,5 +1,6 @@
|
||||||
import rand
|
import musl
|
||||||
import math
|
import math
|
||||||
|
import rand.util
|
||||||
|
|
||||||
const (
|
const (
|
||||||
range_limit = 40
|
range_limit = 40
|
||||||
|
@ -16,7 +17,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(0)].repeat(20)
|
mut randoms := [u64(0)].repeat(20)
|
||||||
mut rnd := rand.MuslRNG{}
|
mut rnd := musl.MuslRNG{}
|
||||||
rnd.seed(seed_data)
|
rnd.seed(seed_data)
|
||||||
for i in 0 .. 20 {
|
for i in 0 .. 20 {
|
||||||
randoms[i] = rnd.u64n(bound_u64)
|
randoms[i] = rnd.u64n(bound_u64)
|
||||||
|
@ -25,7 +26,7 @@ fn gen_randoms(seed_data []u32, bound int) []u64 {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_musl_reproducibility() {
|
fn test_musl_reproducibility() {
|
||||||
seed_data := rand.time_seed_array(1)
|
seed_data := util.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
|
||||||
|
@ -51,7 +52,7 @@ fn test_musl_variability() {
|
||||||
// at fault, try changing the seed values. Repeated values are
|
// at fault, try changing the seed values. Repeated values are
|
||||||
// improbable but not impossible.
|
// improbable but not impossible.
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.MuslRNG{}
|
mut rng := musl.MuslRNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
mut values := []u64{cap: value_count}
|
mut values := []u64{cap: value_count}
|
||||||
for i in 0 .. value_count {
|
for i in 0 .. value_count {
|
||||||
|
@ -63,7 +64,7 @@ fn test_musl_variability() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_uniformity_u64(mut rng rand.MuslRNG, range u64) {
|
fn check_uniformity_u64(mut rng musl.MuslRNG, range u64) {
|
||||||
range_f64 := f64(range)
|
range_f64 := f64(range)
|
||||||
expected_mean := range_f64 / 2.0
|
expected_mean := range_f64 / 2.0
|
||||||
mut variance := 0.0
|
mut variance := 0.0
|
||||||
|
@ -81,7 +82,7 @@ fn check_uniformity_u64(mut rng rand.MuslRNG, range u64) {
|
||||||
fn test_musl_uniformity_u64() {
|
fn test_musl_uniformity_u64() {
|
||||||
ranges := [14019545, 80240, 130]
|
ranges := [14019545, 80240, 130]
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.MuslRNG{}
|
mut rng := musl.MuslRNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for range in ranges {
|
for range in ranges {
|
||||||
check_uniformity_u64(mut rng, u64(range))
|
check_uniformity_u64(mut rng, u64(range))
|
||||||
|
@ -89,7 +90,7 @@ fn test_musl_uniformity_u64() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_uniformity_f64(mut rng rand.MuslRNG) {
|
fn check_uniformity_f64(mut rng musl.MuslRNG) {
|
||||||
expected_mean := 0.5
|
expected_mean := 0.5
|
||||||
mut variance := 0.0
|
mut variance := 0.0
|
||||||
for _ in 0 .. sample_size {
|
for _ in 0 .. sample_size {
|
||||||
|
@ -106,19 +107,19 @@ fn check_uniformity_f64(mut rng rand.MuslRNG) {
|
||||||
fn test_musl_uniformity_f64() {
|
fn test_musl_uniformity_f64() {
|
||||||
// The f64 version
|
// The f64 version
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.MuslRNG{}
|
mut rng := musl.MuslRNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
check_uniformity_f64(mut rng)
|
check_uniformity_f64(mut rng)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_musl_u32n() {
|
fn test_musl_u32n() {
|
||||||
max := 16384
|
max := u32(16384)
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.MuslRNG{}
|
mut rng := musl.MuslRNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.u32n(u32(max))
|
value := rng.u32n(max)
|
||||||
assert value >= 0
|
assert value >= 0
|
||||||
assert value < max
|
assert value < max
|
||||||
}
|
}
|
||||||
|
@ -128,7 +129,7 @@ fn test_musl_u32n() {
|
||||||
fn test_musl_u64n() {
|
fn test_musl_u64n() {
|
||||||
max := u64(379091181005)
|
max := u64(379091181005)
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.MuslRNG{}
|
mut rng := musl.MuslRNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.u64n(max)
|
value := rng.u64n(max)
|
||||||
|
@ -139,13 +140,13 @@ fn test_musl_u64n() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_musl_u32_in_range() {
|
fn test_musl_u32_in_range() {
|
||||||
max := 484468466
|
max := u32(484468466)
|
||||||
min := 316846
|
min := u32(316846)
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.MuslRNG{}
|
mut rng := musl.MuslRNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.u32_in_range(u64(min), u64(max))
|
value := rng.u32_in_range(min, max)
|
||||||
assert value >= min
|
assert value >= min
|
||||||
assert value < max
|
assert value < max
|
||||||
}
|
}
|
||||||
|
@ -156,7 +157,7 @@ fn test_musl_u64_in_range() {
|
||||||
max := u64(216468454685163)
|
max := u64(216468454685163)
|
||||||
min := u64(6848646868)
|
min := u64(6848646868)
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.MuslRNG{}
|
mut rng := musl.MuslRNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.u64_in_range(min, max)
|
value := rng.u64_in_range(min, max)
|
||||||
|
@ -170,7 +171,7 @@ fn test_musl_int31() {
|
||||||
max_u31 := 0x7FFFFFFF
|
max_u31 := 0x7FFFFFFF
|
||||||
sign_mask := 0x80000000
|
sign_mask := 0x80000000
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.MuslRNG{}
|
mut rng := musl.MuslRNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.int31()
|
value := rng.int31()
|
||||||
|
@ -186,7 +187,7 @@ fn test_musl_int63() {
|
||||||
max_u63 := i64(0x7FFFFFFFFFFFFFFF)
|
max_u63 := i64(0x7FFFFFFFFFFFFFFF)
|
||||||
sign_mask := i64(0x8000000000000000)
|
sign_mask := i64(0x8000000000000000)
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.MuslRNG{}
|
mut rng := musl.MuslRNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.int63()
|
value := rng.int63()
|
||||||
|
@ -200,7 +201,7 @@ fn test_musl_int63() {
|
||||||
fn test_musl_intn() {
|
fn test_musl_intn() {
|
||||||
max := 2525642
|
max := 2525642
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.MuslRNG{}
|
mut rng := musl.MuslRNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.intn(max)
|
value := rng.intn(max)
|
||||||
|
@ -213,7 +214,7 @@ fn test_musl_intn() {
|
||||||
fn test_musl_i64n() {
|
fn test_musl_i64n() {
|
||||||
max := i64(3246727724653636)
|
max := i64(3246727724653636)
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.MuslRNG{}
|
mut rng := musl.MuslRNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.i64n(max)
|
value := rng.i64n(max)
|
||||||
|
@ -227,7 +228,7 @@ fn test_musl_int_in_range() {
|
||||||
min := -4252
|
min := -4252
|
||||||
max := 1034
|
max := 1034
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.MuslRNG{}
|
mut rng := musl.MuslRNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.int_in_range(min, max)
|
value := rng.int_in_range(min, max)
|
||||||
|
@ -241,7 +242,7 @@ fn test_musl_i64_in_range() {
|
||||||
min := i64(-24095)
|
min := i64(-24095)
|
||||||
max := i64(324058)
|
max := i64(324058)
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.MuslRNG{}
|
mut rng := musl.MuslRNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.i64_in_range(min, max)
|
value := rng.i64_in_range(min, max)
|
||||||
|
@ -253,7 +254,7 @@ fn test_musl_i64_in_range() {
|
||||||
|
|
||||||
fn test_musl_f32() {
|
fn test_musl_f32() {
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.MuslRNG{}
|
mut rng := musl.MuslRNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.f32()
|
value := rng.f32()
|
||||||
|
@ -265,7 +266,7 @@ fn test_musl_f32() {
|
||||||
|
|
||||||
fn test_musl_f64() {
|
fn test_musl_f64() {
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.MuslRNG{}
|
mut rng := musl.MuslRNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.f64()
|
value := rng.f64()
|
||||||
|
@ -278,10 +279,10 @@ fn test_musl_f64() {
|
||||||
fn test_musl_f32n() {
|
fn test_musl_f32n() {
|
||||||
max := f32(357.0)
|
max := f32(357.0)
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.MuslRNG{}
|
mut rng := musl.MuslRNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.f32()
|
value := rng.f32n(max)
|
||||||
assert value >= 0.0
|
assert value >= 0.0
|
||||||
assert value < max
|
assert value < max
|
||||||
}
|
}
|
||||||
|
@ -291,10 +292,10 @@ fn test_musl_f32n() {
|
||||||
fn test_musl_f64n() {
|
fn test_musl_f64n() {
|
||||||
max := 1.52e6
|
max := 1.52e6
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.MuslRNG{}
|
mut rng := musl.MuslRNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.f64()
|
value := rng.f64n(max)
|
||||||
assert value >= 0.0
|
assert value >= 0.0
|
||||||
assert value < max
|
assert value < max
|
||||||
}
|
}
|
||||||
|
@ -305,10 +306,10 @@ fn test_musl_f32_in_range() {
|
||||||
min := f32(-24.0)
|
min := f32(-24.0)
|
||||||
max := f32(125.0)
|
max := f32(125.0)
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.MuslRNG{}
|
mut rng := musl.MuslRNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.f32()
|
value := rng.f32_in_range(min, max)
|
||||||
assert value >= min
|
assert value >= min
|
||||||
assert value < max
|
assert value < max
|
||||||
}
|
}
|
||||||
|
@ -319,10 +320,10 @@ fn test_musl_f64_in_range() {
|
||||||
min := -548.7
|
min := -548.7
|
||||||
max := 5015.2
|
max := 5015.2
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.MuslRNG{}
|
mut rng := musl.MuslRNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.f64()
|
value := rng.f64_in_range(min, max)
|
||||||
assert value >= min
|
assert value >= min
|
||||||
assert value < max
|
assert value < max
|
||||||
}
|
}
|
|
@ -1,26 +1,17 @@
|
||||||
// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved.
|
// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved.
|
||||||
// Use of this source code is governed by an MIT license
|
// Use of this source code is governed by an MIT license
|
||||||
// that can be found in the LICENSE file.
|
// that can be found in the LICENSE file.
|
||||||
module rand
|
module pcg32
|
||||||
|
|
||||||
|
import rand.util
|
||||||
|
|
||||||
// Ported from http://www.pcg-random.org/download.html,
|
// 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 {
|
||||||
mut:
|
mut:
|
||||||
state u64 = u64(0x853c49e6748fea9b) ^ time_seed_64()
|
state u64 = u64(0x853c49e6748fea9b) ^ util.time_seed_64()
|
||||||
inc u64 = u64(0xda3e39cb94b95bdb) ^ time_seed_64()
|
inc u64 = u64(0xda3e39cb94b95bdb) ^ util.time_seed_64()
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Remove in Phase 2 of reorganizing Random
|
|
||||||
pub fn new_pcg32(init_state, init_seq u64) PCG32RNG {
|
|
||||||
mut rng := PCG32RNG{}
|
|
||||||
rng.seed([u32(init_state), u32(init_state >> 32), u32(init_seq), u32(init_seq >> 32)])
|
|
||||||
return rng
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn (mut rng PCG32RNG) bounded_next(bound u32) u32 {
|
|
||||||
return rng.u32n(bound)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// rng.seed(seed_data) - seed the PCG32RNG with 4 u32 values.
|
// rng.seed(seed_data) - seed the PCG32RNG with 4 u32 values.
|
||||||
|
@ -184,13 +175,13 @@ pub fn (mut rng PCG32RNG) i64_in_range(min, max i64) i64 {
|
||||||
// rng.f32() returns a pseudorandom f32 value between 0.0 (inclusive) and 1.0 (exclusive) i.e [0, 1)
|
// rng.f32() returns a pseudorandom f32 value between 0.0 (inclusive) and 1.0 (exclusive) i.e [0, 1)
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (mut rng PCG32RNG) f32() f32 {
|
pub fn (mut rng PCG32RNG) f32() f32 {
|
||||||
return f32(rng.u32()) / 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)
|
// rng.f64() returns a pseudorandom f64 value between 0.0 (inclusive) and 1.0 (exclusive) i.e [0, 1)
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (mut rng PCG32RNG) f64() f64 {
|
pub fn (mut rng PCG32RNG) f64() f64 {
|
||||||
return f64(rng.u64()) / max_u64_as_f64
|
return f64(rng.u64()) / util.max_u64_as_f64
|
||||||
}
|
}
|
||||||
|
|
||||||
// rng.f32n() returns a pseudorandom f32 value in [0, max)
|
// rng.f32n() returns a pseudorandom f32 value in [0, max)
|
|
@ -1,5 +1,6 @@
|
||||||
import rand
|
|
||||||
import math
|
import math
|
||||||
|
import pcg32
|
||||||
|
import rand.util
|
||||||
|
|
||||||
const (
|
const (
|
||||||
range_limit = 40
|
range_limit = 40
|
||||||
|
@ -15,7 +16,7 @@ const (
|
||||||
|
|
||||||
fn gen_randoms(seed_data []u32, bound int) []u32 {
|
fn gen_randoms(seed_data []u32, bound int) []u32 {
|
||||||
mut randoms := []u32{len: 20}
|
mut randoms := []u32{len: 20}
|
||||||
mut rng := rand.PCG32RNG{}
|
mut rng := pcg32.PCG32RNG{}
|
||||||
rng.seed(seed_data)
|
rng.seed(seed_data)
|
||||||
for i in 0 .. 20 {
|
for i in 0 .. 20 {
|
||||||
randoms[i] = rng.u32n(u32(bound))
|
randoms[i] = rng.u32n(u32(bound))
|
||||||
|
@ -24,8 +25,8 @@ fn gen_randoms(seed_data []u32, bound int) []u32 {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_pcg32_reproducibility() {
|
fn test_pcg32_reproducibility() {
|
||||||
randoms1 := gen_randoms(rand.time_seed_array(4), 1000)
|
randoms1 := gen_randoms(util.time_seed_array(4), 1000)
|
||||||
randoms2 := gen_randoms(rand.time_seed_array(4), 1000)
|
randoms2 := gen_randoms(util.time_seed_array(4), 1000)
|
||||||
assert randoms1.len == randoms2.len
|
assert randoms1.len == randoms2.len
|
||||||
len := randoms1.len
|
len := randoms1.len
|
||||||
for i in 0 .. len {
|
for i in 0 .. len {
|
||||||
|
@ -49,7 +50,7 @@ fn test_pcg32_variability() {
|
||||||
// at fault, try changing the seed values. Repeated values are
|
// at fault, try changing the seed values. Repeated values are
|
||||||
// improbable but not impossible.
|
// improbable but not impossible.
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.PCG32RNG{}
|
mut rng := pcg32.PCG32RNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
mut values := []u64{cap: value_count}
|
mut values := []u64{cap: value_count}
|
||||||
for i in 0 .. value_count {
|
for i in 0 .. value_count {
|
||||||
|
@ -61,7 +62,7 @@ fn test_pcg32_variability() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_uniformity_u64(mut rng rand.PCG32RNG, range u64) {
|
fn check_uniformity_u64(mut rng pcg32.PCG32RNG, range u64) {
|
||||||
range_f64 := f64(range)
|
range_f64 := f64(range)
|
||||||
expected_mean := range_f64 / 2.0
|
expected_mean := range_f64 / 2.0
|
||||||
mut variance := 0.0
|
mut variance := 0.0
|
||||||
|
@ -79,7 +80,7 @@ fn check_uniformity_u64(mut rng rand.PCG32RNG, range u64) {
|
||||||
fn test_pcg32_uniformity_u64() {
|
fn test_pcg32_uniformity_u64() {
|
||||||
ranges := [14019545, 80240, 130]
|
ranges := [14019545, 80240, 130]
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.PCG32RNG{}
|
mut rng := pcg32.PCG32RNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for range in ranges {
|
for range in ranges {
|
||||||
check_uniformity_u64(mut rng, u64(range))
|
check_uniformity_u64(mut rng, u64(range))
|
||||||
|
@ -87,7 +88,7 @@ fn test_pcg32_uniformity_u64() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_uniformity_f64(mut rng rand.PCG32RNG) {
|
fn check_uniformity_f64(mut rng pcg32.PCG32RNG) {
|
||||||
expected_mean := 0.5
|
expected_mean := 0.5
|
||||||
mut variance := 0.0
|
mut variance := 0.0
|
||||||
for _ in 0 .. sample_size {
|
for _ in 0 .. sample_size {
|
||||||
|
@ -104,19 +105,19 @@ fn check_uniformity_f64(mut rng rand.PCG32RNG) {
|
||||||
fn test_pcg32_uniformity_f64() {
|
fn test_pcg32_uniformity_f64() {
|
||||||
// The f64 version
|
// The f64 version
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.PCG32RNG{}
|
mut rng := pcg32.PCG32RNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
check_uniformity_f64(mut rng)
|
check_uniformity_f64(mut rng)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_pcg32_u32n() {
|
fn test_pcg32_u32n() {
|
||||||
max := 16384
|
max := u32(16384)
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.PCG32RNG{}
|
mut rng := pcg32.PCG32RNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.u32n(u32(max))
|
value := rng.u32n(max)
|
||||||
assert value >= 0
|
assert value >= 0
|
||||||
assert value < max
|
assert value < max
|
||||||
}
|
}
|
||||||
|
@ -126,7 +127,7 @@ fn test_pcg32_u32n() {
|
||||||
fn test_pcg32_u64n() {
|
fn test_pcg32_u64n() {
|
||||||
max := u64(379091181005)
|
max := u64(379091181005)
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.PCG32RNG{}
|
mut rng := pcg32.PCG32RNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.u64n(max)
|
value := rng.u64n(max)
|
||||||
|
@ -137,10 +138,10 @@ fn test_pcg32_u64n() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_pcg32_u32_in_range() {
|
fn test_pcg32_u32_in_range() {
|
||||||
max := 484468466
|
max := u64(484468466)
|
||||||
min := 316846
|
min := u64(316846)
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.PCG32RNG{}
|
mut rng := pcg32.PCG32RNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.u32_in_range(u64(min), u64(max))
|
value := rng.u32_in_range(u64(min), u64(max))
|
||||||
|
@ -154,7 +155,7 @@ fn test_pcg32_u64_in_range() {
|
||||||
max := u64(216468454685163)
|
max := u64(216468454685163)
|
||||||
min := u64(6848646868)
|
min := u64(6848646868)
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.PCG32RNG{}
|
mut rng := pcg32.PCG32RNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.u64_in_range(min, max)
|
value := rng.u64_in_range(min, max)
|
||||||
|
@ -168,7 +169,7 @@ fn test_pcg32_int31() {
|
||||||
max_u31 := 0x7FFFFFFF
|
max_u31 := 0x7FFFFFFF
|
||||||
sign_mask := 0x80000000
|
sign_mask := 0x80000000
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.PCG32RNG{}
|
mut rng := pcg32.PCG32RNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.int31()
|
value := rng.int31()
|
||||||
|
@ -184,7 +185,7 @@ fn test_pcg32_int63() {
|
||||||
max_u63 := i64(0x7FFFFFFFFFFFFFFF)
|
max_u63 := i64(0x7FFFFFFFFFFFFFFF)
|
||||||
sign_mask := i64(0x8000000000000000)
|
sign_mask := i64(0x8000000000000000)
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.PCG32RNG{}
|
mut rng := pcg32.PCG32RNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.int63()
|
value := rng.int63()
|
||||||
|
@ -198,7 +199,7 @@ fn test_pcg32_int63() {
|
||||||
fn test_pcg32_intn() {
|
fn test_pcg32_intn() {
|
||||||
max := 2525642
|
max := 2525642
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.PCG32RNG{}
|
mut rng := pcg32.PCG32RNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.intn(max)
|
value := rng.intn(max)
|
||||||
|
@ -211,7 +212,7 @@ fn test_pcg32_intn() {
|
||||||
fn test_pcg32_i64n() {
|
fn test_pcg32_i64n() {
|
||||||
max := i64(3246727724653636)
|
max := i64(3246727724653636)
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.PCG32RNG{}
|
mut rng := pcg32.PCG32RNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.i64n(max)
|
value := rng.i64n(max)
|
||||||
|
@ -225,7 +226,7 @@ fn test_pcg32_int_in_range() {
|
||||||
min := -4252
|
min := -4252
|
||||||
max := 1034
|
max := 1034
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.PCG32RNG{}
|
mut rng := pcg32.PCG32RNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.int_in_range(min, max)
|
value := rng.int_in_range(min, max)
|
||||||
|
@ -239,7 +240,7 @@ fn test_pcg32_i64_in_range() {
|
||||||
min := i64(-24095)
|
min := i64(-24095)
|
||||||
max := i64(324058)
|
max := i64(324058)
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.PCG32RNG{}
|
mut rng := pcg32.PCG32RNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.i64_in_range(min, max)
|
value := rng.i64_in_range(min, max)
|
||||||
|
@ -251,7 +252,7 @@ fn test_pcg32_i64_in_range() {
|
||||||
|
|
||||||
fn test_pcg32_f32() {
|
fn test_pcg32_f32() {
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.PCG32RNG{}
|
mut rng := pcg32.PCG32RNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.f32()
|
value := rng.f32()
|
||||||
|
@ -263,7 +264,7 @@ fn test_pcg32_f32() {
|
||||||
|
|
||||||
fn test_pcg32_f64() {
|
fn test_pcg32_f64() {
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.PCG32RNG{}
|
mut rng := pcg32.PCG32RNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.f64()
|
value := rng.f64()
|
||||||
|
@ -276,10 +277,10 @@ fn test_pcg32_f64() {
|
||||||
fn test_pcg32_f32n() {
|
fn test_pcg32_f32n() {
|
||||||
max := f32(357.0)
|
max := f32(357.0)
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.PCG32RNG{}
|
mut rng := pcg32.PCG32RNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.f32()
|
value := rng.f32n(max)
|
||||||
assert value >= 0.0
|
assert value >= 0.0
|
||||||
assert value < max
|
assert value < max
|
||||||
}
|
}
|
||||||
|
@ -289,10 +290,10 @@ fn test_pcg32_f32n() {
|
||||||
fn test_pcg32_f64n() {
|
fn test_pcg32_f64n() {
|
||||||
max := 1.52e6
|
max := 1.52e6
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.PCG32RNG{}
|
mut rng := pcg32.PCG32RNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.f64()
|
value := rng.f64n(max)
|
||||||
assert value >= 0.0
|
assert value >= 0.0
|
||||||
assert value < max
|
assert value < max
|
||||||
}
|
}
|
||||||
|
@ -303,10 +304,10 @@ fn test_pcg32_f32_in_range() {
|
||||||
min := f32(-24.0)
|
min := f32(-24.0)
|
||||||
max := f32(125.0)
|
max := f32(125.0)
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.PCG32RNG{}
|
mut rng := pcg32.PCG32RNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.f32()
|
value := rng.f32_in_range(min, max)
|
||||||
assert value >= min
|
assert value >= min
|
||||||
assert value < max
|
assert value < max
|
||||||
}
|
}
|
||||||
|
@ -317,10 +318,10 @@ fn test_pcg32_f64_in_range() {
|
||||||
min := -548.7
|
min := -548.7
|
||||||
max := 5015.2
|
max := 5015.2
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.PCG32RNG{}
|
mut rng := pcg32.PCG32RNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.f64()
|
value := rng.f64_in_range(min, max)
|
||||||
assert value >= min
|
assert value >= min
|
||||||
assert value < max
|
assert value < max
|
||||||
}
|
}
|
156
vlib/rand/rand.v
156
vlib/rand/rand.v
|
@ -3,72 +3,128 @@
|
||||||
// that can be found in the LICENSE file.
|
// that can be found in the LICENSE file.
|
||||||
module rand
|
module rand
|
||||||
|
|
||||||
// TODO: Remove these functions once done:
|
import rand.util
|
||||||
// 1. C.rand()
|
import rand.wyrand
|
||||||
// 2. seed()
|
|
||||||
// 3. next()
|
|
||||||
// 4. rand_r()
|
|
||||||
// fn C.rand() int
|
|
||||||
pub fn seed(s int) {
|
|
||||||
C.srand(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn next(max int) int {
|
|
||||||
return C.rand() % max
|
|
||||||
}
|
|
||||||
|
|
||||||
// rand_r returns a pseudo-random number;
|
|
||||||
// writes a result value to the seed argument.
|
|
||||||
pub fn rand_r(seed &int) int {
|
|
||||||
ns := *seed * 1103515245 + 12345
|
|
||||||
unsafe {
|
|
||||||
(*seed) = ns
|
|
||||||
}
|
|
||||||
return ns & 0x7fffffff
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Configuration struct for creating a new instance of the default RNG.
|
||||||
pub struct PRNGConfigStruct {
|
pub struct PRNGConfigStruct {
|
||||||
seed []u32 = time_seed_array(2)
|
seed []u32 = util.time_seed_array(2)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_default(config PRNGConfigStruct) &WyRandRNG {
|
__global default_rng &wyrand.WyRandRNG
|
||||||
rng := &WyRandRNG{}
|
fn init() {
|
||||||
|
default_rng = new_default({})
|
||||||
|
}
|
||||||
|
|
||||||
|
// new_default returns a new instance of the default RNG. If the seed is not provided, the current time will be used to seed the instance.
|
||||||
|
pub fn new_default(config PRNGConfigStruct) &wyrand.WyRandRNG {
|
||||||
|
rng := &wyrand.WyRandRNG{}
|
||||||
rng.seed(config.seed)
|
rng.seed(config.seed)
|
||||||
return rng
|
return rng
|
||||||
}
|
}
|
||||||
|
|
||||||
// rand_f32 return a random f32 between 0 and max
|
// seed sets the given array of `u32` values as the seed for the `default_rng`.
|
||||||
[deprecated]
|
pub fn seed(seed []u32) {
|
||||||
pub fn rand_f32(max f32) f32 {
|
default_rng.seed(seed)
|
||||||
return rand_uniform_f32() * max
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// rand_f32 return a random f32 in range min and max
|
// u32() returns a uniformly distributed u32 in _[0, 2<sup>32</sup>)_
|
||||||
[deprecated]
|
pub fn u32() u32 {
|
||||||
pub fn rand_f32_in_range(min, max f32) f32 {
|
return default_rng.u32()
|
||||||
return min + rand_uniform_f32() * (max - min)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// rand_f64 return a random f64 between 0 (inclusive) and max (exclusive)
|
// u64() returns a uniformly distributed u64 in _[0, 2<sup>64</sup>)_
|
||||||
[deprecated]
|
pub fn u64() u64 {
|
||||||
pub fn rand_f64(max f64) f64 {
|
return default_rng.u64()
|
||||||
return rand_uniform_f64() * max
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// rand_f64 return a random f64 in range min (inclusive) and max (exclusive)
|
// u32n(max) returns a uniformly distributed pseudorandom 32-bit signed positive u32 in _[0, max)_
|
||||||
[deprecated]
|
pub fn u32n(max u32) u32 {
|
||||||
pub fn rand_f64_in_range(min, max f64) f64 {
|
return default_rng.u32n(max)
|
||||||
return min + rand_uniform_f64() * (max - min)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// rand_uniform_f32 returns a uniformly distributed f32 in the range 0 (inclusive) and 1 (exclusive)
|
// u64n(max) returns a uniformly distributed pseudorandom 64-bit signed positive u64 in _[0, max)_
|
||||||
[deprecated]
|
pub fn u64n(max u64) u64 {
|
||||||
pub fn rand_uniform_f32() f32 {
|
return default_rng.u64n(max)
|
||||||
return f32(C.rand()) / f32(C.RAND_MAX)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// rand_uniform_f64 returns a uniformly distributed f64 in the range 0 (inclusive) and 1 (exclusive)
|
// u32_in_range(min, max) returns a uniformly distributed pseudorandom 32-bit unsigned u32 in _[min, max)_
|
||||||
[deprecated]
|
pub fn u32_in_range(min, max u32) u32 {
|
||||||
pub fn rand_uniform_f64() f64 {
|
return default_rng.u32_in_range(min, max)
|
||||||
return f64(C.rand()) / f64(C.RAND_MAX)
|
}
|
||||||
|
|
||||||
|
// u64_in_range(min, max) returns a uniformly distributed pseudorandom 64-bit unsigned u64 in _[min, max)_
|
||||||
|
pub fn u64_in_range(min, max u64) u64 {
|
||||||
|
return default_rng.u64_in_range(min, max)
|
||||||
|
}
|
||||||
|
|
||||||
|
// int() returns a uniformly distributed pseudorandom 32-bit signed (possibly negative) int
|
||||||
|
pub fn int() int {
|
||||||
|
return default_rng.int()
|
||||||
|
}
|
||||||
|
|
||||||
|
// intn(max) returns a uniformly distributed pseudorandom 32-bit signed positive int in _[0, max)_
|
||||||
|
pub fn intn(max int) int {
|
||||||
|
return default_rng.intn(max)
|
||||||
|
}
|
||||||
|
|
||||||
|
// int_in_range(min, max) returns a uniformly distributed pseudorandom
|
||||||
|
// 32-bit signed int in [min, max). Both min and max can be negative, but we must have _min < max_.
|
||||||
|
pub fn int_in_range(min, max int) int {
|
||||||
|
return default_rng.int_in_range(min, max)
|
||||||
|
}
|
||||||
|
|
||||||
|
// int31() returns a uniformly distributed pseudorandom 31-bit signed positive int
|
||||||
|
pub fn int31() int {
|
||||||
|
return default_rng.int31()
|
||||||
|
}
|
||||||
|
|
||||||
|
// i64() returns a uniformly distributed pseudorandom 64-bit signed (possibly negative) i64
|
||||||
|
pub fn i64() i64 {
|
||||||
|
return default_rng.i64()
|
||||||
|
}
|
||||||
|
|
||||||
|
// i64n(max) returns a uniformly distributed pseudorandom 64-bit signed positive i64 in _[0, max)_
|
||||||
|
pub fn i64n(max i64) i64 {
|
||||||
|
return default_rng.i64n(max)
|
||||||
|
}
|
||||||
|
|
||||||
|
// i64_in_range(min, max) returns a uniformly distributed pseudorandom 64-bit signed int in _[min, max)_
|
||||||
|
pub fn i64_in_range(min, max i64) i64 {
|
||||||
|
return default_rng.i64_in_range(min, max)
|
||||||
|
}
|
||||||
|
|
||||||
|
// int63() returns a uniformly distributed pseudorandom 63-bit signed positive int
|
||||||
|
pub fn int63() i64 {
|
||||||
|
return default_rng.int63()
|
||||||
|
}
|
||||||
|
|
||||||
|
// f32() returns a uniformly distributed 32-bit floating point in _[0, 1)_
|
||||||
|
pub fn f32() f32 {
|
||||||
|
return default_rng.f32()
|
||||||
|
}
|
||||||
|
|
||||||
|
// f64() returns a uniformly distributed 64-bit floating point in _[0, 1)_
|
||||||
|
pub fn f64() f64 {
|
||||||
|
return default_rng.f64()
|
||||||
|
}
|
||||||
|
|
||||||
|
// f32n() returns a uniformly distributed 32-bit floating point in _[0, max)_
|
||||||
|
pub fn f32n(max f32) f32 {
|
||||||
|
return default_rng.f32n(max)
|
||||||
|
}
|
||||||
|
|
||||||
|
// f64n() returns a uniformly distributed 64-bit floating point in _[0, max)_
|
||||||
|
pub fn f64n(max f64) f64 {
|
||||||
|
return default_rng.f64n(max)
|
||||||
|
}
|
||||||
|
|
||||||
|
// f32_in_range(min, max) returns a uniformly distributed 32-bit floating point in _[min, max)_
|
||||||
|
pub fn f32_in_range(min, max f32) f32 {
|
||||||
|
return default_rng.f32_in_range(min, max)
|
||||||
|
}
|
||||||
|
|
||||||
|
// f64_in_range(min, max) returns a uniformly distributed 64-bit floating point in _[min, max)_
|
||||||
|
pub fn f64_in_range(min, max f64) f64 {
|
||||||
|
return default_rng.f64_in_range(min, max)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,56 +1,177 @@
|
||||||
import rand
|
import rand
|
||||||
import math
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
rnd_count = 40
|
rnd_count = 40
|
||||||
seeds = [42, 256]
|
seeds = [[u32(42), 0], [u32(256), 0]]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
fn get_n_random_ints(seed_data []u32, n int) []int {
|
||||||
|
mut values := []int{cap: n}
|
||||||
|
rand.seed(seed_data)
|
||||||
|
for _ in 0 .. n {
|
||||||
|
values << rand.intn(n)
|
||||||
|
}
|
||||||
|
return values
|
||||||
|
}
|
||||||
|
|
||||||
fn test_rand_reproducibility() {
|
fn test_rand_reproducibility() {
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut randoms1 := gen_randoms(seed)
|
array1 := get_n_random_ints(seed, 1000)
|
||||||
mut randoms2 := gen_randoms(seed)
|
array2 := get_n_random_ints(seed, 1000)
|
||||||
assert_randoms_equal(randoms1, randoms2)
|
assert array1.len == array2.len
|
||||||
|
assert array1 == array2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_rand_r_reproducibility() {
|
fn test_rand_u32n() {
|
||||||
for seed in seeds {
|
max := u32(16384)
|
||||||
mut randoms1 := gen_randoms_r(seed)
|
|
||||||
mut randoms2 := gen_randoms_r(seed)
|
|
||||||
assert_randoms_equal(randoms1, randoms2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn test_rand_r_seed_update() {
|
|
||||||
seed := 10
|
|
||||||
for _ in 0 .. rnd_count {
|
for _ in 0 .. rnd_count {
|
||||||
prev_seed := seed
|
value := rand.u32n(max)
|
||||||
_ = rand.rand_r(&seed)
|
assert value >= 0
|
||||||
assert prev_seed != seed
|
assert value < max
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gen_randoms(seed int) []int {
|
fn test_rand_u64n() {
|
||||||
mut randoms := [0].repeat(rnd_count)
|
max := u64(379091181005)
|
||||||
rand.seed(seed)
|
for _ in 0 .. rnd_count {
|
||||||
for i in 0 .. rnd_count {
|
value := rand.u64n(max)
|
||||||
randoms[i] = rand.next(100)
|
assert value >= 0
|
||||||
}
|
assert value < max
|
||||||
return randoms
|
|
||||||
}
|
|
||||||
|
|
||||||
fn gen_randoms_r(seed int) []int {
|
|
||||||
mut randoms := [0].repeat(rnd_count)
|
|
||||||
for i in 0 .. rnd_count {
|
|
||||||
randoms[i] = rand.rand_r(&seed)
|
|
||||||
}
|
|
||||||
return randoms
|
|
||||||
}
|
|
||||||
|
|
||||||
fn assert_randoms_equal(r1, r2 []int) {
|
|
||||||
for i in 0 .. rnd_count {
|
|
||||||
assert r1[i] == r2[i]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn test_rand_u32_in_range() {
|
||||||
|
max := u32(484468466)
|
||||||
|
min := u32(316846)
|
||||||
|
for _ in 0 .. rnd_count {
|
||||||
|
value := rand.u32_in_range(min, max)
|
||||||
|
assert value >= min
|
||||||
|
assert value < max
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_rand_u64_in_range() {
|
||||||
|
max := u64(216468454685163)
|
||||||
|
min := u64(6848646868)
|
||||||
|
for _ in 0 .. rnd_count {
|
||||||
|
value := rand.u64_in_range(min, max)
|
||||||
|
assert value >= min
|
||||||
|
assert value < max
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_rand_intn() {
|
||||||
|
max := 2525642
|
||||||
|
for _ in 0 .. rnd_count {
|
||||||
|
value := rand.intn(max)
|
||||||
|
assert value >= 0
|
||||||
|
assert value < max
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_rand_i64n() {
|
||||||
|
max := i64(3246727724653636)
|
||||||
|
for _ in 0 .. rnd_count {
|
||||||
|
value := rand.i64n(max)
|
||||||
|
assert value >= 0
|
||||||
|
assert value < max
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_rand_int_in_range() {
|
||||||
|
min := -4252
|
||||||
|
max := 23054962
|
||||||
|
for _ in 0 .. rnd_count {
|
||||||
|
value := rand.int_in_range(min, max)
|
||||||
|
assert value >= min
|
||||||
|
assert value < max
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_rand_i64_in_range() {
|
||||||
|
min := i64(-24095)
|
||||||
|
max := i64(324058)
|
||||||
|
for _ in 0 .. rnd_count {
|
||||||
|
value := rand.i64_in_range(min, max)
|
||||||
|
assert value >= min
|
||||||
|
assert value < max
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_rand_int31() {
|
||||||
|
max_u31 := 0x7FFFFFFF
|
||||||
|
sign_mask := 0x80000000
|
||||||
|
for _ in 0 .. rnd_count {
|
||||||
|
value := rand.int31()
|
||||||
|
assert value >= 0
|
||||||
|
assert value <= max_u31
|
||||||
|
// This statement ensures that the sign bit is zero
|
||||||
|
assert (value & sign_mask) == 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_rand_int63() {
|
||||||
|
max_u63 := i64(0x7FFFFFFFFFFFFFFF)
|
||||||
|
sign_mask := i64(0x8000000000000000)
|
||||||
|
for _ in 0 .. rnd_count {
|
||||||
|
value := rand.int63()
|
||||||
|
assert value >= 0
|
||||||
|
assert value <= max_u63
|
||||||
|
assert (value & sign_mask) == 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_rand_f32() {
|
||||||
|
for _ in 0 .. rnd_count {
|
||||||
|
value := rand.f32()
|
||||||
|
assert value >= 0.0
|
||||||
|
assert value < 1.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_rand_f64() {
|
||||||
|
for _ in 0 .. rnd_count {
|
||||||
|
value := rand.f64()
|
||||||
|
assert value >= 0.0
|
||||||
|
assert value < 1.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_rand_f32n() {
|
||||||
|
max := f32(357.0)
|
||||||
|
for _ in 0 .. rnd_count {
|
||||||
|
value := rand.f32n(max)
|
||||||
|
assert value >= 0.0
|
||||||
|
assert value < max
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_rand_f64n() {
|
||||||
|
max := f64(1.52e6)
|
||||||
|
for _ in 0 .. rnd_count {
|
||||||
|
value := rand.f64n(max)
|
||||||
|
assert value >= 0.0
|
||||||
|
assert value < max
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_rand_f32_in_range() {
|
||||||
|
min := f32(-24.0)
|
||||||
|
max := f32(125.0)
|
||||||
|
for _ in 0 .. rnd_count {
|
||||||
|
value := rand.f32_in_range(min, max)
|
||||||
|
assert value >= min
|
||||||
|
assert value < max
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_rand_f64_in_range() {
|
||||||
|
min := f64(-548.7)
|
||||||
|
max := f64(5015.2)
|
||||||
|
for _ in 0 .. rnd_count {
|
||||||
|
value := rand.f64_in_range(min, max)
|
||||||
|
assert value >= min
|
||||||
|
assert value < max
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved.
|
// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved.
|
||||||
// Use of this source code is governed by an MIT license
|
// Use of this source code is governed by an MIT license
|
||||||
// that can be found in the LICENSE file.
|
// that can be found in the LICENSE file.
|
||||||
module rand
|
module splitmix64
|
||||||
|
|
||||||
|
import rand.util
|
||||||
|
|
||||||
// Ported from http://xoshiro.di.unimi.it/splitmix64.c
|
// Ported from http://xoshiro.di.unimi.it/splitmix64.c
|
||||||
pub struct SplitMix64RNG {
|
pub struct SplitMix64RNG {
|
||||||
mut:
|
mut:
|
||||||
state u64 = time_seed_64()
|
state u64 = util.time_seed_64()
|
||||||
has_extra bool = false
|
has_extra bool = false
|
||||||
extra u32
|
extra u32
|
||||||
}
|
}
|
||||||
|
@ -30,7 +32,7 @@ pub fn (mut rng SplitMix64RNG) u32() u32 {
|
||||||
return rng.extra
|
return rng.extra
|
||||||
}
|
}
|
||||||
full_value := rng.u64()
|
full_value := rng.u64()
|
||||||
lower := u32(full_value & lower_mask)
|
lower := u32(full_value & util.lower_mask)
|
||||||
upper := u32(full_value >> 32)
|
upper := u32(full_value >> 32)
|
||||||
rng.extra = upper
|
rng.extra = upper
|
||||||
rng.has_extra = true
|
rng.has_extra = true
|
||||||
|
@ -119,13 +121,13 @@ pub fn (mut rng SplitMix64RNG) i64() i64 {
|
||||||
// rng.int31() returns a pseudorandom 31-bit int which is non-negative
|
// rng.int31() returns a pseudorandom 31-bit int which is non-negative
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (mut rng SplitMix64RNG) int31() int {
|
pub fn (mut rng SplitMix64RNG) int31() int {
|
||||||
return int(rng.u32() & 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
|
// rng.int63() returns a pseudorandom 63-bit int which is non-negative
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (mut rng SplitMix64RNG) int63() i64 {
|
pub fn (mut rng SplitMix64RNG) int63() i64 {
|
||||||
return i64(rng.u64() & 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)
|
// rng.intn(max) returns a pseudorandom int that lies in [0, max)
|
||||||
|
@ -172,13 +174,13 @@ pub fn (mut rng SplitMix64RNG) i64_in_range(min, max i64) i64 {
|
||||||
// rng.f32() returns a pseudorandom f32 value between 0.0 (inclusive) and 1.0 (exclusive) i.e [0, 1)
|
// rng.f32() returns a pseudorandom f32 value between 0.0 (inclusive) and 1.0 (exclusive) i.e [0, 1)
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (mut rng SplitMix64RNG) f32() f32 {
|
pub fn (mut rng SplitMix64RNG) f32() f32 {
|
||||||
return f32(rng.u32()) / 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)
|
// rng.f64() returns a pseudorandom f64 value between 0.0 (inclusive) and 1.0 (exclusive) i.e [0, 1)
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (mut rng SplitMix64RNG) f64() f64 {
|
pub fn (mut rng SplitMix64RNG) f64() f64 {
|
||||||
return f64(rng.u64()) / max_u64_as_f64
|
return f64(rng.u64()) / util.max_u64_as_f64
|
||||||
}
|
}
|
||||||
|
|
||||||
// rng.f32n() returns a pseudorandom f32 value in [0, max)
|
// rng.f32n() returns a pseudorandom f32 value in [0, max)
|
|
@ -1,5 +1,6 @@
|
||||||
import rand
|
|
||||||
import math
|
import math
|
||||||
|
import splitmix64
|
||||||
|
import rand.util
|
||||||
|
|
||||||
const (
|
const (
|
||||||
range_limit = 40
|
range_limit = 40
|
||||||
|
@ -16,7 +17,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(0)].repeat(20)
|
mut randoms := [u64(0)].repeat(20)
|
||||||
mut rnd := rand.SplitMix64RNG{}
|
mut rnd := splitmix64.SplitMix64RNG{}
|
||||||
rnd.seed(seed_data)
|
rnd.seed(seed_data)
|
||||||
for i in 0 .. 20 {
|
for i in 0 .. 20 {
|
||||||
randoms[i] = rnd.u64n(bound_u64)
|
randoms[i] = rnd.u64n(bound_u64)
|
||||||
|
@ -25,7 +26,7 @@ fn gen_randoms(seed_data []u32, bound int) []u64 {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_splitmix64_reproducibility() {
|
fn test_splitmix64_reproducibility() {
|
||||||
seed_data := rand.time_seed_array(2)
|
seed_data := util.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
|
||||||
|
@ -51,7 +52,7 @@ fn test_splitmix64_variability() {
|
||||||
// at fault, try changing the seed values. Repeated values are
|
// at fault, try changing the seed values. Repeated values are
|
||||||
// improbable but not impossible.
|
// improbable but not impossible.
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.SplitMix64RNG{}
|
mut rng := splitmix64.SplitMix64RNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
mut values := []u64{cap: value_count}
|
mut values := []u64{cap: value_count}
|
||||||
for i in 0 .. value_count {
|
for i in 0 .. value_count {
|
||||||
|
@ -63,7 +64,7 @@ fn test_splitmix64_variability() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_uniformity_u64(mut rng rand.SplitMix64RNG, range u64) {
|
fn check_uniformity_u64(mut rng splitmix64.SplitMix64RNG, range u64) {
|
||||||
range_f64 := f64(range)
|
range_f64 := f64(range)
|
||||||
expected_mean := range_f64 / 2.0
|
expected_mean := range_f64 / 2.0
|
||||||
mut variance := 0.0
|
mut variance := 0.0
|
||||||
|
@ -81,7 +82,7 @@ fn check_uniformity_u64(mut rng rand.SplitMix64RNG, range u64) {
|
||||||
fn test_splitmix64_uniformity_u64() {
|
fn test_splitmix64_uniformity_u64() {
|
||||||
ranges := [14019545, 80240, 130]
|
ranges := [14019545, 80240, 130]
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.SplitMix64RNG{}
|
mut rng := splitmix64.SplitMix64RNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for range in ranges {
|
for range in ranges {
|
||||||
check_uniformity_u64(mut rng, u64(range))
|
check_uniformity_u64(mut rng, u64(range))
|
||||||
|
@ -89,7 +90,7 @@ fn test_splitmix64_uniformity_u64() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_uniformity_f64(mut rng rand.SplitMix64RNG) {
|
fn check_uniformity_f64(mut rng splitmix64.SplitMix64RNG) {
|
||||||
expected_mean := 0.5
|
expected_mean := 0.5
|
||||||
mut variance := 0.0
|
mut variance := 0.0
|
||||||
for _ in 0 .. sample_size {
|
for _ in 0 .. sample_size {
|
||||||
|
@ -106,19 +107,19 @@ fn check_uniformity_f64(mut rng rand.SplitMix64RNG) {
|
||||||
fn test_splitmix64_uniformity_f64() {
|
fn test_splitmix64_uniformity_f64() {
|
||||||
// The f64 version
|
// The f64 version
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.SplitMix64RNG{}
|
mut rng := splitmix64.SplitMix64RNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
check_uniformity_f64(mut rng)
|
check_uniformity_f64(mut rng)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_splitmix64_u32n() {
|
fn test_splitmix64_u32n() {
|
||||||
max := 16384
|
max := u32(16384)
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.SplitMix64RNG{}
|
mut rng := splitmix64.SplitMix64RNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.u32n(u32(max))
|
value := rng.u32n(max)
|
||||||
assert value >= 0
|
assert value >= 0
|
||||||
assert value < max
|
assert value < max
|
||||||
}
|
}
|
||||||
|
@ -128,7 +129,7 @@ fn test_splitmix64_u32n() {
|
||||||
fn test_splitmix64_u64n() {
|
fn test_splitmix64_u64n() {
|
||||||
max := u64(379091181005)
|
max := u64(379091181005)
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.SplitMix64RNG{}
|
mut rng := splitmix64.SplitMix64RNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.u64n(max)
|
value := rng.u64n(max)
|
||||||
|
@ -139,13 +140,13 @@ fn test_splitmix64_u64n() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_splitmix64_u32_in_range() {
|
fn test_splitmix64_u32_in_range() {
|
||||||
max := 484468466
|
max := u32(484468466)
|
||||||
min := 316846
|
min := u32(316846)
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.SplitMix64RNG{}
|
mut rng := splitmix64.SplitMix64RNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.u32_in_range(u32(min), u32(max))
|
value := rng.u32_in_range(min, max)
|
||||||
assert value >= min
|
assert value >= min
|
||||||
assert value < max
|
assert value < max
|
||||||
}
|
}
|
||||||
|
@ -156,7 +157,7 @@ fn test_splitmix64_u64_in_range() {
|
||||||
max := u64(216468454685163)
|
max := u64(216468454685163)
|
||||||
min := u64(6848646868)
|
min := u64(6848646868)
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.SplitMix64RNG{}
|
mut rng := splitmix64.SplitMix64RNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.u64_in_range(min, max)
|
value := rng.u64_in_range(min, max)
|
||||||
|
@ -170,7 +171,7 @@ fn test_splitmix64_int31() {
|
||||||
max_u31 := 0x7FFFFFFF
|
max_u31 := 0x7FFFFFFF
|
||||||
sign_mask := 0x80000000
|
sign_mask := 0x80000000
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.SplitMix64RNG{}
|
mut rng := splitmix64.SplitMix64RNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.int31()
|
value := rng.int31()
|
||||||
|
@ -186,7 +187,7 @@ fn test_splitmix64_int63() {
|
||||||
max_u63 := i64(0x7FFFFFFFFFFFFFFF)
|
max_u63 := i64(0x7FFFFFFFFFFFFFFF)
|
||||||
sign_mask := i64(0x8000000000000000)
|
sign_mask := i64(0x8000000000000000)
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.SplitMix64RNG{}
|
mut rng := splitmix64.SplitMix64RNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.int63()
|
value := rng.int63()
|
||||||
|
@ -197,10 +198,10 @@ fn test_splitmix64_int63() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_splimix64_intn() {
|
fn test_splitmix64_intn() {
|
||||||
max := 2525642
|
max := 2525642
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.SplitMix64RNG{}
|
mut rng := splitmix64.SplitMix64RNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.intn(max)
|
value := rng.intn(max)
|
||||||
|
@ -210,10 +211,10 @@ fn test_splimix64_intn() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_splimix64_i64n() {
|
fn test_splitmix64_i64n() {
|
||||||
max := i64(3246727724653636)
|
max := i64(3246727724653636)
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.SplitMix64RNG{}
|
mut rng := splitmix64.SplitMix64RNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.i64n(max)
|
value := rng.i64n(max)
|
||||||
|
@ -223,11 +224,11 @@ fn test_splimix64_i64n() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_splimix64_int_in_range() {
|
fn test_splitmix64_int_in_range() {
|
||||||
min := -4252
|
min := -4252
|
||||||
max := 230549862
|
max := 230549862
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.SplitMix64RNG{}
|
mut rng := splitmix64.SplitMix64RNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.int_in_range(min, max)
|
value := rng.int_in_range(min, max)
|
||||||
|
@ -237,11 +238,11 @@ fn test_splimix64_int_in_range() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_splimix64_i64_in_range() {
|
fn test_splitmix64_i64_in_range() {
|
||||||
min := i64(-24095)
|
min := i64(-24095)
|
||||||
max := i64(324058)
|
max := i64(324058)
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.SplitMix64RNG{}
|
mut rng := splitmix64.SplitMix64RNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.i64_in_range(min, max)
|
value := rng.i64_in_range(min, max)
|
||||||
|
@ -253,7 +254,7 @@ fn test_splimix64_i64_in_range() {
|
||||||
|
|
||||||
fn test_splitmix64_f32() {
|
fn test_splitmix64_f32() {
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.SplitMix64RNG{}
|
mut rng := splitmix64.SplitMix64RNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.f32()
|
value := rng.f32()
|
||||||
|
@ -265,7 +266,7 @@ fn test_splitmix64_f32() {
|
||||||
|
|
||||||
fn test_splitmix64_f64() {
|
fn test_splitmix64_f64() {
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.SplitMix64RNG{}
|
mut rng := splitmix64.SplitMix64RNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.f64()
|
value := rng.f64()
|
||||||
|
@ -278,10 +279,10 @@ fn test_splitmix64_f64() {
|
||||||
fn test_splitmix64_f32n() {
|
fn test_splitmix64_f32n() {
|
||||||
max := f32(357.0)
|
max := f32(357.0)
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.SplitMix64RNG{}
|
mut rng := splitmix64.SplitMix64RNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.f32()
|
value := rng.f32n(max)
|
||||||
assert value >= 0.0
|
assert value >= 0.0
|
||||||
assert value < max
|
assert value < max
|
||||||
}
|
}
|
||||||
|
@ -291,10 +292,10 @@ fn test_splitmix64_f32n() {
|
||||||
fn test_splitmix64_f64n() {
|
fn test_splitmix64_f64n() {
|
||||||
max := 1.52e6
|
max := 1.52e6
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.SplitMix64RNG{}
|
mut rng := splitmix64.SplitMix64RNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.f64()
|
value := rng.f64n(max)
|
||||||
assert value >= 0.0
|
assert value >= 0.0
|
||||||
assert value < max
|
assert value < max
|
||||||
}
|
}
|
||||||
|
@ -305,10 +306,10 @@ fn test_splitmix64_f32_in_range() {
|
||||||
min := f32(-24.0)
|
min := f32(-24.0)
|
||||||
max := f32(125.0)
|
max := f32(125.0)
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.SplitMix64RNG{}
|
mut rng := splitmix64.SplitMix64RNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.f32()
|
value := rng.f32_in_range(min, max)
|
||||||
assert value >= min
|
assert value >= min
|
||||||
assert value < max
|
assert value < max
|
||||||
}
|
}
|
||||||
|
@ -319,10 +320,10 @@ fn test_splitmix64_f64_in_range() {
|
||||||
min := -548.7
|
min := -548.7
|
||||||
max := 5015.2
|
max := 5015.2
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.SplitMix64RNG{}
|
mut rng := splitmix64.SplitMix64RNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.f64()
|
value := rng.f64_in_range(min, max)
|
||||||
assert value >= min
|
assert value >= min
|
||||||
assert value < max
|
assert value < max
|
||||||
}
|
}
|
|
@ -1,9 +1,10 @@
|
||||||
// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved.
|
// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved.
|
||||||
// Use of this source code is governed by an MIT license
|
// Use of this source code is governed by an MIT license
|
||||||
// that can be found in the LICENSE file.
|
// that can be found in the LICENSE file.
|
||||||
module rand
|
module sys
|
||||||
|
|
||||||
import math.bits
|
import math.bits
|
||||||
|
import rand.util
|
||||||
|
|
||||||
// Implementation note:
|
// Implementation note:
|
||||||
// ====================
|
// ====================
|
||||||
|
@ -27,20 +28,6 @@ fn calculate_iterations_for(bits int) int {
|
||||||
return base + extra
|
return base + extra
|
||||||
}
|
}
|
||||||
|
|
||||||
// Size constants to avoid importing the entire math module
|
|
||||||
const (
|
|
||||||
max_u32 = 0xFFFFFFFF
|
|
||||||
max_u64 = 0xFFFFFFFFFFFFFFFF
|
|
||||||
max_u32_as_f32 = f32(max_u32)
|
|
||||||
max_u64_as_f64 = f64(max_u64)
|
|
||||||
)
|
|
||||||
|
|
||||||
// Masks for fast modular division
|
|
||||||
const (
|
|
||||||
u31_mask = u32(0x7FFFFFFF)
|
|
||||||
u63_mask = u64(0x7FFFFFFFFFFFFFFF)
|
|
||||||
)
|
|
||||||
|
|
||||||
// C.rand returns a pseudorandom integer from 0 (inclusive) to C.RAND_MAX (exclusive)
|
// C.rand returns a pseudorandom integer from 0 (inclusive) to C.RAND_MAX (exclusive)
|
||||||
fn C.rand() int
|
fn C.rand() int
|
||||||
|
|
||||||
|
@ -49,7 +36,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 = time_seed_32()
|
seed u32 = util.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.
|
||||||
|
@ -188,13 +175,13 @@ pub fn (r SysRNG) i64() i64 {
|
||||||
// r.int31() returns a pseudorandom 31-bit int which is non-negative
|
// r.int31() returns a pseudorandom 31-bit int which is non-negative
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (r SysRNG) int31() int {
|
pub fn (r SysRNG) int31() int {
|
||||||
return int(r.u32() & u31_mask) // Set the 32nd bit to 0.
|
return int(r.u32() & util.u31_mask) // Set the 32nd bit to 0.
|
||||||
}
|
}
|
||||||
|
|
||||||
// r.int63() returns a pseudorandom 63-bit int which is non-negative
|
// r.int63() returns a pseudorandom 63-bit int which is non-negative
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (r SysRNG) int63() i64 {
|
pub fn (r SysRNG) int63() i64 {
|
||||||
return i64(r.u64() & u63_mask) // Set the 64th bit to 0.
|
return i64(r.u64() & util.u63_mask) // Set the 64th bit to 0.
|
||||||
}
|
}
|
||||||
|
|
||||||
// r.intn(max) returns a pseudorandom int that lies in [0, max)
|
// r.intn(max) returns a pseudorandom int that lies in [0, max)
|
||||||
|
@ -241,13 +228,13 @@ pub fn (r SysRNG) i64_in_range(min, max i64) i64 {
|
||||||
// r.f32() returns a pseudorandom f32 value between 0.0 (inclusive) and 1.0 (exclusive) i.e [0, 1)
|
// r.f32() returns a pseudorandom f32 value between 0.0 (inclusive) and 1.0 (exclusive) i.e [0, 1)
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (r SysRNG) f32() f32 {
|
pub fn (r SysRNG) f32() f32 {
|
||||||
return f32(r.u32()) / max_u32_as_f32
|
return f32(r.u32()) / util.max_u32_as_f32
|
||||||
}
|
}
|
||||||
|
|
||||||
// r.f64() returns a pseudorandom f64 value between 0.0 (inclusive) and 1.0 (exclusive) i.e [0, 1)
|
// r.f64() returns a pseudorandom f64 value between 0.0 (inclusive) and 1.0 (exclusive) i.e [0, 1)
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (r SysRNG) f64() f64 {
|
pub fn (r SysRNG) f64() f64 {
|
||||||
return f64(r.u64()) / max_u64_as_f64
|
return f64(r.u64()) / util.max_u64_as_f64
|
||||||
}
|
}
|
||||||
|
|
||||||
// r.f32n() returns a pseudorandom f32 value in [0, max)
|
// r.f32n() returns a pseudorandom f32 value in [0, max)
|
|
@ -1,7 +1,7 @@
|
||||||
// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved.
|
// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved.
|
||||||
// Use of this source code is governed by an MIT license
|
// Use of this source code is governed by an MIT license
|
||||||
// that can be found in the LICENSE file.
|
// that can be found in the LICENSE file.
|
||||||
module rand
|
module sys
|
||||||
|
|
||||||
// Until there's a portable, JS has a seeded way to produce random numbers
|
// Until there's a portable, JS has a seeded way to produce random numbers
|
||||||
// and not just Math.random(), use any of the existing implementations
|
// and not just Math.random(), use any of the existing implementations
|
|
@ -1,5 +1,5 @@
|
||||||
import rand
|
|
||||||
import math
|
import math
|
||||||
|
import sys
|
||||||
|
|
||||||
const (
|
const (
|
||||||
range_limit = 40
|
range_limit = 40
|
||||||
|
@ -13,7 +13,7 @@ const (
|
||||||
inv_sqrt_12 = 1.0 / math.sqrt(12)
|
inv_sqrt_12 = 1.0 / math.sqrt(12)
|
||||||
)
|
)
|
||||||
|
|
||||||
fn get_n_randoms(n int, r rand.SysRNG) []int {
|
fn get_n_randoms(n int, r sys.SysRNG) []int {
|
||||||
mut ints := []int{cap: n}
|
mut ints := []int{cap: n}
|
||||||
for _ in 0 .. n {
|
for _ in 0 .. n {
|
||||||
ints << r.int()
|
ints << r.int()
|
||||||
|
@ -28,8 +28,8 @@ fn test_sys_rng_reproducibility() {
|
||||||
// seed for another batch of data.
|
// seed for another batch of data.
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
seed_data := [seed]
|
seed_data := [seed]
|
||||||
mut r1 := rand.SysRNG{}
|
mut r1 := sys.SysRNG{}
|
||||||
mut r2 := rand.SysRNG{}
|
mut r2 := sys.SysRNG{}
|
||||||
r1.seed(seed_data)
|
r1.seed(seed_data)
|
||||||
ints1 := get_n_randoms(value_count, r1)
|
ints1 := get_n_randoms(value_count, r1)
|
||||||
r2.seed(seed_data)
|
r2.seed(seed_data)
|
||||||
|
@ -55,7 +55,7 @@ fn test_sys_rng_variability() {
|
||||||
// improbable but not impossible.
|
// improbable but not impossible.
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
seed_data := [seed]
|
seed_data := [seed]
|
||||||
mut rng := rand.SysRNG{}
|
mut rng := sys.SysRNG{}
|
||||||
rng.seed(seed_data)
|
rng.seed(seed_data)
|
||||||
mut values := []u64{cap: value_count}
|
mut values := []u64{cap: value_count}
|
||||||
for i in 0 .. value_count {
|
for i in 0 .. value_count {
|
||||||
|
@ -67,7 +67,7 @@ fn test_sys_rng_variability() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_uniformity_u64(rng rand.SysRNG, range u64) {
|
fn check_uniformity_u64(rng sys.SysRNG, range u64) {
|
||||||
range_f64 := f64(range)
|
range_f64 := f64(range)
|
||||||
expected_mean := range_f64 / 2.0
|
expected_mean := range_f64 / 2.0
|
||||||
mut variance := 0.0
|
mut variance := 0.0
|
||||||
|
@ -88,7 +88,7 @@ fn test_sys_rng_uniformity_u64() {
|
||||||
ranges := [14019545, 80240, 130]
|
ranges := [14019545, 80240, 130]
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
seed_data := [seed]
|
seed_data := [seed]
|
||||||
mut rng := rand.SysRNG{}
|
mut rng := sys.SysRNG{}
|
||||||
rng.seed(seed_data)
|
rng.seed(seed_data)
|
||||||
for range in ranges {
|
for range in ranges {
|
||||||
check_uniformity_u64(rng, u64(range))
|
check_uniformity_u64(rng, u64(range))
|
||||||
|
@ -96,7 +96,7 @@ fn test_sys_rng_uniformity_u64() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_uniformity_f64(rng rand.SysRNG) {
|
fn check_uniformity_f64(rng sys.SysRNG) {
|
||||||
expected_mean := 0.5
|
expected_mean := 0.5
|
||||||
mut variance := 0.0
|
mut variance := 0.0
|
||||||
for _ in 0 .. sample_size {
|
for _ in 0 .. sample_size {
|
||||||
|
@ -114,20 +114,20 @@ fn test_sys_rng_uniformity_f64() {
|
||||||
// The f64 version
|
// The f64 version
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
seed_data := [seed]
|
seed_data := [seed]
|
||||||
mut rng := rand.SysRNG{}
|
mut rng := sys.SysRNG{}
|
||||||
rng.seed(seed_data)
|
rng.seed(seed_data)
|
||||||
check_uniformity_f64(rng)
|
check_uniformity_f64(rng)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_sys_rng_u32n() {
|
fn test_sys_rng_u32n() {
|
||||||
max := 16384
|
max := u32(16384)
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
seed_data := [seed]
|
seed_data := [seed]
|
||||||
mut rng := rand.SysRNG{}
|
mut rng := sys.SysRNG{}
|
||||||
rng.seed(seed_data)
|
rng.seed(seed_data)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.u32n(u32(max))
|
value := rng.u32n(max)
|
||||||
assert value >= 0
|
assert value >= 0
|
||||||
assert value < max
|
assert value < max
|
||||||
}
|
}
|
||||||
|
@ -138,7 +138,7 @@ fn test_sys_rng_u64n() {
|
||||||
max := u64(379091181005)
|
max := u64(379091181005)
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
seed_data := [seed]
|
seed_data := [seed]
|
||||||
mut rng := rand.SysRNG{}
|
mut rng := sys.SysRNG{}
|
||||||
rng.seed(seed_data)
|
rng.seed(seed_data)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.u64n(max)
|
value := rng.u64n(max)
|
||||||
|
@ -149,14 +149,14 @@ fn test_sys_rng_u64n() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_sys_rng_u32_in_range() {
|
fn test_sys_rng_u32_in_range() {
|
||||||
max := 484468466
|
max := u32(484468466)
|
||||||
min := 316846
|
min := u32(316846)
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
seed_data := [seed]
|
seed_data := [seed]
|
||||||
mut rng := rand.SysRNG{}
|
mut rng := sys.SysRNG{}
|
||||||
rng.seed(seed_data)
|
rng.seed(seed_data)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.u32_in_range(u32(min), u32(max))
|
value := rng.u32_in_range(min, max)
|
||||||
assert value >= min
|
assert value >= min
|
||||||
assert value < max
|
assert value < max
|
||||||
}
|
}
|
||||||
|
@ -168,7 +168,7 @@ fn test_sys_rng_u64_in_range() {
|
||||||
min := u64(6848646868)
|
min := u64(6848646868)
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
seed_data := [seed]
|
seed_data := [seed]
|
||||||
mut rng := rand.SysRNG{}
|
mut rng := sys.SysRNG{}
|
||||||
rng.seed(seed_data)
|
rng.seed(seed_data)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.u64_in_range(min, max)
|
value := rng.u64_in_range(min, max)
|
||||||
|
@ -182,7 +182,7 @@ fn test_sys_rng_intn() {
|
||||||
max := 2525642
|
max := 2525642
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
seed_data := [seed]
|
seed_data := [seed]
|
||||||
mut rng := rand.SysRNG{}
|
mut rng := sys.SysRNG{}
|
||||||
rng.seed(seed_data)
|
rng.seed(seed_data)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.intn(max)
|
value := rng.intn(max)
|
||||||
|
@ -196,7 +196,7 @@ fn test_sys_rng_i64n() {
|
||||||
max := i64(3246727724653636)
|
max := i64(3246727724653636)
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
seed_data := [seed]
|
seed_data := [seed]
|
||||||
mut rng := rand.SysRNG{}
|
mut rng := sys.SysRNG{}
|
||||||
rng.seed(seed_data)
|
rng.seed(seed_data)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.i64n(max)
|
value := rng.i64n(max)
|
||||||
|
@ -211,7 +211,7 @@ fn test_sys_rng_int_in_range() {
|
||||||
max := 23054962
|
max := 23054962
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
seed_data := [seed]
|
seed_data := [seed]
|
||||||
mut rng := rand.SysRNG{}
|
mut rng := sys.SysRNG{}
|
||||||
rng.seed(seed_data)
|
rng.seed(seed_data)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.int_in_range(min, max)
|
value := rng.int_in_range(min, max)
|
||||||
|
@ -226,7 +226,7 @@ fn test_sys_rng_i64_in_range() {
|
||||||
max := i64(324058)
|
max := i64(324058)
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
seed_data := [seed]
|
seed_data := [seed]
|
||||||
mut rng := rand.SysRNG{}
|
mut rng := sys.SysRNG{}
|
||||||
rng.seed(seed_data)
|
rng.seed(seed_data)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.i64_in_range(min, max)
|
value := rng.i64_in_range(min, max)
|
||||||
|
@ -241,7 +241,7 @@ fn test_sys_rng_int31() {
|
||||||
sign_mask := 0x80000000
|
sign_mask := 0x80000000
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
seed_data := [seed]
|
seed_data := [seed]
|
||||||
mut rng := rand.SysRNG{}
|
mut rng := sys.SysRNG{}
|
||||||
rng.seed(seed_data)
|
rng.seed(seed_data)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.int31()
|
value := rng.int31()
|
||||||
|
@ -258,7 +258,7 @@ fn test_sys_rng_int63() {
|
||||||
sign_mask := i64(0x8000000000000000)
|
sign_mask := i64(0x8000000000000000)
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
seed_data := [seed]
|
seed_data := [seed]
|
||||||
mut rng := rand.SysRNG{}
|
mut rng := sys.SysRNG{}
|
||||||
rng.seed(seed_data)
|
rng.seed(seed_data)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.int63()
|
value := rng.int63()
|
||||||
|
@ -272,7 +272,7 @@ fn test_sys_rng_int63() {
|
||||||
fn test_sys_rng_f32() {
|
fn test_sys_rng_f32() {
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
seed_data := [seed]
|
seed_data := [seed]
|
||||||
mut rng := rand.SysRNG{}
|
mut rng := sys.SysRNG{}
|
||||||
rng.seed(seed_data)
|
rng.seed(seed_data)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.f32()
|
value := rng.f32()
|
||||||
|
@ -285,7 +285,7 @@ fn test_sys_rng_f32() {
|
||||||
fn test_sys_rng_f64() {
|
fn test_sys_rng_f64() {
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
seed_data := [seed]
|
seed_data := [seed]
|
||||||
mut rng := rand.SysRNG{}
|
mut rng := sys.SysRNG{}
|
||||||
rng.seed(seed_data)
|
rng.seed(seed_data)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.f64()
|
value := rng.f64()
|
||||||
|
@ -299,10 +299,10 @@ fn test_sys_rng_f32n() {
|
||||||
max := f32(357.0)
|
max := f32(357.0)
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
seed_data := [seed]
|
seed_data := [seed]
|
||||||
mut rng := rand.SysRNG{}
|
mut rng := sys.SysRNG{}
|
||||||
rng.seed(seed_data)
|
rng.seed(seed_data)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.f32()
|
value := rng.f32n(max)
|
||||||
assert value >= 0.0
|
assert value >= 0.0
|
||||||
assert value < max
|
assert value < max
|
||||||
}
|
}
|
||||||
|
@ -313,10 +313,10 @@ fn test_sys_rng_f64n() {
|
||||||
max := 1.52e6
|
max := 1.52e6
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
seed_data := [seed]
|
seed_data := [seed]
|
||||||
mut rng := rand.SysRNG{}
|
mut rng := sys.SysRNG{}
|
||||||
rng.seed(seed_data)
|
rng.seed(seed_data)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.f64()
|
value := rng.f64n(max)
|
||||||
assert value >= 0.0
|
assert value >= 0.0
|
||||||
assert value < max
|
assert value < max
|
||||||
}
|
}
|
||||||
|
@ -328,10 +328,10 @@ fn test_sys_rng_f32_in_range() {
|
||||||
max := f32(125.0)
|
max := f32(125.0)
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
seed_data := [seed]
|
seed_data := [seed]
|
||||||
mut rng := rand.SysRNG{}
|
mut rng := sys.SysRNG{}
|
||||||
rng.seed(seed_data)
|
rng.seed(seed_data)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.f32()
|
value := rng.f32_in_range(min, max)
|
||||||
assert value >= min
|
assert value >= min
|
||||||
assert value < max
|
assert value < max
|
||||||
}
|
}
|
||||||
|
@ -343,10 +343,10 @@ fn test_sys_rng_f64_in_range() {
|
||||||
max := 5015.2
|
max := 5015.2
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
seed_data := [seed]
|
seed_data := [seed]
|
||||||
mut rng := rand.SysRNG{}
|
mut rng := sys.SysRNG{}
|
||||||
rng.seed(seed_data)
|
rng.seed(seed_data)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.f64()
|
value := rng.f64_in_range(min, max)
|
||||||
assert value >= min
|
assert value >= min
|
||||||
assert value < max
|
assert value < max
|
||||||
}
|
}
|
|
@ -1,13 +1,19 @@
|
||||||
// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved.
|
// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved.
|
||||||
// Use of this source code is governed by an MIT license
|
// Use of this source code is governed by an MIT license
|
||||||
// that can be found in the LICENSE file.
|
// that can be found in the LICENSE file.
|
||||||
module rand
|
module util
|
||||||
|
|
||||||
import time
|
import time
|
||||||
|
|
||||||
// Commonly used constants across RNGs
|
// Commonly used constants across RNGs
|
||||||
const (
|
pub const (
|
||||||
lower_mask = u64(0x00000000ffffffff)
|
lower_mask = u64(0x00000000FFFFFFFF)
|
||||||
|
max_u32 = 0xFFFFFFFF
|
||||||
|
max_u64 = 0xFFFFFFFFFFFFFFFF
|
||||||
|
max_u32_as_f32 = f32(max_u32) + 1
|
||||||
|
max_u64_as_f64 = f64(max_u64) + 1
|
||||||
|
u31_mask = u32(0x7FFFFFFF)
|
||||||
|
u63_mask = u64(0x7FFFFFFFFFFFFFFF)
|
||||||
)
|
)
|
||||||
|
|
||||||
// Constants taken from Numerical Recipes
|
// Constants taken from Numerical Recipes
|
||||||
|
@ -16,7 +22,7 @@ fn nr_next(prev u32) u32 {
|
||||||
return prev * 1664525 + 1013904223
|
return prev * 1664525 + 1013904223
|
||||||
}
|
}
|
||||||
|
|
||||||
// utility function that return the required number of u32s generated from system time
|
// time_seed_array is a utility function that 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 {
|
||||||
mut seed := u32(time.now().unix_time())
|
mut seed := u32(time.now().unix_time())
|
||||||
|
@ -28,13 +34,15 @@ 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
|
||||||
[inline]
|
[inline]
|
||||||
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
|
||||||
[inline]
|
[inline]
|
||||||
fn time_seed_64() u64 {
|
pub fn time_seed_64() u64 {
|
||||||
seed_data := time_seed_array(2)
|
seed_data := time_seed_array(2)
|
||||||
lower := u64(seed_data[0])
|
lower := u64(seed_data[0])
|
||||||
upper := u64(seed_data[1])
|
upper := u64(seed_data[1])
|
|
@ -1,9 +1,10 @@
|
||||||
// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved.
|
// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved.
|
||||||
// Use of this source code is governed by an MIT license
|
// Use of this source code is governed by an MIT license
|
||||||
// that can be found in the LICENSE file.
|
// that can be found in the LICENSE file.
|
||||||
module rand
|
module wyrand
|
||||||
|
|
||||||
import math.bits
|
import math.bits
|
||||||
|
import rand.util
|
||||||
import hash.wyhash
|
import hash.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
|
||||||
|
@ -15,7 +16,7 @@ const (
|
||||||
// RNG based on the WyHash hashing algorithm
|
// RNG based on the WyHash hashing algorithm
|
||||||
pub struct WyRandRNG {
|
pub struct WyRandRNG {
|
||||||
mut:
|
mut:
|
||||||
state u64 = time_seed_64()
|
state u64 = util.time_seed_64()
|
||||||
has_extra bool = false
|
has_extra bool = false
|
||||||
extra u32
|
extra u32
|
||||||
}
|
}
|
||||||
|
@ -30,7 +31,6 @@ 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
|
// rng.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 {
|
||||||
|
@ -39,7 +39,7 @@ pub fn (mut rng WyRandRNG) u32() u32 {
|
||||||
return rng.extra
|
return rng.extra
|
||||||
}
|
}
|
||||||
full_value := rng.u64()
|
full_value := rng.u64()
|
||||||
lower := u32(full_value & lower_mask)
|
lower := u32(full_value & util.lower_mask)
|
||||||
upper := u32(full_value >> 32)
|
upper := u32(full_value >> 32)
|
||||||
rng.extra = upper
|
rng.extra = upper
|
||||||
rng.has_extra = true
|
rng.has_extra = true
|
||||||
|
@ -148,13 +148,13 @@ pub fn (mut rng WyRandRNG) i64() i64 {
|
||||||
// rng.int31() returns a pseudorandom 31-bit int which is non-negative
|
// rng.int31() returns a pseudorandom 31-bit int which is non-negative
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (mut rng WyRandRNG) int31() int {
|
pub fn (mut rng WyRandRNG) int31() int {
|
||||||
return int(rng.u32() & 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
|
// rng.int63() returns a pseudorandom 63-bit int which is non-negative
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (mut rng WyRandRNG) int63() i64 {
|
pub fn (mut rng WyRandRNG) int63() i64 {
|
||||||
return i64(rng.u64() & 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)
|
// rng.intn(max) returns a pseudorandom int that lies in [0, max)
|
||||||
|
@ -201,13 +201,13 @@ pub fn (mut rng WyRandRNG) i64_in_range(min, max i64) i64 {
|
||||||
// rng.f32() returns a pseudorandom f32 value between 0.0 (inclusive) and 1.0 (exclusive) i.e [0, 1)
|
// rng.f32() returns a pseudorandom f32 value between 0.0 (inclusive) and 1.0 (exclusive) i.e [0, 1)
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (mut rng WyRandRNG) f32() f32 {
|
pub fn (mut rng WyRandRNG) f32() f32 {
|
||||||
return f32(rng.u32()) / 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)
|
// rng.f64() returns a pseudorandom f64 value between 0.0 (inclusive) and 1.0 (exclusive) i.e [0, 1)
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (mut rng WyRandRNG) f64() f64 {
|
pub fn (mut rng WyRandRNG) f64() f64 {
|
||||||
return f64(rng.u64()) / max_u64_as_f64
|
return f64(rng.u64()) / util.max_u64_as_f64
|
||||||
}
|
}
|
||||||
|
|
||||||
// rng.f32n() returns a pseudorandom f32 value in [0, max)
|
// rng.f32n() returns a pseudorandom f32 value in [0, max)
|
|
@ -1,5 +1,6 @@
|
||||||
import rand
|
|
||||||
import math
|
import math
|
||||||
|
import rand.util
|
||||||
|
import wyrand
|
||||||
|
|
||||||
const (
|
const (
|
||||||
range_limit = 40
|
range_limit = 40
|
||||||
|
@ -16,7 +17,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(0)].repeat(20)
|
mut randoms := [u64(0)].repeat(20)
|
||||||
mut rnd := rand.WyRandRNG{}
|
mut rnd := wyrand.WyRandRNG{}
|
||||||
rnd.seed(seed_data)
|
rnd.seed(seed_data)
|
||||||
for i in 0 .. 20 {
|
for i in 0 .. 20 {
|
||||||
randoms[i] = rnd.u64n(bound_u64)
|
randoms[i] = rnd.u64n(bound_u64)
|
||||||
|
@ -25,7 +26,7 @@ fn gen_randoms(seed_data []u32, bound int) []u64 {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_wyrand_reproducibility() {
|
fn test_wyrand_reproducibility() {
|
||||||
seed_data := rand.time_seed_array(2)
|
seed_data := util.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
|
||||||
|
@ -51,7 +52,7 @@ fn test_wyrand_variability() {
|
||||||
// at fault, try changing the seed values. Repeated values are
|
// at fault, try changing the seed values. Repeated values are
|
||||||
// improbable but not impossible.
|
// improbable but not impossible.
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.WyRandRNG{}
|
mut rng := wyrand.WyRandRNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
mut values := []u64{cap: value_count}
|
mut values := []u64{cap: value_count}
|
||||||
for i in 0 .. value_count {
|
for i in 0 .. value_count {
|
||||||
|
@ -63,7 +64,7 @@ fn test_wyrand_variability() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_uniformity_u64(mut rng rand.WyRandRNG, range u64) {
|
fn check_uniformity_u64(mut rng wyrand.WyRandRNG, range u64) {
|
||||||
range_f64 := f64(range)
|
range_f64 := f64(range)
|
||||||
expected_mean := range_f64 / 2.0
|
expected_mean := range_f64 / 2.0
|
||||||
mut variance := 0.0
|
mut variance := 0.0
|
||||||
|
@ -81,7 +82,7 @@ fn check_uniformity_u64(mut rng rand.WyRandRNG, range u64) {
|
||||||
fn test_wyrand_uniformity_u64() {
|
fn test_wyrand_uniformity_u64() {
|
||||||
ranges := [14019545, 80240, 130]
|
ranges := [14019545, 80240, 130]
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.WyRandRNG{}
|
mut rng := wyrand.WyRandRNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for range in ranges {
|
for range in ranges {
|
||||||
check_uniformity_u64(mut rng, u64(range))
|
check_uniformity_u64(mut rng, u64(range))
|
||||||
|
@ -89,7 +90,7 @@ fn test_wyrand_uniformity_u64() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_uniformity_f64(mut rng rand.WyRandRNG) {
|
fn check_uniformity_f64(mut rng wyrand.WyRandRNG) {
|
||||||
expected_mean := 0.5
|
expected_mean := 0.5
|
||||||
mut variance := 0.0
|
mut variance := 0.0
|
||||||
for _ in 0 .. sample_size {
|
for _ in 0 .. sample_size {
|
||||||
|
@ -106,19 +107,19 @@ fn check_uniformity_f64(mut rng rand.WyRandRNG) {
|
||||||
fn test_wyrand_uniformity_f64() {
|
fn test_wyrand_uniformity_f64() {
|
||||||
// The f64 version
|
// The f64 version
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.WyRandRNG{}
|
mut rng := wyrand.WyRandRNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
check_uniformity_f64(mut rng)
|
check_uniformity_f64(mut rng)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_wyrand_u32n() {
|
fn test_wyrand_u32n() {
|
||||||
max := 16384
|
max := u32(16384)
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.WyRandRNG{}
|
mut rng := wyrand.WyRandRNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.u32n(u32(max))
|
value := rng.u32n(max)
|
||||||
assert value >= 0
|
assert value >= 0
|
||||||
assert value < max
|
assert value < max
|
||||||
}
|
}
|
||||||
|
@ -128,7 +129,7 @@ fn test_wyrand_u32n() {
|
||||||
fn test_wyrand_u64n() {
|
fn test_wyrand_u64n() {
|
||||||
max := u64(379091181005)
|
max := u64(379091181005)
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.WyRandRNG{}
|
mut rng := wyrand.WyRandRNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.u64n(max)
|
value := rng.u64n(max)
|
||||||
|
@ -139,13 +140,13 @@ fn test_wyrand_u64n() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_wyrand_u32_in_range() {
|
fn test_wyrand_u32_in_range() {
|
||||||
max := 484468466
|
max := u32(484468466)
|
||||||
min := 316846
|
min := u32(316846)
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.WyRandRNG{}
|
mut rng := wyrand.WyRandRNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.u32_in_range(u32(min), u32(max))
|
value := rng.u32_in_range(min, max)
|
||||||
assert value >= min
|
assert value >= min
|
||||||
assert value < max
|
assert value < max
|
||||||
}
|
}
|
||||||
|
@ -156,7 +157,7 @@ fn test_wyrand_u64_in_range() {
|
||||||
max := u64(216468454685163)
|
max := u64(216468454685163)
|
||||||
min := u64(6848646868)
|
min := u64(6848646868)
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.WyRandRNG{}
|
mut rng := wyrand.WyRandRNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.u64_in_range(min, max)
|
value := rng.u64_in_range(min, max)
|
||||||
|
@ -170,7 +171,7 @@ fn test_wyrand_int31() {
|
||||||
max_u31 := 0x7FFFFFFF
|
max_u31 := 0x7FFFFFFF
|
||||||
sign_mask := 0x80000000
|
sign_mask := 0x80000000
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.WyRandRNG{}
|
mut rng := wyrand.WyRandRNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.int31()
|
value := rng.int31()
|
||||||
|
@ -186,7 +187,7 @@ fn test_wyrand_int63() {
|
||||||
max_u63 := i64(0x7FFFFFFFFFFFFFFF)
|
max_u63 := i64(0x7FFFFFFFFFFFFFFF)
|
||||||
sign_mask := i64(0x8000000000000000)
|
sign_mask := i64(0x8000000000000000)
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.WyRandRNG{}
|
mut rng := wyrand.WyRandRNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.int63()
|
value := rng.int63()
|
||||||
|
@ -200,7 +201,7 @@ fn test_wyrand_int63() {
|
||||||
fn test_wyrand_intn() {
|
fn test_wyrand_intn() {
|
||||||
max := 2525642
|
max := 2525642
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.WyRandRNG{}
|
mut rng := wyrand.WyRandRNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.intn(max)
|
value := rng.intn(max)
|
||||||
|
@ -213,7 +214,7 @@ fn test_wyrand_intn() {
|
||||||
fn test_wyrand_i64n() {
|
fn test_wyrand_i64n() {
|
||||||
max := i64(3246727724653636)
|
max := i64(3246727724653636)
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.WyRandRNG{}
|
mut rng := wyrand.WyRandRNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.i64n(max)
|
value := rng.i64n(max)
|
||||||
|
@ -227,7 +228,7 @@ fn test_wyrand_int_in_range() {
|
||||||
min := -4252
|
min := -4252
|
||||||
max := 1034
|
max := 1034
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.WyRandRNG{}
|
mut rng := wyrand.WyRandRNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.int_in_range(min, max)
|
value := rng.int_in_range(min, max)
|
||||||
|
@ -241,7 +242,7 @@ fn test_wyrand_i64_in_range() {
|
||||||
min := i64(-24095)
|
min := i64(-24095)
|
||||||
max := i64(324058)
|
max := i64(324058)
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.WyRandRNG{}
|
mut rng := wyrand.WyRandRNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.i64_in_range(min, max)
|
value := rng.i64_in_range(min, max)
|
||||||
|
@ -253,7 +254,7 @@ fn test_wyrand_i64_in_range() {
|
||||||
|
|
||||||
fn test_wyrand_f32() {
|
fn test_wyrand_f32() {
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.WyRandRNG{}
|
mut rng := wyrand.WyRandRNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.f32()
|
value := rng.f32()
|
||||||
|
@ -265,7 +266,7 @@ fn test_wyrand_f32() {
|
||||||
|
|
||||||
fn test_wyrand_f64() {
|
fn test_wyrand_f64() {
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.WyRandRNG{}
|
mut rng := wyrand.WyRandRNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.f64()
|
value := rng.f64()
|
||||||
|
@ -278,10 +279,10 @@ fn test_wyrand_f64() {
|
||||||
fn test_wyrand_f32n() {
|
fn test_wyrand_f32n() {
|
||||||
max := f32(357.0)
|
max := f32(357.0)
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.WyRandRNG{}
|
mut rng := wyrand.WyRandRNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.f32()
|
value := rng.f32n(max)
|
||||||
assert value >= 0.0
|
assert value >= 0.0
|
||||||
assert value < max
|
assert value < max
|
||||||
}
|
}
|
||||||
|
@ -291,10 +292,10 @@ fn test_wyrand_f32n() {
|
||||||
fn test_wyrand_f64n() {
|
fn test_wyrand_f64n() {
|
||||||
max := 1.52e6
|
max := 1.52e6
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.WyRandRNG{}
|
mut rng := wyrand.WyRandRNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.f64()
|
value := rng.f64n(max)
|
||||||
assert value >= 0.0
|
assert value >= 0.0
|
||||||
assert value < max
|
assert value < max
|
||||||
}
|
}
|
||||||
|
@ -305,10 +306,10 @@ fn test_wyrand_f32_in_range() {
|
||||||
min := f32(-24.0)
|
min := f32(-24.0)
|
||||||
max := f32(125.0)
|
max := f32(125.0)
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.WyRandRNG{}
|
mut rng := wyrand.WyRandRNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.f32()
|
value := rng.f32_in_range(min, max)
|
||||||
assert value >= min
|
assert value >= min
|
||||||
assert value < max
|
assert value < max
|
||||||
}
|
}
|
||||||
|
@ -319,10 +320,10 @@ fn test_wyrand_f64_in_range() {
|
||||||
min := -548.7
|
min := -548.7
|
||||||
max := 5015.2
|
max := 5015.2
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := rand.WyRandRNG{}
|
mut rng := wyrand.WyRandRNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
for _ in 0 .. range_limit {
|
for _ in 0 .. range_limit {
|
||||||
value := rng.f64()
|
value := rng.f64_in_range(min, max)
|
||||||
assert value >= min
|
assert value >= min
|
||||||
assert value < max
|
assert value < max
|
||||||
}
|
}
|
|
@ -8,5 +8,5 @@ const (
|
||||||
)
|
)
|
||||||
// random returns a random time struct in *the past*.
|
// random returns a random time struct in *the past*.
|
||||||
pub fn random() time.Time {
|
pub fn random() time.Time {
|
||||||
return time.unix(rand.next(int(start_time_unix)))
|
return time.unix(int(rand.u64n(start_time_unix)))
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ import rand
|
||||||
|
|
||||||
fn test_random() {
|
fn test_random() {
|
||||||
// guarantee CI test stability, by seeding the random number generator with a known seed
|
// guarantee CI test stability, by seeding the random number generator with a known seed
|
||||||
rand.seed(0)
|
rand.seed([u32(0), 0])
|
||||||
t1 := tmisc.random()
|
t1 := tmisc.random()
|
||||||
t2 := tmisc.random()
|
t2 := tmisc.random()
|
||||||
t3 := tmisc.random()
|
t3 := tmisc.random()
|
||||||
|
|
Loading…
Reference in New Issue