mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
rand: reorganize: phase 2
This commit is contained in:
parent
67fcce2d46
commit
e649cf84e3
@ -12,11 +12,11 @@ fn main() {
|
||||
println('Generating $sample_size strings between $min_str_len - $max_str_len chars long...')
|
||||
mut bytepile := []byte{}
|
||||
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{}
|
||||
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...')
|
||||
t0 := time.ticks()
|
||||
|
@ -22,6 +22,7 @@ const (
|
||||
]
|
||||
skip_on_windows = [
|
||||
'vlib/orm/orm_test.v',
|
||||
'vlib/net/websocket/ws_test.v',
|
||||
]
|
||||
skip_on_non_windows = []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
|
||||
fn rand_f64() f64 {
|
||||
x := (C.rand()+1) & 0x3FFF_FFFF
|
||||
x := (rand.intn(cache_len)+1) & 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()
|
||||
|
||||
// tabbed speed-up
|
||||
r1 := C.rand() & cache_mask
|
||||
r1 := rand.intn(cache_len) & cache_mask
|
||||
|
||||
r2 := rand_f64()
|
||||
r2s := math.sqrt(r2)
|
||||
@ -465,9 +465,8 @@ fn main() {
|
||||
height = os.args[5].int()
|
||||
}
|
||||
|
||||
// init the rand, using the same seed allows to obtain the same result in different runs
|
||||
// change the seed from 2020 for different results
|
||||
rand.seed(2020)
|
||||
// change the seed for a different result
|
||||
rand.seed([u32(2020), 0])
|
||||
|
||||
t1:=time.ticks()
|
||||
|
||||
|
@ -7,11 +7,10 @@ const (
|
||||
)
|
||||
|
||||
fn main() {
|
||||
rand.seed(int(time.now().unix))
|
||||
rand.next(gen_max) // skip the first
|
||||
rand.intn(gen_max) // skip the first
|
||||
mut arr := []int{}
|
||||
for _ in 0..gen_len {
|
||||
arr << rand.next(gen_max)
|
||||
arr << rand.intn(gen_max)
|
||||
}
|
||||
println('length of random array is $arr.len')
|
||||
println('before quick sort whether array is sorted: ${is_sorted(arr)}')
|
||||
|
@ -2,9 +2,7 @@ import rand
|
||||
import time
|
||||
|
||||
fn main() {
|
||||
rand.seed(int(time.now().unix))
|
||||
|
||||
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() {
|
||||
g.parse_tetros()
|
||||
rand.seed(int(time.now().unix))
|
||||
g.generate_tetro()
|
||||
g.field = []
|
||||
// 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() {
|
||||
g.pos_y = 0
|
||||
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.get_tetro()
|
||||
}
|
||||
|
@ -81,7 +81,7 @@ fn get_bet(money int) int {
|
||||
}
|
||||
bet = line.int()
|
||||
if bet <= 0 {
|
||||
println('error: $line is not heigher than 1.')
|
||||
println('error: $line is not higher than 1.')
|
||||
continue
|
||||
} else if bet > money {
|
||||
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 {
|
||||
mut bet := _bet
|
||||
rand.seed(int(time.now().unix))
|
||||
winning_nbr := rand.next(50)
|
||||
winning_nbr := rand.intn(50)
|
||||
print('Roulette Wheel spinning... and stops on the number $winning_nbr which is a ')
|
||||
if winning_nbr % 2 == 1 {
|
||||
println(odd)
|
||||
@ -115,7 +114,7 @@ fn run_wheel(bet_nbr int, _bet int) int {
|
||||
|
||||
fn is_broke(money int) bool {
|
||||
if money <= 0 {
|
||||
println('You\'broke, the game is over..')
|
||||
println('You\'re broke, the game is over..')
|
||||
return false
|
||||
} else {
|
||||
quit := Options{'yes', 'y'}
|
||||
|
@ -19,16 +19,15 @@ fn test_bf_set_clear_toggle_get() {
|
||||
}
|
||||
|
||||
fn test_bf_and_not_or_xor() {
|
||||
rand.seed(int(time.now().unix))
|
||||
len := 80
|
||||
mut input1 := bitfield.new(len)
|
||||
mut input2 := bitfield.new(len)
|
||||
mut i := 0
|
||||
for i < len {
|
||||
if rand.next(2) == 1 {
|
||||
if rand.intn(2) == 1 {
|
||||
input1.set_bit(i)
|
||||
}
|
||||
if rand.next(2) == 1{
|
||||
if rand.intn(2) == 1{
|
||||
input2.set_bit(i)
|
||||
}
|
||||
i++
|
||||
@ -46,11 +45,10 @@ fn test_bf_and_not_or_xor() {
|
||||
}
|
||||
|
||||
fn test_clone_cmp() {
|
||||
rand.seed(int(time.now().unix))
|
||||
len := 80
|
||||
mut input := bitfield.new(len)
|
||||
for i in 0..len {
|
||||
if rand.next(2) == 1 {
|
||||
if rand.intn(2) == 1 {
|
||||
input.set_bit(i)
|
||||
}
|
||||
}
|
||||
@ -60,11 +58,10 @@ fn test_clone_cmp() {
|
||||
}
|
||||
|
||||
fn test_slice_join() {
|
||||
rand.seed(int(time.now().unix))
|
||||
len := 80
|
||||
mut input := bitfield.new(len)
|
||||
for i in 0..len {
|
||||
if rand.next(2) == 1 {
|
||||
if rand.intn(2) == 1 {
|
||||
input.set_bit(i)
|
||||
}
|
||||
}
|
||||
@ -83,12 +80,11 @@ fn test_slice_join() {
|
||||
}
|
||||
|
||||
fn test_pop_count() {
|
||||
rand.seed(int(time.now().unix))
|
||||
len := 80
|
||||
mut count0 := 0
|
||||
mut input := bitfield.new(len)
|
||||
for i in 0..len {
|
||||
if rand.next(2) == 1 {
|
||||
if rand.intn(2) == 1 {
|
||||
input.set_bit(i)
|
||||
count0++
|
||||
}
|
||||
@ -98,13 +94,12 @@ fn test_pop_count() {
|
||||
}
|
||||
|
||||
fn test_hamming() {
|
||||
rand.seed(int(time.now().unix))
|
||||
len := 80
|
||||
mut count := 0
|
||||
mut input1 := bitfield.new(len)
|
||||
mut input2 := bitfield.new(len)
|
||||
for i in 0..len {
|
||||
match rand.next(4) {
|
||||
match rand.intn(4) {
|
||||
0, 1 {
|
||||
input1.set_bit(i)
|
||||
count++
|
||||
@ -138,11 +133,10 @@ fn test_bf_from_bytes() {
|
||||
}
|
||||
|
||||
fn test_bf_from_str() {
|
||||
rand.seed(int(time.now().unix))
|
||||
len := 80
|
||||
mut input := ''
|
||||
for _ in 0..len {
|
||||
if rand.next(2) == 1 {
|
||||
if rand.intn(2) == 1 {
|
||||
input = input + '1'
|
||||
}
|
||||
else {
|
||||
@ -160,11 +154,10 @@ fn test_bf_from_str() {
|
||||
}
|
||||
|
||||
fn test_bf_bf2str() {
|
||||
rand.seed(int(time.now().unix))
|
||||
len := 80
|
||||
mut input := bitfield.new(len)
|
||||
for i in 0..len {
|
||||
if rand.next(2) == 1 {
|
||||
if rand.intn(2) == 1 {
|
||||
input.set_bit(i)
|
||||
}
|
||||
}
|
||||
@ -188,7 +181,6 @@ fn test_bf_bf2str() {
|
||||
}
|
||||
|
||||
fn test_bf_set_all() {
|
||||
rand.seed(int(time.now().unix))
|
||||
len := 80
|
||||
mut input := bitfield.new(len)
|
||||
input.set_all()
|
||||
@ -202,11 +194,10 @@ fn test_bf_set_all() {
|
||||
}
|
||||
|
||||
fn test_bf_clear_all() {
|
||||
rand.seed(int(time.now().unix))
|
||||
len := 80
|
||||
mut input := bitfield.new(len)
|
||||
for i in 0..len {
|
||||
if rand.next(2) == 1 {
|
||||
if rand.intn(2) == 1 {
|
||||
input.set_bit(i)
|
||||
}
|
||||
}
|
||||
@ -221,11 +212,10 @@ fn test_bf_clear_all() {
|
||||
}
|
||||
|
||||
fn test_bf_reverse() {
|
||||
rand.seed(int(time.now().unix))
|
||||
len := 80
|
||||
mut input := bitfield.new(len)
|
||||
for i in 0..len {
|
||||
if rand.next(2) == 1 {
|
||||
if rand.intn(2) == 1 {
|
||||
input.set_bit(i)
|
||||
}
|
||||
}
|
||||
@ -241,11 +231,10 @@ fn test_bf_reverse() {
|
||||
}
|
||||
|
||||
fn test_bf_resize() {
|
||||
rand.seed(int(time.now().unix))
|
||||
len := 80
|
||||
mut input := bitfield.new(rand.next(len) + 1)
|
||||
mut input := bitfield.new(rand.intn(len) + 1)
|
||||
for _ in 0..100 {
|
||||
input.resize(rand.next(len) + 1)
|
||||
input.resize(rand.intn(len) + 1)
|
||||
input.set_bit(input.get_size() - 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,
|
||||
* so search should return non-negative-values
|
||||
**/
|
||||
rand.seed(int(time.now().unix))
|
||||
len := 80
|
||||
mut result := 1
|
||||
for i := 1; i < len; i++ { // needle size
|
||||
@ -269,13 +257,13 @@ fn test_bf_pos() {
|
||||
|
||||
// fill the needle with random values
|
||||
for k in 0..i {
|
||||
if rand.next(2) == 1 {
|
||||
if rand.intn(2) == 1 {
|
||||
needle.set_bit(k)
|
||||
}
|
||||
}
|
||||
|
||||
// make sure the needle contains at least one set bit, selected randomly
|
||||
r := rand.next(i)
|
||||
r := rand.intn(i)
|
||||
needle.set_bit(r)
|
||||
|
||||
// create the haystack, make sure it contains the needle
|
||||
@ -322,11 +310,10 @@ fn test_bf_rotate() {
|
||||
}
|
||||
|
||||
fn test_bf_printing(){
|
||||
rand.seed(int(time.now().unix))
|
||||
len := 80
|
||||
mut input := bitfield.new(len)
|
||||
for i in 0..len {
|
||||
if rand.next(2) == 0 {
|
||||
if rand.intn(2) == 0 {
|
||||
input.set_bit(i)
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,6 @@
|
||||
module websocket
|
||||
|
||||
import time
|
||||
import rand
|
||||
import math
|
||||
import crypto.sha1
|
||||
import encoding.base64
|
||||
|
||||
@ -20,10 +18,7 @@ fn htonl64(payload_len u64) byteptr {
|
||||
}
|
||||
|
||||
fn create_masking_key() []byte {
|
||||
t := time.ticks()
|
||||
tseq := t % 23237671
|
||||
mut rnd := rand.new_pcg32(u64(t), u64(tseq))
|
||||
mask_bit := byte(rnd.bounded_next(u32(math.max_i32)))
|
||||
mask_bit := byte(rand.intn(255))
|
||||
buf := [`0`].repeat(4)
|
||||
C.memcpy(buf.data, &mask_bit, 4)
|
||||
return buf
|
||||
@ -46,7 +41,7 @@ fn get_nonce(nonce_size int) string {
|
||||
mut nonce := []byte{len: nonce_size, cap: nonce_size}
|
||||
alphanum := '0123456789ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvwxyz'
|
||||
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()
|
||||
}
|
||||
|
46
vlib/rand/README.md
Normal file
46
vlib/rand/README.md
Normal file
@ -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.
|
||||
// Use of this source code is governed by an MIT license
|
||||
// that can be found in the LICENSE file.
|
||||
module rand
|
||||
module mt19937
|
||||
|
||||
import math.bits
|
||||
import rand.util
|
||||
|
||||
/*
|
||||
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
|
||||
pub struct MT19937RNG {
|
||||
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
|
||||
next_rnd u32 = 0
|
||||
has_next bool = false
|
@ -1,5 +1,6 @@
|
||||
import rand
|
||||
import mt19937
|
||||
import math
|
||||
import rand.util
|
||||
|
||||
const (
|
||||
range_limit = 40
|
||||
@ -14,7 +15,7 @@ const (
|
||||
)
|
||||
|
||||
fn mt19937_basic_test() {
|
||||
mut rng := rand.MT19937RNG{}
|
||||
mut rng := mt19937.MT19937RNG{}
|
||||
rng.seed([u32(0xdeadbeef)])
|
||||
target := [956529277, 3842322136, 3319553134, 1843186657, 2704993644, 595827513, 938518626,
|
||||
1676224337, 3221315650, 1819026461]
|
||||
@ -26,7 +27,7 @@ fn mt19937_basic_test() {
|
||||
fn gen_randoms(seed_data []u32, bound int) []u64 {
|
||||
bound_u64 := u64(bound)
|
||||
mut randoms := [u64(0)].repeat(20)
|
||||
mut rnd := rand.MT19937RNG{}
|
||||
mut rnd := mt19937.MT19937RNG{}
|
||||
rnd.seed(seed_data)
|
||||
for i in 0 .. 20 {
|
||||
randoms[i] = rnd.u64n(bound_u64)
|
||||
@ -35,7 +36,7 @@ fn gen_randoms(seed_data []u32, bound int) []u64 {
|
||||
}
|
||||
|
||||
fn test_mt19937_reproducibility() {
|
||||
seed_data := rand.time_seed_array(2)
|
||||
seed_data := util.time_seed_array(2)
|
||||
randoms1 := gen_randoms(seed_data, 1000)
|
||||
randoms2 := gen_randoms(seed_data, 1000)
|
||||
assert randoms1.len == randoms2.len
|
||||
@ -61,7 +62,7 @@ fn test_mt19937_variability() {
|
||||
// at fault, try changing the seed values. Repeated values are
|
||||
// improbable but not impossible.
|
||||
for seed in seeds {
|
||||
mut rng := rand.MT19937RNG{}
|
||||
mut rng := mt19937.MT19937RNG{}
|
||||
rng.seed(seed)
|
||||
mut values := []u64{cap: 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)
|
||||
expected_mean := range_f64 / 2.0
|
||||
mut variance := 0.0
|
||||
@ -91,7 +92,7 @@ fn check_uniformity_u64(mut rng rand.MT19937RNG, range u64) {
|
||||
fn test_mt19937_uniformity_u64() {
|
||||
ranges := [14019545, 80240, 130]
|
||||
for seed in seeds {
|
||||
mut rng := rand.MT19937RNG{}
|
||||
mut rng := mt19937.MT19937RNG{}
|
||||
rng.seed(seed)
|
||||
for range in ranges {
|
||||
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
|
||||
mut variance := 0.0
|
||||
for _ in 0 .. sample_size {
|
||||
@ -116,19 +117,19 @@ fn check_uniformity_f64(mut rng rand.MT19937RNG) {
|
||||
fn test_mt19937_uniformity_f64() {
|
||||
// The f64 version
|
||||
for seed in seeds {
|
||||
mut rng := rand.MT19937RNG{}
|
||||
mut rng := mt19937.MT19937RNG{}
|
||||
rng.seed(seed)
|
||||
check_uniformity_f64(mut rng)
|
||||
}
|
||||
}
|
||||
|
||||
fn test_mt19937_u32n() {
|
||||
max := 16384
|
||||
max := u32(16384)
|
||||
for seed in seeds {
|
||||
mut rng := rand.MT19937RNG{}
|
||||
mut rng := mt19937.MT19937RNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.u32n(u32(max))
|
||||
value := rng.u32n(max)
|
||||
assert value >= 0
|
||||
assert value < max
|
||||
}
|
||||
@ -138,7 +139,7 @@ fn test_mt19937_u32n() {
|
||||
fn test_mt19937_u64n() {
|
||||
max := u64(379091181005)
|
||||
for seed in seeds {
|
||||
mut rng := rand.MT19937RNG{}
|
||||
mut rng := mt19937.MT19937RNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.u64n(max)
|
||||
@ -149,13 +150,13 @@ fn test_mt19937_u64n() {
|
||||
}
|
||||
|
||||
fn test_mt19937_u32_in_range() {
|
||||
max := 484468466
|
||||
min := 316846
|
||||
max := u32(484468466)
|
||||
min := u32(316846)
|
||||
for seed in seeds {
|
||||
mut rng := rand.MT19937RNG{}
|
||||
mut rng := mt19937.MT19937RNG{}
|
||||
rng.seed(seed)
|
||||
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 < max
|
||||
}
|
||||
@ -166,7 +167,7 @@ fn test_mt19937_u64_in_range() {
|
||||
max := u64(216468454685163)
|
||||
min := u64(6848646868)
|
||||
for seed in seeds {
|
||||
mut rng := rand.MT19937RNG{}
|
||||
mut rng := mt19937.MT19937RNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.u64_in_range(min, max)
|
||||
@ -180,7 +181,7 @@ fn test_mt19937_int31() {
|
||||
max_u31 := 0x7FFFFFFF
|
||||
sign_mask := 0x80000000
|
||||
for seed in seeds {
|
||||
mut rng := rand.MT19937RNG{}
|
||||
mut rng := mt19937.MT19937RNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.int31()
|
||||
@ -196,7 +197,7 @@ fn test_mt19937_int63() {
|
||||
max_u63 := i64(0x7FFFFFFFFFFFFFFF)
|
||||
sign_mask := i64(0x8000000000000000)
|
||||
for seed in seeds {
|
||||
mut rng := rand.MT19937RNG{}
|
||||
mut rng := mt19937.MT19937RNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.int63()
|
||||
@ -210,7 +211,7 @@ fn test_mt19937_int63() {
|
||||
fn test_mt19937_intn() {
|
||||
max := 2525642
|
||||
for seed in seeds {
|
||||
mut rng := rand.MT19937RNG{}
|
||||
mut rng := mt19937.MT19937RNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.intn(max)
|
||||
@ -223,7 +224,7 @@ fn test_mt19937_intn() {
|
||||
fn test_mt19937_i64n() {
|
||||
max := i64(3246727724653636)
|
||||
for seed in seeds {
|
||||
mut rng := rand.MT19937RNG{}
|
||||
mut rng := mt19937.MT19937RNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.i64n(max)
|
||||
@ -237,7 +238,7 @@ fn test_mt19937_int_in_range() {
|
||||
min := -4252
|
||||
max := 1034
|
||||
for seed in seeds {
|
||||
mut rng := rand.MT19937RNG{}
|
||||
mut rng := mt19937.MT19937RNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.int_in_range(min, max)
|
||||
@ -251,7 +252,7 @@ fn test_mt19937_i64_in_range() {
|
||||
min := i64(-24095)
|
||||
max := i64(324058)
|
||||
for seed in seeds {
|
||||
mut rng := rand.MT19937RNG{}
|
||||
mut rng := mt19937.MT19937RNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.i64_in_range(min, max)
|
||||
@ -263,7 +264,7 @@ fn test_mt19937_i64_in_range() {
|
||||
|
||||
fn test_mt19937_f32() {
|
||||
for seed in seeds {
|
||||
mut rng := rand.MT19937RNG{}
|
||||
mut rng := mt19937.MT19937RNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.f32()
|
||||
@ -275,7 +276,7 @@ fn test_mt19937_f32() {
|
||||
|
||||
fn test_mt19937_f64() {
|
||||
for seed in seeds {
|
||||
mut rng := rand.MT19937RNG{}
|
||||
mut rng := mt19937.MT19937RNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.f64()
|
||||
@ -288,7 +289,7 @@ fn test_mt19937_f64() {
|
||||
fn test_mt19937_f32n() {
|
||||
max := f32(357.0)
|
||||
for seed in seeds {
|
||||
mut rng := rand.MT19937RNG{}
|
||||
mut rng := mt19937.MT19937RNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.f32n(max)
|
||||
@ -301,7 +302,7 @@ fn test_mt19937_f32n() {
|
||||
fn test_mt19937_f64n() {
|
||||
max := 1.52e6
|
||||
for seed in seeds {
|
||||
mut rng := rand.MT19937RNG{}
|
||||
mut rng := mt19937.MT19937RNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.f64n(max)
|
||||
@ -315,7 +316,7 @@ fn test_mt19937_f32_in_range() {
|
||||
min := f32(-24.0)
|
||||
max := f32(125.0)
|
||||
for seed in seeds {
|
||||
mut rng := rand.MT19937RNG{}
|
||||
mut rng := mt19937.MT19937RNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.f32_in_range(min, max)
|
||||
@ -329,7 +330,7 @@ fn test_mt19937_f64_in_range() {
|
||||
min := -548.7
|
||||
max := 5015.2
|
||||
for seed in seeds {
|
||||
mut rng := rand.MT19937RNG{}
|
||||
mut rng := mt19937.MT19937RNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.f64_in_range(min, max)
|
@ -1,14 +1,15 @@
|
||||
// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved.
|
||||
// Use of this source code is governed by an MIT license
|
||||
// that can be found in the LICENSE file.
|
||||
module rand
|
||||
module musl
|
||||
|
||||
import math.bits
|
||||
import rand.util
|
||||
|
||||
// Ported from https://git.musl-libc.org/cgit/musl/tree/src/prng/rand_r.c
|
||||
pub struct MuslRNG {
|
||||
mut:
|
||||
state u32 = time_seed_32()
|
||||
state u32 = util.time_seed_32()
|
||||
}
|
||||
|
||||
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)
|
||||
[inline]
|
||||
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)
|
||||
[inline]
|
||||
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)
|
@ -1,5 +1,6 @@
|
||||
import rand
|
||||
import musl
|
||||
import math
|
||||
import rand.util
|
||||
|
||||
const (
|
||||
range_limit = 40
|
||||
@ -16,7 +17,7 @@ const (
|
||||
fn gen_randoms(seed_data []u32, bound int) []u64 {
|
||||
bound_u64 := u64(bound)
|
||||
mut randoms := [u64(0)].repeat(20)
|
||||
mut rnd := rand.MuslRNG{}
|
||||
mut rnd := musl.MuslRNG{}
|
||||
rnd.seed(seed_data)
|
||||
for i in 0 .. 20 {
|
||||
randoms[i] = rnd.u64n(bound_u64)
|
||||
@ -25,7 +26,7 @@ fn gen_randoms(seed_data []u32, bound int) []u64 {
|
||||
}
|
||||
|
||||
fn test_musl_reproducibility() {
|
||||
seed_data := rand.time_seed_array(1)
|
||||
seed_data := util.time_seed_array(1)
|
||||
randoms1 := gen_randoms(seed_data, 1000)
|
||||
randoms2 := gen_randoms(seed_data, 1000)
|
||||
assert randoms1.len == randoms2.len
|
||||
@ -51,7 +52,7 @@ fn test_musl_variability() {
|
||||
// at fault, try changing the seed values. Repeated values are
|
||||
// improbable but not impossible.
|
||||
for seed in seeds {
|
||||
mut rng := rand.MuslRNG{}
|
||||
mut rng := musl.MuslRNG{}
|
||||
rng.seed(seed)
|
||||
mut values := []u64{cap: 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)
|
||||
expected_mean := range_f64 / 2.0
|
||||
mut variance := 0.0
|
||||
@ -81,7 +82,7 @@ fn check_uniformity_u64(mut rng rand.MuslRNG, range u64) {
|
||||
fn test_musl_uniformity_u64() {
|
||||
ranges := [14019545, 80240, 130]
|
||||
for seed in seeds {
|
||||
mut rng := rand.MuslRNG{}
|
||||
mut rng := musl.MuslRNG{}
|
||||
rng.seed(seed)
|
||||
for range in ranges {
|
||||
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
|
||||
mut variance := 0.0
|
||||
for _ in 0 .. sample_size {
|
||||
@ -106,19 +107,19 @@ fn check_uniformity_f64(mut rng rand.MuslRNG) {
|
||||
fn test_musl_uniformity_f64() {
|
||||
// The f64 version
|
||||
for seed in seeds {
|
||||
mut rng := rand.MuslRNG{}
|
||||
mut rng := musl.MuslRNG{}
|
||||
rng.seed(seed)
|
||||
check_uniformity_f64(mut rng)
|
||||
}
|
||||
}
|
||||
|
||||
fn test_musl_u32n() {
|
||||
max := 16384
|
||||
max := u32(16384)
|
||||
for seed in seeds {
|
||||
mut rng := rand.MuslRNG{}
|
||||
mut rng := musl.MuslRNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.u32n(u32(max))
|
||||
value := rng.u32n(max)
|
||||
assert value >= 0
|
||||
assert value < max
|
||||
}
|
||||
@ -128,7 +129,7 @@ fn test_musl_u32n() {
|
||||
fn test_musl_u64n() {
|
||||
max := u64(379091181005)
|
||||
for seed in seeds {
|
||||
mut rng := rand.MuslRNG{}
|
||||
mut rng := musl.MuslRNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.u64n(max)
|
||||
@ -139,13 +140,13 @@ fn test_musl_u64n() {
|
||||
}
|
||||
|
||||
fn test_musl_u32_in_range() {
|
||||
max := 484468466
|
||||
min := 316846
|
||||
max := u32(484468466)
|
||||
min := u32(316846)
|
||||
for seed in seeds {
|
||||
mut rng := rand.MuslRNG{}
|
||||
mut rng := musl.MuslRNG{}
|
||||
rng.seed(seed)
|
||||
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 < max
|
||||
}
|
||||
@ -156,7 +157,7 @@ fn test_musl_u64_in_range() {
|
||||
max := u64(216468454685163)
|
||||
min := u64(6848646868)
|
||||
for seed in seeds {
|
||||
mut rng := rand.MuslRNG{}
|
||||
mut rng := musl.MuslRNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.u64_in_range(min, max)
|
||||
@ -170,7 +171,7 @@ fn test_musl_int31() {
|
||||
max_u31 := 0x7FFFFFFF
|
||||
sign_mask := 0x80000000
|
||||
for seed in seeds {
|
||||
mut rng := rand.MuslRNG{}
|
||||
mut rng := musl.MuslRNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.int31()
|
||||
@ -186,7 +187,7 @@ fn test_musl_int63() {
|
||||
max_u63 := i64(0x7FFFFFFFFFFFFFFF)
|
||||
sign_mask := i64(0x8000000000000000)
|
||||
for seed in seeds {
|
||||
mut rng := rand.MuslRNG{}
|
||||
mut rng := musl.MuslRNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.int63()
|
||||
@ -200,7 +201,7 @@ fn test_musl_int63() {
|
||||
fn test_musl_intn() {
|
||||
max := 2525642
|
||||
for seed in seeds {
|
||||
mut rng := rand.MuslRNG{}
|
||||
mut rng := musl.MuslRNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.intn(max)
|
||||
@ -213,7 +214,7 @@ fn test_musl_intn() {
|
||||
fn test_musl_i64n() {
|
||||
max := i64(3246727724653636)
|
||||
for seed in seeds {
|
||||
mut rng := rand.MuslRNG{}
|
||||
mut rng := musl.MuslRNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.i64n(max)
|
||||
@ -227,7 +228,7 @@ fn test_musl_int_in_range() {
|
||||
min := -4252
|
||||
max := 1034
|
||||
for seed in seeds {
|
||||
mut rng := rand.MuslRNG{}
|
||||
mut rng := musl.MuslRNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.int_in_range(min, max)
|
||||
@ -241,7 +242,7 @@ fn test_musl_i64_in_range() {
|
||||
min := i64(-24095)
|
||||
max := i64(324058)
|
||||
for seed in seeds {
|
||||
mut rng := rand.MuslRNG{}
|
||||
mut rng := musl.MuslRNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.i64_in_range(min, max)
|
||||
@ -253,7 +254,7 @@ fn test_musl_i64_in_range() {
|
||||
|
||||
fn test_musl_f32() {
|
||||
for seed in seeds {
|
||||
mut rng := rand.MuslRNG{}
|
||||
mut rng := musl.MuslRNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.f32()
|
||||
@ -265,7 +266,7 @@ fn test_musl_f32() {
|
||||
|
||||
fn test_musl_f64() {
|
||||
for seed in seeds {
|
||||
mut rng := rand.MuslRNG{}
|
||||
mut rng := musl.MuslRNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.f64()
|
||||
@ -278,10 +279,10 @@ fn test_musl_f64() {
|
||||
fn test_musl_f32n() {
|
||||
max := f32(357.0)
|
||||
for seed in seeds {
|
||||
mut rng := rand.MuslRNG{}
|
||||
mut rng := musl.MuslRNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.f32()
|
||||
value := rng.f32n(max)
|
||||
assert value >= 0.0
|
||||
assert value < max
|
||||
}
|
||||
@ -291,10 +292,10 @@ fn test_musl_f32n() {
|
||||
fn test_musl_f64n() {
|
||||
max := 1.52e6
|
||||
for seed in seeds {
|
||||
mut rng := rand.MuslRNG{}
|
||||
mut rng := musl.MuslRNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.f64()
|
||||
value := rng.f64n(max)
|
||||
assert value >= 0.0
|
||||
assert value < max
|
||||
}
|
||||
@ -305,10 +306,10 @@ fn test_musl_f32_in_range() {
|
||||
min := f32(-24.0)
|
||||
max := f32(125.0)
|
||||
for seed in seeds {
|
||||
mut rng := rand.MuslRNG{}
|
||||
mut rng := musl.MuslRNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.f32()
|
||||
value := rng.f32_in_range(min, max)
|
||||
assert value >= min
|
||||
assert value < max
|
||||
}
|
||||
@ -319,10 +320,10 @@ fn test_musl_f64_in_range() {
|
||||
min := -548.7
|
||||
max := 5015.2
|
||||
for seed in seeds {
|
||||
mut rng := rand.MuslRNG{}
|
||||
mut rng := musl.MuslRNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.f64()
|
||||
value := rng.f64_in_range(min, max)
|
||||
assert value >= min
|
||||
assert value < max
|
||||
}
|
@ -1,26 +1,17 @@
|
||||
// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved.
|
||||
// Use of this source code is governed by an MIT license
|
||||
// that can be found in the LICENSE file.
|
||||
module rand
|
||||
module pcg32
|
||||
|
||||
import rand.util
|
||||
|
||||
// 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.h
|
||||
pub struct PCG32RNG {
|
||||
mut:
|
||||
state u64 = u64(0x853c49e6748fea9b) ^ time_seed_64()
|
||||
inc u64 = u64(0xda3e39cb94b95bdb) ^ 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)
|
||||
state u64 = u64(0x853c49e6748fea9b) ^ util.time_seed_64()
|
||||
inc u64 = u64(0xda3e39cb94b95bdb) ^ util.time_seed_64()
|
||||
}
|
||||
|
||||
// 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)
|
||||
[inline]
|
||||
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)
|
||||
[inline]
|
||||
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)
|
@ -1,5 +1,6 @@
|
||||
import rand
|
||||
import math
|
||||
import pcg32
|
||||
import rand.util
|
||||
|
||||
const (
|
||||
range_limit = 40
|
||||
@ -15,7 +16,7 @@ const (
|
||||
|
||||
fn gen_randoms(seed_data []u32, bound int) []u32 {
|
||||
mut randoms := []u32{len: 20}
|
||||
mut rng := rand.PCG32RNG{}
|
||||
mut rng := pcg32.PCG32RNG{}
|
||||
rng.seed(seed_data)
|
||||
for i in 0 .. 20 {
|
||||
randoms[i] = rng.u32n(u32(bound))
|
||||
@ -24,8 +25,8 @@ fn gen_randoms(seed_data []u32, bound int) []u32 {
|
||||
}
|
||||
|
||||
fn test_pcg32_reproducibility() {
|
||||
randoms1 := gen_randoms(rand.time_seed_array(4), 1000)
|
||||
randoms2 := gen_randoms(rand.time_seed_array(4), 1000)
|
||||
randoms1 := gen_randoms(util.time_seed_array(4), 1000)
|
||||
randoms2 := gen_randoms(util.time_seed_array(4), 1000)
|
||||
assert randoms1.len == randoms2.len
|
||||
len := randoms1.len
|
||||
for i in 0 .. len {
|
||||
@ -49,7 +50,7 @@ fn test_pcg32_variability() {
|
||||
// at fault, try changing the seed values. Repeated values are
|
||||
// improbable but not impossible.
|
||||
for seed in seeds {
|
||||
mut rng := rand.PCG32RNG{}
|
||||
mut rng := pcg32.PCG32RNG{}
|
||||
rng.seed(seed)
|
||||
mut values := []u64{cap: 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)
|
||||
expected_mean := range_f64 / 2.0
|
||||
mut variance := 0.0
|
||||
@ -79,7 +80,7 @@ fn check_uniformity_u64(mut rng rand.PCG32RNG, range u64) {
|
||||
fn test_pcg32_uniformity_u64() {
|
||||
ranges := [14019545, 80240, 130]
|
||||
for seed in seeds {
|
||||
mut rng := rand.PCG32RNG{}
|
||||
mut rng := pcg32.PCG32RNG{}
|
||||
rng.seed(seed)
|
||||
for range in ranges {
|
||||
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
|
||||
mut variance := 0.0
|
||||
for _ in 0 .. sample_size {
|
||||
@ -104,19 +105,19 @@ fn check_uniformity_f64(mut rng rand.PCG32RNG) {
|
||||
fn test_pcg32_uniformity_f64() {
|
||||
// The f64 version
|
||||
for seed in seeds {
|
||||
mut rng := rand.PCG32RNG{}
|
||||
mut rng := pcg32.PCG32RNG{}
|
||||
rng.seed(seed)
|
||||
check_uniformity_f64(mut rng)
|
||||
}
|
||||
}
|
||||
|
||||
fn test_pcg32_u32n() {
|
||||
max := 16384
|
||||
max := u32(16384)
|
||||
for seed in seeds {
|
||||
mut rng := rand.PCG32RNG{}
|
||||
mut rng := pcg32.PCG32RNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.u32n(u32(max))
|
||||
value := rng.u32n(max)
|
||||
assert value >= 0
|
||||
assert value < max
|
||||
}
|
||||
@ -126,7 +127,7 @@ fn test_pcg32_u32n() {
|
||||
fn test_pcg32_u64n() {
|
||||
max := u64(379091181005)
|
||||
for seed in seeds {
|
||||
mut rng := rand.PCG32RNG{}
|
||||
mut rng := pcg32.PCG32RNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.u64n(max)
|
||||
@ -137,10 +138,10 @@ fn test_pcg32_u64n() {
|
||||
}
|
||||
|
||||
fn test_pcg32_u32_in_range() {
|
||||
max := 484468466
|
||||
min := 316846
|
||||
max := u64(484468466)
|
||||
min := u64(316846)
|
||||
for seed in seeds {
|
||||
mut rng := rand.PCG32RNG{}
|
||||
mut rng := pcg32.PCG32RNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.u32_in_range(u64(min), u64(max))
|
||||
@ -154,7 +155,7 @@ fn test_pcg32_u64_in_range() {
|
||||
max := u64(216468454685163)
|
||||
min := u64(6848646868)
|
||||
for seed in seeds {
|
||||
mut rng := rand.PCG32RNG{}
|
||||
mut rng := pcg32.PCG32RNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.u64_in_range(min, max)
|
||||
@ -168,7 +169,7 @@ fn test_pcg32_int31() {
|
||||
max_u31 := 0x7FFFFFFF
|
||||
sign_mask := 0x80000000
|
||||
for seed in seeds {
|
||||
mut rng := rand.PCG32RNG{}
|
||||
mut rng := pcg32.PCG32RNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.int31()
|
||||
@ -184,7 +185,7 @@ fn test_pcg32_int63() {
|
||||
max_u63 := i64(0x7FFFFFFFFFFFFFFF)
|
||||
sign_mask := i64(0x8000000000000000)
|
||||
for seed in seeds {
|
||||
mut rng := rand.PCG32RNG{}
|
||||
mut rng := pcg32.PCG32RNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.int63()
|
||||
@ -198,7 +199,7 @@ fn test_pcg32_int63() {
|
||||
fn test_pcg32_intn() {
|
||||
max := 2525642
|
||||
for seed in seeds {
|
||||
mut rng := rand.PCG32RNG{}
|
||||
mut rng := pcg32.PCG32RNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.intn(max)
|
||||
@ -211,7 +212,7 @@ fn test_pcg32_intn() {
|
||||
fn test_pcg32_i64n() {
|
||||
max := i64(3246727724653636)
|
||||
for seed in seeds {
|
||||
mut rng := rand.PCG32RNG{}
|
||||
mut rng := pcg32.PCG32RNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.i64n(max)
|
||||
@ -225,7 +226,7 @@ fn test_pcg32_int_in_range() {
|
||||
min := -4252
|
||||
max := 1034
|
||||
for seed in seeds {
|
||||
mut rng := rand.PCG32RNG{}
|
||||
mut rng := pcg32.PCG32RNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.int_in_range(min, max)
|
||||
@ -239,7 +240,7 @@ fn test_pcg32_i64_in_range() {
|
||||
min := i64(-24095)
|
||||
max := i64(324058)
|
||||
for seed in seeds {
|
||||
mut rng := rand.PCG32RNG{}
|
||||
mut rng := pcg32.PCG32RNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.i64_in_range(min, max)
|
||||
@ -251,7 +252,7 @@ fn test_pcg32_i64_in_range() {
|
||||
|
||||
fn test_pcg32_f32() {
|
||||
for seed in seeds {
|
||||
mut rng := rand.PCG32RNG{}
|
||||
mut rng := pcg32.PCG32RNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.f32()
|
||||
@ -263,7 +264,7 @@ fn test_pcg32_f32() {
|
||||
|
||||
fn test_pcg32_f64() {
|
||||
for seed in seeds {
|
||||
mut rng := rand.PCG32RNG{}
|
||||
mut rng := pcg32.PCG32RNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.f64()
|
||||
@ -276,10 +277,10 @@ fn test_pcg32_f64() {
|
||||
fn test_pcg32_f32n() {
|
||||
max := f32(357.0)
|
||||
for seed in seeds {
|
||||
mut rng := rand.PCG32RNG{}
|
||||
mut rng := pcg32.PCG32RNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.f32()
|
||||
value := rng.f32n(max)
|
||||
assert value >= 0.0
|
||||
assert value < max
|
||||
}
|
||||
@ -289,10 +290,10 @@ fn test_pcg32_f32n() {
|
||||
fn test_pcg32_f64n() {
|
||||
max := 1.52e6
|
||||
for seed in seeds {
|
||||
mut rng := rand.PCG32RNG{}
|
||||
mut rng := pcg32.PCG32RNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.f64()
|
||||
value := rng.f64n(max)
|
||||
assert value >= 0.0
|
||||
assert value < max
|
||||
}
|
||||
@ -303,10 +304,10 @@ fn test_pcg32_f32_in_range() {
|
||||
min := f32(-24.0)
|
||||
max := f32(125.0)
|
||||
for seed in seeds {
|
||||
mut rng := rand.PCG32RNG{}
|
||||
mut rng := pcg32.PCG32RNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.f32()
|
||||
value := rng.f32_in_range(min, max)
|
||||
assert value >= min
|
||||
assert value < max
|
||||
}
|
||||
@ -317,10 +318,10 @@ fn test_pcg32_f64_in_range() {
|
||||
min := -548.7
|
||||
max := 5015.2
|
||||
for seed in seeds {
|
||||
mut rng := rand.PCG32RNG{}
|
||||
mut rng := pcg32.PCG32RNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.f64()
|
||||
value := rng.f64_in_range(min, max)
|
||||
assert value >= min
|
||||
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.
|
||||
module rand
|
||||
|
||||
// TODO: Remove these functions once done:
|
||||
// 1. C.rand()
|
||||
// 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
|
||||
}
|
||||
import rand.util
|
||||
import rand.wyrand
|
||||
|
||||
// Configuration struct for creating a new instance of the default RNG.
|
||||
pub struct PRNGConfigStruct {
|
||||
seed []u32 = time_seed_array(2)
|
||||
seed []u32 = util.time_seed_array(2)
|
||||
}
|
||||
|
||||
pub fn new_default(config PRNGConfigStruct) &WyRandRNG {
|
||||
rng := &WyRandRNG{}
|
||||
__global default_rng &wyrand.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)
|
||||
return rng
|
||||
}
|
||||
|
||||
// rand_f32 return a random f32 between 0 and max
|
||||
[deprecated]
|
||||
pub fn rand_f32(max f32) f32 {
|
||||
return rand_uniform_f32() * max
|
||||
// seed sets the given array of `u32` values as the seed for the `default_rng`.
|
||||
pub fn seed(seed []u32) {
|
||||
default_rng.seed(seed)
|
||||
}
|
||||
|
||||
// rand_f32 return a random f32 in range min and max
|
||||
[deprecated]
|
||||
pub fn rand_f32_in_range(min, max f32) f32 {
|
||||
return min + rand_uniform_f32() * (max - min)
|
||||
// u32() returns a uniformly distributed u32 in _[0, 2<sup>32</sup>)_
|
||||
pub fn u32() u32 {
|
||||
return default_rng.u32()
|
||||
}
|
||||
|
||||
// rand_f64 return a random f64 between 0 (inclusive) and max (exclusive)
|
||||
[deprecated]
|
||||
pub fn rand_f64(max f64) f64 {
|
||||
return rand_uniform_f64() * max
|
||||
// u64() returns a uniformly distributed u64 in _[0, 2<sup>64</sup>)_
|
||||
pub fn u64() u64 {
|
||||
return default_rng.u64()
|
||||
}
|
||||
|
||||
// rand_f64 return a random f64 in range min (inclusive) and max (exclusive)
|
||||
[deprecated]
|
||||
pub fn rand_f64_in_range(min, max f64) f64 {
|
||||
return min + rand_uniform_f64() * (max - min)
|
||||
// u32n(max) returns a uniformly distributed pseudorandom 32-bit signed positive u32 in _[0, max)_
|
||||
pub fn u32n(max u32) u32 {
|
||||
return default_rng.u32n(max)
|
||||
}
|
||||
|
||||
// rand_uniform_f32 returns a uniformly distributed f32 in the range 0 (inclusive) and 1 (exclusive)
|
||||
[deprecated]
|
||||
pub fn rand_uniform_f32() f32 {
|
||||
return f32(C.rand()) / f32(C.RAND_MAX)
|
||||
// u64n(max) returns a uniformly distributed pseudorandom 64-bit signed positive u64 in _[0, max)_
|
||||
pub fn u64n(max u64) u64 {
|
||||
return default_rng.u64n(max)
|
||||
}
|
||||
|
||||
// rand_uniform_f64 returns a uniformly distributed f64 in the range 0 (inclusive) and 1 (exclusive)
|
||||
[deprecated]
|
||||
pub fn rand_uniform_f64() f64 {
|
||||
return f64(C.rand()) / f64(C.RAND_MAX)
|
||||
// u32_in_range(min, max) returns a uniformly distributed pseudorandom 32-bit unsigned u32 in _[min, max)_
|
||||
pub fn u32_in_range(min, max u32) u32 {
|
||||
return default_rng.u32_in_range(min, max)
|
||||
}
|
||||
|
||||
// u64_in_range(min, max) returns a uniformly distributed pseudorandom 64-bit unsigned u64 in _[min, max)_
|
||||
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 math
|
||||
|
||||
const (
|
||||
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() {
|
||||
for seed in seeds {
|
||||
mut randoms1 := gen_randoms(seed)
|
||||
mut randoms2 := gen_randoms(seed)
|
||||
assert_randoms_equal(randoms1, randoms2)
|
||||
array1 := get_n_random_ints(seed, 1000)
|
||||
array2 := get_n_random_ints(seed, 1000)
|
||||
assert array1.len == array2.len
|
||||
assert array1 == array2
|
||||
}
|
||||
}
|
||||
|
||||
fn test_rand_r_reproducibility() {
|
||||
for seed in seeds {
|
||||
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
|
||||
fn test_rand_u32n() {
|
||||
max := u32(16384)
|
||||
for _ in 0 .. rnd_count {
|
||||
prev_seed := seed
|
||||
_ = rand.rand_r(&seed)
|
||||
assert prev_seed != seed
|
||||
value := rand.u32n(max)
|
||||
assert value >= 0
|
||||
assert value < max
|
||||
}
|
||||
}
|
||||
|
||||
fn gen_randoms(seed int) []int {
|
||||
mut randoms := [0].repeat(rnd_count)
|
||||
rand.seed(seed)
|
||||
for i in 0 .. rnd_count {
|
||||
randoms[i] = rand.next(100)
|
||||
}
|
||||
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_u64n() {
|
||||
max := u64(379091181005)
|
||||
for _ in 0 .. rnd_count {
|
||||
value := rand.u64n(max)
|
||||
assert value >= 0
|
||||
assert value < max
|
||||
}
|
||||
}
|
||||
|
||||
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.
|
||||
// Use of this source code is governed by an MIT license
|
||||
// that can be found in the LICENSE file.
|
||||
module rand
|
||||
module splitmix64
|
||||
|
||||
import rand.util
|
||||
|
||||
// Ported from http://xoshiro.di.unimi.it/splitmix64.c
|
||||
pub struct SplitMix64RNG {
|
||||
mut:
|
||||
state u64 = time_seed_64()
|
||||
state u64 = util.time_seed_64()
|
||||
has_extra bool = false
|
||||
extra u32
|
||||
}
|
||||
@ -30,7 +32,7 @@ pub fn (mut rng SplitMix64RNG) u32() u32 {
|
||||
return rng.extra
|
||||
}
|
||||
full_value := rng.u64()
|
||||
lower := u32(full_value & lower_mask)
|
||||
lower := u32(full_value & util.lower_mask)
|
||||
upper := u32(full_value >> 32)
|
||||
rng.extra = upper
|
||||
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
|
||||
[inline]
|
||||
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
|
||||
[inline]
|
||||
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)
|
||||
@ -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)
|
||||
[inline]
|
||||
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)
|
||||
[inline]
|
||||
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)
|
@ -1,5 +1,6 @@
|
||||
import rand
|
||||
import math
|
||||
import splitmix64
|
||||
import rand.util
|
||||
|
||||
const (
|
||||
range_limit = 40
|
||||
@ -16,7 +17,7 @@ const (
|
||||
fn gen_randoms(seed_data []u32, bound int) []u64 {
|
||||
bound_u64 := u64(bound)
|
||||
mut randoms := [u64(0)].repeat(20)
|
||||
mut rnd := rand.SplitMix64RNG{}
|
||||
mut rnd := splitmix64.SplitMix64RNG{}
|
||||
rnd.seed(seed_data)
|
||||
for i in 0 .. 20 {
|
||||
randoms[i] = rnd.u64n(bound_u64)
|
||||
@ -25,7 +26,7 @@ fn gen_randoms(seed_data []u32, bound int) []u64 {
|
||||
}
|
||||
|
||||
fn test_splitmix64_reproducibility() {
|
||||
seed_data := rand.time_seed_array(2)
|
||||
seed_data := util.time_seed_array(2)
|
||||
randoms1 := gen_randoms(seed_data, 1000)
|
||||
randoms2 := gen_randoms(seed_data, 1000)
|
||||
assert randoms1.len == randoms2.len
|
||||
@ -51,7 +52,7 @@ fn test_splitmix64_variability() {
|
||||
// at fault, try changing the seed values. Repeated values are
|
||||
// improbable but not impossible.
|
||||
for seed in seeds {
|
||||
mut rng := rand.SplitMix64RNG{}
|
||||
mut rng := splitmix64.SplitMix64RNG{}
|
||||
rng.seed(seed)
|
||||
mut values := []u64{cap: 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)
|
||||
expected_mean := range_f64 / 2.0
|
||||
mut variance := 0.0
|
||||
@ -81,7 +82,7 @@ fn check_uniformity_u64(mut rng rand.SplitMix64RNG, range u64) {
|
||||
fn test_splitmix64_uniformity_u64() {
|
||||
ranges := [14019545, 80240, 130]
|
||||
for seed in seeds {
|
||||
mut rng := rand.SplitMix64RNG{}
|
||||
mut rng := splitmix64.SplitMix64RNG{}
|
||||
rng.seed(seed)
|
||||
for range in ranges {
|
||||
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
|
||||
mut variance := 0.0
|
||||
for _ in 0 .. sample_size {
|
||||
@ -106,19 +107,19 @@ fn check_uniformity_f64(mut rng rand.SplitMix64RNG) {
|
||||
fn test_splitmix64_uniformity_f64() {
|
||||
// The f64 version
|
||||
for seed in seeds {
|
||||
mut rng := rand.SplitMix64RNG{}
|
||||
mut rng := splitmix64.SplitMix64RNG{}
|
||||
rng.seed(seed)
|
||||
check_uniformity_f64(mut rng)
|
||||
}
|
||||
}
|
||||
|
||||
fn test_splitmix64_u32n() {
|
||||
max := 16384
|
||||
max := u32(16384)
|
||||
for seed in seeds {
|
||||
mut rng := rand.SplitMix64RNG{}
|
||||
mut rng := splitmix64.SplitMix64RNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.u32n(u32(max))
|
||||
value := rng.u32n(max)
|
||||
assert value >= 0
|
||||
assert value < max
|
||||
}
|
||||
@ -128,7 +129,7 @@ fn test_splitmix64_u32n() {
|
||||
fn test_splitmix64_u64n() {
|
||||
max := u64(379091181005)
|
||||
for seed in seeds {
|
||||
mut rng := rand.SplitMix64RNG{}
|
||||
mut rng := splitmix64.SplitMix64RNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.u64n(max)
|
||||
@ -139,13 +140,13 @@ fn test_splitmix64_u64n() {
|
||||
}
|
||||
|
||||
fn test_splitmix64_u32_in_range() {
|
||||
max := 484468466
|
||||
min := 316846
|
||||
max := u32(484468466)
|
||||
min := u32(316846)
|
||||
for seed in seeds {
|
||||
mut rng := rand.SplitMix64RNG{}
|
||||
mut rng := splitmix64.SplitMix64RNG{}
|
||||
rng.seed(seed)
|
||||
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 < max
|
||||
}
|
||||
@ -156,7 +157,7 @@ fn test_splitmix64_u64_in_range() {
|
||||
max := u64(216468454685163)
|
||||
min := u64(6848646868)
|
||||
for seed in seeds {
|
||||
mut rng := rand.SplitMix64RNG{}
|
||||
mut rng := splitmix64.SplitMix64RNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.u64_in_range(min, max)
|
||||
@ -170,7 +171,7 @@ fn test_splitmix64_int31() {
|
||||
max_u31 := 0x7FFFFFFF
|
||||
sign_mask := 0x80000000
|
||||
for seed in seeds {
|
||||
mut rng := rand.SplitMix64RNG{}
|
||||
mut rng := splitmix64.SplitMix64RNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.int31()
|
||||
@ -186,7 +187,7 @@ fn test_splitmix64_int63() {
|
||||
max_u63 := i64(0x7FFFFFFFFFFFFFFF)
|
||||
sign_mask := i64(0x8000000000000000)
|
||||
for seed in seeds {
|
||||
mut rng := rand.SplitMix64RNG{}
|
||||
mut rng := splitmix64.SplitMix64RNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.int63()
|
||||
@ -197,10 +198,10 @@ fn test_splitmix64_int63() {
|
||||
}
|
||||
}
|
||||
|
||||
fn test_splimix64_intn() {
|
||||
fn test_splitmix64_intn() {
|
||||
max := 2525642
|
||||
for seed in seeds {
|
||||
mut rng := rand.SplitMix64RNG{}
|
||||
mut rng := splitmix64.SplitMix64RNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.intn(max)
|
||||
@ -210,10 +211,10 @@ fn test_splimix64_intn() {
|
||||
}
|
||||
}
|
||||
|
||||
fn test_splimix64_i64n() {
|
||||
fn test_splitmix64_i64n() {
|
||||
max := i64(3246727724653636)
|
||||
for seed in seeds {
|
||||
mut rng := rand.SplitMix64RNG{}
|
||||
mut rng := splitmix64.SplitMix64RNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
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
|
||||
max := 230549862
|
||||
for seed in seeds {
|
||||
mut rng := rand.SplitMix64RNG{}
|
||||
mut rng := splitmix64.SplitMix64RNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
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)
|
||||
max := i64(324058)
|
||||
for seed in seeds {
|
||||
mut rng := rand.SplitMix64RNG{}
|
||||
mut rng := splitmix64.SplitMix64RNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.i64_in_range(min, max)
|
||||
@ -253,7 +254,7 @@ fn test_splimix64_i64_in_range() {
|
||||
|
||||
fn test_splitmix64_f32() {
|
||||
for seed in seeds {
|
||||
mut rng := rand.SplitMix64RNG{}
|
||||
mut rng := splitmix64.SplitMix64RNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.f32()
|
||||
@ -265,7 +266,7 @@ fn test_splitmix64_f32() {
|
||||
|
||||
fn test_splitmix64_f64() {
|
||||
for seed in seeds {
|
||||
mut rng := rand.SplitMix64RNG{}
|
||||
mut rng := splitmix64.SplitMix64RNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.f64()
|
||||
@ -278,10 +279,10 @@ fn test_splitmix64_f64() {
|
||||
fn test_splitmix64_f32n() {
|
||||
max := f32(357.0)
|
||||
for seed in seeds {
|
||||
mut rng := rand.SplitMix64RNG{}
|
||||
mut rng := splitmix64.SplitMix64RNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.f32()
|
||||
value := rng.f32n(max)
|
||||
assert value >= 0.0
|
||||
assert value < max
|
||||
}
|
||||
@ -291,10 +292,10 @@ fn test_splitmix64_f32n() {
|
||||
fn test_splitmix64_f64n() {
|
||||
max := 1.52e6
|
||||
for seed in seeds {
|
||||
mut rng := rand.SplitMix64RNG{}
|
||||
mut rng := splitmix64.SplitMix64RNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.f64()
|
||||
value := rng.f64n(max)
|
||||
assert value >= 0.0
|
||||
assert value < max
|
||||
}
|
||||
@ -305,10 +306,10 @@ fn test_splitmix64_f32_in_range() {
|
||||
min := f32(-24.0)
|
||||
max := f32(125.0)
|
||||
for seed in seeds {
|
||||
mut rng := rand.SplitMix64RNG{}
|
||||
mut rng := splitmix64.SplitMix64RNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.f32()
|
||||
value := rng.f32_in_range(min, max)
|
||||
assert value >= min
|
||||
assert value < max
|
||||
}
|
||||
@ -319,10 +320,10 @@ fn test_splitmix64_f64_in_range() {
|
||||
min := -548.7
|
||||
max := 5015.2
|
||||
for seed in seeds {
|
||||
mut rng := rand.SplitMix64RNG{}
|
||||
mut rng := splitmix64.SplitMix64RNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.f64()
|
||||
value := rng.f64_in_range(min, max)
|
||||
assert value >= min
|
||||
assert value < max
|
||||
}
|
@ -1,9 +1,10 @@
|
||||
// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved.
|
||||
// Use of this source code is governed by an MIT license
|
||||
// that can be found in the LICENSE file.
|
||||
module rand
|
||||
module sys
|
||||
|
||||
import math.bits
|
||||
import rand.util
|
||||
|
||||
// Implementation note:
|
||||
// ====================
|
||||
@ -27,20 +28,6 @@ fn calculate_iterations_for(bits int) int {
|
||||
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)
|
||||
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.
|
||||
pub struct SysRNG {
|
||||
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.
|
||||
@ -188,13 +175,13 @@ pub fn (r SysRNG) i64() i64 {
|
||||
// r.int31() returns a pseudorandom 31-bit int which is non-negative
|
||||
[inline]
|
||||
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
|
||||
[inline]
|
||||
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)
|
||||
@ -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)
|
||||
[inline]
|
||||
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)
|
||||
[inline]
|
||||
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)
|
@ -1,7 +1,7 @@
|
||||
// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved.
|
||||
// Use of this source code is governed by an MIT license
|
||||
// that can be found in the LICENSE file.
|
||||
module rand
|
||||
module sys
|
||||
|
||||
// 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
|
@ -1,5 +1,5 @@
|
||||
import rand
|
||||
import math
|
||||
import sys
|
||||
|
||||
const (
|
||||
range_limit = 40
|
||||
@ -13,7 +13,7 @@ const (
|
||||
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}
|
||||
for _ in 0 .. n {
|
||||
ints << r.int()
|
||||
@ -28,8 +28,8 @@ fn test_sys_rng_reproducibility() {
|
||||
// seed for another batch of data.
|
||||
for seed in seeds {
|
||||
seed_data := [seed]
|
||||
mut r1 := rand.SysRNG{}
|
||||
mut r2 := rand.SysRNG{}
|
||||
mut r1 := sys.SysRNG{}
|
||||
mut r2 := sys.SysRNG{}
|
||||
r1.seed(seed_data)
|
||||
ints1 := get_n_randoms(value_count, r1)
|
||||
r2.seed(seed_data)
|
||||
@ -55,7 +55,7 @@ fn test_sys_rng_variability() {
|
||||
// improbable but not impossible.
|
||||
for seed in seeds {
|
||||
seed_data := [seed]
|
||||
mut rng := rand.SysRNG{}
|
||||
mut rng := sys.SysRNG{}
|
||||
rng.seed(seed_data)
|
||||
mut values := []u64{cap: 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)
|
||||
expected_mean := range_f64 / 2.0
|
||||
mut variance := 0.0
|
||||
@ -88,7 +88,7 @@ fn test_sys_rng_uniformity_u64() {
|
||||
ranges := [14019545, 80240, 130]
|
||||
for seed in seeds {
|
||||
seed_data := [seed]
|
||||
mut rng := rand.SysRNG{}
|
||||
mut rng := sys.SysRNG{}
|
||||
rng.seed(seed_data)
|
||||
for range in ranges {
|
||||
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
|
||||
mut variance := 0.0
|
||||
for _ in 0 .. sample_size {
|
||||
@ -114,20 +114,20 @@ fn test_sys_rng_uniformity_f64() {
|
||||
// The f64 version
|
||||
for seed in seeds {
|
||||
seed_data := [seed]
|
||||
mut rng := rand.SysRNG{}
|
||||
mut rng := sys.SysRNG{}
|
||||
rng.seed(seed_data)
|
||||
check_uniformity_f64(rng)
|
||||
}
|
||||
}
|
||||
|
||||
fn test_sys_rng_u32n() {
|
||||
max := 16384
|
||||
max := u32(16384)
|
||||
for seed in seeds {
|
||||
seed_data := [seed]
|
||||
mut rng := rand.SysRNG{}
|
||||
mut rng := sys.SysRNG{}
|
||||
rng.seed(seed_data)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.u32n(u32(max))
|
||||
value := rng.u32n(max)
|
||||
assert value >= 0
|
||||
assert value < max
|
||||
}
|
||||
@ -138,7 +138,7 @@ fn test_sys_rng_u64n() {
|
||||
max := u64(379091181005)
|
||||
for seed in seeds {
|
||||
seed_data := [seed]
|
||||
mut rng := rand.SysRNG{}
|
||||
mut rng := sys.SysRNG{}
|
||||
rng.seed(seed_data)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.u64n(max)
|
||||
@ -149,14 +149,14 @@ fn test_sys_rng_u64n() {
|
||||
}
|
||||
|
||||
fn test_sys_rng_u32_in_range() {
|
||||
max := 484468466
|
||||
min := 316846
|
||||
max := u32(484468466)
|
||||
min := u32(316846)
|
||||
for seed in seeds {
|
||||
seed_data := [seed]
|
||||
mut rng := rand.SysRNG{}
|
||||
mut rng := sys.SysRNG{}
|
||||
rng.seed(seed_data)
|
||||
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 < max
|
||||
}
|
||||
@ -168,7 +168,7 @@ fn test_sys_rng_u64_in_range() {
|
||||
min := u64(6848646868)
|
||||
for seed in seeds {
|
||||
seed_data := [seed]
|
||||
mut rng := rand.SysRNG{}
|
||||
mut rng := sys.SysRNG{}
|
||||
rng.seed(seed_data)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.u64_in_range(min, max)
|
||||
@ -182,7 +182,7 @@ fn test_sys_rng_intn() {
|
||||
max := 2525642
|
||||
for seed in seeds {
|
||||
seed_data := [seed]
|
||||
mut rng := rand.SysRNG{}
|
||||
mut rng := sys.SysRNG{}
|
||||
rng.seed(seed_data)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.intn(max)
|
||||
@ -196,7 +196,7 @@ fn test_sys_rng_i64n() {
|
||||
max := i64(3246727724653636)
|
||||
for seed in seeds {
|
||||
seed_data := [seed]
|
||||
mut rng := rand.SysRNG{}
|
||||
mut rng := sys.SysRNG{}
|
||||
rng.seed(seed_data)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.i64n(max)
|
||||
@ -211,7 +211,7 @@ fn test_sys_rng_int_in_range() {
|
||||
max := 23054962
|
||||
for seed in seeds {
|
||||
seed_data := [seed]
|
||||
mut rng := rand.SysRNG{}
|
||||
mut rng := sys.SysRNG{}
|
||||
rng.seed(seed_data)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.int_in_range(min, max)
|
||||
@ -226,7 +226,7 @@ fn test_sys_rng_i64_in_range() {
|
||||
max := i64(324058)
|
||||
for seed in seeds {
|
||||
seed_data := [seed]
|
||||
mut rng := rand.SysRNG{}
|
||||
mut rng := sys.SysRNG{}
|
||||
rng.seed(seed_data)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.i64_in_range(min, max)
|
||||
@ -241,7 +241,7 @@ fn test_sys_rng_int31() {
|
||||
sign_mask := 0x80000000
|
||||
for seed in seeds {
|
||||
seed_data := [seed]
|
||||
mut rng := rand.SysRNG{}
|
||||
mut rng := sys.SysRNG{}
|
||||
rng.seed(seed_data)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.int31()
|
||||
@ -258,7 +258,7 @@ fn test_sys_rng_int63() {
|
||||
sign_mask := i64(0x8000000000000000)
|
||||
for seed in seeds {
|
||||
seed_data := [seed]
|
||||
mut rng := rand.SysRNG{}
|
||||
mut rng := sys.SysRNG{}
|
||||
rng.seed(seed_data)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.int63()
|
||||
@ -272,7 +272,7 @@ fn test_sys_rng_int63() {
|
||||
fn test_sys_rng_f32() {
|
||||
for seed in seeds {
|
||||
seed_data := [seed]
|
||||
mut rng := rand.SysRNG{}
|
||||
mut rng := sys.SysRNG{}
|
||||
rng.seed(seed_data)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.f32()
|
||||
@ -285,7 +285,7 @@ fn test_sys_rng_f32() {
|
||||
fn test_sys_rng_f64() {
|
||||
for seed in seeds {
|
||||
seed_data := [seed]
|
||||
mut rng := rand.SysRNG{}
|
||||
mut rng := sys.SysRNG{}
|
||||
rng.seed(seed_data)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.f64()
|
||||
@ -299,10 +299,10 @@ fn test_sys_rng_f32n() {
|
||||
max := f32(357.0)
|
||||
for seed in seeds {
|
||||
seed_data := [seed]
|
||||
mut rng := rand.SysRNG{}
|
||||
mut rng := sys.SysRNG{}
|
||||
rng.seed(seed_data)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.f32()
|
||||
value := rng.f32n(max)
|
||||
assert value >= 0.0
|
||||
assert value < max
|
||||
}
|
||||
@ -313,10 +313,10 @@ fn test_sys_rng_f64n() {
|
||||
max := 1.52e6
|
||||
for seed in seeds {
|
||||
seed_data := [seed]
|
||||
mut rng := rand.SysRNG{}
|
||||
mut rng := sys.SysRNG{}
|
||||
rng.seed(seed_data)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.f64()
|
||||
value := rng.f64n(max)
|
||||
assert value >= 0.0
|
||||
assert value < max
|
||||
}
|
||||
@ -328,10 +328,10 @@ fn test_sys_rng_f32_in_range() {
|
||||
max := f32(125.0)
|
||||
for seed in seeds {
|
||||
seed_data := [seed]
|
||||
mut rng := rand.SysRNG{}
|
||||
mut rng := sys.SysRNG{}
|
||||
rng.seed(seed_data)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.f32()
|
||||
value := rng.f32_in_range(min, max)
|
||||
assert value >= min
|
||||
assert value < max
|
||||
}
|
||||
@ -343,10 +343,10 @@ fn test_sys_rng_f64_in_range() {
|
||||
max := 5015.2
|
||||
for seed in seeds {
|
||||
seed_data := [seed]
|
||||
mut rng := rand.SysRNG{}
|
||||
mut rng := sys.SysRNG{}
|
||||
rng.seed(seed_data)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.f64()
|
||||
value := rng.f64_in_range(min, max)
|
||||
assert value >= min
|
||||
assert value < max
|
||||
}
|
@ -1,13 +1,19 @@
|
||||
// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved.
|
||||
// Use of this source code is governed by an MIT license
|
||||
// that can be found in the LICENSE file.
|
||||
module rand
|
||||
module util
|
||||
|
||||
import time
|
||||
|
||||
// Commonly used constants across RNGs
|
||||
const (
|
||||
lower_mask = u64(0x00000000ffffffff)
|
||||
pub const (
|
||||
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
|
||||
@ -16,7 +22,7 @@ fn nr_next(prev u32) u32 {
|
||||
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]
|
||||
pub fn time_seed_array(count int) []u32 {
|
||||
mut seed := u32(time.now().unix_time())
|
||||
@ -28,13 +34,15 @@ pub fn time_seed_array(count int) []u32 {
|
||||
return seed_data
|
||||
}
|
||||
|
||||
// time_seed_32 returns a 32-bit seed geenrated from system time
|
||||
[inline]
|
||||
fn time_seed_32() u32 {
|
||||
pub fn time_seed_32() u32 {
|
||||
return time_seed_array(1)[0]
|
||||
}
|
||||
|
||||
// time_seed_64 returns a 64-bit seed geenrated from system time
|
||||
[inline]
|
||||
fn time_seed_64() u64 {
|
||||
pub fn time_seed_64() u64 {
|
||||
seed_data := time_seed_array(2)
|
||||
lower := u64(seed_data[0])
|
||||
upper := u64(seed_data[1])
|
@ -1,9 +1,10 @@
|
||||
// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved.
|
||||
// Use of this source code is governed by an MIT license
|
||||
// that can be found in the LICENSE file.
|
||||
module rand
|
||||
module wyrand
|
||||
|
||||
import math.bits
|
||||
import rand.util
|
||||
import hash.wyhash
|
||||
|
||||
// Redefinition of some constants that we will need for pseudorandom number generation
|
||||
@ -15,7 +16,7 @@ const (
|
||||
// RNG based on the WyHash hashing algorithm
|
||||
pub struct WyRandRNG {
|
||||
mut:
|
||||
state u64 = time_seed_64()
|
||||
state u64 = util.time_seed_64()
|
||||
has_extra bool = false
|
||||
extra u32
|
||||
}
|
||||
@ -30,7 +31,6 @@ pub fn (mut rng WyRandRNG) seed(seed_data []u32) {
|
||||
rng.has_extra = false
|
||||
}
|
||||
|
||||
|
||||
// rng.u32() updates the PRNG state and returns the next pseudorandom u32
|
||||
[inline]
|
||||
pub fn (mut rng WyRandRNG) u32() u32 {
|
||||
@ -39,7 +39,7 @@ pub fn (mut rng WyRandRNG) u32() u32 {
|
||||
return rng.extra
|
||||
}
|
||||
full_value := rng.u64()
|
||||
lower := u32(full_value & lower_mask)
|
||||
lower := u32(full_value & util.lower_mask)
|
||||
upper := u32(full_value >> 32)
|
||||
rng.extra = upper
|
||||
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
|
||||
[inline]
|
||||
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
|
||||
[inline]
|
||||
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)
|
||||
@ -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)
|
||||
[inline]
|
||||
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)
|
||||
[inline]
|
||||
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)
|
@ -1,5 +1,6 @@
|
||||
import rand
|
||||
import math
|
||||
import rand.util
|
||||
import wyrand
|
||||
|
||||
const (
|
||||
range_limit = 40
|
||||
@ -16,7 +17,7 @@ const (
|
||||
fn gen_randoms(seed_data []u32, bound int) []u64 {
|
||||
bound_u64 := u64(bound)
|
||||
mut randoms := [u64(0)].repeat(20)
|
||||
mut rnd := rand.WyRandRNG{}
|
||||
mut rnd := wyrand.WyRandRNG{}
|
||||
rnd.seed(seed_data)
|
||||
for i in 0 .. 20 {
|
||||
randoms[i] = rnd.u64n(bound_u64)
|
||||
@ -25,7 +26,7 @@ fn gen_randoms(seed_data []u32, bound int) []u64 {
|
||||
}
|
||||
|
||||
fn test_wyrand_reproducibility() {
|
||||
seed_data := rand.time_seed_array(2)
|
||||
seed_data := util.time_seed_array(2)
|
||||
randoms1 := gen_randoms(seed_data, 1000)
|
||||
randoms2 := gen_randoms(seed_data, 1000)
|
||||
assert randoms1.len == randoms2.len
|
||||
@ -51,7 +52,7 @@ fn test_wyrand_variability() {
|
||||
// at fault, try changing the seed values. Repeated values are
|
||||
// improbable but not impossible.
|
||||
for seed in seeds {
|
||||
mut rng := rand.WyRandRNG{}
|
||||
mut rng := wyrand.WyRandRNG{}
|
||||
rng.seed(seed)
|
||||
mut values := []u64{cap: 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)
|
||||
expected_mean := range_f64 / 2.0
|
||||
mut variance := 0.0
|
||||
@ -81,7 +82,7 @@ fn check_uniformity_u64(mut rng rand.WyRandRNG, range u64) {
|
||||
fn test_wyrand_uniformity_u64() {
|
||||
ranges := [14019545, 80240, 130]
|
||||
for seed in seeds {
|
||||
mut rng := rand.WyRandRNG{}
|
||||
mut rng := wyrand.WyRandRNG{}
|
||||
rng.seed(seed)
|
||||
for range in ranges {
|
||||
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
|
||||
mut variance := 0.0
|
||||
for _ in 0 .. sample_size {
|
||||
@ -106,19 +107,19 @@ fn check_uniformity_f64(mut rng rand.WyRandRNG) {
|
||||
fn test_wyrand_uniformity_f64() {
|
||||
// The f64 version
|
||||
for seed in seeds {
|
||||
mut rng := rand.WyRandRNG{}
|
||||
mut rng := wyrand.WyRandRNG{}
|
||||
rng.seed(seed)
|
||||
check_uniformity_f64(mut rng)
|
||||
}
|
||||
}
|
||||
|
||||
fn test_wyrand_u32n() {
|
||||
max := 16384
|
||||
max := u32(16384)
|
||||
for seed in seeds {
|
||||
mut rng := rand.WyRandRNG{}
|
||||
mut rng := wyrand.WyRandRNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.u32n(u32(max))
|
||||
value := rng.u32n(max)
|
||||
assert value >= 0
|
||||
assert value < max
|
||||
}
|
||||
@ -128,7 +129,7 @@ fn test_wyrand_u32n() {
|
||||
fn test_wyrand_u64n() {
|
||||
max := u64(379091181005)
|
||||
for seed in seeds {
|
||||
mut rng := rand.WyRandRNG{}
|
||||
mut rng := wyrand.WyRandRNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.u64n(max)
|
||||
@ -139,13 +140,13 @@ fn test_wyrand_u64n() {
|
||||
}
|
||||
|
||||
fn test_wyrand_u32_in_range() {
|
||||
max := 484468466
|
||||
min := 316846
|
||||
max := u32(484468466)
|
||||
min := u32(316846)
|
||||
for seed in seeds {
|
||||
mut rng := rand.WyRandRNG{}
|
||||
mut rng := wyrand.WyRandRNG{}
|
||||
rng.seed(seed)
|
||||
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 < max
|
||||
}
|
||||
@ -156,7 +157,7 @@ fn test_wyrand_u64_in_range() {
|
||||
max := u64(216468454685163)
|
||||
min := u64(6848646868)
|
||||
for seed in seeds {
|
||||
mut rng := rand.WyRandRNG{}
|
||||
mut rng := wyrand.WyRandRNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.u64_in_range(min, max)
|
||||
@ -170,7 +171,7 @@ fn test_wyrand_int31() {
|
||||
max_u31 := 0x7FFFFFFF
|
||||
sign_mask := 0x80000000
|
||||
for seed in seeds {
|
||||
mut rng := rand.WyRandRNG{}
|
||||
mut rng := wyrand.WyRandRNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.int31()
|
||||
@ -186,7 +187,7 @@ fn test_wyrand_int63() {
|
||||
max_u63 := i64(0x7FFFFFFFFFFFFFFF)
|
||||
sign_mask := i64(0x8000000000000000)
|
||||
for seed in seeds {
|
||||
mut rng := rand.WyRandRNG{}
|
||||
mut rng := wyrand.WyRandRNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.int63()
|
||||
@ -200,7 +201,7 @@ fn test_wyrand_int63() {
|
||||
fn test_wyrand_intn() {
|
||||
max := 2525642
|
||||
for seed in seeds {
|
||||
mut rng := rand.WyRandRNG{}
|
||||
mut rng := wyrand.WyRandRNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.intn(max)
|
||||
@ -213,7 +214,7 @@ fn test_wyrand_intn() {
|
||||
fn test_wyrand_i64n() {
|
||||
max := i64(3246727724653636)
|
||||
for seed in seeds {
|
||||
mut rng := rand.WyRandRNG{}
|
||||
mut rng := wyrand.WyRandRNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.i64n(max)
|
||||
@ -227,7 +228,7 @@ fn test_wyrand_int_in_range() {
|
||||
min := -4252
|
||||
max := 1034
|
||||
for seed in seeds {
|
||||
mut rng := rand.WyRandRNG{}
|
||||
mut rng := wyrand.WyRandRNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.int_in_range(min, max)
|
||||
@ -241,7 +242,7 @@ fn test_wyrand_i64_in_range() {
|
||||
min := i64(-24095)
|
||||
max := i64(324058)
|
||||
for seed in seeds {
|
||||
mut rng := rand.WyRandRNG{}
|
||||
mut rng := wyrand.WyRandRNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.i64_in_range(min, max)
|
||||
@ -253,7 +254,7 @@ fn test_wyrand_i64_in_range() {
|
||||
|
||||
fn test_wyrand_f32() {
|
||||
for seed in seeds {
|
||||
mut rng := rand.WyRandRNG{}
|
||||
mut rng := wyrand.WyRandRNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.f32()
|
||||
@ -265,7 +266,7 @@ fn test_wyrand_f32() {
|
||||
|
||||
fn test_wyrand_f64() {
|
||||
for seed in seeds {
|
||||
mut rng := rand.WyRandRNG{}
|
||||
mut rng := wyrand.WyRandRNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.f64()
|
||||
@ -278,10 +279,10 @@ fn test_wyrand_f64() {
|
||||
fn test_wyrand_f32n() {
|
||||
max := f32(357.0)
|
||||
for seed in seeds {
|
||||
mut rng := rand.WyRandRNG{}
|
||||
mut rng := wyrand.WyRandRNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.f32()
|
||||
value := rng.f32n(max)
|
||||
assert value >= 0.0
|
||||
assert value < max
|
||||
}
|
||||
@ -291,10 +292,10 @@ fn test_wyrand_f32n() {
|
||||
fn test_wyrand_f64n() {
|
||||
max := 1.52e6
|
||||
for seed in seeds {
|
||||
mut rng := rand.WyRandRNG{}
|
||||
mut rng := wyrand.WyRandRNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.f64()
|
||||
value := rng.f64n(max)
|
||||
assert value >= 0.0
|
||||
assert value < max
|
||||
}
|
||||
@ -305,10 +306,10 @@ fn test_wyrand_f32_in_range() {
|
||||
min := f32(-24.0)
|
||||
max := f32(125.0)
|
||||
for seed in seeds {
|
||||
mut rng := rand.WyRandRNG{}
|
||||
mut rng := wyrand.WyRandRNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.f32()
|
||||
value := rng.f32_in_range(min, max)
|
||||
assert value >= min
|
||||
assert value < max
|
||||
}
|
||||
@ -319,10 +320,10 @@ fn test_wyrand_f64_in_range() {
|
||||
min := -548.7
|
||||
max := 5015.2
|
||||
for seed in seeds {
|
||||
mut rng := rand.WyRandRNG{}
|
||||
mut rng := wyrand.WyRandRNG{}
|
||||
rng.seed(seed)
|
||||
for _ in 0 .. range_limit {
|
||||
value := rng.f64()
|
||||
value := rng.f64_in_range(min, max)
|
||||
assert value >= min
|
||||
assert value < max
|
||||
}
|
@ -8,5 +8,5 @@ const (
|
||||
)
|
||||
// random returns a random time struct in *the past*.
|
||||
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() {
|
||||
// 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()
|
||||
t2 := tmisc.random()
|
||||
t3 := tmisc.random()
|
||||
|
Loading…
Reference in New Issue
Block a user