Skip to content

Commit

Permalink
rand: add missing i32 APIs, corresponding to the int ones
Browse files Browse the repository at this point in the history
  • Loading branch information
spytheman committed Dec 5, 2024
1 parent b6b9654 commit 3254987
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 1 deletion.
40 changes: 39 additions & 1 deletion vlib/rand/rand.v
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,13 @@ pub fn (mut rng PRNG) read(mut buf []u8) {
read_internal(mut rng, mut buf)
}

// u32n returns a uniformly distributed pseudorandom 32-bit signed positive `u32` in range `[0, max)`.
// i32n returns a uniformly distributed pseudorandom 32-bit signed positive `i32` in range `[0, max)`.
@[inline]
pub fn (mut rng PRNG) i32n(max i32) !i32 {
return i32(rng.intn(max)!)
}

// u32n returns a uniformly distributed pseudorandom 32-bit unsigned positive `u32` in range `[0, max)`.
@[inline]
pub fn (mut rng PRNG) u32n(max u32) !u32 {
if max == 0 {
Expand Down Expand Up @@ -138,6 +144,12 @@ pub fn (mut rng PRNG) i16() i16 {
return i16(rng.u16())
}

// i32 returns a (possibly negative) pseudorandom 32-bit `i32`.
@[inline]
pub fn (mut rng PRNG) i32() i32 {
return i32(rng.u32())
}

// int returns a (possibly negative) pseudorandom 32-bit `int`.
@[inline]
pub fn (mut rng PRNG) int() int {
Expand Down Expand Up @@ -190,6 +202,16 @@ pub fn (mut rng PRNG) int_in_range(min int, max int) !int {
return min + rng.intn(max - min)!
}

// int_in_range returns a pseudorandom `int` in range `[min, max)`.
@[inline]
pub fn (mut rng PRNG) i32_in_range(min i32, max i32) !i32 {
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 + i32(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 {
Expand Down Expand Up @@ -564,11 +586,21 @@ pub fn i16() i16 {
return default_rng.i16()
}

// i32 returns a uniformly distributed pseudorandom 32-bit signed (possibly negative) `i32`.
pub fn i32() i32 {
return default_rng.i32()
}

// int returns a uniformly distributed pseudorandom 32-bit signed (possibly negative) `int`.
pub fn int() int {
return default_rng.int()
}

// i32n returns a uniformly distributed pseudorandom 32-bit signed positive `i32` in range `[0, max)`.
pub fn i32n(max i32) !i32 {
return default_rng.i32n(max)
}

// intn returns a uniformly distributed pseudorandom 32-bit signed positive `int` in range `[0, max)`.
pub fn intn(max int) !int {
return default_rng.intn(max)
Expand All @@ -580,6 +612,12 @@ pub fn int_in_range(min int, max int) !int {
return default_rng.int_in_range(min, max)
}

// 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 i32_in_range(min i32, max i32) !i32 {
return default_rng.i32_in_range(min, max)
}

// int31 returns a uniformly distributed pseudorandom 31-bit signed positive `int`.
pub fn int31() int {
return default_rng.int31()
Expand Down
21 changes: 21 additions & 0 deletions vlib/rand/random_numbers_test.v
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,15 @@ fn test_rand_intn() {
}
}

fn test_rand_i32n() {
max := i32(2525642)
for _ in 0 .. rnd_count {
value := rand.i32n(max) or { panic("Couldn't obtain i32") }
assert value >= 0
assert value < max
}
}

fn test_rand_i64n() {
max := i64(3246727724653636)
for _ in 0 .. rnd_count {
Expand All @@ -90,6 +99,16 @@ fn test_rand_int_in_range() {
}
}

fn test_rand_i32_in_range() {
min := i32(-4252)
max := i32(23054962)
for _ in 0 .. rnd_count {
value := rand.i32_in_range(min, max) or { panic("Couldn't obtain i32 in range") }
assert value >= min
assert value < max
}
}

fn test_rand_i64_in_range() {
min := i64(-24095)
max := i64(324058)
Expand Down Expand Up @@ -324,7 +343,9 @@ fn test_rand_ascii() {
fn ensure_same_output(mut rng rand.PRNG) {
for _ in 0 .. 100 {
assert rand.int() == rng.int()
assert rand.i32() == rng.i32()
assert rand.intn(45) or { 0 } == rng.intn(45) or { 0 }
assert rand.i32n(45) or { 0 } == rng.i32n(45) or { 0 }
assert rand.u64() == rng.u64()
assert rand.f64() == rng.f64()
assert rand.u32n(25) or { 0 } == rng.u32n(25) or { 0 }
Expand Down
29 changes: 29 additions & 0 deletions vlib/rand/sys/system_rng_test.v
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,20 @@ fn test_sys_rng_intn() {
}
}

fn test_sys_rng_i32n() {
max := i32(2525642)
for seed in seeds {
seed_data := [seed]
mut rng := &rand.PRNG(&sys.SysRNG{})
rng.seed(seed_data)
for _ in 0 .. range_limit {
value := rng.i32n(max) or { panic("Couldn't obtain i32") }
assert value >= 0
assert value < max
}
}
}

fn test_sys_rng_i64n() {
max := i64(3246727724653636)
for seed in seeds {
Expand Down Expand Up @@ -207,6 +221,21 @@ fn test_sys_rng_int_in_range() {
}
}

fn test_sys_rng_i32_in_range() {
min := i32(-4252)
max := i32(23054962)
for seed in seeds {
seed_data := [seed]
mut rng := &rand.PRNG(&sys.SysRNG{})
rng.seed(seed_data)
for _ in 0 .. range_limit {
value := rng.i32_in_range(min, max) or { panic("Couldn't obtain i32 in range") }
assert value >= min
assert value < max
}
}
}

fn test_sys_rng_i64_in_range() {
min := i64(-24095)
max := i64(324058)
Expand Down

0 comments on commit 3254987

Please sign in to comment.