From 9c823fa0454fa9b12b5849754d734163f7d1dc56 Mon Sep 17 00:00:00 2001 From: mossa Date: Fri, 1 May 2020 16:50:43 +0200 Subject: [PATCH 01/14] Added serde1 feature to WeightedIndex It required adding serde as an optional dependency. Also added a test using bincode like in the other crate. --- Cargo.toml | 5 ++- src/distributions/uniform.rs | 46 ++++++++++++++--------- src/distributions/weighted_index.rs | 58 ++++++++++++++++++++++------- 3 files changed, 77 insertions(+), 32 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index e0581952329..4cc019f6c99 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,7 +24,7 @@ appveyor = { repository = "rust-random/rand" } # Meta-features: default = ["std", "std_rng"] nightly = ["simd_support"] # enables all features requiring nightly rust -serde1 = [] # does nothing, deprecated +serde1 = ["serde"] # Option (enabled by default): without "std" rand uses libcore; this option # enables functionality expected to be available on a standard platform. @@ -58,6 +58,7 @@ members = [ rand_core = { path = "rand_core", version = "0.5.1" } rand_pcg = { path = "rand_pcg", version = "0.2", optional = true } log = { version = "0.4.4", optional = true } +serde = { version = "1", features = ["derive"], optional = true } [dependencies.packed_simd] # NOTE: so far no version works reliably due to dependence on unstable features @@ -81,6 +82,8 @@ rand_hc = { path = "rand_hc", version = "0.2", optional = true } rand_pcg = { path = "rand_pcg", version = "0.2" } # Only for benches: rand_hc = { path = "rand_hc", version = "0.2" } +# only to test serde1 +bincode = {version = "1.2.1"} [package.metadata.docs.rs] all-features = true diff --git a/src/distributions/uniform.rs b/src/distributions/uniform.rs index 8584152f039..dd88f590365 100644 --- a/src/distributions/uniform.rs +++ b/src/distributions/uniform.rs @@ -103,8 +103,10 @@ //! [`UniformDuration`]: crate::distributions::uniform::UniformDuration //! [`SampleBorrow::borrow`]: crate::distributions::uniform::SampleBorrow::borrow -#[cfg(not(feature = "std"))] use core::time::Duration; -#[cfg(feature = "std")] use std::time::Duration; +#[cfg(not(feature = "std"))] +use core::time::Duration; +#[cfg(feature = "std")] +use std::time::Duration; use crate::distributions::float::IntoFloat; use crate::distributions::utils::{BoolAsSIMD, FloatAsSIMD, FloatSIMDUtils, WideningMultiply}; @@ -115,8 +117,11 @@ use crate::Rng; #[allow(unused_imports)] // rustc doesn't detect that this is actually used use crate::distributions::utils::Float; +#[cfg(feature = "simd_support")] +use packed_simd::*; -#[cfg(feature = "simd_support")] use packed_simd::*; +#[cfg(feature = "serde1")] +use serde::{Deserialize, Serialize}; /// Sample values uniformly between two bounds. /// @@ -291,7 +296,8 @@ pub trait SampleBorrow { fn borrow(&self) -> &Borrowed; } impl SampleBorrow for Borrowed -where Borrowed: SampleUniform +where + Borrowed: SampleUniform, { #[inline(always)] fn borrow(&self) -> &Borrowed { @@ -299,7 +305,8 @@ where Borrowed: SampleUniform } } impl<'a, Borrowed> SampleBorrow for &'a Borrowed -where Borrowed: SampleUniform +where + Borrowed: SampleUniform, { #[inline(always)] fn borrow(&self) -> &Borrowed { @@ -311,7 +318,6 @@ where Borrowed: SampleUniform // What follows are all back-ends. - /// The back-end implementing [`UniformSampler`] for integer types. /// /// Unless you are implementing [`UniformSampler`] for your own type, this type @@ -347,6 +353,7 @@ where Borrowed: SampleUniform /// multiply by `range`, the result is in the high word. Then comparing the low /// word against `zone` makes sure our distribution is uniform. #[derive(Clone, Copy, Debug)] +#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] pub struct UniformInt { low: X, range: X, @@ -623,7 +630,6 @@ uniform_simd_int_impl! { u8 } - /// The back-end implementing [`UniformSampler`] for floating-point types. /// /// Unless you are implementing [`UniformSampler`] for your own type, this type @@ -831,7 +837,6 @@ uniform_float_impl! { f64x4, u64x4, f64, u64, 64 - 52 } #[cfg(feature = "simd_support")] uniform_float_impl! { f64x8, u64x8, f64, u64, 64 - 52 } - /// The back-end implementing [`UniformSampler`] for `Duration`. /// /// Unless you are implementing [`UniformSampler`] for your own types, this type @@ -991,7 +996,8 @@ mod tests { #[test] #[cfg_attr(miri, ignore)] // Miri is too slow fn test_integers() { - #[cfg(not(target_os = "emscripten"))] use core::{i128, u128}; + #[cfg(not(target_os = "emscripten"))] + use core::{i128, u128}; use core::{i16, i32, i64, i8, isize}; use core::{u16, u32, u64, u8, usize}; @@ -1228,12 +1234,13 @@ mod tests { } } - #[test] #[cfg_attr(miri, ignore)] // Miri is too slow fn test_durations() { - #[cfg(not(feature = "std"))] use core::time::Duration; - #[cfg(feature = "std")] use std::time::Duration; + #[cfg(not(feature = "std"))] + use core::time::Duration; + #[cfg(feature = "std")] + use std::time::Duration; let mut rng = crate::test::rng(253); @@ -1328,7 +1335,9 @@ mod tests { fn value_stability() { fn test_samples( lb: T, ub: T, expected_single: &[T], expected_multiple: &[T], - ) where Uniform: Distribution { + ) where + Uniform: Distribution, + { let mut rng = crate::test::rng(897); let mut buf = [lb; 3]; @@ -1350,11 +1359,12 @@ mod tests { test_samples(11u8, 219, &[17, 66, 214], &[181, 93, 165]); test_samples(11u32, 219, &[17, 66, 214], &[181, 93, 165]); - test_samples(0f32, 1e-2f32, &[0.0003070104, 0.0026630748, 0.00979833], &[ - 0.008194133, - 0.00398172, - 0.007428536, - ]); + test_samples( + 0f32, + 1e-2f32, + &[0.0003070104, 0.0026630748, 0.00979833], + &[0.008194133, 0.00398172, 0.007428536], + ); test_samples( -1e10f64, 1e10f64, diff --git a/src/distributions/weighted_index.rs b/src/distributions/weighted_index.rs index b73bc43af02..9e2c0dc5bd1 100644 --- a/src/distributions/weighted_index.rs +++ b/src/distributions/weighted_index.rs @@ -15,7 +15,11 @@ use core::cmp::PartialOrd; use core::fmt; // Note that this whole module is only imported if feature="alloc" is enabled. -#[cfg(not(feature = "std"))] use crate::alloc::vec::Vec; +#[cfg(not(feature = "std"))] +use crate::alloc::vec::Vec; + +#[cfg(feature = "serde1")] +use serde::{Deserialize, Serialize}; /// A distribution using weighted sampling of discrete items /// @@ -73,6 +77,7 @@ use core::fmt; /// [`Uniform`]: crate::distributions::uniform::Uniform /// [`RngCore`]: crate::RngCore #[derive(Debug, Clone)] +#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] pub struct WeightedIndex { cumulative_weights: Vec, total_weight: X, @@ -133,10 +138,12 @@ impl WeightedIndex { /// /// In case of error, `self` is not modified. pub fn update_weights(&mut self, new_weights: &[(usize, &X)]) -> Result<(), WeightedError> - where X: for<'a> ::core::ops::AddAssign<&'a X> + where + X: for<'a> ::core::ops::AddAssign<&'a X> + for<'a> ::core::ops::SubAssign<&'a X> + Clone - + Default { + + Default, + { if new_weights.is_empty() { return Ok(()); } @@ -214,7 +221,8 @@ impl WeightedIndex { } impl Distribution for WeightedIndex -where X: SampleUniform + PartialOrd +where + X: SampleUniform + PartialOrd, { fn sample(&self, rng: &mut R) -> usize { use ::core::cmp::Ordering; @@ -236,6 +244,24 @@ where X: SampleUniform + PartialOrd mod test { use super::*; + #[cfg(feature = "serde1")] + #[test] + fn test_weightedindex_serde1() { + let weighted_index = WeightedIndex::new(vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]).unwrap(); + + let ser_weighted_index = bincode::serialize(&weighted_index).unwrap(); + let de_weighted_index: WeightedIndex = + bincode::deserialize(&ser_weighted_index).unwrap(); + + // these doesn't work because lack of PartialEq, Eq + // assert_eq!(de_weighted_index, weighted_index); + assert_eq!( + de_weighted_index.cumulative_weights, + weighted_index.cumulative_weights + ); + assert_eq!(de_weighted_index.total_weight, weighted_index.total_weight); + } + #[test] #[cfg_attr(miri, ignore)] // Miri is too slow fn test_weightedindex() { @@ -360,15 +386,21 @@ mod test { } let mut buf = [0; 10]; - test_samples(&[1i32, 1, 1, 1, 1, 1, 1, 1, 1], &mut buf, &[ - 0, 6, 2, 6, 3, 4, 7, 8, 2, 5, - ]); - test_samples(&[0.7f32, 0.1, 0.1, 0.1], &mut buf, &[ - 0, 0, 0, 1, 0, 0, 2, 3, 0, 0, - ]); - test_samples(&[1.0f64, 0.999, 0.998, 0.997], &mut buf, &[ - 2, 2, 1, 3, 2, 1, 3, 3, 2, 1, - ]); + test_samples( + &[1i32, 1, 1, 1, 1, 1, 1, 1, 1], + &mut buf, + &[0, 6, 2, 6, 3, 4, 7, 8, 2, 5], + ); + test_samples( + &[0.7f32, 0.1, 0.1, 0.1], + &mut buf, + &[0, 0, 0, 1, 0, 0, 2, 3, 0, 0], + ); + test_samples( + &[1.0f64, 0.999, 0.998, 0.997], + &mut buf, + &[2, 2, 1, 3, 2, 1, 3, 3, 2, 1], + ); } } From f6871d0603e51237b454498f89f290ff9a36c901 Mon Sep 17 00:00:00 2001 From: mossa Date: Sat, 2 May 2020 00:27:12 +0200 Subject: [PATCH 02/14] Revert "Added serde1 feature to WeightedIndex" This reverts commit 9c823fa0454fa9b12b5849754d734163f7d1dc56. --- Cargo.toml | 5 +-- src/distributions/uniform.rs | 46 +++++++++-------------- src/distributions/weighted_index.rs | 58 +++++++---------------------- 3 files changed, 32 insertions(+), 77 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 4cc019f6c99..e0581952329 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,7 +24,7 @@ appveyor = { repository = "rust-random/rand" } # Meta-features: default = ["std", "std_rng"] nightly = ["simd_support"] # enables all features requiring nightly rust -serde1 = ["serde"] +serde1 = [] # does nothing, deprecated # Option (enabled by default): without "std" rand uses libcore; this option # enables functionality expected to be available on a standard platform. @@ -58,7 +58,6 @@ members = [ rand_core = { path = "rand_core", version = "0.5.1" } rand_pcg = { path = "rand_pcg", version = "0.2", optional = true } log = { version = "0.4.4", optional = true } -serde = { version = "1", features = ["derive"], optional = true } [dependencies.packed_simd] # NOTE: so far no version works reliably due to dependence on unstable features @@ -82,8 +81,6 @@ rand_hc = { path = "rand_hc", version = "0.2", optional = true } rand_pcg = { path = "rand_pcg", version = "0.2" } # Only for benches: rand_hc = { path = "rand_hc", version = "0.2" } -# only to test serde1 -bincode = {version = "1.2.1"} [package.metadata.docs.rs] all-features = true diff --git a/src/distributions/uniform.rs b/src/distributions/uniform.rs index dd88f590365..8584152f039 100644 --- a/src/distributions/uniform.rs +++ b/src/distributions/uniform.rs @@ -103,10 +103,8 @@ //! [`UniformDuration`]: crate::distributions::uniform::UniformDuration //! [`SampleBorrow::borrow`]: crate::distributions::uniform::SampleBorrow::borrow -#[cfg(not(feature = "std"))] -use core::time::Duration; -#[cfg(feature = "std")] -use std::time::Duration; +#[cfg(not(feature = "std"))] use core::time::Duration; +#[cfg(feature = "std")] use std::time::Duration; use crate::distributions::float::IntoFloat; use crate::distributions::utils::{BoolAsSIMD, FloatAsSIMD, FloatSIMDUtils, WideningMultiply}; @@ -117,11 +115,8 @@ use crate::Rng; #[allow(unused_imports)] // rustc doesn't detect that this is actually used use crate::distributions::utils::Float; -#[cfg(feature = "simd_support")] -use packed_simd::*; -#[cfg(feature = "serde1")] -use serde::{Deserialize, Serialize}; +#[cfg(feature = "simd_support")] use packed_simd::*; /// Sample values uniformly between two bounds. /// @@ -296,8 +291,7 @@ pub trait SampleBorrow { fn borrow(&self) -> &Borrowed; } impl SampleBorrow for Borrowed -where - Borrowed: SampleUniform, +where Borrowed: SampleUniform { #[inline(always)] fn borrow(&self) -> &Borrowed { @@ -305,8 +299,7 @@ where } } impl<'a, Borrowed> SampleBorrow for &'a Borrowed -where - Borrowed: SampleUniform, +where Borrowed: SampleUniform { #[inline(always)] fn borrow(&self) -> &Borrowed { @@ -318,6 +311,7 @@ where // What follows are all back-ends. + /// The back-end implementing [`UniformSampler`] for integer types. /// /// Unless you are implementing [`UniformSampler`] for your own type, this type @@ -353,7 +347,6 @@ where /// multiply by `range`, the result is in the high word. Then comparing the low /// word against `zone` makes sure our distribution is uniform. #[derive(Clone, Copy, Debug)] -#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] pub struct UniformInt { low: X, range: X, @@ -630,6 +623,7 @@ uniform_simd_int_impl! { u8 } + /// The back-end implementing [`UniformSampler`] for floating-point types. /// /// Unless you are implementing [`UniformSampler`] for your own type, this type @@ -837,6 +831,7 @@ uniform_float_impl! { f64x4, u64x4, f64, u64, 64 - 52 } #[cfg(feature = "simd_support")] uniform_float_impl! { f64x8, u64x8, f64, u64, 64 - 52 } + /// The back-end implementing [`UniformSampler`] for `Duration`. /// /// Unless you are implementing [`UniformSampler`] for your own types, this type @@ -996,8 +991,7 @@ mod tests { #[test] #[cfg_attr(miri, ignore)] // Miri is too slow fn test_integers() { - #[cfg(not(target_os = "emscripten"))] - use core::{i128, u128}; + #[cfg(not(target_os = "emscripten"))] use core::{i128, u128}; use core::{i16, i32, i64, i8, isize}; use core::{u16, u32, u64, u8, usize}; @@ -1234,13 +1228,12 @@ mod tests { } } + #[test] #[cfg_attr(miri, ignore)] // Miri is too slow fn test_durations() { - #[cfg(not(feature = "std"))] - use core::time::Duration; - #[cfg(feature = "std")] - use std::time::Duration; + #[cfg(not(feature = "std"))] use core::time::Duration; + #[cfg(feature = "std")] use std::time::Duration; let mut rng = crate::test::rng(253); @@ -1335,9 +1328,7 @@ mod tests { fn value_stability() { fn test_samples( lb: T, ub: T, expected_single: &[T], expected_multiple: &[T], - ) where - Uniform: Distribution, - { + ) where Uniform: Distribution { let mut rng = crate::test::rng(897); let mut buf = [lb; 3]; @@ -1359,12 +1350,11 @@ mod tests { test_samples(11u8, 219, &[17, 66, 214], &[181, 93, 165]); test_samples(11u32, 219, &[17, 66, 214], &[181, 93, 165]); - test_samples( - 0f32, - 1e-2f32, - &[0.0003070104, 0.0026630748, 0.00979833], - &[0.008194133, 0.00398172, 0.007428536], - ); + test_samples(0f32, 1e-2f32, &[0.0003070104, 0.0026630748, 0.00979833], &[ + 0.008194133, + 0.00398172, + 0.007428536, + ]); test_samples( -1e10f64, 1e10f64, diff --git a/src/distributions/weighted_index.rs b/src/distributions/weighted_index.rs index 9e2c0dc5bd1..b73bc43af02 100644 --- a/src/distributions/weighted_index.rs +++ b/src/distributions/weighted_index.rs @@ -15,11 +15,7 @@ use core::cmp::PartialOrd; use core::fmt; // Note that this whole module is only imported if feature="alloc" is enabled. -#[cfg(not(feature = "std"))] -use crate::alloc::vec::Vec; - -#[cfg(feature = "serde1")] -use serde::{Deserialize, Serialize}; +#[cfg(not(feature = "std"))] use crate::alloc::vec::Vec; /// A distribution using weighted sampling of discrete items /// @@ -77,7 +73,6 @@ use serde::{Deserialize, Serialize}; /// [`Uniform`]: crate::distributions::uniform::Uniform /// [`RngCore`]: crate::RngCore #[derive(Debug, Clone)] -#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] pub struct WeightedIndex { cumulative_weights: Vec, total_weight: X, @@ -138,12 +133,10 @@ impl WeightedIndex { /// /// In case of error, `self` is not modified. pub fn update_weights(&mut self, new_weights: &[(usize, &X)]) -> Result<(), WeightedError> - where - X: for<'a> ::core::ops::AddAssign<&'a X> + where X: for<'a> ::core::ops::AddAssign<&'a X> + for<'a> ::core::ops::SubAssign<&'a X> + Clone - + Default, - { + + Default { if new_weights.is_empty() { return Ok(()); } @@ -221,8 +214,7 @@ impl WeightedIndex { } impl Distribution for WeightedIndex -where - X: SampleUniform + PartialOrd, +where X: SampleUniform + PartialOrd { fn sample(&self, rng: &mut R) -> usize { use ::core::cmp::Ordering; @@ -244,24 +236,6 @@ where mod test { use super::*; - #[cfg(feature = "serde1")] - #[test] - fn test_weightedindex_serde1() { - let weighted_index = WeightedIndex::new(vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]).unwrap(); - - let ser_weighted_index = bincode::serialize(&weighted_index).unwrap(); - let de_weighted_index: WeightedIndex = - bincode::deserialize(&ser_weighted_index).unwrap(); - - // these doesn't work because lack of PartialEq, Eq - // assert_eq!(de_weighted_index, weighted_index); - assert_eq!( - de_weighted_index.cumulative_weights, - weighted_index.cumulative_weights - ); - assert_eq!(de_weighted_index.total_weight, weighted_index.total_weight); - } - #[test] #[cfg_attr(miri, ignore)] // Miri is too slow fn test_weightedindex() { @@ -386,21 +360,15 @@ mod test { } let mut buf = [0; 10]; - test_samples( - &[1i32, 1, 1, 1, 1, 1, 1, 1, 1], - &mut buf, - &[0, 6, 2, 6, 3, 4, 7, 8, 2, 5], - ); - test_samples( - &[0.7f32, 0.1, 0.1, 0.1], - &mut buf, - &[0, 0, 0, 1, 0, 0, 2, 3, 0, 0], - ); - test_samples( - &[1.0f64, 0.999, 0.998, 0.997], - &mut buf, - &[2, 2, 1, 3, 2, 1, 3, 3, 2, 1], - ); + test_samples(&[1i32, 1, 1, 1, 1, 1, 1, 1, 1], &mut buf, &[ + 0, 6, 2, 6, 3, 4, 7, 8, 2, 5, + ]); + test_samples(&[0.7f32, 0.1, 0.1, 0.1], &mut buf, &[ + 0, 0, 0, 1, 0, 0, 2, 3, 0, 0, + ]); + test_samples(&[1.0f64, 0.999, 0.998, 0.997], &mut buf, &[ + 2, 2, 1, 3, 2, 1, 3, 3, 2, 1, + ]); } } From 50bc0782418dba3db26c7b9900d9ba4dd29f5265 Mon Sep 17 00:00:00 2001 From: mossa Date: Sat, 2 May 2020 00:44:25 +0200 Subject: [PATCH 03/14] Added Serialize/Deserialize to WeightedIndex and UniformInt This time without the rustfmt invocation. --- Cargo.toml | 5 ++++- src/distributions/uniform.rs | 5 ++++- src/distributions/weighted_index.rs | 21 +++++++++++++++++++++ 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index e0581952329..d13d5ba5d3a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,7 +24,7 @@ appveyor = { repository = "rust-random/rand" } # Meta-features: default = ["std", "std_rng"] nightly = ["simd_support"] # enables all features requiring nightly rust -serde1 = [] # does nothing, deprecated +serde1 = ["serde"] # Option (enabled by default): without "std" rand uses libcore; this option # enables functionality expected to be available on a standard platform. @@ -58,6 +58,7 @@ members = [ rand_core = { path = "rand_core", version = "0.5.1" } rand_pcg = { path = "rand_pcg", version = "0.2", optional = true } log = { version = "0.4.4", optional = true } +serde = { version = "1", features = ["derive"], optional = true } [dependencies.packed_simd] # NOTE: so far no version works reliably due to dependence on unstable features @@ -81,6 +82,8 @@ rand_hc = { path = "rand_hc", version = "0.2", optional = true } rand_pcg = { path = "rand_pcg", version = "0.2" } # Only for benches: rand_hc = { path = "rand_hc", version = "0.2" } +# Only to test serde1 +bincode = "1.2.1" [package.metadata.docs.rs] all-features = true diff --git a/src/distributions/uniform.rs b/src/distributions/uniform.rs index 8584152f039..7d4baa32add 100644 --- a/src/distributions/uniform.rs +++ b/src/distributions/uniform.rs @@ -115,9 +115,11 @@ use crate::Rng; #[allow(unused_imports)] // rustc doesn't detect that this is actually used use crate::distributions::utils::Float; - #[cfg(feature = "simd_support")] use packed_simd::*; +#[cfg(feature = "serde1")] +use serde::{Serialize, Deserialize}; + /// Sample values uniformly between two bounds. /// /// [`Uniform::new`] and [`Uniform::new_inclusive`] construct a uniform @@ -347,6 +349,7 @@ where Borrowed: SampleUniform /// multiply by `range`, the result is in the high word. Then comparing the low /// word against `zone` makes sure our distribution is uniform. #[derive(Clone, Copy, Debug)] +#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] pub struct UniformInt { low: X, range: X, diff --git a/src/distributions/weighted_index.rs b/src/distributions/weighted_index.rs index b73bc43af02..a75d41eae0c 100644 --- a/src/distributions/weighted_index.rs +++ b/src/distributions/weighted_index.rs @@ -17,6 +17,9 @@ use core::fmt; // Note that this whole module is only imported if feature="alloc" is enabled. #[cfg(not(feature = "std"))] use crate::alloc::vec::Vec; +#[cfg(feature = "serde1")] +use serde::{Serialize, Deserialize}; + /// A distribution using weighted sampling of discrete items /// /// Sampling a `WeightedIndex` distribution returns the index of a randomly @@ -73,6 +76,7 @@ use core::fmt; /// [`Uniform`]: crate::distributions::uniform::Uniform /// [`RngCore`]: crate::RngCore #[derive(Debug, Clone)] +#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] pub struct WeightedIndex { cumulative_weights: Vec, total_weight: X, @@ -236,6 +240,23 @@ where X: SampleUniform + PartialOrd mod test { use super::*; + #[cfg(feature = "serde1")] + #[test] + fn test_weightedindex_serde1() { + let weighted_index = WeightedIndex::new(vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]).unwrap(); + + let ser_weighted_index = bincode::serialize(&weighted_index).unwrap(); + let de_weighted_index: WeightedIndex = + bincode::deserialize(&ser_weighted_index).unwrap(); + + assert_eq!( + de_weighted_index.cumulative_weights, + weighted_index.cumulative_weights + ); + assert_eq!(de_weighted_index.total_weight, weighted_index.total_weight); + } + + #[test] #[cfg_attr(miri, ignore)] // Miri is too slow fn test_weightedindex() { From 2bf89f61c101d82fd7f4734c4c3a9ab9f8130e17 Mon Sep 17 00:00:00 2001 From: mossa Date: Sat, 2 May 2020 00:47:04 +0200 Subject: [PATCH 04/14] Updated changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 103abea7a31..208b63167a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,10 @@ A [separate changelog is kept for rand_core](rand_core/CHANGELOG.md). You may also find the [Upgrade Guide](https://rust-random.github.io/book/update.html) useful. +## [0.7.4] - 2020-05-02 +### Additions +- Added a `serde1` feature and added Serialize/Deserialize to `UniformInt` and `WeightedIndex`. + ## [0.7.3] - 2020-01-10 ### Fixes - The `Bernoulli` distribution constructors now reports an error on NaN and on From 9ddd57e895ae24241e88cc0bec92f58e398644be Mon Sep 17 00:00:00 2001 From: mossa Date: Sat, 2 May 2020 00:48:25 +0200 Subject: [PATCH 05/14] Unreleased changes --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 208b63167a0..4003661609f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,9 +8,9 @@ A [separate changelog is kept for rand_core](rand_core/CHANGELOG.md). You may also find the [Upgrade Guide](https://rust-random.github.io/book/update.html) useful. -## [0.7.4] - 2020-05-02 +## [Unreleased] ### Additions -- Added a `serde1` feature and added Serialize/Deserialize to `UniformInt` and `WeightedIndex`. +- Added a `serde1` feature and added Serialize/Deserialize to `UniformInt` and `WeightedIndex` (#974) ## [0.7.3] - 2020-01-10 ### Fixes From 1ec330f8bad1deaec8f1acdc7fb68f248d0eec99 Mon Sep 17 00:00:00 2001 From: mossa Date: Sun, 3 May 2020 20:21:04 +0200 Subject: [PATCH 06/14] Cahnged the minimal req. serde version Hopefully this will do it. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index d13d5ba5d3a..a67d53021f0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -58,7 +58,7 @@ members = [ rand_core = { path = "rand_core", version = "0.5.1" } rand_pcg = { path = "rand_pcg", version = "0.2", optional = true } log = { version = "0.4.4", optional = true } -serde = { version = "1", features = ["derive"], optional = true } +serde = { version = "1.0.105", features = ["derive"], optional = true } [dependencies.packed_simd] # NOTE: so far no version works reliably due to dependence on unstable features From 8bb81d2af0f78418d49bd5fde9fbd2f260a9d312 Mon Sep 17 00:00:00 2001 From: mossa Date: Mon, 4 May 2020 12:12:06 +0200 Subject: [PATCH 07/14] Minimal supported serde version --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index a67d53021f0..ce5f53e9ce4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -58,7 +58,7 @@ members = [ rand_core = { path = "rand_core", version = "0.5.1" } rand_pcg = { path = "rand_pcg", version = "0.2", optional = true } log = { version = "0.4.4", optional = true } -serde = { version = "1.0.105", features = ["derive"], optional = true } +serde = { version = "1.0.103", features = ["derive"], optional = true } [dependencies.packed_simd] # NOTE: so far no version works reliably due to dependence on unstable features From 0e97b6035091e8392f7fe70bb2f0f67e2f2a24fb Mon Sep 17 00:00:00 2001 From: mossa Date: Mon, 4 May 2020 12:12:21 +0200 Subject: [PATCH 08/14] Ser/de Bernoulli --- src/distributions/bernoulli.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/distributions/bernoulli.rs b/src/distributions/bernoulli.rs index a1fa86e14d4..b968ca046ed 100644 --- a/src/distributions/bernoulli.rs +++ b/src/distributions/bernoulli.rs @@ -12,6 +12,8 @@ use crate::distributions::Distribution; use crate::Rng; use core::{fmt, u64}; +#[cfg(feature = "serde1")] +use serde::{Serialize, Deserialize}; /// The Bernoulli distribution. /// /// This is a special case of the Binomial distribution where `n = 1`. @@ -32,6 +34,7 @@ use core::{fmt, u64}; /// so only probabilities that are multiples of 2-64 can be /// represented. #[derive(Clone, Copy, Debug)] +#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] pub struct Bernoulli { /// Probability of success, relative to the maximal integer. p_int: u64, @@ -143,6 +146,15 @@ mod test { use crate::distributions::Distribution; use crate::Rng; + #[test] + #[cfg(feature="serde1")] + fn test_serializing_deserializing_bernoulli() { + let coin_flip = Bernoulli::new(0.5).unwrap(); + let de_coin_flip : Bernoulli = bincode::deserialize(&bincode::serialize(&coin_flip).unwrap()).unwrap(); + + assert_eq!(coin_flip.p_int, de_coin_flip.p_int); + } + #[test] fn test_trivial() { let mut r = crate::test::rng(1); From 11ade61156bea0b444506999b7e09b85b46bb898 Mon Sep 17 00:00:00 2001 From: mossa Date: Mon, 4 May 2020 12:18:33 +0200 Subject: [PATCH 09/14] Added ser/de to Uniform #TODO: Test of equality between ser/de is needed. --- src/distributions/uniform.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/distributions/uniform.rs b/src/distributions/uniform.rs index 7d4baa32add..8af2cf05aad 100644 --- a/src/distributions/uniform.rs +++ b/src/distributions/uniform.rs @@ -161,6 +161,7 @@ use serde::{Serialize, Deserialize}; /// [`new`]: Uniform::new /// [`new_inclusive`]: Uniform::new_inclusive #[derive(Clone, Copy, Debug)] +#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] pub struct Uniform(X::Sampler); impl Uniform { @@ -970,6 +971,14 @@ mod tests { use super::*; use crate::rngs::mock::StepRng; + #[test] + #[cfg(feature="serde1")] + fn test_uniform_serialization() { + let unit_box = Uniform::new(-1, 1); + let de_unit_box: Uniform = bincode::deserialize(&bincode::serialize(&unit_box).unwrap()).unwrap(); + //FIXME: assertion needed to check + } + #[should_panic] #[test] fn test_uniform_bad_limits_equal_int() { From 5b23d218eec97897d337493e4148196a454f9ad1 Mon Sep 17 00:00:00 2001 From: mossa Date: Mon, 4 May 2020 12:28:00 +0200 Subject: [PATCH 10/14] Added ser/de for UniformDuration #TODO: Unable to test equality in mode between de-serialized and original UniformDuration --- src/distributions/uniform.rs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/distributions/uniform.rs b/src/distributions/uniform.rs index 8af2cf05aad..5a77b0a68a1 100644 --- a/src/distributions/uniform.rs +++ b/src/distributions/uniform.rs @@ -648,6 +648,7 @@ uniform_simd_int_impl! { /// [`new_inclusive`]: UniformSampler::new_inclusive /// [`Standard`]: crate::distributions::Standard #[derive(Clone, Copy, Debug)] +#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] pub struct UniformFloat { low: X, scale: X, @@ -841,12 +842,14 @@ uniform_float_impl! { f64x8, u64x8, f64, u64, 64 - 52 } /// Unless you are implementing [`UniformSampler`] for your own types, this type /// should not be used directly, use [`Uniform`] instead. #[derive(Clone, Copy, Debug)] +#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] pub struct UniformDuration { mode: UniformDurationMode, offset: u32, } #[derive(Debug, Copy, Clone)] +#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] enum UniformDurationMode { Small { secs: u64, @@ -970,9 +973,20 @@ impl UniformSampler for UniformDuration { mod tests { use super::*; use crate::rngs::mock::StepRng; - + + #[test] + #[cfg(feature = "serde1")] + fn test_serialization_uniform_duration() { + let distr = UniformDuration::new(-25, 50); + let de_distr: UniformDuration = bincode::deserialize(&bincode::serialize(&distr).unwrap()).unwrap(); + assert_eq!( + distr.offset, de_distr.offset + ); + //FIXME: check if distr.mode are the same + } + #[test] - #[cfg(feature="serde1")] + #[cfg(feature = "serde1")] fn test_uniform_serialization() { let unit_box = Uniform::new(-1, 1); let de_unit_box: Uniform = bincode::deserialize(&bincode::serialize(&unit_box).unwrap()).unwrap(); From b393d7526bb55ec90505e5deeababe16ffc3f91e Mon Sep 17 00:00:00 2001 From: mossa Date: Mon, 4 May 2020 12:42:47 +0200 Subject: [PATCH 11/14] Added ser/deto `IndexVec`, `StepRng`, `Alphanumeric`, `OpenClosed01`, `Open01`, and `Standard` --- src/distributions/mod.rs | 4 ++++ src/distributions/other.rs | 4 ++++ src/distributions/uniform.rs | 37 ++++++++++++++++++------------------ src/rngs/mock.rs | 19 ++++++++++++++++++ src/seq/index.rs | 12 ++++++++++++ 5 files changed, 58 insertions(+), 18 deletions(-) diff --git a/src/distributions/mod.rs b/src/distributions/mod.rs index cf1c8b19815..525e29eddd6 100644 --- a/src/distributions/mod.rs +++ b/src/distributions/mod.rs @@ -111,6 +111,9 @@ pub mod uniform; #[cfg(feature = "alloc")] pub mod weighted; #[cfg(feature = "alloc")] mod weighted_index; +#[cfg(feature = "serde1")] +use serde::{Serialize, Deserialize}; + mod float; #[doc(hidden)] pub mod hidden_export { @@ -320,6 +323,7 @@ where /// /// [`Uniform`]: uniform::Uniform #[derive(Clone, Copy, Debug)] +#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] pub struct Standard; diff --git a/src/distributions/other.rs b/src/distributions/other.rs index c95060e5104..32cc470d1eb 100644 --- a/src/distributions/other.rs +++ b/src/distributions/other.rs @@ -14,6 +14,9 @@ use core::num::Wrapping; use crate::distributions::{Distribution, Standard, Uniform}; use crate::Rng; +#[cfg(feature = "serde1")] +use serde::{Serialize, Deserialize}; + // ----- Sampling distributions ----- /// Sample a `char`, uniformly distributed over ASCII letters and numbers: @@ -34,6 +37,7 @@ use crate::Rng; /// println!("Random chars: {}", chars); /// ``` #[derive(Debug)] +#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] pub struct Alphanumeric; diff --git a/src/distributions/uniform.rs b/src/distributions/uniform.rs index 5a77b0a68a1..8470b27dd1c 100644 --- a/src/distributions/uniform.rs +++ b/src/distributions/uniform.rs @@ -973,25 +973,26 @@ impl UniformSampler for UniformDuration { mod tests { use super::*; use crate::rngs::mock::StepRng; + + //FIXME: instantiate a UniformDuration + // #[test] + // #[cfg(feature = "serde1")] + // fn test_serialization_uniform_duration() { + // let distr = UniformDuration::new(-25, 50); + // let de_distr: UniformDuration = bincode::deserialize(&bincode::serialize(&distr).unwrap()).unwrap(); + // assert_eq!( + // distr.offset, de_distr.offset + // ); + // //FIXME: check if distr.mode are the same + // } - #[test] - #[cfg(feature = "serde1")] - fn test_serialization_uniform_duration() { - let distr = UniformDuration::new(-25, 50); - let de_distr: UniformDuration = bincode::deserialize(&bincode::serialize(&distr).unwrap()).unwrap(); - assert_eq!( - distr.offset, de_distr.offset - ); - //FIXME: check if distr.mode are the same - } - - #[test] - #[cfg(feature = "serde1")] - fn test_uniform_serialization() { - let unit_box = Uniform::new(-1, 1); - let de_unit_box: Uniform = bincode::deserialize(&bincode::serialize(&unit_box).unwrap()).unwrap(); - //FIXME: assertion needed to check - } + // #[test] + // #[cfg(feature = "serde1")] + // fn test_uniform_serialization() { + // let unit_box = Uniform::new(-1, 1); + // let de_unit_box: Uniform = bincode::deserialize(&bincode::serialize(&unit_box).unwrap()).unwrap(); + // //FIXME: assertion needed to check + // } #[should_panic] #[test] diff --git a/src/rngs/mock.rs b/src/rngs/mock.rs index 9a47264a762..86190fd9826 100644 --- a/src/rngs/mock.rs +++ b/src/rngs/mock.rs @@ -10,6 +10,9 @@ use rand_core::{impls, Error, RngCore}; +#[cfg(feature = "serde1")] +use serde::{Serialize, Deserialize}; + /// A simple implementation of `RngCore` for testing purposes. /// /// This generates an arithmetic sequence (i.e. adds a constant each step) @@ -25,6 +28,7 @@ use rand_core::{impls, Error, RngCore}; /// assert_eq!(sample, [2, 3, 4]); /// ``` #[derive(Debug, Clone)] +#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] pub struct StepRng { v: u64, a: u64, @@ -65,3 +69,18 @@ impl RngCore for StepRng { Ok(()) } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + #[cfg(feature = "serde1")] + fn test_serialization_step_rng() { + let some_rng = StepRng::new(42, 7); + let de_some_rng: StepRng = bincode::deserialize(&bincode::serialize(&some_rng).unwrap()).unwrap(); + assert_eq!(some_rng.v, de_some_rng.v); + assert_eq!(some_rng.a, de_some_rng.a); + + } +} diff --git a/src/seq/index.rs b/src/seq/index.rs index 79cc5e9c11c..70acde7c1b9 100644 --- a/src/seq/index.rs +++ b/src/seq/index.rs @@ -22,10 +22,14 @@ use crate::alloc::collections::BTreeSet; use crate::distributions::{uniform::SampleUniform, Distribution, Uniform}; use crate::Rng; +#[cfg(feature = "serde1")] +use serde::{Serialize, Deserialize}; + /// A vector of indices. /// /// Multiple internal representations are possible. #[derive(Clone, Debug)] +#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] pub enum IndexVec { #[doc(hidden)] U32(Vec), @@ -376,6 +380,14 @@ where #[cfg(test)] mod test { use super::*; + + // #[test] + // #cfg(feature = "serde1") + // fn test_serialization_index_vec() { + // let some_index_vec = IndexVec::from(vec![254,234,2,1]); + // let de_some_index_vec: IndexVec = bincode::deserialize(&bincode::serialize(&some_index_vec).unwrap()).unwrap(); + // } + #[cfg(all(feature = "alloc", not(feature = "std")))] use crate::alloc::vec; #[cfg(feature = "std")] use std::vec; From fda36399a2b6f91570210df261f203907c526e93 Mon Sep 17 00:00:00 2001 From: mossa Date: Mon, 4 May 2020 12:42:52 +0200 Subject: [PATCH 12/14] Update float.rs --- src/distributions/float.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/distributions/float.rs b/src/distributions/float.rs index 0a45f397743..733a40394dd 100644 --- a/src/distributions/float.rs +++ b/src/distributions/float.rs @@ -14,6 +14,9 @@ use crate::Rng; use core::mem; #[cfg(feature = "simd_support")] use packed_simd::*; +#[cfg(feature = "serde1")] +use serde::{Serialize, Deserialize}; + /// A distribution to sample floating point numbers uniformly in the half-open /// interval `(0, 1]`, i.e. including 1 but not 0. /// @@ -39,6 +42,7 @@ use core::mem; /// [`Open01`]: crate::distributions::Open01 /// [`Uniform`]: crate::distributions::uniform::Uniform #[derive(Clone, Copy, Debug)] +#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] pub struct OpenClosed01; /// A distribution to sample floating point numbers uniformly in the open @@ -65,6 +69,7 @@ pub struct OpenClosed01; /// [`OpenClosed01`]: crate::distributions::OpenClosed01 /// [`Uniform`]: crate::distributions::uniform::Uniform #[derive(Clone, Copy, Debug)] +#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] pub struct Open01; From fd72a6e71c8faacff23f30440030b1bfd9357403 Mon Sep 17 00:00:00 2001 From: mossa Date: Fri, 15 May 2020 15:39:36 +0200 Subject: [PATCH 13/14] Added tests for Uniform, UniformDurationSampler, and IndexVec --- src/distributions/uniform.rs | 66 ++++++++++++++++++++++++++---------- src/seq/index.rs | 21 ++++++++---- 2 files changed, 63 insertions(+), 24 deletions(-) diff --git a/src/distributions/uniform.rs b/src/distributions/uniform.rs index 8470b27dd1c..a8fb0dc3f27 100644 --- a/src/distributions/uniform.rs +++ b/src/distributions/uniform.rs @@ -974,25 +974,55 @@ mod tests { use super::*; use crate::rngs::mock::StepRng; - //FIXME: instantiate a UniformDuration - // #[test] - // #[cfg(feature = "serde1")] - // fn test_serialization_uniform_duration() { - // let distr = UniformDuration::new(-25, 50); - // let de_distr: UniformDuration = bincode::deserialize(&bincode::serialize(&distr).unwrap()).unwrap(); - // assert_eq!( - // distr.offset, de_distr.offset - // ); - // //FIXME: check if distr.mode are the same - // } + #[test] + #[cfg(feature = "serde1")] + fn test_serialization_uniform_duration() { + let distr = UniformDuration::new(std::time::Duration::from_secs(10), std::time::Duration::from_secs(60)); + let de_distr: UniformDuration = bincode::deserialize(&bincode::serialize(&distr).unwrap()).unwrap(); + assert_eq!( + distr.offset, de_distr.offset + ); + match (distr.mode, de_distr.mode) { + (UniformDurationMode::Small {secs: a_secs, nanos: a_nanos}, UniformDurationMode::Small {secs, nanos}) => { + assert_eq!(a_secs, secs); + + assert_eq!(a_nanos.0.low, nanos.0.low); + assert_eq!(a_nanos.0.range, nanos.0.range); + assert_eq!(a_nanos.0.z, nanos.0.z); + } + (UniformDurationMode::Medium {nanos: a_nanos} , UniformDurationMode::Medium {nanos}) => { + assert_eq!(a_nanos.0.low, nanos.0.low); + assert_eq!(a_nanos.0.range, nanos.0.range); + assert_eq!(a_nanos.0.z, nanos.0.z); + } + (UniformDurationMode::Large {max_secs:a_max_secs, max_nanos:a_max_nanos, secs:a_secs}, UniformDurationMode::Large {max_secs, max_nanos, secs} ) => { + assert_eq!(a_max_secs, max_secs); + assert_eq!(a_max_nanos, max_nanos); + + assert_eq!(a_secs.0.low, secs.0.low); + assert_eq!(a_secs.0.range, secs.0.range); + assert_eq!(a_secs.0.z, secs.0.z); + } + _ => panic!("`UniformDurationMode` was not serialized/deserialized correctly") + } + } - // #[test] - // #[cfg(feature = "serde1")] - // fn test_uniform_serialization() { - // let unit_box = Uniform::new(-1, 1); - // let de_unit_box: Uniform = bincode::deserialize(&bincode::serialize(&unit_box).unwrap()).unwrap(); - // //FIXME: assertion needed to check - // } + #[test] + #[cfg(feature = "serde1")] + fn test_uniform_serialization() { + let unit_box: Uniform = Uniform::new(-1, 1); + let de_unit_box: Uniform = bincode::deserialize(&bincode::serialize(&unit_box).unwrap()).unwrap(); + + assert_eq!(unit_box.0.low, de_unit_box.0.low); + assert_eq!(unit_box.0.range, de_unit_box.0.range); + assert_eq!(unit_box.0.z, de_unit_box.0.z); + + let unit_box: Uniform = Uniform::new(-1., 1.); + let de_unit_box: Uniform = bincode::deserialize(&bincode::serialize(&unit_box).unwrap()).unwrap(); + + assert_eq!(unit_box.0.low, de_unit_box.0.low); + assert_eq!(unit_box.0.scale, de_unit_box.0.scale); + } #[should_panic] #[test] diff --git a/src/seq/index.rs b/src/seq/index.rs index 70acde7c1b9..23d8a39332e 100644 --- a/src/seq/index.rs +++ b/src/seq/index.rs @@ -381,12 +381,21 @@ where mod test { use super::*; - // #[test] - // #cfg(feature = "serde1") - // fn test_serialization_index_vec() { - // let some_index_vec = IndexVec::from(vec![254,234,2,1]); - // let de_some_index_vec: IndexVec = bincode::deserialize(&bincode::serialize(&some_index_vec).unwrap()).unwrap(); - // } + #[test] + #[cfg(feature = "serde1")] + fn test_serialization_index_vec() { + let some_index_vec = IndexVec::from(vec![254_usize, 234, 2, 1]); + let de_some_index_vec: IndexVec = bincode::deserialize(&bincode::serialize(&some_index_vec).unwrap()).unwrap(); + match (some_index_vec, de_some_index_vec) { + (IndexVec::U32(a), IndexVec::U32(b)) => { + assert_eq!(a,b); + }, + (IndexVec::USize(a), IndexVec::USize(b)) => { + assert_eq!(a,b); + }, + _ => {panic!("failed to seralize/deserialize `IndexVec`")} + } + } #[cfg(all(feature = "alloc", not(feature = "std")))] use crate::alloc::vec; #[cfg(feature = "std")] use std::vec; From dc3cda6f26c2cf60250f161c9a6c22abe2db0a11 Mon Sep 17 00:00:00 2001 From: mossa Date: Sun, 17 May 2020 17:33:23 +0200 Subject: [PATCH 14/14] Added spaces --- src/seq/index.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/seq/index.rs b/src/seq/index.rs index 23d8a39332e..92be0a33fd2 100644 --- a/src/seq/index.rs +++ b/src/seq/index.rs @@ -388,10 +388,10 @@ mod test { let de_some_index_vec: IndexVec = bincode::deserialize(&bincode::serialize(&some_index_vec).unwrap()).unwrap(); match (some_index_vec, de_some_index_vec) { (IndexVec::U32(a), IndexVec::U32(b)) => { - assert_eq!(a,b); + assert_eq!(a, b); }, (IndexVec::USize(a), IndexVec::USize(b)) => { - assert_eq!(a,b); + assert_eq!(a, b); }, _ => {panic!("failed to seralize/deserialize `IndexVec`")} }