Skip to content

Commit

Permalink
impl PartialEq, Eq for rngs (#979)
Browse files Browse the repository at this point in the history
Implements #974. As in #975, but defining equality such that the user is
not exposed to the fact that one logical state may have different
representations in an implementation-specific way.
  • Loading branch information
kazcw committed May 29, 2020
1 parent 22cc8fe commit 4b99567
Show file tree
Hide file tree
Showing 16 changed files with 56 additions and 17 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -10,6 +10,7 @@ You may also find the [Upgrade Guide](https://rust-random.github.io/book/update.

## [Unreleased]
### Additions
- impl PartialEq+Eq for StdRng, SmallRng, and StepRng (#975)
- Added a `serde1` feature and added Serialize/Deserialize to `UniformInt` and `WeightedIndex` (#974)

## [0.7.3] - 2020-01-10
Expand Down
8 changes: 4 additions & 4 deletions Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "rand"
version = "0.7.3"
version = "0.7.4"
authors = ["The Rand Project Developers", "The Rust Project Developers"]
license = "MIT OR Apache-2.0"
readme = "README.md"
Expand Down Expand Up @@ -56,7 +56,7 @@ members = [

[dependencies]
rand_core = { path = "rand_core", version = "0.5.1" }
rand_pcg = { path = "rand_pcg", version = "0.2", optional = true }
rand_pcg = { path = "rand_pcg", version = "0.2.1", optional = true }
log = { version = "0.4.4", optional = true }
serde = { version = "1.0.103", features = ["derive"], optional = true }

Expand All @@ -74,9 +74,9 @@ libc = { version = "0.2.22", optional = true, default-features = false }
# Emscripten does not support 128-bit integers, which are used by ChaCha code.
# We work around this by using a different RNG.
[target.'cfg(not(target_os = "emscripten"))'.dependencies]
rand_chacha = { path = "rand_chacha", version = "0.2.1", default-features = false, optional = true }
rand_chacha = { path = "rand_chacha", version = "0.2.3", default-features = false, optional = true }
[target.'cfg(target_os = "emscripten")'.dependencies]
rand_hc = { path = "rand_hc", version = "0.2", optional = true }
rand_hc = { path = "rand_hc", version = "0.2.1", optional = true }

[dev-dependencies]
rand_pcg = { path = "rand_pcg", version = "0.2" }
Expand Down
1 change: 1 addition & 0 deletions rand_chacha/CHANGELOG.md
Expand Up @@ -5,6 +5,7 @@ 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).

## [Unreleased]
- impl PartialEq+Eq for ChaChaXRng and ChaChaXCore (#975)
- Fix panic on block counter wrap that was occurring in debug builds

## [0.2.2] - 2020-03-09
Expand Down
6 changes: 3 additions & 3 deletions rand_chacha/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "rand_chacha"
version = "0.2.2"
version = "0.2.3"
authors = ["The Rand Project Developers", "The Rust Project Developers", "The CryptoCorrosion Contributors"]
license = "MIT OR Apache-2.0"
readme = "README.md"
Expand All @@ -20,9 +20,9 @@ appveyor = { repository = "rust-random/rand" }

[dependencies]
rand_core = { path = "../rand_core", version = "0.5" }
ppv-lite86 = { version = "0.2.6", default-features = false, features = ["simd"] }
ppv-lite86 = { version = "0.2.8", default-features = false }

[features]
default = ["std", "simd"]
default = ["std"]
std = ["ppv-lite86/std"]
simd = [] # deprecated
10 changes: 9 additions & 1 deletion rand_chacha/src/chacha.rs
Expand Up @@ -70,7 +70,7 @@ impl<T> fmt::Debug for Array64<T> {
macro_rules! chacha_impl {
($ChaChaXCore:ident, $ChaChaXRng:ident, $rounds:expr, $doc:expr) => {
#[doc=$doc]
#[derive(Clone)]
#[derive(Clone, PartialEq, Eq)]
pub struct $ChaChaXCore {
state: ChaCha,
}
Expand Down Expand Up @@ -255,6 +255,14 @@ macro_rules! chacha_impl {
}
}
}

impl PartialEq<$ChaChaXRng> for $ChaChaXRng {
fn eq(&self, rhs: &$ChaChaXRng) -> bool {
self.rng.core.state.stream64_eq(&rhs.rng.core.state)
&& self.get_word_pos() == rhs.get_word_pos()
}
}
impl Eq for $ChaChaXRng {}
}
}

Expand Down
10 changes: 9 additions & 1 deletion rand_chacha/src/guts.rs
Expand Up @@ -21,7 +21,7 @@ const BUFBLOCKS: u64 = 1 << LOG2_BUFBLOCKS;
pub(crate) const BUFSZ64: u64 = BLOCK64 * BUFBLOCKS;
pub(crate) const BUFSZ: usize = BUFSZ64 as usize;

#[derive(Clone)]
#[derive(Clone, PartialEq, Eq)]
pub struct ChaCha {
pub(crate) b: vec128_storage,
pub(crate) c: vec128_storage,
Expand Down Expand Up @@ -91,6 +91,14 @@ impl ChaCha {
pub fn get_stream_param(&self, param: u32) -> u64 {
get_stream_param(self, param)
}

/// Return whether rhs is equal in all parameters except current 64-bit position.
#[inline]
pub fn stream64_eq(&self, rhs: &Self) -> bool {
let self_d: [u32; 4] = self.d.into();
let rhs_d: [u32; 4] = rhs.d.into();
self.b == rhs.b && self.c == rhs.c && self_d[3] == rhs_d[3] && self_d[2] == rhs_d[2]
}
}

#[inline(always)]
Expand Down
3 changes: 3 additions & 0 deletions rand_hc/CHANGELOG.md
Expand Up @@ -4,6 +4,9 @@ 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).

## [Unreleased]
- impl PartialEq+Eq for Hc128Rng and Hc128Core (#975)

## [0.2.0] - 2019-06-12
- Bump minor crate version since rand_core bump is a breaking change
- Switch to Edition 2018
Expand Down
2 changes: 1 addition & 1 deletion rand_hc/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "rand_hc"
version = "0.2.0"
version = "0.2.1"
authors = ["The Rand Project Developers"]
license = "MIT OR Apache-2.0"
readme = "README.md"
Expand Down
15 changes: 15 additions & 0 deletions rand_hc/src/hc128.rs
Expand Up @@ -104,6 +104,13 @@ impl SeedableRng for Hc128Rng {

impl CryptoRng for Hc128Rng {}

impl PartialEq for Hc128Rng {
fn eq(&self, rhs: &Self) -> bool {
self.0.core == rhs.0.core && self.0.index() == rhs.0.index()
}
}
impl Eq for Hc128Rng {}

/// The core of `Hc128Rng`, used with `BlockRng`.
#[derive(Clone)]
pub struct Hc128Core {
Expand Down Expand Up @@ -344,6 +351,14 @@ impl SeedableRng for Hc128Core {

impl CryptoRng for Hc128Core {}

// Custom PartialEq implementation as it can't currently be derived from an array of size 1024
impl PartialEq for Hc128Core {
fn eq(&self, rhs: &Self) -> bool {
&self.t[..] == &rhs.t[..] && self.counter1024 == rhs.counter1024
}
}
impl Eq for Hc128Core {}

#[cfg(test)]
mod test {
use super::Hc128Rng;
Expand Down
3 changes: 3 additions & 0 deletions rand_pcg/CHANGELOG.md
Expand Up @@ -4,6 +4,9 @@ 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).

## [Unreleased]
- Derive PartialEq+Eq for Lcg64Xsh32, Lcg128Xsl64, and Mcg128Xsl64 (#975)

## [0.2.1] - 2019-10-22
- Bump `bincode` version to 1.1.4 to fix minimal-dependency builds
- Removed unused `autocfg` build dependency.
Expand Down
2 changes: 1 addition & 1 deletion rand_pcg/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "rand_pcg"
version = "0.2.1"
version = "0.2.2"
authors = ["The Rand Project Developers"]
license = "MIT OR Apache-2.0"
readme = "README.md"
Expand Down
4 changes: 2 additions & 2 deletions rand_pcg/src/pcg128.rs
Expand Up @@ -29,7 +29,7 @@ use rand_core::{le, Error, RngCore, SeedableRng};
/// Despite the name, this implementation uses 32 bytes (256 bit) space
/// comprising 128 bits of state and 128 bits stream selector. These are both
/// set by `SeedableRng`, using a 256-bit seed.
#[derive(Clone)]
#[derive(Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
pub struct Lcg128Xsl64 {
state: u128,
Expand Down Expand Up @@ -130,7 +130,7 @@ impl RngCore for Lcg128Xsl64 {
/// Note that compared to the standard `pcg64` (128-bit LCG with PCG-XSL-RR
/// output function), this RNG is faster, also has a long cycle, and still has
/// good performance on statistical tests.
#[derive(Clone)]
#[derive(Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
pub struct Mcg128Xsl64 {
state: u128,
Expand Down
2 changes: 1 addition & 1 deletion rand_pcg/src/pcg64.rs
Expand Up @@ -29,7 +29,7 @@ const MULTIPLIER: u64 = 6364136223846793005;
/// Despite the name, this implementation uses 16 bytes (128 bit) space
/// comprising 64 bits of state and 64 bits stream selector. These are both set
/// by `SeedableRng`, using a 128-bit seed.
#[derive(Clone)]
#[derive(Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
pub struct Lcg64Xsh32 {
state: u64,
Expand Down
2 changes: 1 addition & 1 deletion src/rngs/mock.rs
Expand Up @@ -27,7 +27,7 @@ use serde::{Serialize, Deserialize};
/// let sample: [u64; 3] = my_rng.gen();
/// assert_eq!(sample, [2, 3, 4]);
/// ```
#[derive(Debug, Clone)]
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
pub struct StepRng {
v: u64,
Expand Down
2 changes: 1 addition & 1 deletion src/rngs/small.rs
Expand Up @@ -73,7 +73,7 @@ type Rng = rand_pcg::Pcg32;
/// [`thread_rng`]: crate::thread_rng
/// [rand_chacha]: https://crates.io/crates/rand_chacha
/// [rand_pcg]: https://crates.io/crates/rand_pcg
#[derive(Clone, Debug)]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct SmallRng(Rng);

impl RngCore for SmallRng {
Expand Down
2 changes: 1 addition & 1 deletion src/rngs/std.rs
Expand Up @@ -32,7 +32,7 @@ pub(crate) use rand_hc::Hc128Core as Core;
/// the [rand_chacha] crate directly.
///
/// [rand_chacha]: https://crates.io/crates/rand_chacha
#[derive(Clone, Debug)]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct StdRng(Rng);

impl RngCore for StdRng {
Expand Down

0 comments on commit 4b99567

Please sign in to comment.