Skip to content

Commit

Permalink
Merge pull request #1083 from dhardy/work
Browse files Browse the repository at this point in the history
Fix #1082 (seed_from_u64 with non multiple of 4)
  • Loading branch information
dhardy committed Jan 4, 2021
2 parents 34aa769 + 594aed8 commit bda9974
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 7 deletions.
5 changes: 4 additions & 1 deletion rand_core/CHANGELOG.md
Expand Up @@ -4,7 +4,10 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.6.1] - 2020-12-31
## [0.6.1] - 2021-01-03
### Fixed
- Avoid panic when using `RngCore::seed_from_u64` with a seed which is not a
multiple of four (#1082)
### Other
- Enable all stable features in the playground (#1081)

Expand Down
22 changes: 16 additions & 6 deletions rand_core/src/lib.rs
Expand Up @@ -300,20 +300,30 @@ pub trait SeedableRng: Sized {
/// considered a value-breaking change.
fn seed_from_u64(mut state: u64) -> Self {
// We use PCG32 to generate a u32 sequence, and copy to the seed
const MUL: u64 = 6364136223846793005;
const INC: u64 = 11634580027462260723;
fn pcg32(state: &mut u64) -> [u8; 4] {
const MUL: u64 = 6364136223846793005;
const INC: u64 = 11634580027462260723;

let mut seed = Self::Seed::default();
for chunk in seed.as_mut().chunks_mut(4) {
// We advance the state first (to get away from the input value,
// in case it has low Hamming Weight).
state = state.wrapping_mul(MUL).wrapping_add(INC);
*state = state.wrapping_mul(MUL).wrapping_add(INC);
let state = *state;

// Use PCG output function with to_le to generate x:
let xorshifted = (((state >> 18) ^ state) >> 27) as u32;
let rot = (state >> 59) as u32;
let x = xorshifted.rotate_right(rot);
chunk.copy_from_slice(&x.to_le_bytes());
x.to_le_bytes()
}

let mut seed = Self::Seed::default();
let mut iter = seed.as_mut().chunks_exact_mut(4);
for chunk in &mut iter {
chunk.copy_from_slice(&pcg32(&mut state));
}
let rem = iter.into_remainder();
if !rem.is_empty() {
rem.copy_from_slice(&pcg32(&mut state)[..rem.len()]);
}

Self::from_seed(seed)
Expand Down

0 comments on commit bda9974

Please sign in to comment.