diff --git a/vlib/rand/rand.v b/vlib/rand/rand.v index 8df348dc32..18168e499e 100644 --- a/vlib/rand/rand.v +++ b/vlib/rand/rand.v @@ -12,4 +12,18 @@ pub fn next(max int) int { return C.rand() % max } -fn C.rand() int +fn C.rand() int + +/** + * rand_r - reentrant pseudo-random number generator + * + * @param seed byref reentrant seed, holding current state + * + * @return a value between 0 and C.RAND_MAX (inclusive) + */ +pub fn rand_r(seed &int) int { + mut rs := seed + ns := ( *rs * 1103515245 + 12345 ) + *rs = ns + return ns & 0x7fffffff +} diff --git a/vlib/rand/rand_test.v b/vlib/rand/rand_test.v index cdfc193cb4..61ddbeaa29 100644 --- a/vlib/rand/rand_test.v +++ b/vlib/rand/rand_test.v @@ -28,3 +28,31 @@ fn test_rand_reproducibility() { assert randoms1[i] == randoms2[i] } } + +fn gen_randoms_r(seed int) []int { + mut randoms := [0].repeat(20) + for i in 0..20 { + randoms[i] = rand.rand_r(&seed) + } + return randoms +} + +fn test_rand_r_reproducibility() { + mut randoms1 := gen_randoms_r(42) + mut randoms2 := gen_randoms_r(42) + assert randoms1.len == randoms2.len + + mut len := randoms1.len + for i in 0..len { + assert randoms1[i] == randoms2[i] + } + + randoms1 = gen_randoms_r(256) + randoms2 = gen_randoms_r(256) + assert randoms1.len == randoms2.len + + len = randoms1.len + for i in 0..len { + assert randoms1[i] == randoms2[i] + } +}