From 114a341f5f97855beb888be4b56f43bd9134fcd8 Mon Sep 17 00:00:00 2001 From: Subhomoy Haldar Date: Wed, 23 Feb 2022 16:06:14 +0530 Subject: [PATCH] rand: simplify rand.PRNG, move to optional types for error handling (#13570) --- cmd/tools/bench/wyhash.v | 4 +- cmd/tools/fuzz/map_fuzz.v | 24 +- examples/2048/2048.v | 7 +- examples/fireworks/fireworks.v | 2 +- examples/fireworks/modules/objects/color.v | 6 +- examples/fireworks/modules/objects/rocket.v | 6 +- examples/fireworks/modules/objects/vector.v | 2 +- examples/gg/stars.v | 38 +-- examples/quick_sort.v | 2 +- examples/rule110.v | 2 +- examples/snek/snek.js.v | 4 +- examples/snek/snek.v | 4 +- .../sokol/particles/modules/particle/system.v | 9 +- examples/term.ui/rectangles.v | 6 +- examples/term.ui/vyper.v | 8 +- examples/tetris/tetris.js.v | 4 +- examples/tetris/tetris.v | 4 +- examples/vcasino/vcasino.v | 2 +- examples/vweb/vweb_example.v | 2 +- vlib/bitfield/bitfield_test.v | 30 +- .../internal/edwards25519/element_test.v | 12 +- .../ed25519/internal/edwards25519/scalar.v | 2 +- vlib/io/util/util.v | 2 +- vlib/math/big/division_array_ops_test.v | 2 +- vlib/net/websocket/utils.v | 4 +- vlib/net/websocket/websocket_test.v | 4 +- vlib/rand/dist/dist.v | 4 +- vlib/rand/mt19937/mt19937.v | 193 ------------ vlib/rand/mt19937/mt19937_test.v | 89 +++--- vlib/rand/musl/musl_rng.v | 193 ------------ vlib/rand/musl/musl_rng_test.v | 86 +++--- vlib/rand/pcg32/pcg32.v | 177 ----------- vlib/rand/pcg32/pcg32_test.v | 89 +++--- vlib/rand/rand.c.v | 2 +- vlib/rand/rand.v | 282 +++++++++++++++--- vlib/rand/random_numbers_test.v | 34 +-- vlib/rand/splitmix64/splitmix64.v | 174 ----------- vlib/rand/splitmix64/splitmix64_test.v | 86 +++--- vlib/rand/sys/system_rng.c.v | 199 ------------ vlib/rand/sys/system_rng_test.v | 96 +++--- vlib/rand/util/util.v | 4 +- vlib/rand/wyrand/wyrand.v | 193 ------------ vlib/rand/wyrand/wyrand_test.v | 86 +++--- vlib/sync/channels.c.v | 4 +- vlib/time/misc/misc.v | 2 +- vlib/v/tests/const_init_order_test.v | 2 +- ...generics_with_recursive_generics_fn_test.v | 2 +- vlib/v/tests/keep_args_alive_test.v | 4 +- vlib/v/tests/valgrind/rand_module.v | 2 +- 49 files changed, 609 insertions(+), 1586 deletions(-) diff --git a/cmd/tools/bench/wyhash.v b/cmd/tools/bench/wyhash.v index b760ad6b5..302ee4345 100644 --- a/cmd/tools/bench/wyhash.v +++ b/cmd/tools/bench/wyhash.v @@ -16,11 +16,11 @@ fn main() { mut bgenerating := benchmark.start() mut bytepile := []byte{} for _ in 0 .. sample_size * max_str_len { - bytepile << byte(rand.int_in_range(40, 125)) + bytepile << byte(rand.int_in_range(40, 125) or { 40 }) } mut str_lens := []int{} for _ in 0 .. sample_size { - str_lens << rand.int_in_range(min_str_len, max_str_len) + str_lens << rand.int_in_range(min_str_len, max_str_len) or { min_str_len } } bgenerating.measure('generating strings') println('Hashing each of the generated strings...') diff --git a/cmd/tools/fuzz/map_fuzz.v b/cmd/tools/fuzz/map_fuzz.v index f1c62f2d5..19d845d33 100644 --- a/cmd/tools/fuzz/map_fuzz.v +++ b/cmd/tools/fuzz/map_fuzz.v @@ -10,9 +10,9 @@ fn generate_strings(str_len int, arr_len int) []string { } fn fuzz1() { - amount := 200000 - rand.intn(100000) - amount2 := 200000 - rand.intn(100000) - len := 25 - rand.intn(10) + amount := 200000 - rand.intn(100000) or { 0 } + amount2 := 200000 - rand.intn(100000) or { 0 } + len := 25 - rand.intn(10) or { 0 } arr := generate_strings(len, amount) arr2 := generate_strings(len, amount2) mut m := map[string]int{} @@ -34,8 +34,8 @@ fn fuzz1() { fn fuzz2() { mut m := map[string]int{} - amount := rand.intn(500000) + 1 - len := 25 - rand.intn(10) + amount := rand.intn(500000) or { 0 } + 1 + len := 25 - rand.intn(10) or { 0 } arr := generate_strings(len, amount) for i, x in arr { m[x] = i @@ -54,8 +54,8 @@ fn fuzz2() { fn fuzz3() { mut m := map[string]int{} - amount := rand.intn(500000) + 1 - len := 25 - rand.intn(10) + amount := rand.intn(500000) or { 0 } + 1 + len := 25 - rand.intn(10) or { 0 } arr := generate_strings(len, amount) for i, x in arr { if (i % 10000) == 0 { @@ -74,8 +74,8 @@ fn fuzz3() { } fn fuzz4() { - amount := rand.intn(500000) - len := 25 - rand.intn(10) + amount := rand.intn(500000) or { 0 } + len := 25 - rand.intn(10) or { 0 } arr := generate_strings(len, amount) mut m := map[string]int{} for i in 0 .. amount { @@ -93,7 +93,7 @@ fn fuzz4() { } fn fuzz5() { - amount := rand.intn(500000) + 1 + amount := rand.intn(500000) or { 0 } + 1 arr := generate_strings(20, amount) mut m := map[string]int{} for i in 0 .. amount { @@ -114,8 +114,8 @@ fn fuzz5() { fn fuzz6() { mut m := map[string]int{} - amount := rand.intn(500000) + 1 - len := 25 - rand.intn(10) + amount := rand.intn(500000) or { 0 } + 1 + len := 25 - rand.intn(10) or { 0 } arr := generate_strings(len, amount) for i, x in arr { m[x]++ diff --git a/examples/2048/2048.v b/examples/2048/2048.v index 899e8e8f1..42a238cf7 100644 --- a/examples/2048/2048.v +++ b/examples/2048/2048.v @@ -390,10 +390,11 @@ fn (mut b Board) place_random_tile() (Pos, int) { } } if empty_tiles_max > 0 { - new_random_tile_index := rand.intn(empty_tiles_max) + new_random_tile_index := rand.intn(empty_tiles_max) or { 0 } empty_pos := etiles[new_random_tile_index] // 10% chance of getting a `4` tile - random_value := if rand.f64n(1.0) < 0.9 { 1 } else { 2 } + value := rand.f64n(1.0) or { 0.0 } + random_value := if value < 0.9 { 1 } else { 2 } b.field[empty_pos.y][empty_pos.x] = random_value return empty_pos, random_value } @@ -465,7 +466,7 @@ fn (mut app App) ai_move() { cboard.place_random_tile() mut cmoves := 0 for !cboard.is_game_over() { - nmove := possible_moves[rand.intn(possible_moves.len)] + nmove := possible_moves[rand.intn(possible_moves.len) or { 0 }] cboard, is_valid = cboard.move(nmove) if !is_valid { continue diff --git a/examples/fireworks/fireworks.v b/examples/fireworks/fireworks.v index 431e39133..5a7948a9e 100644 --- a/examples/fireworks/fireworks.v +++ b/examples/fireworks/fireworks.v @@ -32,7 +32,7 @@ fn on_frame(mut app App) { } // chance of firing new rocket - if rand.intn(30) == 0 { + if rand.intn(30) or { 0 } == 0 { app.rockets << objects.new_rocket() } // simulating rockets diff --git a/examples/fireworks/modules/objects/color.v b/examples/fireworks/modules/objects/color.v index 6761f26a8..8edbcfebd 100644 --- a/examples/fireworks/modules/objects/color.v +++ b/examples/fireworks/modules/objects/color.v @@ -5,8 +5,8 @@ import rand pub fn random_color() gx.Color { return gx.Color{ - r: byte(rand.int_in_range(0, 256)) - g: byte(rand.int_in_range(0, 256)) - b: byte(rand.int_in_range(0, 256)) + r: rand.byte() + g: rand.byte() + b: rand.byte() } } diff --git a/examples/fireworks/modules/objects/rocket.v b/examples/fireworks/modules/objects/rocket.v index 118ffc381..3f5ab0dc3 100644 --- a/examples/fireworks/modules/objects/rocket.v +++ b/examples/fireworks/modules/objects/rocket.v @@ -51,11 +51,11 @@ pub fn new_rocket() Rocket { return Rocket{ color: random_color() pos: Vector{ - x: rand.f32_in_range(50, get_params().width - 50) + x: rand.f32_in_range(50, get_params().width - 50) or { 50 } } vel: Vector{ - x: rand.f32_in_range(-1.5, 1.5) - y: rand.f32_in_range(5, 7) + x: rand.f32_in_range(-1.5, 1.5) or { -1.5 } + y: rand.f32_in_range(5, 7) or { 5 } } } } diff --git a/examples/fireworks/modules/objects/vector.v b/examples/fireworks/modules/objects/vector.v index 0e29283fb..4bd07e8bb 100644 --- a/examples/fireworks/modules/objects/vector.v +++ b/examples/fireworks/modules/objects/vector.v @@ -18,7 +18,7 @@ pub fn (vector Vector) mult(scalar f32) Vector { } pub fn random_vector_in_circle() Vector { - theta := rand.f32n(2 * math.pi) + theta := rand.f32n(2 * math.pi) or { 0 } y := rand.f32() return Vector{ diff --git a/examples/gg/stars.v b/examples/gg/stars.v index c909f3018..7dca5c05e 100644 --- a/examples/gg/stars.v +++ b/examples/gg/stars.v @@ -60,22 +60,22 @@ fn main() { user_data: app ) for i in 0 .. max_stars { - app.stars[i].x = rand.f32_in_range(-200.0, 200.0) - app.stars[i].y = rand.f32_in_range(-200.0, 200.0) - app.stars[i].z = rand.f32_in_range(-200.0, -100.0) - app.stars[i].r = rand.f32_in_range(0.1, 1.0) - app.stars[i].g = rand.f32_in_range(0.1, 1.0) - app.stars[i].b = rand.f32_in_range(0.1, 1.0) + app.stars[i].x = rand.f32_in_range(-200.0, 200.0) or { -200.0 } + app.stars[i].y = rand.f32_in_range(-200.0, 200.0) or { -200.0 } + app.stars[i].z = rand.f32_in_range(-200.0, -100.0) or { -200.0 } + app.stars[i].r = rand.f32_in_range(0.1, 1.0) or { 0.1 } + app.stars[i].g = rand.f32_in_range(0.1, 1.0) or { 0.1 } + app.stars[i].b = rand.f32_in_range(0.1, 1.0) or { 0.1 } } for i in 0 .. max_v_letters { - app.v_letters[i].x = rand.f32_in_range(-20.0, 20.0) - app.v_letters[i].y = rand.f32_in_range(-20.0, 20.0) - app.v_letters[i].z = rand.f32_in_range(-5.0, -1.0) - app.v_letters[i].w = rand.f32_in_range(5, 20) + app.v_letters[i].x = rand.f32_in_range(-20.0, 20.0) or { -20.0 } + app.v_letters[i].y = rand.f32_in_range(-20.0, 20.0) or { -20.0 } + app.v_letters[i].z = rand.f32_in_range(-5.0, -1.0) or { -5.0 } + app.v_letters[i].w = rand.f32_in_range(5, 20) or { 5 } app.v_letters[i].h = app.v_letters[i].w - app.v_letters[i].angle = rand.f32_in_range(0, 6.283184) - app.v_letters[i].dangle = rand.f32_in_range(-0.05, 0.05) - app.v_letters[i].dz = rand.f32_in_range(-0.1, -0.01) + app.v_letters[i].angle = rand.f32_in_range(0, 6.283184) or { 0 } + app.v_letters[i].dangle = rand.f32_in_range(-0.05, 0.05) or { -0.05 } + app.v_letters[i].dz = rand.f32_in_range(-0.1, -0.01) or { -0.1 } } app.gg.run() } @@ -102,9 +102,9 @@ fn (mut app App) draw() { sgl.v3f_c3f(s.x, s.y, s.z, s.r, s.g, s.b) app.stars[i].z += 0.3 if app.stars[i].z > -1.0 { - app.stars[i].x = rand.f32_in_range(-200.0, 200.0) - app.stars[i].y = rand.f32_in_range(-200.0, 200.0) - app.stars[i].z = rand.f32_in_range(-200.0, -100.0) + app.stars[i].x = rand.f32_in_range(-200.0, 200.0) or { -200.0 } + app.stars[i].y = rand.f32_in_range(-200.0, 200.0) or { -200.0 } + app.stars[i].z = rand.f32_in_range(-200.0, -100.0) or { -200.0 } } } sgl.end() @@ -119,15 +119,15 @@ fn (mut app App) draw() { app.v_letters[i].z += app.v_letters[i].dz app.v_letters[i].angle += app.v_letters[i].dangle if app.v_letters[i].z > -60.0 { - app.v_letters[i].x += rand.f32_in_range(-0.05, 0.05) - app.v_letters[i].y += rand.f32_in_range(-0.05, 0.05) + app.v_letters[i].x += rand.f32_in_range(-0.05, 0.05) or { -0.05 } + app.v_letters[i].y += rand.f32_in_range(-0.05, 0.05) or { -0.05 } } if app.v_letters[i].z < -95.0 { app.v_letters[i].h *= 0.8 app.v_letters[i].w *= 0.8 } if app.v_letters[i].z < -100.0 { - app.v_letters[i].z = rand.f32_in_range(-5.0, -1.0) + app.v_letters[i].z = rand.f32_in_range(-5.0, -1.0) or { -5.0 } app.v_letters[i].h = 10.0 app.v_letters[i].w = 10.0 } diff --git a/examples/quick_sort.v b/examples/quick_sort.v index f89074999..ebfb9c317 100644 --- a/examples/quick_sort.v +++ b/examples/quick_sort.v @@ -8,7 +8,7 @@ const ( fn main() { mut arr := []int{} for _ in 0 .. gen_len { - arr << rand.intn(gen_max) + arr << rand.intn(gen_max) or { 0 } } println('length of random array is $arr.len') println('before quick sort whether array is sorted: ${is_sorted(arr)}') diff --git a/examples/rule110.v b/examples/rule110.v index 10e439fee..4eecd6228 100644 --- a/examples/rule110.v +++ b/examples/rule110.v @@ -33,7 +33,7 @@ fn main() { mut generation_bin := []int{len: n} for i in 0 .. n { - generation_bin[i] = rand.intn(2) + generation_bin[i] = rand.intn(2) or { 0 } } print('\n') diff --git a/examples/snek/snek.js.v b/examples/snek/snek.js.v index ee347331a..b6f8e3f4e 100644 --- a/examples/snek/snek.js.v +++ b/examples/snek/snek.js.v @@ -64,8 +64,8 @@ fn (mut app App) reset_game() { fn (mut app App) move_food() { for { - x := rand.int_in_range(0, game_size) - y := rand.int_in_range(0, game_size) + x := rand.intn(game_size) or { 0 } + y := rand.intn(game_size) or { 0 } app.food = Pos{x, y} if app.food !in app.snake { diff --git a/examples/snek/snek.v b/examples/snek/snek.v index 8ac5e8199..f4a944173 100644 --- a/examples/snek/snek.v +++ b/examples/snek/snek.v @@ -79,8 +79,8 @@ fn (mut app App) reset_game() { fn (mut app App) move_food() { for { - x := rand.int_in_range(0, game_size) - y := rand.int_in_range(0, game_size) + x := rand.intn(game_size) or { 0 } + y := rand.intn(game_size) or { 0 } app.food = Pos{x, y} if app.food !in app.snake { diff --git a/examples/sokol/particles/modules/particle/system.v b/examples/sokol/particles/modules/particle/system.v index a1573abb0..51874aa52 100644 --- a/examples/sokol/particles/modules/particle/system.v +++ b/examples/sokol/particles/modules/particle/system.v @@ -68,10 +68,11 @@ pub fn (mut s System) explode(x f32, y f32) { p = s.bin[i] p.reset() p.location.from(center) - p.acceleration = vec2.Vec2{rand.f32_in_range(-0.5, 0.5), rand.f32_in_range(-0.5, - 0.5)} - p.velocity = vec2.Vec2{rand.f32_in_range(-0.5, 0.5), rand.f32_in_range(-0.5, 0.5)} - p.life_time = rand.f64_in_range(500, 2000) + p.acceleration = vec2.Vec2{rand.f32_in_range(-0.5, 0.5) or { -0.5 }, rand.f32_in_range(-0.5, + 0.5) or { -0.5 }} + p.velocity = vec2.Vec2{rand.f32_in_range(-0.5, 0.5) or { -0.5 }, rand.f32_in_range(-0.5, + 0.5) or { -0.5 }} + p.life_time = rand.f64_in_range(500, 2000) or { 500 } s.pool << p s.bin.delete(i) reserve-- diff --git a/examples/term.ui/rectangles.v b/examples/term.ui/rectangles.v index 09e9d6ad5..82a1f4d55 100644 --- a/examples/term.ui/rectangles.v +++ b/examples/term.ui/rectangles.v @@ -21,9 +21,9 @@ mut: fn random_color() tui.Color { return tui.Color{ - r: byte(rand.intn(256)) - g: byte(rand.intn(256)) - b: byte(rand.intn(256)) + r: rand.byte() + g: rand.byte() + b: rand.byte() } } diff --git a/examples/term.ui/vyper.v b/examples/term.ui/vyper.v index cf41e605f..5a5f4cbcb 100644 --- a/examples/term.ui/vyper.v +++ b/examples/term.ui/vyper.v @@ -53,8 +53,8 @@ fn (v Vec) facing() Orientation { // generate a random vector with x in [min_x, max_x] and y in [min_y, max_y] fn (mut v Vec) randomize(min_x int, min_y int, max_x int, max_y int) { - v.x = rand.int_in_range(min_x, max_x) - v.y = rand.int_in_range(min_y, max_y) + v.x = rand.int_in_range(min_x, max_x) or { min_x } + v.y = rand.int_in_range(min_y, max_y) or { min_y } } // part of snake's body representation @@ -192,8 +192,8 @@ fn (mut s Snake) randomize() { for pos.x % 2 != 0 || (pos.x < buffer && pos.x > s.app.width - buffer) { pos.randomize(buffer, buffer, s.app.width - buffer, s.app.height - buffer) } - s.velocity.y = rand.int_in_range(-1 * block_size, block_size) - s.velocity.x = speeds[rand.intn(speeds.len)] + s.velocity.y = rand.int_in_range(-1 * block_size, block_size) or { 0 } + s.velocity.x = speeds[rand.intn(speeds.len) or { 0 }] s.direction = s.velocity.facing() s.body[0].pos = pos } diff --git a/examples/tetris/tetris.js.v b/examples/tetris/tetris.js.v index 954246415..580e9d3df 100644 --- a/examples/tetris/tetris.js.v +++ b/examples/tetris/tetris.js.v @@ -179,7 +179,7 @@ fn main() { fn (mut g Game) init_game() { g.parse_tetros() - g.next_tetro_idx = rand.intn(b_tetros.len) // generate initial "next" + g.next_tetro_idx = rand.intn(b_tetros.len) or { 0 } // generate initial "next" g.generate_tetro() g.field = [] // Generate the field, fill it with 0's, add -1's on each edge @@ -307,7 +307,7 @@ fn (mut g Game) generate_tetro() { g.pos_y = 0 g.pos_x = field_width / 2 - tetro_size / 2 g.tetro_idx = g.next_tetro_idx - g.next_tetro_idx = rand.intn(b_tetros.len) + g.next_tetro_idx = rand.intn(b_tetros.len) or { 0 } g.rotation_idx = 0 g.get_tetro() } diff --git a/examples/tetris/tetris.v b/examples/tetris/tetris.v index a66b9a2dc..6a1cb61f5 100644 --- a/examples/tetris/tetris.v +++ b/examples/tetris/tetris.v @@ -183,7 +183,7 @@ fn main() { fn (mut g Game) init_game() { g.parse_tetros() - g.next_tetro_idx = rand.intn(b_tetros.len) // generate initial "next" + g.next_tetro_idx = rand.intn(b_tetros.len) or { 0 } // generate initial "next" g.generate_tetro() g.field = [] // Generate the field, fill it with 0's, add -1's on each edge @@ -311,7 +311,7 @@ fn (mut g Game) generate_tetro() { g.pos_y = 0 g.pos_x = field_width / 2 - tetro_size / 2 g.tetro_idx = g.next_tetro_idx - g.next_tetro_idx = rand.intn(b_tetros.len) + g.next_tetro_idx = rand.intn(b_tetros.len) or { 0 } g.rotation_idx = 0 g.get_tetro() } diff --git a/examples/vcasino/vcasino.v b/examples/vcasino/vcasino.v index e6fd87c2b..46f25aba9 100644 --- a/examples/vcasino/vcasino.v +++ b/examples/vcasino/vcasino.v @@ -91,7 +91,7 @@ fn get_bet(money int) int { fn run_wheel(bet_nbr int, _bet int) int { mut bet := _bet - winning_nbr := rand.intn(50) + winning_nbr := rand.intn(50) or { 0 } print('Roulette Wheel spinning... and stops on the number $winning_nbr which is a ') if winning_nbr % 2 == 1 { println(odd) diff --git a/examples/vweb/vweb_example.v b/examples/vweb/vweb_example.v index 44409877a..c7a0267bb 100644 --- a/examples/vweb/vweb_example.v +++ b/examples/vweb/vweb_example.v @@ -25,7 +25,7 @@ fn main() { ['/users/:user'] pub fn (mut app App) user_endpoint(user string) vweb.Result { - id := rand.intn(100) + id := rand.intn(100) or { 0 } return app.json({ user: id }) diff --git a/vlib/bitfield/bitfield_test.v b/vlib/bitfield/bitfield_test.v index ae61d386b..08240903a 100644 --- a/vlib/bitfield/bitfield_test.v +++ b/vlib/bitfield/bitfield_test.v @@ -36,10 +36,10 @@ fn test_bf_and_not_or_xor() { mut input2 := bitfield.new(len) mut i := 0 for i < len { - if rand.intn(2) == 1 { + if rand.intn(2) or { 0 } == 1 { input1.set_bit(i) } - if rand.intn(2) == 1 { + if rand.intn(2) or { 0 } == 1 { input2.set_bit(i) } i++ @@ -62,7 +62,7 @@ fn test_clone_cmp() { len := 80 mut input := bitfield.new(len) for i in 0 .. len { - if rand.intn(2) == 1 { + if rand.intn(2) or { 0 } == 1 { input.set_bit(i) } } @@ -75,7 +75,7 @@ fn test_slice_join() { len := 80 mut input := bitfield.new(len) for i in 0 .. len { - if rand.intn(2) == 1 { + if rand.intn(2) or { 0 } == 1 { input.set_bit(i) } } @@ -98,7 +98,7 @@ fn test_pop_count() { mut count0 := 0 mut input := bitfield.new(len) for i in 0 .. len { - if rand.intn(2) == 1 { + if rand.intn(2) or { 0 } == 1 { input.set_bit(i) count0++ } @@ -113,7 +113,7 @@ fn test_hamming() { mut input1 := bitfield.new(len) mut input2 := bitfield.new(len) for i in 0 .. len { - match rand.intn(4) { + match rand.intn(4) or { 0 } { 0, 1 { input1.set_bit(i) count++ @@ -152,7 +152,7 @@ fn test_bf_from_str() { len := 80 mut input := '' for _ in 0 .. len { - if rand.intn(2) == 1 { + if rand.intn(2) or { 0 } == 1 { input = input + '1' } else { input = input + '0' @@ -172,7 +172,7 @@ fn test_bf_bf2str() { len := 80 mut input := bitfield.new(len) for i in 0 .. len { - if rand.intn(2) == 1 { + if rand.intn(2) or { 0 } == 1 { input.set_bit(i) } } @@ -211,7 +211,7 @@ fn test_bf_clear_all() { len := 80 mut input := bitfield.new(len) for i in 0 .. len { - if rand.intn(2) == 1 { + if rand.intn(2) or { 0 } == 1 { input.set_bit(i) } } @@ -229,7 +229,7 @@ fn test_bf_reverse() { len := 80 mut input := bitfield.new(len) for i in 0 .. len { - if rand.intn(2) == 1 { + if rand.intn(2) or { 0 } == 1 { input.set_bit(i) } } @@ -246,9 +246,9 @@ fn test_bf_reverse() { fn test_bf_resize() { len := 80 - mut input := bitfield.new(rand.intn(len) + 1) + mut input := bitfield.new(rand.intn(len) or { 0 } + 1) for _ in 0 .. 100 { - input.resize(rand.intn(len) + 1) + input.resize(rand.intn(len) or { 0 } + 1) input.set_bit(input.get_size() - 1) } assert input.get_bit(input.get_size() - 1) == 1 @@ -272,12 +272,12 @@ fn test_bf_pos() { mut needle := bitfield.new(i) // fill the needle with random values for k in 0 .. i { - if rand.intn(2) == 1 { + if rand.intn(2) or { 0 } == 1 { needle.set_bit(k) } } // make sure the needle contains at least one set bit, selected randomly - r := rand.intn(i) + r := rand.intn(i) or { 0 } needle.set_bit(r) // create the haystack, make sure it contains the needle mut haystack := needle.clone() @@ -323,7 +323,7 @@ fn test_bf_printing() { len := 80 mut input := bitfield.new(len) for i in 0 .. len { - if rand.intn(2) == 0 { + if rand.intn(2) or { 0 } == 0 { input.set_bit(i) } } diff --git a/vlib/crypto/ed25519/internal/edwards25519/element_test.v b/vlib/crypto/ed25519/internal/edwards25519/element_test.v index 85a790200..7fae26946 100644 --- a/vlib/crypto/ed25519/internal/edwards25519/element_test.v +++ b/vlib/crypto/ed25519/internal/edwards25519/element_test.v @@ -82,16 +82,16 @@ const ( fn generate_weird_field_element() Element { return Element{ - l0: edwards25519.weird_limbs_52[rand.intn(edwards25519.weird_limbs_52.len)] - l1: edwards25519.weird_limbs_51[rand.intn(edwards25519.weird_limbs_51.len)] - l2: edwards25519.weird_limbs_51[rand.intn(edwards25519.weird_limbs_51.len)] - l3: edwards25519.weird_limbs_51[rand.intn(edwards25519.weird_limbs_51.len)] - l4: edwards25519.weird_limbs_51[rand.intn(edwards25519.weird_limbs_51.len)] + l0: edwards25519.weird_limbs_52[rand.intn(edwards25519.weird_limbs_52.len) or { 0 }] + l1: edwards25519.weird_limbs_51[rand.intn(edwards25519.weird_limbs_51.len) or { 0 }] + l2: edwards25519.weird_limbs_51[rand.intn(edwards25519.weird_limbs_51.len) or { 0 }] + l3: edwards25519.weird_limbs_51[rand.intn(edwards25519.weird_limbs_51.len) or { 0 }] + l4: edwards25519.weird_limbs_51[rand.intn(edwards25519.weird_limbs_51.len) or { 0 }] } } fn (e Element) generate_element() Element { - if rand.intn(2) == 0 { + if rand.intn(2) or { 0 } == 0 { return generate_weird_field_element() } return generate_field_element() diff --git a/vlib/crypto/ed25519/internal/edwards25519/scalar.v b/vlib/crypto/ed25519/internal/edwards25519/scalar.v index ce80e3fd0..ee8fffffe 100644 --- a/vlib/crypto/ed25519/internal/edwards25519/scalar.v +++ b/vlib/crypto/ed25519/internal/edwards25519/scalar.v @@ -1099,7 +1099,7 @@ fn generate_scalar(size int) ?Scalar { return reflect.ValueOf(s) */ mut s := edwards25519.sc_zero - diceroll := rand.intn(100) + diceroll := rand.intn(100) or {0} match true { /* case diceroll == 0: diff --git a/vlib/io/util/util.v b/vlib/io/util/util.v index 845579af4..895a1c06b 100644 --- a/vlib/io/util/util.v +++ b/vlib/io/util/util.v @@ -75,7 +75,7 @@ pub fn temp_dir(tdo TempFileOptions) ?string { // * Utility functions fn random_number() string { - s := (1_000_000_000 + (u32(os.getpid()) + rand.u32n(1_000_000_000))).str() + s := (1_000_000_000 + (u32(os.getpid()) + rand.u32n(1_000_000_000) or { 0 })).str() return s.substr(1, s.len) } diff --git a/vlib/math/big/division_array_ops_test.v b/vlib/math/big/division_array_ops_test.v index 0d9b13a14..7c5f3dd83 100644 --- a/vlib/math/big/division_array_ops_test.v +++ b/vlib/math/big/division_array_ops_test.v @@ -142,7 +142,7 @@ fn random_number(length int) Integer { numbers := '0123456789' mut stri := '' for _ in 0 .. length { - i := rand.intn(10) + i := rand.intn(10) or { 0 } nr := numbers[i] stri = stri + nr.ascii_str() } diff --git a/vlib/net/websocket/utils.v b/vlib/net/websocket/utils.v index 4e48359b0..2131fb8e2 100644 --- a/vlib/net/websocket/utils.v +++ b/vlib/net/websocket/utils.v @@ -20,7 +20,7 @@ fn htonl64(payload_len u64) []byte { // create_masking_key returs a new masking key to use when masking websocket messages fn create_masking_key() []byte { - mask_bit := byte(rand.intn(255)) + mask_bit := rand.byte() buf := []byte{len: 4, init: `0`} unsafe { C.memcpy(buf.data, &mask_bit, 4) } return buf @@ -48,7 +48,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.intn(alphanum.len)] + nonce[i] = alphanum[rand.intn(alphanum.len) or { 0 }] } return unsafe { tos(nonce.data, nonce.len) }.clone() } diff --git a/vlib/net/websocket/websocket_test.v b/vlib/net/websocket/websocket_test.v index 3ec133814..88401a8f0 100644 --- a/vlib/net/websocket/websocket_test.v +++ b/vlib/net/websocket/websocket_test.v @@ -21,7 +21,7 @@ fn test_ws_ipv6() { if should_skip { return } - port := 30000 + rand.intn(1024) + port := 30000 + rand.intn(1024) or { 0 } go start_server(.ip6, port) time.sleep(500 * time.millisecond) ws_test(.ip6, 'ws://localhost:$port') or { assert false } @@ -32,7 +32,7 @@ fn test_ws_ipv4() { if should_skip { return } - port := 30000 + rand.intn(1024) + port := 30000 + rand.intn(1024) or { 0 } go start_server(.ip, port) time.sleep(500 * time.millisecond) ws_test(.ip, 'ws://localhost:$port') or { assert false } diff --git a/vlib/rand/dist/dist.v b/vlib/rand/dist/dist.v index 3259d0db5..f028d166d 100644 --- a/vlib/rand/dist/dist.v +++ b/vlib/rand/dist/dist.v @@ -49,8 +49,8 @@ pub fn normal_pair(config NormalConfigStruct) (f64, f64) { // See: https://doi.org/10.1137%2F1006063 // Also: https://en.wikipedia.org/wiki/Marsaglia_polar_method for { - u := rand.f64_in_range(-1, 1) - v := rand.f64_in_range(-1, 1) + u := rand.f64_in_range(-1, 1) or { 0.0 } + v := rand.f64_in_range(-1, 1) or { 0.0 } s := u * u + v * v if s >= 1 || s == 0 { diff --git a/vlib/rand/mt19937/mt19937.v b/vlib/rand/mt19937/mt19937.v index 8f93782c3..bb6d3dfe4 100644 --- a/vlib/rand/mt19937/mt19937.v +++ b/vlib/rand/mt19937/mt19937.v @@ -3,8 +3,6 @@ // that can be found in the LICENSE file. module mt19937 -import math.bits - /* C++ functions for MT19937, with initialization improved 2002/2/10. Coded by Takuji Nishimura and Makoto Matsumoto. @@ -133,197 +131,6 @@ pub fn (mut rng MT19937RNG) u64() u64 { return x } -// int returns a 32-bit signed (possibly negative) `int`. -[inline] -pub fn (mut rng MT19937RNG) int() int { - return int(rng.u32()) -} - -// i64 returns a 64-bit signed (possibly negative) `i64`. -[inline] -pub fn (mut rng MT19937RNG) i64() i64 { - return i64(rng.u64()) -} - -// int31 returns a 31bit positive pseudorandom `int`. -[inline] -pub fn (mut rng MT19937RNG) int31() int { - return int(rng.u32() >> 1) -} - -// int63 returns a 63bit positive pseudorandom `i64`. -[inline] -pub fn (mut rng MT19937RNG) int63() i64 { - return i64(rng.u64() >> 1) -} - -// u32n returns a 32bit `u32` in range `[0, max)`. -[inline] -pub fn (mut rng MT19937RNG) u32n(max u32) u32 { - if max == 0 { - eprintln('max must be positive integer.') - exit(1) - } - // Check SysRNG in system_rng.c.v for explanation - bit_len := bits.len_32(max) - if bit_len == 32 { - for { - value := rng.u32() - if value < max { - return value - } - } - } else { - mask := (u32(1) << (bit_len + 1)) - 1 - for { - value := rng.u32() & mask - if value < max { - return value - } - } - } - return u32(0) -} - -// u64n returns a 64bit `u64` in range `[0, max)`. -[inline] -pub fn (mut rng MT19937RNG) u64n(max u64) u64 { - if max == 0 { - eprintln('max must be positive integer.') - exit(1) - } - bit_len := bits.len_64(max) - if bit_len == 64 { - for { - value := rng.u64() - if value < max { - return value - } - } - } else { - mask := (u64(1) << (bit_len + 1)) - 1 - for { - value := rng.u64() & mask - if value < max { - return value - } - } - } - return u64(0) -} - -// u32n returns a pseudorandom `u32` value that is guaranteed to be in range `[min, max)`. -[inline] -pub fn (mut rng MT19937RNG) u32_in_range(min u32, max u32) u32 { - if max <= min { - eprintln('max must be greater than min.') - exit(1) - } - return min + rng.u32n(max - min) -} - -// u64n returns a pseudorandom `u64` value that is guaranteed to be in range `[min, max)`. -[inline] -pub fn (mut rng MT19937RNG) u64_in_range(min u64, max u64) u64 { - if max <= min { - eprintln('max must be greater than min.') - exit(1) - } - return min + rng.u64n(max - min) -} - -// intn returns a 32bit positive `int` in range `[0, max)`. -[inline] -pub fn (mut rng MT19937RNG) intn(max int) int { - if max <= 0 { - eprintln('max has to be positive.') - exit(1) - } - return int(rng.u32n(u32(max))) -} - -// i64n returns a 64bit positive `i64` in range `[0, max)`. -[inline] -pub fn (mut rng MT19937RNG) i64n(max i64) i64 { - if max <= 0 { - eprintln('max has to be positive.') - exit(1) - } - return i64(rng.u64n(u64(max))) -} - -// int_in_range returns a 32bit positive `int` in range `[min, max)`. -[inline] -pub fn (mut rng MT19937RNG) int_in_range(min int, max int) int { - if max <= min { - eprintln('max must be greater than min.') - exit(1) - } - return min + rng.intn(max - min) -} - -// i64_in_range returns a 64bit positive `i64` in range `[min, max)`. -[inline] -pub fn (mut rng MT19937RNG) i64_in_range(min i64, max i64) i64 { - if max <= min { - eprintln('max must be greater than min.') - exit(1) - } - return min + rng.i64n(max - min) -} - -// f32 returns a 32bit real (`f32`) in range `[0, 1)`. -[inline] -pub fn (mut rng MT19937RNG) f32() f32 { - return f32(rng.f64()) -} - -// f64 returns 64bit real (`f64`) in range `[0, 1)`. -[inline] -pub fn (mut rng MT19937RNG) f64() f64 { - return f64(rng.u64() >> 11) * mt19937.inv_f64_limit -} - -// f32n returns a 32bit real (`f32`) in range [0, max)`. -[inline] -pub fn (mut rng MT19937RNG) f32n(max f32) f32 { - if max <= 0 { - eprintln('max has to be positive.') - exit(1) - } - return rng.f32() * max -} - -// f64n returns a 64bit real (`f64`) in range `[0, max)`. -[inline] -pub fn (mut rng MT19937RNG) f64n(max f64) f64 { - if max <= 0 { - eprintln('max has to be positive.') - exit(1) - } - return rng.f64() * max -} - -// f32_in_range returns a pseudorandom `f32` that lies in range `[min, max)`. -[inline] -pub fn (mut rng MT19937RNG) f32_in_range(min f32, max f32) f32 { - if max <= min { - eprintln('max must be greater than min.') - exit(1) - } - return min + rng.f32n(max - min) -} - -// i64_in_range returns a pseudorandom `i64` that lies in range `[min, max)`. -[inline] -pub fn (mut rng MT19937RNG) f64_in_range(min f64, max f64) f64 { - if max <= min { - eprintln('max must be greater than min.') - exit(1) - } - return min + rng.f64n(max - min) -} - // free should be called when the generator is no longer needed [unsafe] pub fn (mut rng MT19937RNG) free() { diff --git a/vlib/rand/mt19937/mt19937_test.v b/vlib/rand/mt19937/mt19937_test.v index f2a41de70..65a9d12bc 100644 --- a/vlib/rand/mt19937/mt19937_test.v +++ b/vlib/rand/mt19937/mt19937_test.v @@ -1,4 +1,5 @@ import math +import rand import rand.mt19937 import rand.seed @@ -15,7 +16,7 @@ const ( ) fn mt19937_basic_test() { - mut rng := mt19937.MT19937RNG{} + mut rng := &rand.PRNG(&mt19937.MT19937RNG{}) rng.seed([u32(0xdeadbeef)]) target := [u32(956529277), 3842322136, 3319553134, 1843186657, 2704993644, 595827513, 938518626, 1676224337, 3221315650, 1819026461] @@ -27,10 +28,11 @@ fn mt19937_basic_test() { fn gen_randoms(seed_data []u32, bound int) []u64 { bound_u64 := u64(bound) mut randoms := []u64{len: (20)} - mut rnd := mt19937.MT19937RNG{} + x := mt19937.MT19937RNG{} + mut rnd := rand.PRNG(x) rnd.seed(seed_data) for i in 0 .. 20 { - randoms[i] = rnd.u64n(bound_u64) + randoms[i] = rnd.u64n(bound_u64) or { panic("Couldn't obtain random u64") } } return randoms } @@ -46,40 +48,29 @@ fn test_mt19937_reproducibility() { } } -// TODO: use the `in` syntax and remove this function -// after generics has been completely implemented -fn found(value u64, arr []u64) bool { - for item in arr { - if value == item { - return true - } - } - return false -} - fn test_mt19937_variability() { // If this test fails and if it is certainly not the implementation // at fault, try changing the seed values. Repeated values are // improbable but not impossible. for seed in seeds { - mut rng := mt19937.MT19937RNG{} + mut rng := &rand.PRNG(&mt19937.MT19937RNG{}) rng.seed(seed) mut values := []u64{cap: value_count} for i in 0 .. value_count { value := rng.u64() - assert !found(value, values) + assert value !in values assert values.len == i values << value } } } -fn check_uniformity_u64(mut rng mt19937.MT19937RNG, range u64) { +fn check_uniformity_u64(mut rng rand.PRNG, range u64) { range_f64 := f64(range) expected_mean := range_f64 / 2.0 mut variance := 0.0 for _ in 0 .. sample_size { - diff := f64(rng.u64n(range)) - expected_mean + diff := f64(rng.u64n(range) or { panic("Couldn't obtain random u64") }) - expected_mean variance += diff * diff } variance /= sample_size - 1 @@ -92,7 +83,7 @@ fn check_uniformity_u64(mut rng mt19937.MT19937RNG, range u64) { fn test_mt19937_uniformity_u64() { ranges := [14019545, 80240, 130] for seed in seeds { - mut rng := mt19937.MT19937RNG{} + mut rng := &rand.PRNG(&mt19937.MT19937RNG{}) rng.seed(seed) for range in ranges { check_uniformity_u64(mut rng, u64(range)) @@ -100,7 +91,7 @@ fn test_mt19937_uniformity_u64() { } } -fn check_uniformity_f64(mut rng mt19937.MT19937RNG) { +fn check_uniformity_f64(mut rng rand.PRNG) { expected_mean := 0.5 mut variance := 0.0 for _ in 0 .. sample_size { @@ -117,7 +108,7 @@ fn check_uniformity_f64(mut rng mt19937.MT19937RNG) { fn test_mt19937_uniformity_f64() { // The f64 version for seed in seeds { - mut rng := mt19937.MT19937RNG{} + mut rng := &rand.PRNG(&mt19937.MT19937RNG{}) rng.seed(seed) check_uniformity_f64(mut rng) } @@ -126,10 +117,10 @@ fn test_mt19937_uniformity_f64() { fn test_mt19937_u32n() { max := u32(16384) for seed in seeds { - mut rng := mt19937.MT19937RNG{} + mut rng := &rand.PRNG(&mt19937.MT19937RNG{}) rng.seed(seed) for _ in 0 .. range_limit { - value := rng.u32n(max) + value := rng.u32n(max) or { panic("Couldn't obtain random u32") } assert value >= 0 assert value < max } @@ -139,10 +130,10 @@ fn test_mt19937_u32n() { fn test_mt19937_u64n() { max := u64(379091181005) for seed in seeds { - mut rng := mt19937.MT19937RNG{} + mut rng := &rand.PRNG(&mt19937.MT19937RNG{}) rng.seed(seed) for _ in 0 .. range_limit { - value := rng.u64n(max) + value := rng.u64n(max) or { panic("Couldn't obtain random u64") } assert value >= 0 assert value < max } @@ -153,10 +144,10 @@ fn test_mt19937_u32_in_range() { max := u32(484468466) min := u32(316846) for seed in seeds { - mut rng := mt19937.MT19937RNG{} + mut rng := &rand.PRNG(&mt19937.MT19937RNG{}) rng.seed(seed) for _ in 0 .. range_limit { - value := rng.u32_in_range(min, max) + value := rng.u32_in_range(min, max) or { panic("Couldn't obtain random u32 in range.") } assert value >= min assert value < max } @@ -167,10 +158,10 @@ fn test_mt19937_u64_in_range() { max := u64(216468454685163) min := u64(6848646868) for seed in seeds { - mut rng := mt19937.MT19937RNG{} + mut rng := &rand.PRNG(&mt19937.MT19937RNG{}) rng.seed(seed) for _ in 0 .. range_limit { - value := rng.u64_in_range(min, max) + value := rng.u64_in_range(min, max) or { panic("Couldn't obtain random u64 in range.") } assert value >= min assert value < max } @@ -181,7 +172,7 @@ fn test_mt19937_int31() { max_u31 := int(0x7FFFFFFF) sign_mask := int(0x80000000) for seed in seeds { - mut rng := mt19937.MT19937RNG{} + mut rng := &rand.PRNG(&mt19937.MT19937RNG{}) rng.seed(seed) for _ in 0 .. range_limit { value := rng.int31() @@ -197,7 +188,7 @@ fn test_mt19937_int63() { max_u63 := i64(0x7FFFFFFFFFFFFFFF) sign_mask := i64(0x8000000000000000) for seed in seeds { - mut rng := mt19937.MT19937RNG{} + mut rng := &rand.PRNG(&mt19937.MT19937RNG{}) rng.seed(seed) for _ in 0 .. range_limit { value := rng.int63() @@ -211,10 +202,10 @@ fn test_mt19937_int63() { fn test_mt19937_intn() { max := 2525642 for seed in seeds { - mut rng := mt19937.MT19937RNG{} + mut rng := &rand.PRNG(&mt19937.MT19937RNG{}) rng.seed(seed) for _ in 0 .. range_limit { - value := rng.intn(max) + value := rng.intn(max) or { panic("Couldn't obtain random int") } assert value >= 0 assert value < max } @@ -224,10 +215,10 @@ fn test_mt19937_intn() { fn test_mt19937_i64n() { max := i64(3246727724653636) for seed in seeds { - mut rng := mt19937.MT19937RNG{} + mut rng := &rand.PRNG(&mt19937.MT19937RNG{}) rng.seed(seed) for _ in 0 .. range_limit { - value := rng.i64n(max) + value := rng.i64n(max) or { panic("Couldn't obtain random i64") } assert value >= 0 assert value < max } @@ -238,10 +229,10 @@ fn test_mt19937_int_in_range() { min := -4252 max := 1034 for seed in seeds { - mut rng := mt19937.MT19937RNG{} + mut rng := &rand.PRNG(&mt19937.MT19937RNG{}) rng.seed(seed) for _ in 0 .. range_limit { - value := rng.int_in_range(min, max) + value := rng.int_in_range(min, max) or { panic("Couldn't obtain random int in range.") } assert value >= min assert value < max } @@ -252,10 +243,10 @@ fn test_mt19937_i64_in_range() { min := i64(-24095) max := i64(324058) for seed in seeds { - mut rng := mt19937.MT19937RNG{} + mut rng := &rand.PRNG(&mt19937.MT19937RNG{}) rng.seed(seed) for _ in 0 .. range_limit { - value := rng.i64_in_range(min, max) + value := rng.i64_in_range(min, max) or { panic("Couldn't obtain random i64 in range.") } assert value >= min assert value < max } @@ -264,7 +255,7 @@ fn test_mt19937_i64_in_range() { fn test_mt19937_f32() { for seed in seeds { - mut rng := mt19937.MT19937RNG{} + mut rng := &rand.PRNG(&mt19937.MT19937RNG{}) rng.seed(seed) for _ in 0 .. range_limit { value := rng.f32() @@ -276,7 +267,7 @@ fn test_mt19937_f32() { fn test_mt19937_f64() { for seed in seeds { - mut rng := mt19937.MT19937RNG{} + mut rng := &rand.PRNG(&mt19937.MT19937RNG{}) rng.seed(seed) for _ in 0 .. range_limit { value := rng.f64() @@ -289,10 +280,10 @@ fn test_mt19937_f64() { fn test_mt19937_f32n() { max := f32(357.0) for seed in seeds { - mut rng := mt19937.MT19937RNG{} + mut rng := &rand.PRNG(&mt19937.MT19937RNG{}) rng.seed(seed) for _ in 0 .. range_limit { - value := rng.f32n(max) + value := rng.f32n(max) or { panic("Couldn't obtain random f32") } assert value >= 0.0 assert value < max } @@ -302,10 +293,10 @@ fn test_mt19937_f32n() { fn test_mt19937_f64n() { max := 1.52e6 for seed in seeds { - mut rng := mt19937.MT19937RNG{} + mut rng := &rand.PRNG(&mt19937.MT19937RNG{}) rng.seed(seed) for _ in 0 .. range_limit { - value := rng.f64n(max) + value := rng.f64n(max) or { panic("Couldn't obtain random f64") } assert value >= 0.0 assert value < max } @@ -316,10 +307,10 @@ fn test_mt19937_f32_in_range() { min := f32(-24.0) max := f32(125.0) for seed in seeds { - mut rng := mt19937.MT19937RNG{} + mut rng := &rand.PRNG(&mt19937.MT19937RNG{}) rng.seed(seed) for _ in 0 .. range_limit { - value := rng.f32_in_range(min, max) + value := rng.f32_in_range(min, max) or { panic("Couldn't obtain random f32 in range.") } assert value >= min assert value < max } @@ -330,10 +321,10 @@ fn test_mt19937_f64_in_range() { min := -548.7 max := 5015.2 for seed in seeds { - mut rng := mt19937.MT19937RNG{} + mut rng := &rand.PRNG(&mt19937.MT19937RNG{}) rng.seed(seed) for _ in 0 .. range_limit { - value := rng.f64_in_range(min, max) + value := rng.f64_in_range(min, max) or { panic("Couldn't obtain random f64 in range.") } assert value >= min assert value < max } diff --git a/vlib/rand/musl/musl_rng.v b/vlib/rand/musl/musl_rng.v index 942b8a400..ff008308d 100644 --- a/vlib/rand/musl/musl_rng.v +++ b/vlib/rand/musl/musl_rng.v @@ -3,9 +3,7 @@ // that can be found in the LICENSE file. module musl -import math.bits import rand.seed -import rand.constants // MuslRNG ported from https://git.musl-libc.org/cgit/musl/tree/src/prng/rand_r.c pub struct MuslRNG { @@ -49,197 +47,6 @@ pub fn (mut rng MuslRNG) u64() u64 { return u64(rng.u32()) | (u64(rng.u32()) << 32) } -// u32n returns a pseudorandom 32-bit unsigned integer `u32` in range `[0, max)`. -[inline] -pub fn (mut rng MuslRNG) u32n(max u32) u32 { - if max == 0 { - eprintln('max must be positive integer.') - exit(1) - } - // Check SysRNG in system_rng.c.v for explanation - bit_len := bits.len_32(max) - if bit_len == 32 { - for { - value := rng.u32() - if value < max { - return value - } - } - } else { - mask := (u32(1) << (bit_len + 1)) - 1 - for { - value := rng.u32() & mask - if value < max { - return value - } - } - } - return u32(0) -} - -// u64n returns a pseudorandom 64-bit unsigned integer (`u64`) in range `[0, max)`. -[inline] -pub fn (mut rng MuslRNG) u64n(max u64) u64 { - if max == 0 { - eprintln('max must be positive integer.') - exit(1) - } - bit_len := bits.len_64(max) - if bit_len == 64 { - for { - value := rng.u64() - if value < max { - return value - } - } - } else { - mask := (u64(1) << (bit_len + 1)) - 1 - for { - value := rng.u64() & mask - if value < max { - return value - } - } - } - return u64(0) -} - -// u32_in_range returns a pseudorandom 32-bit unsigned integer (`u32`) in range `[min, max)`. -[inline] -pub fn (mut rng MuslRNG) u32_in_range(min u32, max u32) u32 { - if max <= min { - eprintln('max must be greater than min.') - exit(1) - } - return min + rng.u32n(u32(max - min)) -} - -// u64_in_range returns a pseudorandom 64-bit unsigned integer (`u64`) in range `[min, max)`. -[inline] -pub fn (mut rng MuslRNG) u64_in_range(min u64, max u64) u64 { - if max <= min { - eprintln('max must be greater than min.') - exit(1) - } - return min + rng.u64n(max - min) -} - -// int returns a 32-bit signed (possibly negative) integer (`int`). -[inline] -pub fn (mut rng MuslRNG) int() int { - return int(rng.u32()) -} - -// i64 returns a 64-bit signed (possibly negative) integer (`i64`). -[inline] -pub fn (mut rng MuslRNG) i64() i64 { - return i64(rng.u64()) -} - -// int31 returns a 31-bit positive pseudorandom integer (`int`). -[inline] -pub fn (mut rng MuslRNG) int31() int { - return int(rng.u32() >> 1) -} - -// int63 returns a 63-bit positive pseudorandom integer (`i64`). -[inline] -pub fn (mut rng MuslRNG) int63() i64 { - return i64(rng.u64() >> 1) -} - -// intn returns a 32-bit positive int in range `[0, max)`. -[inline] -pub fn (mut rng MuslRNG) intn(max int) int { - if max <= 0 { - eprintln('max has to be positive.') - exit(1) - } - return int(rng.u32n(u32(max))) -} - -// i64n returns a 64-bit positive integer `i64` in range `[0, max)`. -[inline] -pub fn (mut rng MuslRNG) i64n(max i64) i64 { - if max <= 0 { - eprintln('max has to be positive.') - exit(1) - } - return i64(rng.u64n(u64(max))) -} - -// int_in_range returns a 32-bit positive integer `int` in range `[0, max)`. -[inline] -pub fn (mut rng MuslRNG) int_in_range(min int, max int) int { - if max <= min { - eprintln('max must be greater than min.') - exit(1) - } - return min + rng.intn(max - min) -} - -// i64_in_range returns a 64-bit positive integer `i64` in range `[0, max)`. -[inline] -pub fn (mut rng MuslRNG) i64_in_range(min i64, max i64) i64 { - if max <= min { - eprintln('max must be greater than min.') - exit(1) - } - return min + rng.i64n(max - min) -} - -// f32 returns a pseudorandom `f32` value in range `[0, 1)`. -[inline] -pub fn (mut rng MuslRNG) f32() f32 { - return f32(rng.u32()) / constants.max_u32_as_f32 -} - -// f64 returns a pseudorandom `f64` value in range `[0, 1)`. -[inline] -pub fn (mut rng MuslRNG) f64() f64 { - return f64(rng.u64()) / constants.max_u64_as_f64 -} - -// f32n returns a pseudorandom `f32` value in range `[0, max)`. -[inline] -pub fn (mut rng MuslRNG) f32n(max f32) f32 { - if max <= 0 { - eprintln('max has to be positive.') - exit(1) - } - return rng.f32() * max -} - -// f64n returns a pseudorandom `f64` value in range `[0, max)`. -[inline] -pub fn (mut rng MuslRNG) f64n(max f64) f64 { - if max <= 0 { - eprintln('max has to be positive.') - exit(1) - } - return rng.f64() * max -} - -// f32_in_range returns a pseudorandom `f32` in range `[min, max)`. -[inline] -pub fn (mut rng MuslRNG) f32_in_range(min f32, max f32) f32 { - if max <= min { - eprintln('max must be greater than min.') - exit(1) - } - return min + rng.f32n(max - min) -} - -// i64_in_range returns a pseudorandom `i64` in range `[min, max)`. -[inline] -pub fn (mut rng MuslRNG) f64_in_range(min f64, max f64) f64 { - if max <= min { - eprintln('max must be greater than min.') - exit(1) - } - return min + rng.f64n(max - min) -} - // free should be called when the generator is no longer needed [unsafe] pub fn (mut rng MuslRNG) free() { diff --git a/vlib/rand/musl/musl_rng_test.v b/vlib/rand/musl/musl_rng_test.v index e6406f90b..198430656 100644 --- a/vlib/rand/musl/musl_rng_test.v +++ b/vlib/rand/musl/musl_rng_test.v @@ -1,4 +1,5 @@ import math +import rand import rand.musl import rand.seed @@ -17,10 +18,10 @@ const ( fn gen_randoms(seed_data []u32, bound int) []u64 { bound_u64 := u64(bound) mut randoms := []u64{len: (20)} - mut rnd := musl.MuslRNG{} + mut rnd := &rand.PRNG(&musl.MuslRNG{}) rnd.seed(seed_data) for i in 0 .. 20 { - randoms[i] = rnd.u64n(bound_u64) + randoms[i] = rnd.u64n(bound_u64) or { panic("Couldn't obtain u64") } } return randoms } @@ -36,40 +37,29 @@ fn test_musl_reproducibility() { } } -// TODO: use the `in` syntax and remove this function -// after generics has been completely implemented -fn found(value u64, arr []u64) bool { - for item in arr { - if value == item { - return true - } - } - return false -} - fn test_musl_variability() { // If this test fails and if it is certainly not the implementation // at fault, try changing the seed values. Repeated values are // improbable but not impossible. for seed in seeds { - mut rng := musl.MuslRNG{} + mut rng := &rand.PRNG(&musl.MuslRNG{}) rng.seed(seed) mut values := []u64{cap: value_count} for i in 0 .. value_count { value := rng.u64() - assert !found(value, values) + assert value !in values assert values.len == i values << value } } } -fn check_uniformity_u64(mut rng musl.MuslRNG, range u64) { +fn check_uniformity_u64(mut rng rand.PRNG, range u64) { range_f64 := f64(range) expected_mean := range_f64 / 2.0 mut variance := 0.0 for _ in 0 .. sample_size { - diff := f64(rng.u64n(range)) - expected_mean + diff := f64(rng.u64n(range) or { panic("Couldn't obtain u64") }) - expected_mean variance += diff * diff } variance /= sample_size - 1 @@ -82,7 +72,7 @@ fn check_uniformity_u64(mut rng musl.MuslRNG, range u64) { fn test_musl_uniformity_u64() { ranges := [14019545, 80240, 130] for seed in seeds { - mut rng := musl.MuslRNG{} + mut rng := &rand.PRNG(&musl.MuslRNG{}) rng.seed(seed) for range in ranges { check_uniformity_u64(mut rng, u64(range)) @@ -90,7 +80,7 @@ fn test_musl_uniformity_u64() { } } -fn check_uniformity_f64(mut rng musl.MuslRNG) { +fn check_uniformity_f64(mut rng rand.PRNG) { expected_mean := 0.5 mut variance := 0.0 for _ in 0 .. sample_size { @@ -107,7 +97,7 @@ fn check_uniformity_f64(mut rng musl.MuslRNG) { fn test_musl_uniformity_f64() { // The f64 version for seed in seeds { - mut rng := musl.MuslRNG{} + mut rng := &rand.PRNG(&musl.MuslRNG{}) rng.seed(seed) check_uniformity_f64(mut rng) } @@ -116,10 +106,10 @@ fn test_musl_uniformity_f64() { fn test_musl_u32n() { max := u32(16384) for seed in seeds { - mut rng := musl.MuslRNG{} + mut rng := &rand.PRNG(&musl.MuslRNG{}) rng.seed(seed) for _ in 0 .. range_limit { - value := rng.u32n(max) + value := rng.u32n(max) or { panic("Couldn't obtain u32") } assert value >= 0 assert value < max } @@ -129,10 +119,10 @@ fn test_musl_u32n() { fn test_musl_u64n() { max := u64(379091181005) for seed in seeds { - mut rng := musl.MuslRNG{} + mut rng := &rand.PRNG(&musl.MuslRNG{}) rng.seed(seed) for _ in 0 .. range_limit { - value := rng.u64n(max) + value := rng.u64n(max) or { panic("Couldn't obtain u64") } assert value >= 0 assert value < max } @@ -143,10 +133,10 @@ fn test_musl_u32_in_range() { max := u32(484468466) min := u32(316846) for seed in seeds { - mut rng := musl.MuslRNG{} + mut rng := &rand.PRNG(&musl.MuslRNG{}) rng.seed(seed) for _ in 0 .. range_limit { - value := rng.u32_in_range(min, max) + value := rng.u32_in_range(min, max) or { panic("Couldn't obtain u32 in range") } assert value >= min assert value < max } @@ -157,10 +147,10 @@ fn test_musl_u64_in_range() { max := u64(216468454685163) min := u64(6848646868) for seed in seeds { - mut rng := musl.MuslRNG{} + mut rng := &rand.PRNG(&musl.MuslRNG{}) rng.seed(seed) for _ in 0 .. range_limit { - value := rng.u64_in_range(min, max) + value := rng.u64_in_range(min, max) or { panic("Couldn't obtain u64 in range") } assert value >= min assert value < max } @@ -171,7 +161,7 @@ fn test_musl_int31() { max_u31 := int(0x7FFFFFFF) sign_mask := int(0x80000000) for seed in seeds { - mut rng := musl.MuslRNG{} + mut rng := &rand.PRNG(&musl.MuslRNG{}) rng.seed(seed) for _ in 0 .. range_limit { value := rng.int31() @@ -187,7 +177,7 @@ fn test_musl_int63() { max_u63 := i64(0x7FFFFFFFFFFFFFFF) sign_mask := i64(0x8000000000000000) for seed in seeds { - mut rng := musl.MuslRNG{} + mut rng := &rand.PRNG(&musl.MuslRNG{}) rng.seed(seed) for _ in 0 .. range_limit { value := rng.int63() @@ -201,10 +191,10 @@ fn test_musl_int63() { fn test_musl_intn() { max := 2525642 for seed in seeds { - mut rng := musl.MuslRNG{} + mut rng := &rand.PRNG(&musl.MuslRNG{}) rng.seed(seed) for _ in 0 .. range_limit { - value := rng.intn(max) + value := rng.intn(max) or { panic("Couldn't obtain int") } assert value >= 0 assert value < max } @@ -214,10 +204,10 @@ fn test_musl_intn() { fn test_musl_i64n() { max := i64(3246727724653636) for seed in seeds { - mut rng := musl.MuslRNG{} + mut rng := &rand.PRNG(&musl.MuslRNG{}) rng.seed(seed) for _ in 0 .. range_limit { - value := rng.i64n(max) + value := rng.i64n(max) or { panic("Couldn't obtain i64") } assert value >= 0 assert value < max } @@ -228,10 +218,10 @@ fn test_musl_int_in_range() { min := -4252 max := 1034 for seed in seeds { - mut rng := musl.MuslRNG{} + mut rng := &rand.PRNG(&musl.MuslRNG{}) rng.seed(seed) for _ in 0 .. range_limit { - value := rng.int_in_range(min, max) + value := rng.int_in_range(min, max) or { panic("Couldn't obtain int in range") } assert value >= min assert value < max } @@ -242,10 +232,10 @@ fn test_musl_i64_in_range() { min := i64(-24095) max := i64(324058) for seed in seeds { - mut rng := musl.MuslRNG{} + mut rng := &rand.PRNG(&musl.MuslRNG{}) rng.seed(seed) for _ in 0 .. range_limit { - value := rng.i64_in_range(min, max) + value := rng.i64_in_range(min, max) or { panic("Couldn't obtain i64 in range") } assert value >= min assert value < max } @@ -254,7 +244,7 @@ fn test_musl_i64_in_range() { fn test_musl_f32() { for seed in seeds { - mut rng := musl.MuslRNG{} + mut rng := &rand.PRNG(&musl.MuslRNG{}) rng.seed(seed) for _ in 0 .. range_limit { value := rng.f32() @@ -266,7 +256,7 @@ fn test_musl_f32() { fn test_musl_f64() { for seed in seeds { - mut rng := musl.MuslRNG{} + mut rng := &rand.PRNG(&musl.MuslRNG{}) rng.seed(seed) for _ in 0 .. range_limit { value := rng.f64() @@ -279,10 +269,10 @@ fn test_musl_f64() { fn test_musl_f32n() { max := f32(357.0) for seed in seeds { - mut rng := musl.MuslRNG{} + mut rng := &rand.PRNG(&musl.MuslRNG{}) rng.seed(seed) for _ in 0 .. range_limit { - value := rng.f32n(max) + value := rng.f32n(max) or { panic("Couldn't obtain f32") } assert value >= 0.0 assert value < max } @@ -292,10 +282,10 @@ fn test_musl_f32n() { fn test_musl_f64n() { max := 1.52e6 for seed in seeds { - mut rng := musl.MuslRNG{} + mut rng := &rand.PRNG(&musl.MuslRNG{}) rng.seed(seed) for _ in 0 .. range_limit { - value := rng.f64n(max) + value := rng.f64n(max) or { panic("Couldn't obtain f64") } assert value >= 0.0 assert value < max } @@ -306,10 +296,10 @@ fn test_musl_f32_in_range() { min := f32(-24.0) max := f32(125.0) for seed in seeds { - mut rng := musl.MuslRNG{} + mut rng := &rand.PRNG(&musl.MuslRNG{}) rng.seed(seed) for _ in 0 .. range_limit { - value := rng.f32_in_range(min, max) + value := rng.f32_in_range(min, max) or { panic("Couldn't obtain f32 in range") } assert value >= min assert value < max } @@ -320,10 +310,10 @@ fn test_musl_f64_in_range() { min := -548.7 max := 5015.2 for seed in seeds { - mut rng := musl.MuslRNG{} + mut rng := &rand.PRNG(&musl.MuslRNG{}) rng.seed(seed) for _ in 0 .. range_limit { - value := rng.f64_in_range(min, max) + value := rng.f64_in_range(min, max) or { panic("Couldn't obtain f64 in range") } assert value >= min assert value < max } diff --git a/vlib/rand/pcg32/pcg32.v b/vlib/rand/pcg32/pcg32.v index 40a54b8fe..0a49d9a92 100644 --- a/vlib/rand/pcg32/pcg32.v +++ b/vlib/rand/pcg32/pcg32.v @@ -48,183 +48,6 @@ pub fn (mut rng PCG32RNG) u64() u64 { return u64(rng.u32()) | (u64(rng.u32()) << 32) } -// u32n returns a pseudorandom 32-bit unsigned `u32` in range `[0, max)`. -[inline] -pub fn (mut rng PCG32RNG) u32n(max u32) u32 { - if max == 0 { - eprintln('max must be positive') - exit(1) - } - // To avoid bias, we need to make the range of the RNG a multiple of - // max, which we do by dropping output less than a threshold. - threshold := (-max % max) - // Uniformity guarantees that loop below will terminate. In practice, it - // should usually terminate quickly; on average (assuming all max's are - // equally likely), 82.25% of the time, we can expect it to require just - // one iteration. In practice, max's are typically small and only a - // tiny amount of the range is eliminated. - for { - r := rng.u32() - if r >= threshold { - return r % max - } - } - return u32(0) -} - -// u64n returns a pseudorandom 64-bit unsigned `u64` in range `[0, max)`. -[inline] -pub fn (mut rng PCG32RNG) u64n(max u64) u64 { - if max == 0 { - eprintln('max must be positive') - exit(1) - } - threshold := (-max % max) - for { - r := rng.u64() - if r >= threshold { - return r % max - } - } - return u64(0) -} - -// u32_in_range returns a pseudorandom 32-bit unsigned `u32` in range `[min, max)`. -[inline] -pub fn (mut rng PCG32RNG) u32_in_range(min u32, max u32) u32 { - if max <= min { - eprintln('max must be greater than min') - exit(1) - } - return min + rng.u32n(u32(max - min)) -} - -// u64_in_range returns a pseudorandom 64-bit unsigned `u64` in range `[min, max)`. -[inline] -pub fn (mut rng PCG32RNG) u64_in_range(min u64, max u64) u64 { - if max <= min { - eprintln('max must be greater than min') - exit(1) - } - return min + rng.u64n(max - min) -} - -// int returns a 32-bit signed (possibly negative) `int`. -[inline] -pub fn (mut rng PCG32RNG) int() int { - return int(rng.u32()) -} - -// i64 returns a 64-bit signed (possibly negative) `i64`. -[inline] -pub fn (mut rng PCG32RNG) i64() i64 { - return i64(rng.u64()) -} - -// int31 returns a 31-bit positive pseudorandom `int`. -[inline] -pub fn (mut rng PCG32RNG) int31() int { - return int(rng.u32() >> 1) -} - -// int63 returns a 63-bit positive pseudorandom `i64`. -[inline] -pub fn (mut rng PCG32RNG) int63() i64 { - return i64(rng.u64() >> 1) -} - -// intn returns a 32-bit positive `int` in range `[0, max)`. -[inline] -pub fn (mut rng PCG32RNG) intn(max int) int { - if max <= 0 { - eprintln('max has to be positive.') - exit(1) - } - return int(rng.u32n(u32(max))) -} - -// i64n returns a 64-bit positive `i64` in range `[0, max)`. -[inline] -pub fn (mut rng PCG32RNG) i64n(max i64) i64 { - if max <= 0 { - eprintln('max has to be positive.') - exit(1) - } - return i64(rng.u64n(u64(max))) -} - -// int_in_range returns a 32-bit positive `int` in range `[0, max)`. -[inline] -pub fn (mut rng PCG32RNG) int_in_range(min int, max int) int { - if max <= min { - eprintln('max must be greater than min.') - exit(1) - } - return min + rng.intn(max - min) -} - -// i64_in_range returns a 64-bit positive `i64` in range `[0, max)`. -[inline] -pub fn (mut rng PCG32RNG) i64_in_range(min i64, max i64) i64 { - if max <= min { - eprintln('max must be greater than min.') - exit(1) - } - return min + rng.i64n(max - min) -} - -// f32 returns a pseudorandom `f32` value in range `[0, 1)`. -[inline] -pub fn (mut rng PCG32RNG) f32() f32 { - return f32(rng.u32()) / constants.max_u32_as_f32 -} - -// f64 returns a pseudorandom `f64` value in range `[0, 1)`. -[inline] -pub fn (mut rng PCG32RNG) f64() f64 { - return f64(rng.u64()) / constants.max_u64_as_f64 -} - -// f32n returns a pseudorandom `f32` value in range `[0, max)`. -[inline] -pub fn (mut rng PCG32RNG) f32n(max f32) f32 { - if max <= 0 { - eprintln('max has to be positive.') - exit(1) - } - return rng.f32() * max -} - -// f64n returns a pseudorandom `f64` value in range `[0, max)`. -[inline] -pub fn (mut rng PCG32RNG) f64n(max f64) f64 { - if max <= 0 { - eprintln('max has to be positive.') - exit(1) - } - return rng.f64() * max -} - -// f32_in_range returns a pseudorandom `f32` in range `[min, max)`. -[inline] -pub fn (mut rng PCG32RNG) f32_in_range(min f32, max f32) f32 { - if max <= min { - eprintln('max must be greater than min') - exit(1) - } - return min + rng.f32n(max - min) -} - -// i64_in_range returns a pseudorandom `i64` in range `[min, max)`. -[inline] -pub fn (mut rng PCG32RNG) f64_in_range(min f64, max f64) f64 { - if max <= min { - eprintln('max must be greater than min') - exit(1) - } - return min + rng.f64n(max - min) -} - // free should be called when the generator is no longer needed [unsafe] pub fn (mut rng PCG32RNG) free() { diff --git a/vlib/rand/pcg32/pcg32_test.v b/vlib/rand/pcg32/pcg32_test.v index 17048a02c..98fd97848 100644 --- a/vlib/rand/pcg32/pcg32_test.v +++ b/vlib/rand/pcg32/pcg32_test.v @@ -17,10 +17,10 @@ const ( fn gen_randoms(seed_data []u32, bound int) []u32 { mut randoms := []u32{len: 20} - mut rng := pcg32.PCG32RNG{} + mut rng := &rand.PRNG(&pcg32.PCG32RNG{}) rng.seed(seed_data) for i in 0 .. 20 { - randoms[i] = rng.u32n(u32(bound)) + randoms[i] = rng.u32n(u32(bound)) or { panic("Couldn't obtain u32") } } return randoms } @@ -38,40 +38,29 @@ fn test_pcg32_reproducibility() { } } -// TODO: use the `in` syntax and remove this function -// after generics has been completely implemented -fn found(value u64, arr []u64) bool { - for item in arr { - if value == item { - return true - } - } - return false -} - fn test_pcg32_variability() { // If this test fails and if it is certainly not the implementation // at fault, try changing the seed values. Repeated values are // improbable but not impossible. for seed in seeds { - mut rng := pcg32.PCG32RNG{} + mut rng := &rand.PRNG(&pcg32.PCG32RNG{}) rng.seed(seed) mut values := []u64{cap: value_count} for i in 0 .. value_count { value := rng.u64() - assert !found(value, values) + assert value !in values assert values.len == i values << value } } } -fn check_uniformity_u64(mut rng pcg32.PCG32RNG, range u64) { +fn check_uniformity_u64(mut rng rand.PRNG, range u64) { range_f64 := f64(range) expected_mean := range_f64 / 2.0 mut variance := 0.0 for _ in 0 .. sample_size { - diff := f64(rng.u64n(range)) - expected_mean + diff := f64(rng.u64n(range) or { panic("Couldn't obtain u64") }) - expected_mean variance += diff * diff } variance /= sample_size - 1 @@ -84,7 +73,7 @@ fn check_uniformity_u64(mut rng pcg32.PCG32RNG, range u64) { fn test_pcg32_uniformity_u64() { ranges := [14019545, 80240, 130] for seed in seeds { - mut rng := pcg32.PCG32RNG{} + mut rng := &rand.PRNG(&pcg32.PCG32RNG{}) rng.seed(seed) for range in ranges { check_uniformity_u64(mut rng, u64(range)) @@ -92,7 +81,7 @@ fn test_pcg32_uniformity_u64() { } } -fn check_uniformity_f64(mut rng pcg32.PCG32RNG) { +fn check_uniformity_f64(mut rng rand.PRNG) { expected_mean := 0.5 mut variance := 0.0 for _ in 0 .. sample_size { @@ -109,7 +98,7 @@ fn check_uniformity_f64(mut rng pcg32.PCG32RNG) { fn test_pcg32_uniformity_f64() { // The f64 version for seed in seeds { - mut rng := pcg32.PCG32RNG{} + mut rng := &rand.PRNG(&pcg32.PCG32RNG{}) rng.seed(seed) check_uniformity_f64(mut rng) } @@ -118,10 +107,10 @@ fn test_pcg32_uniformity_f64() { fn test_pcg32_u32n() { max := u32(16384) for seed in seeds { - mut rng := pcg32.PCG32RNG{} + mut rng := &rand.PRNG(&pcg32.PCG32RNG{}) rng.seed(seed) for _ in 0 .. range_limit { - value := rng.u32n(max) + value := rng.u32n(max) or { panic("Couldn't obtain u32") } assert value >= 0 assert value < max } @@ -131,10 +120,10 @@ fn test_pcg32_u32n() { fn test_pcg32_u64n() { max := u64(379091181005) for seed in seeds { - mut rng := pcg32.PCG32RNG{} + mut rng := &rand.PRNG(&pcg32.PCG32RNG{}) rng.seed(seed) for _ in 0 .. range_limit { - value := rng.u64n(max) + value := rng.u64n(max) or { panic("Couldn't obtain u64") } assert value >= 0 assert value < max } @@ -145,10 +134,12 @@ fn test_pcg32_u32_in_range() { max := u32(484468466) min := u32(316846) for seed in seeds { - mut rng := pcg32.PCG32RNG{} + mut rng := &rand.PRNG(&pcg32.PCG32RNG{}) rng.seed(seed) for _ in 0 .. range_limit { - value := rng.u32_in_range(u32(min), u32(max)) + value := rng.u32_in_range(u32(min), u32(max)) or { + panic("Couldn't obtain u32 in range") + } assert value >= min assert value < max } @@ -159,10 +150,10 @@ fn test_pcg32_u64_in_range() { max := u64(216468454685163) min := u64(6848646868) for seed in seeds { - mut rng := pcg32.PCG32RNG{} + mut rng := &rand.PRNG(&pcg32.PCG32RNG{}) rng.seed(seed) for _ in 0 .. range_limit { - value := rng.u64_in_range(min, max) + value := rng.u64_in_range(min, max) or { panic("Couldn't obtain u64 in range") } assert value >= min assert value < max } @@ -173,7 +164,7 @@ fn test_pcg32_int31() { max_u31 := int(0x7FFFFFFF) sign_mask := int(0x80000000) for seed in seeds { - mut rng := pcg32.PCG32RNG{} + mut rng := &rand.PRNG(&pcg32.PCG32RNG{}) rng.seed(seed) for _ in 0 .. range_limit { value := rng.int31() @@ -189,7 +180,7 @@ fn test_pcg32_int63() { max_u63 := i64(0x7FFFFFFFFFFFFFFF) sign_mask := i64(0x8000000000000000) for seed in seeds { - mut rng := pcg32.PCG32RNG{} + mut rng := &rand.PRNG(&pcg32.PCG32RNG{}) rng.seed(seed) for _ in 0 .. range_limit { value := rng.int63() @@ -203,10 +194,10 @@ fn test_pcg32_int63() { fn test_pcg32_intn() { max := 2525642 for seed in seeds { - mut rng := pcg32.PCG32RNG{} + mut rng := &rand.PRNG(&pcg32.PCG32RNG{}) rng.seed(seed) for _ in 0 .. range_limit { - value := rng.intn(max) + value := rng.intn(max) or { panic("Couldn't obtain int") } assert value >= 0 assert value < max } @@ -216,10 +207,10 @@ fn test_pcg32_intn() { fn test_pcg32_i64n() { max := i64(3246727724653636) for seed in seeds { - mut rng := pcg32.PCG32RNG{} + mut rng := &rand.PRNG(&pcg32.PCG32RNG{}) rng.seed(seed) for _ in 0 .. range_limit { - value := rng.i64n(max) + value := rng.i64n(max) or { panic("Couldn't obtain i64") } assert value >= 0 assert value < max } @@ -230,10 +221,10 @@ fn test_pcg32_int_in_range() { min := -4252 max := 1034 for seed in seeds { - mut rng := pcg32.PCG32RNG{} + mut rng := &rand.PRNG(&pcg32.PCG32RNG{}) rng.seed(seed) for _ in 0 .. range_limit { - value := rng.int_in_range(min, max) + value := rng.int_in_range(min, max) or { panic("Couldn't obtain int in range") } assert value >= min assert value < max } @@ -244,10 +235,10 @@ fn test_pcg32_i64_in_range() { min := i64(-24095) max := i64(324058) for seed in seeds { - mut rng := pcg32.PCG32RNG{} + mut rng := &rand.PRNG(&pcg32.PCG32RNG{}) rng.seed(seed) for _ in 0 .. range_limit { - value := rng.i64_in_range(min, max) + value := rng.i64_in_range(min, max) or { panic("Couldn't obtain i64 in range") } assert value >= min assert value < max } @@ -256,7 +247,7 @@ fn test_pcg32_i64_in_range() { fn test_pcg32_f32() { for seed in seeds { - mut rng := pcg32.PCG32RNG{} + mut rng := &rand.PRNG(&pcg32.PCG32RNG{}) rng.seed(seed) for _ in 0 .. range_limit { value := rng.f32() @@ -268,7 +259,7 @@ fn test_pcg32_f32() { fn test_pcg32_f64() { for seed in seeds { - mut rng := pcg32.PCG32RNG{} + mut rng := &rand.PRNG(&pcg32.PCG32RNG{}) rng.seed(seed) for _ in 0 .. range_limit { value := rng.f64() @@ -281,10 +272,10 @@ fn test_pcg32_f64() { fn test_pcg32_f32n() { max := f32(357.0) for seed in seeds { - mut rng := pcg32.PCG32RNG{} + mut rng := &rand.PRNG(&pcg32.PCG32RNG{}) rng.seed(seed) for _ in 0 .. range_limit { - value := rng.f32n(max) + value := rng.f32n(max) or { panic("Couldn't obtain f32") } assert value >= 0.0 assert value < max } @@ -294,10 +285,10 @@ fn test_pcg32_f32n() { fn test_pcg32_f64n() { max := 1.52e6 for seed in seeds { - mut rng := pcg32.PCG32RNG{} + mut rng := &rand.PRNG(&pcg32.PCG32RNG{}) rng.seed(seed) for _ in 0 .. range_limit { - value := rng.f64n(max) + value := rng.f64n(max) or { panic("Couldn't obtain f64") } assert value >= 0.0 assert value < max } @@ -308,10 +299,10 @@ fn test_pcg32_f32_in_range() { min := f32(-24.0) max := f32(125.0) for seed in seeds { - mut rng := pcg32.PCG32RNG{} + mut rng := &rand.PRNG(&pcg32.PCG32RNG{}) rng.seed(seed) for _ in 0 .. range_limit { - value := rng.f32_in_range(min, max) + value := rng.f32_in_range(min, max) or { panic("Couldn't obtain f32 in range") } assert value >= min assert value < max } @@ -322,10 +313,10 @@ fn test_pcg32_f64_in_range() { min := -548.7 max := 5015.2 for seed in seeds { - mut rng := pcg32.PCG32RNG{} + mut rng := &rand.PRNG(&pcg32.PCG32RNG{}) rng.seed(seed) for _ in 0 .. range_limit { - value := rng.f64_in_range(min, max) + value := rng.f64_in_range(min, max) or { panic("Couldn't obtain f64 in range") } assert value >= min assert value < max } @@ -333,5 +324,5 @@ fn test_pcg32_f64_in_range() { } fn test_change_default_random_generator() { - rand.set_rng(pcg32.PCG32RNG{}) + rand.set_rng(&rand.PRNG(&pcg32.PCG32RNG{})) } diff --git a/vlib/rand/rand.c.v b/vlib/rand/rand.c.v index a5e3c407d..d7ab386f9 100644 --- a/vlib/rand/rand.c.v +++ b/vlib/rand/rand.c.v @@ -110,7 +110,7 @@ pub fn string_from_set(charset string, len int) string { mut buf := unsafe { malloc_noscan(len + 1) } for i in 0 .. len { unsafe { - buf[i] = charset[intn(charset.len)] + buf[i] = charset[intn(charset.len) or { 0 }] } } unsafe { diff --git a/vlib/rand/rand.v b/vlib/rand/rand.v index 5c62e5bea..400a69928 100644 --- a/vlib/rand/rand.v +++ b/vlib/rand/rand.v @@ -4,7 +4,9 @@ [has_globals] module rand +import math.bits import rand.config +import rand.constants import rand.wyrand // PRNG is a common interface for all PRNGs that can be used seamlessly with the rand @@ -13,29 +15,240 @@ import rand.wyrand pub interface PRNG { mut: seed(seed_data []u32) + // TODO: Support buffering for bytes + // byte() byte + // bytes(bytes_needed int) ?[]byte + // u16() u16 u32() u32 u64() u64 - u32n(max u32) u32 - u64n(max u64) u64 - u32_in_range(min u32, max u32) u32 - u64_in_range(min u64, max u64) u64 - int() int - i64() i64 - int31() int - int63() i64 - intn(max int) int - i64n(max i64) i64 - int_in_range(min int, max int) int - i64_in_range(min i64, max i64) i64 - f32() f32 - f64() f64 - f32n(max f32) f32 - f64n(max f64) f64 - f32_in_range(min f32, max f32) f32 - f64_in_range(min f64, max f64) f64 free() } +// byte returns a uniformly distributed pseudorandom 8-bit unsigned positive `byte`. +[inline] +pub fn (mut rng PRNG) byte() byte { + // TODO: Reimplement for all PRNGs efficiently + return byte(rng.u32() & 0xff) +} + +// bytes returns a buffer of `bytes_needed` random bytes. +[inline] +pub fn (mut rng PRNG) bytes(bytes_needed int) ?[]byte { + // TODO: Reimplement for all PRNGs efficiently + if bytes_needed < 0 { + return error('can not read < 0 random bytes') + } + mut res := []byte{cap: bytes_needed} + mut remaining := bytes_needed + + for remaining > 8 { + mut value := rng.u64() + for _ in 0 .. 8 { + res << byte(value & 0xff) + value >>= 8 + } + remaining -= 8 + } + for remaining > 4 { + mut value := rng.u32() + for _ in 0 .. 4 { + res << byte(value & 0xff) + value >>= 8 + } + remaining -= 4 + } + for remaining > 0 { + res << rng.byte() + remaining -= 1 + } + return res +} + +// u32n returns a uniformly distributed pseudorandom 32-bit signed positive `u32` in range `[0, max)`. +[inline] +pub fn (mut rng PRNG) u32n(max u32) ?u32 { + if max == 0 { + return error('max must be positive integer') + } + // Owing to the pigeon-hole principle, we can't simply do + // val := rng.u32() % max. + // It'll wreck the properties of the distribution unless + // max evenly divides 2^32. So we divide evenly to + // the closest power of two. Then we loop until we find + // an int in the required range + bit_len := bits.len_32(max) + if bit_len == 32 { + for { + value := rng.u32() + if value < max { + return value + } + } + } else { + mask := (u32(1) << (bit_len + 1)) - 1 + for { + value := rng.u32() & mask + if value < max { + return value + } + } + } + return u32(0) +} + +// u64n returns a uniformly distributed pseudorandom 64-bit signed positive `u64` in range `[0, max)`. +[inline] +pub fn (mut rng PRNG) u64n(max u64) ?u64 { + if max == 0 { + return error('max must be positive integer') + } + bit_len := bits.len_64(max) + if bit_len == 64 { + for { + value := rng.u64() + if value < max { + return value + } + } + } else { + mask := (u64(1) << (bit_len + 1)) - 1 + for { + value := rng.u64() & mask + if value < max { + return value + } + } + } + return u64(0) +} + +// u32_in_range returns a uniformly distributed pseudorandom 32-bit unsigned `u32` in range `[min, max)`. +[inline] +pub fn (mut rng PRNG) u32_in_range(min u32, max u32) ?u32 { + if max <= min { + return error('max must be greater than min') + } + return min + rng.u32n(max - min) ? +} + +// u64_in_range returns a uniformly distributed pseudorandom 64-bit unsigned `u64` in range `[min, max)`. +[inline] +pub fn (mut rng PRNG) u64_in_range(min u64, max u64) ?u64 { + if max <= min { + return error('max must be greater than min') + } + return min + rng.u64n(max - min) ? +} + +// int returns a (possibly negative) pseudorandom 32-bit `int`. +[inline] +pub fn (mut rng PRNG) int() int { + return int(rng.u32()) +} + +// i64 returns a (possibly negative) pseudorandom 64-bit `i64`. +[inline] +pub fn (mut rng PRNG) i64() i64 { + return i64(rng.u64()) +} + +// int31 returns a positive pseudorandom 31-bit `int`. +[inline] +pub fn (mut rng PRNG) int31() int { + return int(rng.u32() & constants.u31_mask) // Set the 32nd bit to 0. +} + +// int63 returns a positive pseudorandom 63-bit `i64`. +[inline] +pub fn (mut rng PRNG) int63() i64 { + return i64(rng.u64() & constants.u63_mask) // Set the 64th bit to 0. +} + +// intn returns a pseudorandom `int` in range `[0, max)`. +[inline] +pub fn (mut rng PRNG) intn(max int) ?int { + if max <= 0 { + return error('max has to be positive.') + } + return int(rng.u32n(u32(max)) ?) +} + +// i64n returns a pseudorandom int that lies in `[0, max)`. +[inline] +pub fn (mut rng PRNG) i64n(max i64) ?i64 { + if max <= 0 { + return error('max has to be positive.') + } + return i64(rng.u64n(u64(max)) ?) +} + +// int_in_range returns a pseudorandom `int` in range `[min, max)`. +[inline] +pub fn (mut rng PRNG) int_in_range(min int, max int) ?int { + if max <= min { + return error('max must be greater than min') + } + // This supports negative ranges like [-10, -5) because the difference is positive + return min + rng.intn(max - min) ? +} + +// i64_in_range returns a pseudorandom `i64` in range `[min, max)`. +[inline] +pub fn (mut rng PRNG) i64_in_range(min i64, max i64) ?i64 { + if max <= min { + return error('max must be greater than min') + } + return min + rng.i64n(max - min) ? +} + +// f32 returns a pseudorandom `f32` value in range `[0, 1)`. +[inline] +pub fn (mut rng PRNG) f32() f32 { + return f32(rng.u32()) / constants.max_u32_as_f32 +} + +// f64 returns a pseudorandom `f64` value in range `[0, 1)`. +[inline] +pub fn (mut rng PRNG) f64() f64 { + return f64(rng.u64()) / constants.max_u64_as_f64 +} + +// f32n returns a pseudorandom `f32` value in range `[0, max)`. +[inline] +pub fn (mut rng PRNG) f32n(max f32) ?f32 { + if max <= 0 { + return error('max has to be positive.') + } + return rng.f32() * max +} + +// f64n returns a pseudorandom `f64` value in range `[0, max)`. +[inline] +pub fn (mut rng PRNG) f64n(max f64) ?f64 { + if max <= 0 { + return error('max has to be positive.') + } + return rng.f64() * max +} + +// f32_in_range returns a pseudorandom `f32` in range `[min, max)`. +[inline] +pub fn (mut rng PRNG) f32_in_range(min f32, max f32) ?f32 { + if max <= min { + return error('max must be greater than min') + } + return min + rng.f32n(max - min) ? +} + +// i64_in_range returns a pseudorandom `i64` in range `[min, max)`. +[inline] +pub fn (mut rng PRNG) f64_in_range(min f64, max f64) ?f64 { + if max <= min { + return error('max must be greater than min') + } + return min + rng.f64n(max - min) ? +} + __global default_rng &PRNG // 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. @@ -79,22 +292,22 @@ pub fn u64() u64 { } // u32n returns a uniformly distributed pseudorandom 32-bit signed positive `u32` in range `[0, max)`. -pub fn u32n(max u32) u32 { +pub fn u32n(max u32) ?u32 { return default_rng.u32n(max) } // u64n returns a uniformly distributed pseudorandom 64-bit signed positive `u64` in range `[0, max)`. -pub fn u64n(max u64) u64 { +pub fn u64n(max u64) ?u64 { return default_rng.u64n(max) } // u32_in_range returns a uniformly distributed pseudorandom 32-bit unsigned `u32` in range `[min, max)`. -pub fn u32_in_range(min u32, max u32) u32 { +pub fn u32_in_range(min u32, max u32) ?u32 { return default_rng.u32_in_range(min, max) } // u64_in_range returns a uniformly distributed pseudorandom 64-bit unsigned `u64` in range `[min, max)`. -pub fn u64_in_range(min u64, max u64) u64 { +pub fn u64_in_range(min u64, max u64) ?u64 { return default_rng.u64_in_range(min, max) } @@ -104,18 +317,18 @@ pub fn int() int { } // intn returns a uniformly distributed pseudorandom 32-bit signed positive `int` in range `[0, max)`. -pub fn intn(max int) int { +pub fn intn(max int) ?int { return default_rng.intn(max) } // byte returns a uniformly distributed pseudorandom 8-bit unsigned positive `byte`. pub fn byte() byte { - return byte(default_rng.u32() & 0xff) + return default_rng.byte() } // int_in_range returns a uniformly distributed pseudorandom 32-bit signed int in range `[min, max)`. // Both `min` and `max` can be negative, but we must have `min < max`. -pub fn int_in_range(min int, max int) int { +pub fn int_in_range(min int, max int) ?int { return default_rng.int_in_range(min, max) } @@ -130,12 +343,12 @@ pub fn i64() i64 { } // i64n returns a uniformly distributed pseudorandom 64-bit signed positive `i64` in range `[0, max)`. -pub fn i64n(max i64) i64 { +pub fn i64n(max i64) ?i64 { return default_rng.i64n(max) } // i64_in_range returns a uniformly distributed pseudorandom 64-bit signed `i64` in range `[min, max)`. -pub fn i64_in_range(min i64, max i64) i64 { +pub fn i64_in_range(min i64, max i64) ?i64 { return default_rng.i64_in_range(min, max) } @@ -155,33 +368,28 @@ pub fn f64() f64 { } // f32n returns a uniformly distributed 32-bit floating point in range `[0, max)`. -pub fn f32n(max f32) f32 { +pub fn f32n(max f32) ?f32 { return default_rng.f32n(max) } // f64n returns a uniformly distributed 64-bit floating point in range `[0, max)`. -pub fn f64n(max f64) f64 { +pub fn f64n(max f64) ?f64 { return default_rng.f64n(max) } // f32_in_range returns a uniformly distributed 32-bit floating point in range `[min, max)`. -pub fn f32_in_range(min f32, max f32) f32 { +pub fn f32_in_range(min f32, max f32) ?f32 { return default_rng.f32_in_range(min, max) } // f64_in_range returns a uniformly distributed 64-bit floating point in range `[min, max)`. -pub fn f64_in_range(min f64, max f64) f64 { +pub fn f64_in_range(min f64, max f64) ?f64 { return default_rng.f64_in_range(min, max) } // bytes returns a buffer of `bytes_needed` random bytes pub fn bytes(bytes_needed int) ?[]byte { - if bytes_needed < 0 { - return error('can not read < 0 random bytes') - } - mut res := []byte{len: bytes_needed} - read(mut res) - return res + return default_rng.bytes(bytes_needed) } const ( diff --git a/vlib/rand/random_numbers_test.v b/vlib/rand/random_numbers_test.v index f09fa3c64..0f32adc7c 100644 --- a/vlib/rand/random_numbers_test.v +++ b/vlib/rand/random_numbers_test.v @@ -12,7 +12,7 @@ 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) + values << rand.intn(n) or { panic("Couldn't obtain int") } } return values } @@ -29,7 +29,7 @@ fn test_rand_reproducibility() { fn test_rand_u32n() { max := u32(16384) for _ in 0 .. rnd_count { - value := rand.u32n(max) + value := rand.u32n(max) or { panic("Couldn't obtain u32") } assert value >= 0 assert value < max } @@ -38,7 +38,7 @@ fn test_rand_u32n() { fn test_rand_u64n() { max := u64(379091181005) for _ in 0 .. rnd_count { - value := rand.u64n(max) + value := rand.u64n(max) or { panic("Couldn't obtain u64") } assert value >= 0 assert value < max } @@ -48,7 +48,7 @@ fn test_rand_u32_in_range() { max := u32(484468466) min := u32(316846) for _ in 0 .. rnd_count { - value := rand.u32_in_range(min, max) + value := rand.u32_in_range(min, max) or { panic("Couldn't obtain u32 in range") } assert value >= min assert value < max } @@ -58,7 +58,7 @@ fn test_rand_u64_in_range() { max := u64(216468454685163) min := u64(6848646868) for _ in 0 .. rnd_count { - value := rand.u64_in_range(min, max) + value := rand.u64_in_range(min, max) or { panic("Couldn't obtain u64 in range") } assert value >= min assert value < max } @@ -67,7 +67,7 @@ fn test_rand_u64_in_range() { fn test_rand_intn() { max := 2525642 for _ in 0 .. rnd_count { - value := rand.intn(max) + value := rand.intn(max) or { panic("Couldn't obtain int") } assert value >= 0 assert value < max } @@ -76,7 +76,7 @@ fn test_rand_intn() { fn test_rand_i64n() { max := i64(3246727724653636) for _ in 0 .. rnd_count { - value := rand.i64n(max) + value := rand.i64n(max) or { panic("Couldn't obtain i64") } assert value >= 0 assert value < max } @@ -86,7 +86,7 @@ fn test_rand_int_in_range() { min := -4252 max := 23054962 for _ in 0 .. rnd_count { - value := rand.int_in_range(min, max) + value := rand.int_in_range(min, max) or { panic("Couldn't obtain int in range") } assert value >= min assert value < max } @@ -96,7 +96,7 @@ fn test_rand_i64_in_range() { min := i64(-24095) max := i64(324058) for _ in 0 .. rnd_count { - value := rand.i64_in_range(min, max) + value := rand.i64_in_range(min, max) or { panic("Couldn't obtain i64 in range") } assert value >= min assert value < max } @@ -144,7 +144,7 @@ fn test_rand_f64() { fn test_rand_f32n() { max := f32(357.0) for _ in 0 .. rnd_count { - value := rand.f32n(max) + value := rand.f32n(max) or { panic("Couldn't obtain f32") } assert value >= 0.0 assert value < max } @@ -153,7 +153,7 @@ fn test_rand_f32n() { fn test_rand_f64n() { max := f64(1.52e6) for _ in 0 .. rnd_count { - value := rand.f64n(max) + value := rand.f64n(max) or { panic("Couldn't obtain f64") } assert value >= 0.0 assert value < max } @@ -163,7 +163,7 @@ 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) + value := rand.f32_in_range(min, max) or { panic("Couldn't obtain f32 in range") } assert value >= min assert value < max } @@ -173,7 +173,7 @@ 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) + value := rand.f64_in_range(min, max) or { panic("Couldn't obtain f64 in range") } assert value >= min assert value < max } @@ -204,7 +204,7 @@ fn test_rand_string_from_set() { ] for charset in sets { for _ in 0 .. string_count { - len := rand.intn(rnd_count) + len := rand.intn(rnd_count) or { panic("Couldn't obtain int") } str := rand.string_from_set(charset, len) assert str.len == len for character in str { @@ -275,17 +275,17 @@ fn test_rand_ascii() { fn ensure_same_output(mut rng rand.PRNG) { for _ in 0 .. 100 { assert rand.int() == rng.int() - assert rand.intn(45) == rng.intn(45) + assert rand.intn(45) or { 0 } == rng.intn(45) or { 0 } assert rand.u64() == rng.u64() assert rand.f64() == rng.f64() - assert rand.u32n(25) == rng.u32n(25) + assert rand.u32n(25) or { 0 } == rng.u32n(25) or { 0 } } } fn test_new_global_rng() { old := rand.get_current_rng() - // MuslRNG + // MuslRNG mut rng1a := musl.MuslRNG{} mut rng1b := musl.MuslRNG{} seed1 := [u32(1234)] diff --git a/vlib/rand/splitmix64/splitmix64.v b/vlib/rand/splitmix64/splitmix64.v index 99d475a4a..b2660b202 100644 --- a/vlib/rand/splitmix64/splitmix64.v +++ b/vlib/rand/splitmix64/splitmix64.v @@ -50,180 +50,6 @@ pub fn (mut rng SplitMix64RNG) u64() u64 { return z ^ (z >> (31)) } -// u32n returns a pseudorandom `u32` less than `bound`. -[inline] -pub fn (mut rng SplitMix64RNG) u32n(bound u32) u32 { - // This function is kept similar to the u64 version - if bound == 0 { - eprintln('max must be non-zero') - exit(1) - } - threshold := -bound % bound - for { - r := rng.u32() - if r >= threshold { - return r % bound - } - } - return u32(0) -} - -// u64n returns a pseudorandom `u64` less than `bound`. -[inline] -pub fn (mut rng SplitMix64RNG) u64n(bound u64) u64 { - // See pcg32.v for explanation of comment. This algorithm - // existed before the refactoring. - if bound == 0 { - eprintln('max must be non-zero') - exit(1) - } - threshold := -bound % bound - for { - r := rng.u64() - if r >= threshold { - return r % bound - } - } - return u64(0) -} - -// u32n returns a pseudorandom `u32` value that is guaranteed to be in range `[min, max)`. -[inline] -pub fn (mut rng SplitMix64RNG) u32_in_range(min u32, max u32) u32 { - if max <= min { - eprintln('max must be greater than min') - exit(1) - } - return min + rng.u32n(max - min) -} - -// u64n returns a pseudorandom `u64` value that is guaranteed to be in range `[min, max)`. -[inline] -pub fn (mut rng SplitMix64RNG) u64_in_range(min u64, max u64) u64 { - if max <= min { - eprintln('max must be greater than min') - exit(1) - } - return min + rng.u64n(max - min) -} - -// int returns a pseudorandom 32-bit (possibly negative) `int`. -[inline] -pub fn (mut rng SplitMix64RNG) int() int { - return int(rng.u32()) -} - -// i64 returns a pseudorandom 64-bit (possibly negative) `i64`. -[inline] -pub fn (mut rng SplitMix64RNG) i64() i64 { - return i64(rng.u64()) -} - -// int31 returns a positive pseudorandom 31-bit `int`. -[inline] -pub fn (mut rng SplitMix64RNG) int31() int { - return int(rng.u32() & constants.u31_mask) // Set the 32nd bit to 0. -} - -// int63 returns a positive pseudorandom 63-bit `i64`. -[inline] -pub fn (mut rng SplitMix64RNG) int63() i64 { - return i64(rng.u64() & constants.u63_mask) // Set the 64th bit to 0. -} - -// intn returns a pseudorandom `int` in range `[0, max)`. -[inline] -pub fn (mut rng SplitMix64RNG) intn(max int) int { - if max <= 0 { - eprintln('max has to be positive.') - exit(1) - } - return int(rng.u32n(u32(max))) -} - -// i64n returns a pseudorandom `i64` in range `[0, max)`. -[inline] -pub fn (mut rng SplitMix64RNG) i64n(max i64) i64 { - if max <= 0 { - eprintln('max has to be positive.') - exit(1) - } - return i64(rng.u64n(u64(max))) -} - -// int_in_range returns a pseudorandom `int` in range `[min, max)`. -[inline] -pub fn (mut rng SplitMix64RNG) int_in_range(min int, max int) int { - if max <= min { - eprintln('max must be greater than min') - exit(1) - } - // This supports negative ranges like [-10, -5) because the difference is positive - return min + rng.intn(max - min) -} - -// i64_in_range returns a pseudorandom `i64` in range `[min, max)`. -[inline] -pub fn (mut rng SplitMix64RNG) i64_in_range(min i64, max i64) i64 { - if max <= min { - eprintln('max must be greater than min') - exit(1) - } - return min + rng.i64n(max - min) -} - -// f32 returns a pseudorandom `f32` value in range `[0, 1)`. -[inline] -pub fn (mut rng SplitMix64RNG) f32() f32 { - return f32(rng.u32()) / constants.max_u32_as_f32 -} - -// f64 returns a pseudorandom `f64` value in range `[0, 1)`. -[inline] -pub fn (mut rng SplitMix64RNG) f64() f64 { - return f64(rng.u64()) / constants.max_u64_as_f64 -} - -// f32n returns a pseudorandom `f32` value in range `[0, max)`. -[inline] -pub fn (mut rng SplitMix64RNG) f32n(max f32) f32 { - if max <= 0 { - eprintln('max has to be positive.') - exit(1) - } - return rng.f32() * max -} - -// f64n returns a pseudorandom `f64` value in range `[0, max)`. -[inline] -pub fn (mut rng SplitMix64RNG) f64n(max f64) f64 { - if max <= 0 { - eprintln('max has to be positive.') - exit(1) - } - return rng.f64() * max -} - -// f32_in_range returns a pseudorandom `f32` in range `[min, max)`. -[inline] -pub fn (mut rng SplitMix64RNG) f32_in_range(min f32, max f32) f32 { - if max <= min { - eprintln('max must be greater than min') - exit(1) - } - return min + rng.f32n(max - min) -} - -// i64_in_range returns a pseudorandom `i64` in range `[min, max)`. -[inline] -pub fn (mut rng SplitMix64RNG) f64_in_range(min f64, max f64) f64 { - if max <= min { - eprintln('max must be greater than min') - exit(1) - } - return min + rng.f64n(max - min) -} - // free should be called when the generator is no longer needed [unsafe] pub fn (mut rng SplitMix64RNG) free() { diff --git a/vlib/rand/splitmix64/splitmix64_test.v b/vlib/rand/splitmix64/splitmix64_test.v index 669da3ccd..0edf704d7 100644 --- a/vlib/rand/splitmix64/splitmix64_test.v +++ b/vlib/rand/splitmix64/splitmix64_test.v @@ -1,4 +1,5 @@ import math +import rand import rand.splitmix64 import rand.seed @@ -17,10 +18,10 @@ const ( fn gen_randoms(seed_data []u32, bound int) []u64 { bound_u64 := u64(bound) mut randoms := []u64{len: (20)} - mut rnd := splitmix64.SplitMix64RNG{} + mut rnd := &rand.PRNG(&splitmix64.SplitMix64RNG{}) rnd.seed(seed_data) for i in 0 .. 20 { - randoms[i] = rnd.u64n(bound_u64) + randoms[i] = rnd.u64n(bound_u64) or { panic("Couldn't obtain u64") } } return randoms } @@ -36,40 +37,29 @@ fn test_splitmix64_reproducibility() { } } -// TODO: use the `in` syntax and remove this function -// after generics has been completely implemented -fn found(value u64, arr []u64) bool { - for item in arr { - if value == item { - return true - } - } - return false -} - fn test_splitmix64_variability() { // If this test fails and if it is certainly not the implementation // at fault, try changing the seed values. Repeated values are // improbable but not impossible. for seed in seeds { - mut rng := splitmix64.SplitMix64RNG{} + mut rng := &rand.PRNG(&splitmix64.SplitMix64RNG{}) rng.seed(seed) mut values := []u64{cap: value_count} for i in 0 .. value_count { value := rng.u64() - assert !found(value, values) + assert value !in values assert values.len == i values << value } } } -fn check_uniformity_u64(mut rng splitmix64.SplitMix64RNG, range u64) { +fn check_uniformity_u64(mut rng rand.PRNG, range u64) { range_f64 := f64(range) expected_mean := range_f64 / 2.0 mut variance := 0.0 for _ in 0 .. sample_size { - diff := f64(rng.u64n(range)) - expected_mean + diff := f64(rng.u64n(range) or { panic("Couldn't obtain u64") }) - expected_mean variance += diff * diff } variance /= sample_size - 1 @@ -82,7 +72,7 @@ fn check_uniformity_u64(mut rng splitmix64.SplitMix64RNG, range u64) { fn test_splitmix64_uniformity_u64() { ranges := [14019545, 80240, 130] for seed in seeds { - mut rng := splitmix64.SplitMix64RNG{} + mut rng := &rand.PRNG(&splitmix64.SplitMix64RNG{}) rng.seed(seed) for range in ranges { check_uniformity_u64(mut rng, u64(range)) @@ -90,7 +80,7 @@ fn test_splitmix64_uniformity_u64() { } } -fn check_uniformity_f64(mut rng splitmix64.SplitMix64RNG) { +fn check_uniformity_f64(mut rng rand.PRNG) { expected_mean := 0.5 mut variance := 0.0 for _ in 0 .. sample_size { @@ -107,7 +97,7 @@ fn check_uniformity_f64(mut rng splitmix64.SplitMix64RNG) { fn test_splitmix64_uniformity_f64() { // The f64 version for seed in seeds { - mut rng := splitmix64.SplitMix64RNG{} + mut rng := &rand.PRNG(&splitmix64.SplitMix64RNG{}) rng.seed(seed) check_uniformity_f64(mut rng) } @@ -116,10 +106,10 @@ fn test_splitmix64_uniformity_f64() { fn test_splitmix64_u32n() { max := u32(16384) for seed in seeds { - mut rng := splitmix64.SplitMix64RNG{} + mut rng := &rand.PRNG(&splitmix64.SplitMix64RNG{}) rng.seed(seed) for _ in 0 .. range_limit { - value := rng.u32n(max) + value := rng.u32n(max) or { panic("Couldn't obtain u32") } assert value >= 0 assert value < max } @@ -129,10 +119,10 @@ fn test_splitmix64_u32n() { fn test_splitmix64_u64n() { max := u64(379091181005) for seed in seeds { - mut rng := splitmix64.SplitMix64RNG{} + mut rng := &rand.PRNG(&splitmix64.SplitMix64RNG{}) rng.seed(seed) for _ in 0 .. range_limit { - value := rng.u64n(max) + value := rng.u64n(max) or { panic("Couldn't obtain u64") } assert value >= 0 assert value < max } @@ -143,10 +133,10 @@ fn test_splitmix64_u32_in_range() { max := u32(484468466) min := u32(316846) for seed in seeds { - mut rng := splitmix64.SplitMix64RNG{} + mut rng := &rand.PRNG(&splitmix64.SplitMix64RNG{}) rng.seed(seed) for _ in 0 .. range_limit { - value := rng.u32_in_range(min, max) + value := rng.u32_in_range(min, max) or { panic("Couldn't obtain u32 in range") } assert value >= min assert value < max } @@ -157,10 +147,10 @@ fn test_splitmix64_u64_in_range() { max := u64(216468454685163) min := u64(6848646868) for seed in seeds { - mut rng := splitmix64.SplitMix64RNG{} + mut rng := &rand.PRNG(&splitmix64.SplitMix64RNG{}) rng.seed(seed) for _ in 0 .. range_limit { - value := rng.u64_in_range(min, max) + value := rng.u64_in_range(min, max) or { panic("Couldn't obtain u64 in range") } assert value >= min assert value < max } @@ -171,7 +161,7 @@ fn test_splitmix64_int31() { max_u31 := int(0x7FFFFFFF) sign_mask := int(0x80000000) for seed in seeds { - mut rng := splitmix64.SplitMix64RNG{} + mut rng := &rand.PRNG(&splitmix64.SplitMix64RNG{}) rng.seed(seed) for _ in 0 .. range_limit { value := rng.int31() @@ -187,7 +177,7 @@ fn test_splitmix64_int63() { max_u63 := i64(0x7FFFFFFFFFFFFFFF) sign_mask := i64(0x8000000000000000) for seed in seeds { - mut rng := splitmix64.SplitMix64RNG{} + mut rng := &rand.PRNG(&splitmix64.SplitMix64RNG{}) rng.seed(seed) for _ in 0 .. range_limit { value := rng.int63() @@ -201,10 +191,10 @@ fn test_splitmix64_int63() { fn test_splitmix64_intn() { max := 2525642 for seed in seeds { - mut rng := splitmix64.SplitMix64RNG{} + mut rng := &rand.PRNG(&splitmix64.SplitMix64RNG{}) rng.seed(seed) for _ in 0 .. range_limit { - value := rng.intn(max) + value := rng.intn(max) or { panic("Couldn't obtain int") } assert value >= 0 assert value < max } @@ -214,10 +204,10 @@ fn test_splitmix64_intn() { fn test_splitmix64_i64n() { max := i64(3246727724653636) for seed in seeds { - mut rng := splitmix64.SplitMix64RNG{} + mut rng := &rand.PRNG(&splitmix64.SplitMix64RNG{}) rng.seed(seed) for _ in 0 .. range_limit { - value := rng.i64n(max) + value := rng.i64n(max) or { panic("Couldn't obtain i64") } assert value >= 0 assert value < max } @@ -228,10 +218,10 @@ fn test_splitmix64_int_in_range() { min := -4252 max := 230549862 for seed in seeds { - mut rng := splitmix64.SplitMix64RNG{} + mut rng := &rand.PRNG(&splitmix64.SplitMix64RNG{}) rng.seed(seed) for _ in 0 .. range_limit { - value := rng.int_in_range(min, max) + value := rng.int_in_range(min, max) or { panic("Couldn't obtain int in range") } assert value >= min assert value < max } @@ -242,10 +232,10 @@ fn test_splitmix64_i64_in_range() { min := i64(-24095) max := i64(324058) for seed in seeds { - mut rng := splitmix64.SplitMix64RNG{} + mut rng := &rand.PRNG(&splitmix64.SplitMix64RNG{}) rng.seed(seed) for _ in 0 .. range_limit { - value := rng.i64_in_range(min, max) + value := rng.i64_in_range(min, max) or { panic("Couldn't obtain i64 in range") } assert value >= min assert value < max } @@ -254,7 +244,7 @@ fn test_splitmix64_i64_in_range() { fn test_splitmix64_f32() { for seed in seeds { - mut rng := splitmix64.SplitMix64RNG{} + mut rng := &rand.PRNG(&splitmix64.SplitMix64RNG{}) rng.seed(seed) for _ in 0 .. range_limit { value := rng.f32() @@ -266,7 +256,7 @@ fn test_splitmix64_f32() { fn test_splitmix64_f64() { for seed in seeds { - mut rng := splitmix64.SplitMix64RNG{} + mut rng := &rand.PRNG(&splitmix64.SplitMix64RNG{}) rng.seed(seed) for _ in 0 .. range_limit { value := rng.f64() @@ -279,10 +269,10 @@ fn test_splitmix64_f64() { fn test_splitmix64_f32n() { max := f32(357.0) for seed in seeds { - mut rng := splitmix64.SplitMix64RNG{} + mut rng := &rand.PRNG(&splitmix64.SplitMix64RNG{}) rng.seed(seed) for _ in 0 .. range_limit { - value := rng.f32n(max) + value := rng.f32n(max) or { panic("Couldn't obtain f32") } assert value >= 0.0 assert value < max } @@ -292,10 +282,10 @@ fn test_splitmix64_f32n() { fn test_splitmix64_f64n() { max := 1.52e6 for seed in seeds { - mut rng := splitmix64.SplitMix64RNG{} + mut rng := &rand.PRNG(&splitmix64.SplitMix64RNG{}) rng.seed(seed) for _ in 0 .. range_limit { - value := rng.f64n(max) + value := rng.f64n(max) or { panic("Couldn't obtain f64") } assert value >= 0.0 assert value < max } @@ -306,10 +296,10 @@ fn test_splitmix64_f32_in_range() { min := f32(-24.0) max := f32(125.0) for seed in seeds { - mut rng := splitmix64.SplitMix64RNG{} + mut rng := &rand.PRNG(&splitmix64.SplitMix64RNG{}) rng.seed(seed) for _ in 0 .. range_limit { - value := rng.f32_in_range(min, max) + value := rng.f32_in_range(min, max) or { panic("Couldn't obtain f32 in range") } assert value >= min assert value < max } @@ -320,10 +310,10 @@ fn test_splitmix64_f64_in_range() { min := -548.7 max := 5015.2 for seed in seeds { - mut rng := splitmix64.SplitMix64RNG{} + mut rng := &rand.PRNG(&splitmix64.SplitMix64RNG{}) rng.seed(seed) for _ in 0 .. range_limit { - value := rng.f64_in_range(min, max) + value := rng.f64_in_range(min, max) or { panic("Couldn't obtain f64 in range") } assert value >= min assert value < max } diff --git a/vlib/rand/sys/system_rng.c.v b/vlib/rand/sys/system_rng.c.v index 5bd3c9f52..42a3bdf83 100644 --- a/vlib/rand/sys/system_rng.c.v +++ b/vlib/rand/sys/system_rng.c.v @@ -5,7 +5,6 @@ module sys import math.bits import rand.seed -import rand.constants // Implementation note: // ==================== @@ -76,204 +75,6 @@ pub fn (r SysRNG) u64() u64 { return result } -// r.u32n(max) returns a pseudorandom u32 value that is guaranteed to be less than max -[inline] -pub fn (r SysRNG) u32n(max u32) u32 { - if max == 0 { - eprintln('max must be positive integer') - exit(1) - } - // Owing to the pigeon-hole principle, we can't simply do - // val := rng.u32() % max. - // It'll wreck the properties of the distribution unless - // max evenly divides 2^32. So we divide evenly to - // the closest power of two. Then we loop until we find - // an int in the required range - bit_len := bits.len_32(max) - if bit_len == 32 { - for { - value := r.u32() - if value < max { - return value - } - } - } else { - mask := (u32(1) << (bit_len + 1)) - 1 - for { - value := r.u32() & mask - if value < max { - return value - } - } - } - return u32(0) -} - -// r.u64n(max) returns a pseudorandom u64 value that is guaranteed to be less than max -[inline] -pub fn (r SysRNG) u64n(max u64) u64 { - if max == 0 { - eprintln('max must be positive integer') - exit(1) - } - // Similar procedure for u64s - bit_len := bits.len_64(max) - if bit_len == 64 { - for { - value := r.u64() - if value < max { - return value - } - } - } else { - mask := (u64(1) << (bit_len + 1)) - 1 - for { - value := r.u64() & mask - if value < max { - return value - } - } - } - return u64(0) -} - -// r.u32n(min, max) returns a pseudorandom u32 value that is guaranteed to be in [min, max) -[inline] -pub fn (r SysRNG) u32_in_range(min u32, max u32) u32 { - if max <= min { - eprintln('max must be greater than min') - exit(1) - } - return min + r.u32n(max - min) -} - -// r.u64n(min, max) returns a pseudorandom u64 value that is guaranteed to be in [min, max) -[inline] -pub fn (r SysRNG) u64_in_range(min u64, max u64) u64 { - if max <= min { - eprintln('max must be greater than min') - exit(1) - } - return min + r.u64n(max - min) -} - -// r.int() returns a pseudorandom 32-bit int (which may be negative) -[inline] -pub fn (r SysRNG) int() int { - return int(r.u32()) -} - -// r.i64() returns a pseudorandom 64-bit i64 (which may be negative) -[inline] -pub fn (r SysRNG) i64() i64 { - return i64(r.u64()) -} - -// r.int31() returns a pseudorandom 31-bit int which is non-negative -[inline] -pub fn (r SysRNG) int31() int { - return int(r.u32() & constants.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() & constants.u63_mask) // Set the 64th bit to 0. -} - -// r.intn(max) returns a pseudorandom int that lies in [0, max) -[inline] -pub fn (r SysRNG) intn(max int) int { - if max <= 0 { - eprintln('max has to be positive.') - exit(1) - } - return int(r.u32n(u32(max))) -} - -// r.i64n(max) returns a pseudorandom i64 that lies in [0, max) -[inline] -pub fn (r SysRNG) i64n(max i64) i64 { - if max <= 0 { - eprintln('max has to be positive.') - exit(1) - } - return i64(r.u64n(u64(max))) -} - -// r.int_in_range(min, max) returns a pseudorandom int that lies in [min, max) -[inline] -pub fn (r SysRNG) int_in_range(min int, max int) int { - if max <= min { - eprintln('max must be greater than min') - exit(1) - } - // This supports negative ranges like [-10, -5) because the difference is positive - return min + r.intn(max - min) -} - -// r.i64_in_range(min, max) returns a pseudorandom i64 that lies in [min, max) -[inline] -pub fn (r SysRNG) i64_in_range(min i64, max i64) i64 { - if max <= min { - eprintln('max must be greater than min') - exit(1) - } - return min + r.i64n(max - min) -} - -// 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()) / constants.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()) / constants.max_u64_as_f64 -} - -// r.f32n() returns a pseudorandom f32 value in [0, max) -[inline] -pub fn (r SysRNG) f32n(max f32) f32 { - if max <= 0 { - eprintln('max has to be positive.') - exit(1) - } - return r.f32() * max -} - -// r.f64n() returns a pseudorandom f64 value in [0, max) -[inline] -pub fn (r SysRNG) f64n(max f64) f64 { - if max <= 0 { - eprintln('max has to be positive.') - exit(1) - } - return r.f64() * max -} - -// r.f32_in_range(min, max) returns a pseudorandom f32 that lies in [min, max) -[inline] -pub fn (r SysRNG) f32_in_range(min f32, max f32) f32 { - if max <= min { - eprintln('max must be greater than min') - exit(1) - } - return min + r.f32n(max - min) -} - -// r.i64_in_range(min, max) returns a pseudorandom i64 that lies in [min, max) -[inline] -pub fn (r SysRNG) f64_in_range(min f64, max f64) f64 { - if max <= min { - eprintln('max must be greater than min') - exit(1) - } - return min + r.f64n(max - min) -} - // free should be called when the generator is no longer needed [unsafe] pub fn (mut rng SysRNG) free() { diff --git a/vlib/rand/sys/system_rng_test.v b/vlib/rand/sys/system_rng_test.v index 638ed1018..8d0866b71 100644 --- a/vlib/rand/sys/system_rng_test.v +++ b/vlib/rand/sys/system_rng_test.v @@ -1,4 +1,5 @@ import math +import rand import rand.sys const ( @@ -13,7 +14,7 @@ const ( inv_sqrt_12 = 1.0 / math.sqrt(12) ) -fn get_n_randoms(n int, r sys.SysRNG) []int { +fn get_n_randoms(n int, mut r rand.PRNG) []int { mut ints := []int{cap: n} for _ in 0 .. n { ints << r.int() @@ -28,51 +29,40 @@ fn test_sys_rng_reproducibility() { // seed for another batch of data. for seed in seeds { seed_data := [seed] - mut r1 := sys.SysRNG{} - mut r2 := sys.SysRNG{} + mut r1 := &rand.PRNG(&sys.SysRNG{}) + mut r2 := &rand.PRNG(&sys.SysRNG{}) r1.seed(seed_data) - ints1 := get_n_randoms(value_count, r1) + ints1 := get_n_randoms(value_count, mut r1) r2.seed(seed_data) - ints2 := get_n_randoms(value_count, r2) + ints2 := get_n_randoms(value_count, mut r2) assert ints1 == ints2 } } -// TODO: use the `in` syntax and remove this function -// after generics has been completely implemented -fn found(value u64, arr []u64) bool { - for item in arr { - if value == item { - return true - } - } - return false -} - fn test_sys_rng_variability() { // If this test fails and if it is certainly not the implementation // at fault, try changing the seed values. Repeated values are // improbable but not impossible. for seed in seeds { seed_data := [seed] - mut rng := sys.SysRNG{} + mut rng := &rand.PRNG(&sys.SysRNG{}) rng.seed(seed_data) mut values := []u64{cap: value_count} for i in 0 .. value_count { value := rng.u64() - assert !found(value, values) + assert value !in values assert values.len == i values << value } } } -fn check_uniformity_u64(rng sys.SysRNG, range u64) { +fn check_uniformity_u64(mut rng rand.PRNG, range u64) { range_f64 := f64(range) expected_mean := range_f64 / 2.0 mut variance := 0.0 for _ in 0 .. sample_size { - diff := f64(rng.u64n(range)) - expected_mean + diff := f64(rng.u64n(range) or { panic("Couldn't obtain u64") }) - expected_mean variance += diff * diff } variance /= sample_size - 1 @@ -88,15 +78,15 @@ fn test_sys_rng_uniformity_u64() { ranges := [14019545, 80240, 130] for seed in seeds { seed_data := [seed] - mut rng := sys.SysRNG{} + mut rng := &rand.PRNG(&sys.SysRNG{}) rng.seed(seed_data) for range in ranges { - check_uniformity_u64(rng, u64(range)) + check_uniformity_u64(mut rng, u64(range)) } } } -fn check_uniformity_f64(rng sys.SysRNG) { +fn check_uniformity_f64(mut rng rand.PRNG) { expected_mean := 0.5 mut variance := 0.0 for _ in 0 .. sample_size { @@ -114,9 +104,9 @@ fn test_sys_rng_uniformity_f64() { // The f64 version for seed in seeds { seed_data := [seed] - mut rng := sys.SysRNG{} + mut rng := &rand.PRNG(&sys.SysRNG{}) rng.seed(seed_data) - check_uniformity_f64(rng) + check_uniformity_f64(mut rng) } } @@ -124,10 +114,10 @@ fn test_sys_rng_u32n() { max := u32(16384) for seed in seeds { seed_data := [seed] - mut rng := sys.SysRNG{} + mut rng := &rand.PRNG(&sys.SysRNG{}) rng.seed(seed_data) for _ in 0 .. range_limit { - value := rng.u32n(max) + value := rng.u32n(max) or { panic("Couldn't obtain u32") } assert value >= 0 assert value < max } @@ -138,10 +128,10 @@ fn test_sys_rng_u64n() { max := u64(379091181005) for seed in seeds { seed_data := [seed] - mut rng := sys.SysRNG{} + mut rng := &rand.PRNG(&sys.SysRNG{}) rng.seed(seed_data) for _ in 0 .. range_limit { - value := rng.u64n(max) + value := rng.u64n(max) or { panic("Couldn't obtain u64") } assert value >= 0 assert value < max } @@ -153,10 +143,10 @@ fn test_sys_rng_u32_in_range() { min := u32(316846) for seed in seeds { seed_data := [seed] - mut rng := sys.SysRNG{} + mut rng := &rand.PRNG(&sys.SysRNG{}) rng.seed(seed_data) for _ in 0 .. range_limit { - value := rng.u32_in_range(min, max) + value := rng.u32_in_range(min, max) or { panic("Couldn't obtain u32 in range") } assert value >= min assert value < max } @@ -168,10 +158,10 @@ fn test_sys_rng_u64_in_range() { min := u64(6848646868) for seed in seeds { seed_data := [seed] - mut rng := sys.SysRNG{} + mut rng := &rand.PRNG(&sys.SysRNG{}) rng.seed(seed_data) for _ in 0 .. range_limit { - value := rng.u64_in_range(min, max) + value := rng.u64_in_range(min, max) or { panic("Couldn't obtain u64 in range") } assert value >= min assert value < max } @@ -182,10 +172,10 @@ fn test_sys_rng_intn() { max := 2525642 for seed in seeds { seed_data := [seed] - mut rng := sys.SysRNG{} + mut rng := &rand.PRNG(&sys.SysRNG{}) rng.seed(seed_data) for _ in 0 .. range_limit { - value := rng.intn(max) + value := rng.intn(max) or { panic("Couldn't obtain int") } assert value >= 0 assert value < max } @@ -196,10 +186,10 @@ fn test_sys_rng_i64n() { max := i64(3246727724653636) for seed in seeds { seed_data := [seed] - mut rng := sys.SysRNG{} + mut rng := &rand.PRNG(&sys.SysRNG{}) rng.seed(seed_data) for _ in 0 .. range_limit { - value := rng.i64n(max) + value := rng.i64n(max) or { panic("Couldn't obtain i64") } assert value >= 0 assert value < max } @@ -211,10 +201,10 @@ fn test_sys_rng_int_in_range() { max := 23054962 for seed in seeds { seed_data := [seed] - mut rng := sys.SysRNG{} + mut rng := &rand.PRNG(&sys.SysRNG{}) rng.seed(seed_data) for _ in 0 .. range_limit { - value := rng.int_in_range(min, max) + value := rng.int_in_range(min, max) or { panic("Couldn't obtain int in range") } assert value >= min assert value < max } @@ -226,10 +216,10 @@ fn test_sys_rng_i64_in_range() { max := i64(324058) for seed in seeds { seed_data := [seed] - mut rng := sys.SysRNG{} + mut rng := &rand.PRNG(&sys.SysRNG{}) rng.seed(seed_data) for _ in 0 .. range_limit { - value := rng.i64_in_range(min, max) + value := rng.i64_in_range(min, max) or { panic("Couldn't obtain i64 in range") } assert value >= min assert value < max } @@ -241,7 +231,7 @@ fn test_sys_rng_int31() { sign_mask := int(0x80000000) for seed in seeds { seed_data := [seed] - mut rng := sys.SysRNG{} + mut rng := &rand.PRNG(&sys.SysRNG{}) rng.seed(seed_data) for _ in 0 .. range_limit { value := rng.int31() @@ -258,7 +248,7 @@ fn test_sys_rng_int63() { sign_mask := i64(0x8000000000000000) for seed in seeds { seed_data := [seed] - mut rng := sys.SysRNG{} + mut rng := &rand.PRNG(&sys.SysRNG{}) rng.seed(seed_data) for _ in 0 .. range_limit { value := rng.int63() @@ -272,7 +262,7 @@ fn test_sys_rng_int63() { fn test_sys_rng_f32() { for seed in seeds { seed_data := [seed] - mut rng := sys.SysRNG{} + mut rng := &rand.PRNG(&sys.SysRNG{}) rng.seed(seed_data) for _ in 0 .. range_limit { value := rng.f32() @@ -285,7 +275,7 @@ fn test_sys_rng_f32() { fn test_sys_rng_f64() { for seed in seeds { seed_data := [seed] - mut rng := sys.SysRNG{} + mut rng := &rand.PRNG(&sys.SysRNG{}) rng.seed(seed_data) for _ in 0 .. range_limit { value := rng.f64() @@ -299,10 +289,10 @@ fn test_sys_rng_f32n() { max := f32(357.0) for seed in seeds { seed_data := [seed] - mut rng := sys.SysRNG{} + mut rng := &rand.PRNG(&sys.SysRNG{}) rng.seed(seed_data) for _ in 0 .. range_limit { - value := rng.f32n(max) + value := rng.f32n(max) or { panic("Couldn't obtain f32") } assert value >= 0.0 assert value < max } @@ -313,10 +303,10 @@ fn test_sys_rng_f64n() { max := 1.52e6 for seed in seeds { seed_data := [seed] - mut rng := sys.SysRNG{} + mut rng := &rand.PRNG(&sys.SysRNG{}) rng.seed(seed_data) for _ in 0 .. range_limit { - value := rng.f64n(max) + value := rng.f64n(max) or { panic("Couldn't obtain f64") } assert value >= 0.0 assert value < max } @@ -328,10 +318,10 @@ fn test_sys_rng_f32_in_range() { max := f32(125.0) for seed in seeds { seed_data := [seed] - mut rng := sys.SysRNG{} + mut rng := &rand.PRNG(&sys.SysRNG{}) rng.seed(seed_data) for _ in 0 .. range_limit { - value := rng.f32_in_range(min, max) + value := rng.f32_in_range(min, max) or { panic("Couldn't obtain f32 in range") } assert value >= min assert value < max } @@ -343,10 +333,10 @@ fn test_sys_rng_f64_in_range() { max := 5015.2 for seed in seeds { seed_data := [seed] - mut rng := sys.SysRNG{} + mut rng := &rand.PRNG(&sys.SysRNG{}) rng.seed(seed_data) for _ in 0 .. range_limit { - value := rng.f64_in_range(min, max) + value := rng.f64_in_range(min, max) or { panic("Couldn't obtain f64 in range") } assert value >= min assert value < max } diff --git a/vlib/rand/util/util.v b/vlib/rand/util/util.v index 22343047e..82a8c7318 100644 --- a/vlib/rand/util/util.v +++ b/vlib/rand/util/util.v @@ -30,7 +30,7 @@ pub fn sample_r(array []T, k int) []T { n := array.len mut results := []T{len: k} for i in 0 .. k { - results[i] = array[rand.intn(n)] + results[i] = array[rand.intn(n) or { 0 }] } return results } @@ -43,7 +43,7 @@ pub fn shuffle(mut a []T, n int) { } cnt := if n == 0 { a.len - 1 } else { n } for i in 0 .. cnt { - x := rand.int_in_range(i, a.len) + x := rand.int_in_range(i, a.len) or { 0 } // swap a_i := a[i] a[i] = a[x] diff --git a/vlib/rand/wyrand/wyrand.v b/vlib/rand/wyrand/wyrand.v index 9b1fb997f..34037429b 100644 --- a/vlib/rand/wyrand/wyrand.v +++ b/vlib/rand/wyrand/wyrand.v @@ -3,7 +3,6 @@ // that can be found in the LICENSE file. module wyrand -import math.bits import rand.seed import rand.constants import hash @@ -58,195 +57,3 @@ pub fn (mut rng WyRandRNG) u64() u64 { } return 0 } - -// u32n returns a pseudorandom `u32` less than `max`. -[inline] -pub fn (mut rng WyRandRNG) u32n(max u32) u32 { - if max == 0 { - eprintln('max must be positive integer') - exit(1) - } - // Check SysRNG in system_rng.c.v for explanation - bit_len := bits.len_32(max) - if bit_len == 32 { - for { - value := rng.u32() - if value < max { - return value - } - } - } else { - mask := (u32(1) << (bit_len + 1)) - 1 - for { - value := rng.u32() & mask - if value < max { - return value - } - } - } - return u32(0) -} - -// u64n returns a pseudorandom `u64` less than `max`. -[inline] -pub fn (mut rng WyRandRNG) u64n(max u64) u64 { - if max == 0 { - eprintln('max must be positive integer') - exit(1) - } - bit_len := bits.len_64(max) - if bit_len == 64 { - for { - value := rng.u64() - if value < max { - return value - } - } - } else { - mask := (u64(1) << (bit_len + 1)) - 1 - for { - value := rng.u64() & mask - if value < max { - return value - } - } - } - return u64(0) -} - -// u32n returns a pseudorandom `u32` value that is guaranteed to be in range `[min, max)`. -[inline] -pub fn (mut rng WyRandRNG) u32_in_range(min u32, max u32) u32 { - if max <= min { - eprintln('max must be greater than min') - exit(1) - } - return min + rng.u32n(max - min) -} - -// u64n returns a pseudorandom `u64` value that is guaranteed to be in range `[min, max)`. -[inline] -pub fn (mut rng WyRandRNG) u64_in_range(min u64, max u64) u64 { - if max <= min { - eprintln('max must be greater than min') - exit(1) - } - return min + rng.u64n(max - min) -} - -// int returns a (possibly negative) pseudorandom 32-bit `int`. -[inline] -pub fn (mut rng WyRandRNG) int() int { - return int(rng.u32()) -} - -// i64 returns a (possibly negative) pseudorandom 64-bit `i64`. -[inline] -pub fn (mut rng WyRandRNG) i64() i64 { - return i64(rng.u64()) -} - -// int31 returns a positive pseudorandom 31-bit `int`. -[inline] -pub fn (mut rng WyRandRNG) int31() int { - return int(rng.u32() & constants.u31_mask) // Set the 32nd bit to 0. -} - -// int63 returns a positive pseudorandom 63-bit `i64`. -[inline] -pub fn (mut rng WyRandRNG) int63() i64 { - return i64(rng.u64() & constants.u63_mask) // Set the 64th bit to 0. -} - -// intn returns a pseudorandom `int` in range `[0, max)`. -[inline] -pub fn (mut rng WyRandRNG) intn(max int) int { - if max <= 0 { - eprintln('max has to be positive.') - exit(1) - } - return int(rng.u32n(u32(max))) -} - -// i64n returns a pseudorandom int that lies in `[0, max)`. -[inline] -pub fn (mut rng WyRandRNG) i64n(max i64) i64 { - if max <= 0 { - eprintln('max has to be positive.') - exit(1) - } - return i64(rng.u64n(u64(max))) -} - -// int_in_range returns a pseudorandom `int` in range `[min, max)`. -[inline] -pub fn (mut rng WyRandRNG) int_in_range(min int, max int) int { - if max <= min { - eprintln('max must be greater than min') - exit(1) - } - // This supports negative ranges like [-10, -5) because the difference is positive - return min + rng.intn(max - min) -} - -// i64_in_range returns a pseudorandom `i64` in range `[min, max)`. -[inline] -pub fn (mut rng WyRandRNG) i64_in_range(min i64, max i64) i64 { - if max <= min { - eprintln('max must be greater than min') - exit(1) - } - return min + rng.i64n(max - min) -} - -// f32 returns a pseudorandom `f32` value in range `[0, 1)`. -[inline] -pub fn (mut rng WyRandRNG) f32() f32 { - return f32(rng.u32()) / constants.max_u32_as_f32 -} - -// f64 returns a pseudorandom `f64` value in range `[0, 1)`. -[inline] -pub fn (mut rng WyRandRNG) f64() f64 { - return f64(rng.u64()) / constants.max_u64_as_f64 -} - -// f32n returns a pseudorandom `f32` value in range `[0, max)`. -[inline] -pub fn (mut rng WyRandRNG) f32n(max f32) f32 { - if max <= 0 { - eprintln('max has to be positive.') - exit(1) - } - return rng.f32() * max -} - -// f64n returns a pseudorandom `f64` value in range `[0, max)`. -[inline] -pub fn (mut rng WyRandRNG) f64n(max f64) f64 { - if max <= 0 { - eprintln('max has to be positive.') - exit(1) - } - return rng.f64() * max -} - -// f32_in_range returns a pseudorandom `f32` in range `[min, max)`. -[inline] -pub fn (mut rng WyRandRNG) f32_in_range(min f32, max f32) f32 { - if max <= min { - eprintln('max must be greater than min') - exit(1) - } - return min + rng.f32n(max - min) -} - -// i64_in_range returns a pseudorandom `i64` in range `[min, max)`. -[inline] -pub fn (mut rng WyRandRNG) f64_in_range(min f64, max f64) f64 { - if max <= min { - eprintln('max must be greater than min') - exit(1) - } - return min + rng.f64n(max - min) -} diff --git a/vlib/rand/wyrand/wyrand_test.v b/vlib/rand/wyrand/wyrand_test.v index 4cdfdb654..13350ddf3 100644 --- a/vlib/rand/wyrand/wyrand_test.v +++ b/vlib/rand/wyrand/wyrand_test.v @@ -1,4 +1,5 @@ import math +import rand import rand.seed import rand.wyrand @@ -17,10 +18,10 @@ const ( fn gen_randoms(seed_data []u32, bound int) []u64 { bound_u64 := u64(bound) mut randoms := []u64{len: (20)} - mut rnd := wyrand.WyRandRNG{} + mut rnd := &rand.PRNG(&wyrand.WyRandRNG{}) rnd.seed(seed_data) for i in 0 .. 20 { - randoms[i] = rnd.u64n(bound_u64) + randoms[i] = rnd.u64n(bound_u64) or { panic("Couldn't obtain u64") } } return randoms } @@ -36,40 +37,29 @@ fn test_wyrand_reproducibility() { } } -// TODO: use the `in` syntax and remove this function -// after generics has been completely implemented -fn found(value u64, arr []u64) bool { - for item in arr { - if value == item { - return true - } - } - return false -} - fn test_wyrand_variability() { // If this test fails and if it is certainly not the implementation // at fault, try changing the seed values. Repeated values are // improbable but not impossible. for seed in seeds { - mut rng := wyrand.WyRandRNG{} + mut rng := &rand.PRNG(&wyrand.WyRandRNG{}) rng.seed(seed) mut values := []u64{cap: value_count} for i in 0 .. value_count { value := rng.u64() - assert !found(value, values) + assert value !in values assert values.len == i values << value } } } -fn check_uniformity_u64(mut rng wyrand.WyRandRNG, range u64) { +fn check_uniformity_u64(mut rng rand.PRNG, range u64) { range_f64 := f64(range) expected_mean := range_f64 / 2.0 mut variance := 0.0 for _ in 0 .. sample_size { - diff := f64(rng.u64n(range)) - expected_mean + diff := f64(rng.u64n(range) or { panic("Couldn't obtain u64") }) - expected_mean variance += diff * diff } variance /= sample_size - 1 @@ -82,7 +72,7 @@ fn check_uniformity_u64(mut rng wyrand.WyRandRNG, range u64) { fn test_wyrand_uniformity_u64() { ranges := [14019545, 80240, 130] for seed in seeds { - mut rng := wyrand.WyRandRNG{} + mut rng := &rand.PRNG(&wyrand.WyRandRNG{}) rng.seed(seed) for range in ranges { check_uniformity_u64(mut rng, u64(range)) @@ -90,7 +80,7 @@ fn test_wyrand_uniformity_u64() { } } -fn check_uniformity_f64(mut rng wyrand.WyRandRNG) { +fn check_uniformity_f64(mut rng rand.PRNG) { expected_mean := 0.5 mut variance := 0.0 for _ in 0 .. sample_size { @@ -107,7 +97,7 @@ fn check_uniformity_f64(mut rng wyrand.WyRandRNG) { fn test_wyrand_uniformity_f64() { // The f64 version for seed in seeds { - mut rng := wyrand.WyRandRNG{} + mut rng := &rand.PRNG(&wyrand.WyRandRNG{}) rng.seed(seed) check_uniformity_f64(mut rng) } @@ -116,10 +106,10 @@ fn test_wyrand_uniformity_f64() { fn test_wyrand_u32n() { max := u32(16384) for seed in seeds { - mut rng := wyrand.WyRandRNG{} + mut rng := &rand.PRNG(&wyrand.WyRandRNG{}) rng.seed(seed) for _ in 0 .. range_limit { - value := rng.u32n(max) + value := rng.u32n(max) or { panic("Couldn't obtain u32") } assert value >= 0 assert value < max } @@ -129,10 +119,10 @@ fn test_wyrand_u32n() { fn test_wyrand_u64n() { max := u64(379091181005) for seed in seeds { - mut rng := wyrand.WyRandRNG{} + mut rng := &rand.PRNG(&wyrand.WyRandRNG{}) rng.seed(seed) for _ in 0 .. range_limit { - value := rng.u64n(max) + value := rng.u64n(max) or { panic("Couldn't obtain u64") } assert value >= 0 assert value < max } @@ -143,10 +133,10 @@ fn test_wyrand_u32_in_range() { max := u32(484468466) min := u32(316846) for seed in seeds { - mut rng := wyrand.WyRandRNG{} + mut rng := &rand.PRNG(&wyrand.WyRandRNG{}) rng.seed(seed) for _ in 0 .. range_limit { - value := rng.u32_in_range(min, max) + value := rng.u32_in_range(min, max) or { panic("Couldn't obtain u32 in range") } assert value >= min assert value < max } @@ -157,10 +147,10 @@ fn test_wyrand_u64_in_range() { max := u64(216468454685163) min := u64(6848646868) for seed in seeds { - mut rng := wyrand.WyRandRNG{} + mut rng := &rand.PRNG(&wyrand.WyRandRNG{}) rng.seed(seed) for _ in 0 .. range_limit { - value := rng.u64_in_range(min, max) + value := rng.u64_in_range(min, max) or { panic("Couldn't obtain u64 in range") } assert value >= min assert value < max } @@ -171,7 +161,7 @@ fn test_wyrand_int31() { max_u31 := int(0x7FFFFFFF) sign_mask := int(0x80000000) for seed in seeds { - mut rng := wyrand.WyRandRNG{} + mut rng := &rand.PRNG(&wyrand.WyRandRNG{}) rng.seed(seed) for _ in 0 .. range_limit { value := rng.int31() @@ -187,7 +177,7 @@ fn test_wyrand_int63() { max_u63 := i64(0x7FFFFFFFFFFFFFFF) sign_mask := i64(0x8000000000000000) for seed in seeds { - mut rng := wyrand.WyRandRNG{} + mut rng := &rand.PRNG(&wyrand.WyRandRNG{}) rng.seed(seed) for _ in 0 .. range_limit { value := rng.int63() @@ -201,10 +191,10 @@ fn test_wyrand_int63() { fn test_wyrand_intn() { max := 2525642 for seed in seeds { - mut rng := wyrand.WyRandRNG{} + mut rng := &rand.PRNG(&wyrand.WyRandRNG{}) rng.seed(seed) for _ in 0 .. range_limit { - value := rng.intn(max) + value := rng.intn(max) or { panic("Couldn't obtain int") } assert value >= 0 assert value < max } @@ -214,10 +204,10 @@ fn test_wyrand_intn() { fn test_wyrand_i64n() { max := i64(3246727724653636) for seed in seeds { - mut rng := wyrand.WyRandRNG{} + mut rng := &rand.PRNG(&wyrand.WyRandRNG{}) rng.seed(seed) for _ in 0 .. range_limit { - value := rng.i64n(max) + value := rng.i64n(max) or { panic("Couldn't obtain i64") } assert value >= 0 assert value < max } @@ -228,10 +218,10 @@ fn test_wyrand_int_in_range() { min := -4252 max := 1034 for seed in seeds { - mut rng := wyrand.WyRandRNG{} + mut rng := &rand.PRNG(&wyrand.WyRandRNG{}) rng.seed(seed) for _ in 0 .. range_limit { - value := rng.int_in_range(min, max) + value := rng.int_in_range(min, max) or { panic("Couldn't obtain int in range") } assert value >= min assert value < max } @@ -242,10 +232,10 @@ fn test_wyrand_i64_in_range() { min := i64(-24095) max := i64(324058) for seed in seeds { - mut rng := wyrand.WyRandRNG{} + mut rng := &rand.PRNG(&wyrand.WyRandRNG{}) rng.seed(seed) for _ in 0 .. range_limit { - value := rng.i64_in_range(min, max) + value := rng.i64_in_range(min, max) or { panic("Couldn't obtain i64 in range") } assert value >= min assert value < max } @@ -254,7 +244,7 @@ fn test_wyrand_i64_in_range() { fn test_wyrand_f32() { for seed in seeds { - mut rng := wyrand.WyRandRNG{} + mut rng := &rand.PRNG(&wyrand.WyRandRNG{}) rng.seed(seed) for _ in 0 .. range_limit { value := rng.f32() @@ -266,7 +256,7 @@ fn test_wyrand_f32() { fn test_wyrand_f64() { for seed in seeds { - mut rng := wyrand.WyRandRNG{} + mut rng := &rand.PRNG(&wyrand.WyRandRNG{}) rng.seed(seed) for _ in 0 .. range_limit { value := rng.f64() @@ -279,10 +269,10 @@ fn test_wyrand_f64() { fn test_wyrand_f32n() { max := f32(357.0) for seed in seeds { - mut rng := wyrand.WyRandRNG{} + mut rng := &rand.PRNG(&wyrand.WyRandRNG{}) rng.seed(seed) for _ in 0 .. range_limit { - value := rng.f32n(max) + value := rng.f32n(max) or { panic("Couldn't obtain f32") } assert value >= 0.0 assert value < max } @@ -292,10 +282,10 @@ fn test_wyrand_f32n() { fn test_wyrand_f64n() { max := 1.52e6 for seed in seeds { - mut rng := wyrand.WyRandRNG{} + mut rng := &rand.PRNG(&wyrand.WyRandRNG{}) rng.seed(seed) for _ in 0 .. range_limit { - value := rng.f64n(max) + value := rng.f64n(max) or { panic("Couldn't obtain f64") } assert value >= 0.0 assert value < max } @@ -306,10 +296,10 @@ fn test_wyrand_f32_in_range() { min := f32(-24.0) max := f32(125.0) for seed in seeds { - mut rng := wyrand.WyRandRNG{} + mut rng := &rand.PRNG(&wyrand.WyRandRNG{}) rng.seed(seed) for _ in 0 .. range_limit { - value := rng.f32_in_range(min, max) + value := rng.f32_in_range(min, max) or { panic("Couldn't obtain f32 in range") } assert value >= min assert value < max } @@ -320,10 +310,10 @@ fn test_wyrand_f64_in_range() { min := -548.7 max := 5015.2 for seed in seeds { - mut rng := wyrand.WyRandRNG{} + mut rng := &rand.PRNG(&wyrand.WyRandRNG{}) rng.seed(seed) for _ in 0 .. range_limit { - value := rng.f64_in_range(min, max) + value := rng.f64_in_range(min, max) or { panic("Couldn't obtain f64 in range") } assert value >= min assert value < max } diff --git a/vlib/sync/channels.c.v b/vlib/sync/channels.c.v index 26cda0d9f..1854809fb 100644 --- a/vlib/sync/channels.c.v +++ b/vlib/sync/channels.c.v @@ -592,10 +592,10 @@ pub fn channel_select(mut channels []&Channel, dir []Direction, mut objrefs []vo mut event_idx := -1 // negative index means `timed out` outer: for { - rnd := rand.u32_in_range(0, u32(channels.len)) + rnd := rand.intn(channels.len) or { 0 } mut num_closed := 0 for j, _ in channels { - mut i := j + int(rnd) + mut i := j + rnd if i >= channels.len { i -= channels.len } diff --git a/vlib/time/misc/misc.v b/vlib/time/misc/misc.v index b0be1269a..408903644 100644 --- a/vlib/time/misc/misc.v +++ b/vlib/time/misc/misc.v @@ -9,5 +9,5 @@ const ( // random returns a random time struct in *the past*. pub fn random() time.Time { - return time.unix(int(rand.i64n(misc.start_time_unix))) + return time.unix(int(rand.i64n(misc.start_time_unix) or { 0 })) } diff --git a/vlib/v/tests/const_init_order_test.v b/vlib/v/tests/const_init_order_test.v index 35bb5586c..f0e47cfbc 100644 --- a/vlib/v/tests/const_init_order_test.v +++ b/vlib/v/tests/const_init_order_test.v @@ -1,7 +1,7 @@ import rand const ( - my_random_letter_const = byte(65 + rand.u32n(25)) + my_random_letter_const = byte(65) + (rand.byte() % 26) ) fn test_rand_is_initialized_before_main() { diff --git a/vlib/v/tests/generics_with_recursive_generics_fn_test.v b/vlib/v/tests/generics_with_recursive_generics_fn_test.v index 2e927e793..f4b55475f 100644 --- a/vlib/v/tests/generics_with_recursive_generics_fn_test.v +++ b/vlib/v/tests/generics_with_recursive_generics_fn_test.v @@ -8,7 +8,7 @@ const ( fn test_generics_with_recursive_generics_fn() { mut arr := []int{} for _ in 0 .. gen_len { - arr << rand.intn(gen_max) + arr << rand.intn(gen_max) or { 0 } } println('before quick sort whether array is sorted: ${is_sorted(arr)}') assert !is_sorted(arr) diff --git a/vlib/v/tests/keep_args_alive_test.v b/vlib/v/tests/keep_args_alive_test.v index 44375bd60..55fd4fb9d 100644 --- a/vlib/v/tests/keep_args_alive_test.v +++ b/vlib/v/tests/keep_args_alive_test.v @@ -49,9 +49,9 @@ fn tt(mut sem sync.Semaphore) int { fn waste_mem(n int, mut sem sync.Semaphore) { mut m := []voidptr{len: 30} for j := 0; n < 0 || j < n; j++ { - i := rand.intn(30) + i := rand.intn(30) or { 0 } m[i] = unsafe { malloc(10000) } - fill := rand.intn(256) + fill := rand.intn(256) or { 0 } unsafe { C.memset(m[i], fill, 10000) } if n < 0 && sem.try_wait() { break diff --git a/vlib/v/tests/valgrind/rand_module.v b/vlib/v/tests/valgrind/rand_module.v index eaa3e8c93..262654879 100644 --- a/vlib/v/tests/valgrind/rand_module.v +++ b/vlib/v/tests/valgrind/rand_module.v @@ -1,7 +1,7 @@ import rand fn main() { - n := rand.intn(1000) + n := rand.intn(1000) or { 0 } println(n) u := rand.uuid_v4() println(u) -- 2.30.2