Skip to content
Snippets Groups Projects
Commit 13a10ce7 authored by Alex Lyon's avatar Alex Lyon
Browse files

stdlib: implement rand_r() using XorShiftRng

parent 60746168
No related branches found
No related tags found
No related merge requests found
......@@ -628,9 +628,21 @@ pub unsafe extern "C" fn rand() -> c_int {
}
}
// #[no_mangle]
pub extern "C" fn rand_r(seed: *mut c_uint) -> c_int {
unimplemented!();
#[no_mangle]
pub unsafe extern "C" fn rand_r(seed: *mut c_uint) -> c_int {
if seed.is_null() {
errno::EINVAL
} else {
// set the type explicitly so this will fail if the array size for XorShiftRng changes
let seed_arr: [u8; 16] = mem::transmute([*seed; 16 / mem::size_of::<c_uint>()]);
let mut rng = XorShiftRng::from_seed(seed_arr);
let ret = rng.gen_range(0, RAND_MAX);
*seed = ret as _;
ret
}
}
// #[no_mangle]
......
......@@ -2,3 +2,7 @@
201425341
201425341
67141780
264204
271585843
264204
271585843
......@@ -31,4 +31,40 @@ int main(void) {
puts("srand(1) doesn't work");
exit(EXIT_FAILURE);
}
// Ensure rand_r() fails with NULL input
if (rand_r(NULL) != EINVAL) {
puts("rand_r(NULL) doesn't return EINVAL");
exit(EXIT_FAILURE);
}
// Ensure rand_r() produces unique values
int seed = 259;
int rand_r_seed259_1 = rand_r((unsigned *)&seed);
printf("%d\n", rand_r_seed259_1);
int rand_r_seed259_2 = rand_r((unsigned *)&seed);
printf("%d\n", rand_r_seed259_2);
if (rand_r_seed259_1 == rand_r_seed259_2) {
puts("rand_r() fails to produce unique values");
exit(EXIT_FAILURE);
}
// Ensure rand_r() returns reproducible values
seed = 259;
int rand_r_seed259_1_2 = rand_r((unsigned *)&seed);
printf("%d\n", rand_r_seed259_1_2);
int rand_r_seed259_2_2 = rand_r((unsigned *)&seed);
printf("%d\n", rand_r_seed259_2_2);
if (rand_r_seed259_1 != rand_r_seed259_1_2
|| rand_r_seed259_2 != rand_r_seed259_2_2)
{
puts("rand_r() is not reproducible");
exit(EXIT_FAILURE);
}
return 0;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment