-
Notifications
You must be signed in to change notification settings - Fork 36
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
clone() does not behave as expected #36
Comments
How does |
It is auto derived. So it basically works by cloning internal state. |
Hmm, looking at the PR that added Clone impl (#4 by @cloudhead), it seems that the current behavior is intentional? |
It was intentional yes, as pointed out by the docs. Perhaps the |
I am not sure that was intentional. For example current pull request 3e11c10 still passes same doctest as it was defined in https://github.com/smol-rs/fastrand/blob/master/src/lib.rs#L101-L113 and covers clone() related properties. |
See the first line of the PR: By "splitting" it's meant that we generate a new RNG that isn't equal to the previous one. The documentation also explains that we derive a generator from the previous one. The test is also carefully chosen not to compare the derived generator with the original generator. The problem is really the name chosen: "clone", so I'd propose we implement actual cloning under the clone function, and move the current clone functionality to a new function called "fork". |
I see. |
Let me bump this with suggested improvement to Once rng is forked it is expected that output of each generator is uncorrelated with each other. For example if one splits generator for use in multiple threads, each generator should generate different numbers. I suggest we have public function that makes forking clear.
And implementation, for example pub fn fork(self) -> (Self, Self) {
let rand_a: u64 = 0xc0d43516ee92d71f;
let rand_b: u64 = 0x91b6dcec5810da71;
(
Self::with_seed(self.gen_u64() ^ rand_a),
Self::with_seed(self.gen_u64() ^ rand_b),
)
} |
That is creating two forks though. It's a bit impractical as an API because you move self, and you return a tuple, so you can't just do eg.: let base = Rng::new();
thread1(base.fork());
thread2(base.fork());
thread3(base.fork()); |
I see your point @cloudhead . It less ergonomic compared to moving tuple around. I guess we have two options. What is your opinion of fn fork(&self) -> Self vs fn fork(&mut self) -> Self |
Hmm, so I would opt for Rng::alphabetic(&self) -> char
Rng::bool(&self) -> bool
Rng::fork(&self) -> Rng You could almost call the function |
My personal vote is for |
I went with |
There is PR available and should include features and interface as discussed here. #38 |
|
Related to PR #49. Is it bug or feature that forked rng is correlated with sourced rng? |
Could you please clarify? |
I did, but it seems that my reasoning was incorrect. |
This fails, but I think it should not.
The text was updated successfully, but these errors were encountered: