rust-random / rand

A Rust library for random number generation.
https://crates.io/crates/rand
Other
1.6k stars 423 forks source link

rand::rngs::StdRng produces different values in/out struct #1463

Closed TOPbuaa closed 1 week ago

TOPbuaa commented 1 week ago

Code sample

I provide a minimal repo with 40 lines of code for this issue: https://github.com/TOPbuaa/mini_test_rand.

Summary

When I use rand inside a struct with the same seed, the results are different from when it is outside the struct. Is my usage wrong? or is there a bug causing undefined behavior?

dhardy commented 1 week ago

This can be run from the playground: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=8d72ab06f71630e19818510ea55b2261

I noticed that commenting out one line in particular affects the result.

dhardy commented 1 week ago

Testing with v0.9.0-alpha.1 yields the same sequence for direct usage of StdRng and a different sequence for usage via the struct. Testing with the latest (ca9e1198596ef766714c4c4fdb0070a45334b077) yields the same results as v0.9.0-alpha.1.

dhardy commented 1 week ago

Without diving into the code, it is feasible that there is a bug in rand_chacha or one of its dependencies. These use unsafe CPU-specific optimisations, which seems the most likely cause.

We have plans to replace this entire implementation (#934), so this bug might get fixed as a side-effect.

TheIronBorn commented 1 week ago

I don't think it's an issue with ChaCha. I just reproduced this issue with the Isaac rngs, Hc128, and various Xorshift/Xoshiro/Xoroshiro rngs

TheIronBorn commented 1 week ago

Ah it's because the compiler is changing the type of gen_range. gen_range(0_u64 fixes it

TOPbuaa commented 1 week ago

Ah it's because the compiler is changing the type of gen_range. gen_range(0_u64 fixes it

Fine. Adding the _u64 suffix works well for me.

vks commented 1 week ago

For clarity: In the struct, you are specifying the type as u64, which gets propagated to gen_range. Outside the struct, you are not specifying the type, and therefore the compiler falls back to the default integer type, which is i32.