Skip to content

Commit

Permalink
Merge pull request #425 from rust-lang-nursery/blockrng
Browse files Browse the repository at this point in the history
BlockRng: make core public and remove inner() and inner_mut()
  • Loading branch information
dhardy authored May 7, 2018
2 parents f25c24e + 736a6e0 commit 2c3d34d
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 43 deletions.
2 changes: 1 addition & 1 deletion rand_core/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [0.2.0] - Unreleased
- Enable the `std` feature by default. (#409)
- Change `BlockRng64::inner` and add `BlockRng64::inner_mut` to mirror `BlockRng`. (#419)
- Remove `BlockRng{64}::inner` and `BlockRng::inner_mut`; instead making `core` public
- Add `BlockRng{64}::index` and `BlockRng{64}::generate_and_set`. (#374, #419)
- Change `BlockRngCore::Results` bound to also require `AsMut<[Self::Item]>`. (#419)

Expand Down
60 changes: 31 additions & 29 deletions rand_core/src/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,18 +165,28 @@ pub fn next_u64_via_fill<R: RngCore + ?Sized>(rng: &mut R) -> u64 {
impl_uint_from_fill!(rng, u64, 8)
}

/// Wrapper around PRNGs that implement [`BlockRngCore`] to keep a results
/// buffer and offer the methods from [`RngCore`].
/// A wrapper type implementing [`RngCore`] for some type implementing
/// [`BlockRngCore`] with `u32` array buffer; i.e. this can be used to implement
/// a full RNG from just a `generate` function.
///
/// The `core` field may be accessed directly but the results buffer may not.
/// PRNG implementations can simply use a type alias
/// (`pub type MyRng = BlockRng<MyRngCore>;`) but might prefer to use a
/// wrapper type (`pub struct MyRng(BlockRng<MyRngCore>);`); the latter must
/// re-implement `RngCore` but hides the implementation details and allows
/// extra functionality to be defined on the RNG
/// (e.g. `impl MyRng { fn set_stream(...){...} }`).
///
/// `BlockRng` has heavily optimized implementations of the [`RngCore`] methods
/// reading values from the results buffer, as well as
/// calling `BlockRngCore::generate` directly on the output array when
/// `fill_bytes` / `try_fill_bytes` is called on a large array. These methods
/// also handle the bookkeeping of when to generate a new batch of values.
/// No generated values are ever thown away.
/// No generated values are ever thown away and all values are consumed
/// in-order (this may be important for reproducibility).
///
/// Currently `BlockRng` only implements `RngCore` for buffers which are slices
/// of `u32` elements; this may be extended to other types in the future.
/// See also [`BlockRng64`] which uses `u64` array buffers. Currently there is
/// no direct support for other buffer types.
///
/// For easy initialization `BlockRng` also implements [`SeedableRng`].
///
Expand All @@ -188,7 +198,8 @@ pub fn next_u64_via_fill<R: RngCore + ?Sized>(rng: &mut R) -> u64 {
pub struct BlockRng<R: BlockRngCore + ?Sized> {
results: R::Results,
index: usize,
core: R,
/// The *core* part of the RNG, implementing the `generate` function.
pub core: R,
}

// Custom Debug implementation that does not expose the contents of `results`.
Expand All @@ -214,16 +225,6 @@ impl<R: BlockRngCore> BlockRng<R> {
}
}

/// Return a reference the wrapped `BlockRngCore`.
pub fn inner(&self) -> &R {
&self.core
}

/// Return a mutable reference the wrapped `BlockRngCore`.
pub fn inner_mut(&mut self) -> &mut R {
&mut self.core
}

/// Get the index into the result buffer.
///
/// If this is equal to or larger than the size of the result buffer then
Expand Down Expand Up @@ -370,12 +371,20 @@ impl<R: BlockRngCore + SeedableRng> SeedableRng for BlockRng<R> {



/// Wrapper around PRNGs that implement [`BlockRngCore`] to keep a results
/// buffer and offer the methods from [`RngCore`].
/// A wrapper type implementing [`RngCore`] for some type implementing
/// [`BlockRngCore`] with `u64` array buffer; i.e. this can be used to implement
/// a full RNG from just a `generate` function.
///
/// This is similar to [`BlockRng`], but specialized for algorithms that operate
/// on `u64` values.
///
/// Like [`BlockRng`], this wrapper does not throw away whole results and does
/// use all generated values in-order. The behaviour of `next_u32` is however
/// a bit special: half of a `u64` is consumed, leaving the other half in the
/// buffer. If the next function called is `next_u32` then the other half is
/// then consumed, however both `next_u64` and `fill_bytes` discard any
/// half-consumed `u64`s when called.
///
/// [`BlockRngCore`]: ../BlockRngCore.t.html
/// [`RngCore`]: ../RngCore.t.html
/// [`BlockRng`]: struct.BlockRng.html
Expand All @@ -385,7 +394,8 @@ pub struct BlockRng64<R: BlockRngCore + ?Sized> {
results: R::Results,
index: usize,
half_used: bool, // true if only half of the previous result is used
core: R,
/// The *core* part of the RNG, implementing the `generate` function.
pub core: R,
}

// Custom Debug implementation that does not expose the contents of `results`.
Expand Down Expand Up @@ -413,16 +423,6 @@ impl<R: BlockRngCore> BlockRng64<R> {
}
}

/// Return a reference the wrapped `BlockRngCore`.
pub fn inner(&self) -> &R {
&self.core
}

/// Return a mutable reference the wrapped `BlockRngCore`.
pub fn inner_mut(&mut self) -> &mut R {
&mut self.core
}

/// Get the index into the result buffer.
///
/// If this is equal to or larger than the size of the result buffer then
Expand All @@ -436,6 +436,7 @@ impl<R: BlockRngCore> BlockRng64<R> {
/// This will force a new set of results to be generated on next use.
pub fn reset(&mut self) {
self.index = self.results.as_ref().len();
self.half_used = false;
}

/// Generate a new set of results immediately, setting the index to the
Expand All @@ -444,6 +445,7 @@ impl<R: BlockRngCore> BlockRng64<R> {
assert!(index < self.results.as_ref().len());
self.core.generate(&mut self.results);
self.index = index;
self.half_used = false;
}
}

Expand Down
20 changes: 9 additions & 11 deletions src/prng/chacha.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,9 +138,8 @@ impl ChaChaRng {
/// feature is enabled. In the future this will be enabled by default.
#[cfg(feature = "i128_support")]
pub fn get_word_pos(&self) -> u128 {
let core = self.0.inner();
let mut c = (core.state[13] as u64) << 32
| (core.state[12] as u64);
let mut c = (self.0.core.state[13] as u64) << 32
| (self.0.core.state[12] as u64);
let mut index = self.0.index();
// c is the end of the last block generated, unless index is at end
if index >= STATE_WORDS {
Expand All @@ -163,8 +162,8 @@ impl ChaChaRng {
pub fn set_word_pos(&mut self, word_offset: u128) {
let index = (word_offset as usize) & 0xF;
let counter = (word_offset >> 4) as u64;
self.0.inner_mut().state[12] = counter as u32;
self.0.inner_mut().state[13] = (counter >> 32) as u32;
self.0.core.state[12] = counter as u32;
self.0.core.state[13] = (counter >> 32) as u32;
if index != 0 {
self.0.generate_and_set(index); // also increments counter
} else {
Expand All @@ -185,17 +184,16 @@ impl ChaChaRng {
/// indirectly via `set_word_pos`), but this is not directly supported.
pub fn set_stream(&mut self, stream: u64) {
let index = self.0.index();
self.0.inner_mut().state[14] = stream as u32;
self.0.inner_mut().state[15] = (stream >> 32) as u32;
self.0.core.state[14] = stream as u32;
self.0.core.state[15] = (stream >> 32) as u32;
if index < STATE_WORDS {
// we need to regenerate a partial result buffer
{
// reverse of counter adjustment in generate()
let core = self.0.inner_mut();
if core.state[12] == 0 {
core.state[13] = core.state[13].wrapping_sub(1);
if self.0.core.state[12] == 0 {
self.0.core.state[13] = self.0.core.state[13].wrapping_sub(1);
}
core.state[12] = core.state[12].wrapping_sub(1);
self.0.core.state[12] = self.0.core.state[12].wrapping_sub(1);
}
self.0.generate_and_set(index);
}
Expand Down
4 changes: 2 additions & 2 deletions src/reseeding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ where R: BlockRngCore + SeedableRng,

/// Reseed the internal PRNG.
pub fn reseed(&mut self) -> Result<(), Error> {
self.0.inner_mut().reseed()
self.0.core.reseed()
}
}

Expand Down Expand Up @@ -112,7 +112,7 @@ where R: BlockRngCore + SeedableRng + Clone,
fn clone(&self) -> ReseedingRng<R, Rsdr> {
// Recreating `BlockRng` seems easier than cloning it and resetting
// the index.
ReseedingRng(BlockRng::new(self.0.inner().clone()))
ReseedingRng(BlockRng::new(self.0.core.clone()))
}
}

Expand Down

0 comments on commit 2c3d34d

Please sign in to comment.