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], + ); } }