-
Notifications
You must be signed in to change notification settings - Fork 430
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
Convenient PRNG construction: seed_from_u64
/ from_hashable
#522
Comments
Thank you for opening the issue and the good description. A couple of months ago I started working on this (code), but it may be easier to start fresh. |
Vigna suggests to seed his RNGs using SplitMix64. This could work for other RNGs as well.
…On Thu, Jun 21, 2018, 18:08 Paul Dicker ***@***.***> wrote:
Thank you for opening the issue and the good description. A couple of
months ago I started working on this (code
<pitdicker@324471d>),
but it may be easier to start fresh.
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
<#522 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AACCtBGiORSL4mJEaoZbs6ujdBv6BY-jks5t-8UPgaJpZM4UyVoQ>
.
|
So In other words, this is a cut-down version of the Also sounds like a good option. Though we could consider using something like SipHash over SplitMix. |
Lets not forget that we already have an implementation: pub fn rng(seed: u64) -> TestRng<StdRng> {
// TODO: use from_hashable
let mut state = seed;
let mut seed = <StdRng as SeedableRng>::Seed::default();
for x in seed.iter_mut() {
// PCG algorithm
const MUL: u64 = 6364136223846793005;
const INC: u64 = 11634580027462260723;
let oldstate = state;
state = oldstate.wrapping_mul(MUL).wrapping_add(INC);
let xorshifted = (((oldstate >> 18) ^ oldstate) >> 27) as u32;
let rot = (oldstate >> 59) as u32;
*x = xorshifted.rotate_right(rot) as u8;
}
TestRng { inner: StdRng::from_seed(seed) }
} This is literally all the code we need. Is there any reason that another algorithm, e.g. SplitMix, would be preferably over this? As far as I am aware there are no issues seeding PCG from itself. |
|
Sounds like a decent approach. But isn't that site down for you? I haven't been able to access So I decided to do a brute force check for the longest zero sequence output by PCG:
|
Any PRNG with a 64-bit state will produce only one I agree both SplitMix and PCG could be equally good as a form of seed expansion (I had a small SplitMix helper function in my branch). But this is just a detail. Rust implementations of Xoroshiro and co. can use SplitMix. Other PRNGs can use what is common for those, probably running it a couple of rounds. |
Assuming equidistribution of output, which generally isn't a given. True; individual PRNGs can provide their own implementation of |
I used an archived version of the website. |
If you have a link to the dsiutils package you can share that would be helpful. It seems that PCG is a better quality generator than SplitMix, yet since we need so little output to fill a seed it doesn't matter much. If we use PCG and don't pre-process the seed we should discard the first value (since seeds like 0 and 1 produce poor output), though if we only use one byte as in the code above it doesn't matter much. Hash functions let users turn arbitrary input into a Perhaps then we should
|
Rough implementation: dhardy@6ea3f6a But it might be better to base this on the 0.5 branch (so that we don't release |
The download isn't archived but the API is: https://web.archive.org/web/20171218222630/http://dsiutils.di.unimi.it:80/docs/ |
Introducing |
Note that using an RNG like splitmix64 for seeding is similar to seeding using a weak hash function: The mixing functions in a hash are supposed to make sure that flipping a bit in the input results in all output bits changing with probability 0.5. (This is called Avalanche effect). Cryptographically secure hashes make this probability as close as possible to 0.5, while non-CS hashes trade avalanche accuracy for performance. This translates to CSPRNGs and non-CSPRNGs. For example, splitmix64 uses such a weak mixing function that is similar to the one used by MurmurHash3. In that regard, I think My suggestion is to add a |
|
Why not? We can't use negative trait bounds, but we can still only implement it for non-crypto RNGs.
That's true, but is it worth the risk that it might be misused? (OTOH, it is not so diffferent from misusing |
The only definition of a "non-crypto RNG" is a negative bound. I'm not so concerned about mis-use here: you don't have to know very much about cryptography to know that a 64-bit seed is insufficient. In any case, cryptography should normally be handled by a higher-level library. |
History: when discussing the design of the
SeedableRng
trait (dhardy#18), we came up with a number of proposals, before settling on the current design. However we always intended on adding another function for convenient generic construction.Motivation: provide a convenient way to seed any PRNGs via a trait function. This is primarily aimed at users wanting to construct reproducible PRNGs for games and simulations, and is not for password hashing.
Requirements
And non-requirements:
Proposals
fn seed_from_u64(&mut self, seed: u64) -> Self
This function is proposed as the simplest option fulfilling all requirements. Quoting @pitdicker (Seeding PRNGs (traits and bit size) dhardy/rand#18 (comment)):
fn from_hashable<T: Hashable>(x: T) -> Self
: SeedableRng::Seed and from_hashable dhardy/rand#62; codeThis proposal is very flexible (any PRNG can be constructed from any hashable type), but involves adding a hash function to
rand_core
(or potentiallyrand
, but this preventsfrom_hashable
being defined onSeedableRng
), as well as questions of whether we should use a cryptographic hash function or optimise for speed (neither appears necessary).Note that we wish to allow users to reproduce output from PRNGs constructed via this mechanism, thus we cannot rely on
std::hash
(which is not portable and whose implementation may change).No extra functionality.
SeedableRng::Seed
already supportsDefault
andAsMut<[u8]>
, i.e. it can be constructed withdefault()
and then accessed as&mut [u8]
. This is sufficient to construct arbitrary seeds using generic code, but not necessarily convenient.Note: whatever we go with, it is possible for both of these proposals to be implemented by an external crate, with the only restriction being that this function cannot be added to the
SeedableRng
trait.Currently I like @pitdicker's recent suggestion best: add
SeedableRng::seed_from_u64
with a default implementation.The text was updated successfully, but these errors were encountered: