From a2d454675c1aff3e021d027702bf5fb64b113710 Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Thu, 25 Jan 2018 17:34:28 +0000 Subject: [PATCH 1/3] Add trait SampleRng: Rng and related doc --- rand-derive/src/lib.rs | 2 +- rand-derive/tests/rand_macros.rs | 2 +- src/distributions/exponential.rs | 2 +- src/distributions/gamma.rs | 2 +- src/distributions/mod.rs | 2 +- src/distributions/normal.rs | 2 +- src/distributions/range.rs | 2 +- src/lib.rs | 84 ++++++++++++++++++++++++-------- src/rand_impls.rs | 4 +- src/read.rs | 2 +- src/seq.rs | 16 +++--- 11 files changed, 82 insertions(+), 38 deletions(-) diff --git a/rand-derive/src/lib.rs b/rand-derive/src/lib.rs index 80c803af29c..71eecf1461b 100644 --- a/rand-derive/src/lib.rs +++ b/rand-derive/src/lib.rs @@ -108,7 +108,7 @@ fn impl_rand_derive(ast: &syn::MacroInput) -> quote::Tokens { quote! { impl #impl_generics ::rand::Rand for #name #ty_generics #where_clause { #[inline] - fn rand<__R: ::rand::Rng>(__rng: &mut __R) -> Self { + fn rand<__R: ::rand::SampleRng>(__rng: &mut __R) -> Self { #rand } } diff --git a/rand-derive/tests/rand_macros.rs b/rand-derive/tests/rand_macros.rs index 938f2b06a79..f0d0c3aa70d 100644 --- a/rand-derive/tests/rand_macros.rs +++ b/rand-derive/tests/rand_macros.rs @@ -4,7 +4,7 @@ extern crate rand; #[macro_use] extern crate rand_derive; -use rand::Rng; +use rand::SampleRng; #[derive(Rand)] struct Struct { diff --git a/src/distributions/exponential.rs b/src/distributions/exponential.rs index d3e48fc84f8..afb076905b1 100644 --- a/src/distributions/exponential.rs +++ b/src/distributions/exponential.rs @@ -10,7 +10,7 @@ //! The exponential distribution. -use {Rng, Rand}; +use {Rng, SampleRng, Rand}; use distributions::{ziggurat, ziggurat_tables, Sample, IndependentSample}; /// A wrapper around an `f64` to generate Exp(1) random numbers. diff --git a/src/distributions/gamma.rs b/src/distributions/gamma.rs index 9c4ac45aa44..787e8482e10 100644 --- a/src/distributions/gamma.rs +++ b/src/distributions/gamma.rs @@ -15,7 +15,7 @@ use self::GammaRepr::*; use self::ChiSquaredRepr::*; -use {Rng, Open01}; +use {Rng, SampleRng, Open01}; use super::normal::StandardNormal; use super::{IndependentSample, Sample, Exp}; diff --git a/src/distributions/mod.rs b/src/distributions/mod.rs index 9eb2e464baf..2a0817efbc1 100644 --- a/src/distributions/mod.rs +++ b/src/distributions/mod.rs @@ -19,7 +19,7 @@ use core::marker; -use {Rng, Rand}; +use {Rng, SampleRng, Rand}; pub use self::range::Range; #[cfg(feature="std")] diff --git a/src/distributions/normal.rs b/src/distributions/normal.rs index 71d498b573a..4aaf4355377 100644 --- a/src/distributions/normal.rs +++ b/src/distributions/normal.rs @@ -10,7 +10,7 @@ //! The normal and derived distributions. -use {Rng, Rand, Open01}; +use {Rng, SampleRng, Rand, Open01}; use distributions::{ziggurat, ziggurat_tables, Sample, IndependentSample}; /// A wrapper around an `f64` to generate N(0, 1) random numbers diff --git a/src/distributions/range.rs b/src/distributions/range.rs index 051fb7a85ab..f8f7119e4c6 100644 --- a/src/distributions/range.rs +++ b/src/distributions/range.rs @@ -14,7 +14,7 @@ use core::num::Wrapping as w; -use Rng; +use {Rng, SampleRng}; use distributions::{Sample, IndependentSample}; /// Sample values uniformly between two bounds. diff --git a/src/lib.rs b/src/lib.rs index 48c4acf8d3d..eaf7d6263c4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -79,7 +79,7 @@ //! # Examples //! //! ```rust -//! use rand::Rng; +//! use rand::SampleRng; //! //! let mut rng = rand::thread_rng(); //! if rng.gen() { // random bool @@ -152,7 +152,7 @@ //! [Monty Hall Problem]: https://en.wikipedia.org/wiki/Monty_Hall_problem //! //! ``` -//! use rand::Rng; +//! use rand::SampleRng; //! use rand::distributions::{IndependentSample, Range}; //! //! struct SimulationResult { @@ -161,7 +161,7 @@ //! } //! //! // Run a single simulation of the Monty Hall problem. -//! fn simulate(random_door: &Range, rng: &mut R) +//! fn simulate(random_door: &Range, rng: &mut R) //! -> SimulationResult { //! let car = random_door.ind_sample(rng); //! @@ -182,7 +182,7 @@ //! //! // Returns the door the game host opens given our choice and knowledge of //! // where the car is. The game host will never open the door with the car. -//! fn game_host_open(car: u32, choice: u32, rng: &mut R) -> u32 { +//! fn game_host_open(car: u32, choice: u32, rng: &mut R) -> u32 { //! let choices = free_doors(&[car, choice]); //! rand::seq::sample_slice(rng, &choices, 1)[0] //! } @@ -346,6 +346,21 @@ pub trait Rand : Sized { } /// A random number generator. +/// +/// This trait encapsulates the low-level functionality common to all +/// generators, and is the "back end", to be implemented by generators. +/// Several extension traits exist: +/// +/// * [`SampleRng`] provides high-level generic functionality built on top of +/// `Rng` +/// * [`SeedableRng`] is another "back end" trait covering creation and +/// seeding of algorithmic RNGs (PRNGs) +/// * [`NewRng`] is a high-level trait providing a convenient way to create +/// freshly-seeded PRNGs +/// +/// [`SampleRng`]: trait.SampleRng.html +/// [`SeedableRng`]: trait.SeedableRng.html +/// [`NewRng`]: trait.NewRng.html pub trait Rng { /// Return the next random `u32`. /// @@ -473,13 +488,28 @@ pub trait Rng { fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { Ok(self.fill_bytes(dest)) } +} +/// An automatically-implemented extension trait on [`Rng`] providing high-level +/// generic methods for sampling values and other convenience methods. +/// +/// Users should "use" this trait to enable its extension methods on [`Rng`] +/// or require this type directly (i.e. ``). Since `SampleRng` +/// extends `Rng` and every `Rng` implements `SampleRng`, usage of the two +/// traits is somewhat interchangeable. +/// +/// This functionality is provided as an extension trait to allow separation +/// between the backend (the [`Rng`] providing randomness) and the front-end +/// (converting that randomness to the desired type and distribution). +/// +/// [`Rng`]: trait.Rng.html +pub trait SampleRng: Rng { /// Return a random value of a `Rand` type. /// /// # Example /// /// ```rust - /// use rand::{thread_rng, Rng}; + /// use rand::{thread_rng, SampleRng}; /// /// let mut rng = thread_rng(); /// let x: u32 = rng.gen(); @@ -497,7 +527,7 @@ pub trait Rng { /// # Example /// /// ``` - /// use rand::{thread_rng, Rng}; + /// use rand::{thread_rng, SampleRng}; /// /// let mut rng = thread_rng(); /// let x = rng.gen_iter::().take(10).collect::>(); @@ -524,7 +554,7 @@ pub trait Rng { /// # Example /// /// ```rust - /// use rand::{thread_rng, Rng}; + /// use rand::{thread_rng, SampleRng}; /// /// let mut rng = thread_rng(); /// let n: u32 = rng.gen_range(0, 10); @@ -533,7 +563,7 @@ pub trait Rng { /// println!("{}", m); /// ``` fn gen_range(&mut self, low: T, high: T) -> T where Self: Sized { - assert!(low < high, "Rng.gen_range called with low >= high"); + assert!(low < high, "SampleRng::gen_range called with low >= high"); Range::new(low, high).ind_sample(self) } @@ -542,7 +572,7 @@ pub trait Rng { /// # Example /// /// ```rust - /// use rand::{thread_rng, Rng}; + /// use rand::{thread_rng, SampleRng}; /// /// let mut rng = thread_rng(); /// println!("{}", rng.gen_weighted_bool(3)); @@ -556,7 +586,7 @@ pub trait Rng { /// # Example /// /// ```rust - /// use rand::{thread_rng, Rng}; + /// use rand::{thread_rng, SampleRng}; /// /// let s: String = thread_rng().gen_ascii_chars().take(10).collect(); /// println!("{}", s); @@ -572,7 +602,7 @@ pub trait Rng { /// # Example /// /// ``` - /// use rand::{thread_rng, Rng}; + /// use rand::{thread_rng, SampleRng}; /// /// let choices = [1, 2, 4, 8, 16, 32]; /// let mut rng = thread_rng(); @@ -607,7 +637,7 @@ pub trait Rng { /// # Example /// /// ```rust - /// use rand::{thread_rng, Rng}; + /// use rand::{thread_rng, SampleRng}; /// /// let mut rng = thread_rng(); /// let mut y = [1, 2, 3]; @@ -627,6 +657,8 @@ pub trait Rng { } } +impl SampleRng for R {} + impl<'a, R: ?Sized> Rng for &'a mut R where R: Rng { #[inline] fn next_u32(&mut self) -> u32 { @@ -737,7 +769,15 @@ impl<'a, R: Rng> Iterator for AsciiGenerator<'a, R> { /// A random number generator that can be explicitly seeded. /// -/// Each pseudo-random number generator (PRNG) should implement this. +/// This trait encapsulates the low-level functionality common to all +/// pseudo-random number generators (PRNGs, or algorithmic generators). +/// +/// Normally users should use the [`NewRng`] extension trait, excepting when a +/// fixed seed must be used, in which case usage of [`SeedableRng::from_seed`] +/// is recommended. +/// +/// [`NewRng`]: trait.NewRng.html +/// [`SeedableRng::from_seed`]: #tymethod.from_seed pub trait SeedableRng: Sized { /// Seed type, which is restricted to types mutably-dereferencable as `u8` /// arrays (we recommend `[u8; N]` for some `N`). @@ -767,8 +807,12 @@ pub trait SeedableRng: Sized { /// Create a new PRNG seeded from another `Rng`. /// - /// This is the recommended way to initialize PRNGs. The [`NewRng`] trait - /// provides a convenient new method based on `from_rng`. + /// This is the recommended way to initialize PRNGs with fresh entropy. The + /// [`NewRng`] trait provides a convenient new method based on `from_rng`. + /// + /// Usage of this method is not recommended when reproducibility is required + /// since implementing PRNGs are not required to fix Endianness and are + /// allowed to modify implementations in new releases. /// /// It is important to use a good source of randomness to initialize the /// PRNG. Cryptographic PRNG may be rendered insecure when seeded from a @@ -789,7 +833,6 @@ pub trait SeedableRng: Sized { /// /// PRNG implementations are allowed to assume that a good RNG is provided /// for seeding, and that it is cryptographically secure when appropriate. - /// There are no reproducibility requirements like endianness conversion. /// /// [`NewRng`]: trait.NewRng.html /// [`OsRng`]: os/struct.OsRng.html @@ -806,7 +849,7 @@ pub trait SeedableRng: Sized { /// pseudo-random number generators (PRNGs). /// /// This is the recommended way to create PRNGs, unless a deterministic seed is -/// desired (in which case `SeedableRng::from_seed` should be used). +/// desired (in which case [`SeedableRng::from_seed`] should be used). /// /// Note: this trait is automatically implemented for any PRNG implementing /// [`SeedableRng`] and is not intended to be implemented by users. @@ -814,13 +857,14 @@ pub trait SeedableRng: Sized { /// ## Example /// /// ``` -/// use rand::{StdRng, Rng, NewRng}; +/// use rand::{StdRng, SampleRng, NewRng}; /// /// let mut rng = StdRng::new().unwrap(); /// println!("Random die roll: {}", rng.gen_range(1, 7)); /// ``` /// /// [`SeedableRng`]: trait.SeedableRng.html +/// [`SeedableRng::from_seed`]: trait.SeedableRng.html#tymethod.from_seed #[cfg(feature="std")] pub trait NewRng: SeedableRng { /// Creates a new instance, automatically seeded with fresh entropy. @@ -1032,7 +1076,7 @@ impl Rng for ThreadRng { /// Caching the thread local random number generator: /// /// ``` -/// use rand::Rng; +/// use rand::SampleRng; /// /// let mut v = vec![1, 2, 3]; /// @@ -1085,7 +1129,7 @@ mod test { use impls; #[cfg(feature="std")] use super::{random, thread_rng}; - use super::{Rng, SeedableRng, StdRng}; + use super::{Rng, SampleRng, SeedableRng, StdRng}; #[cfg(feature="alloc")] use alloc::boxed::Box; diff --git a/src/rand_impls.rs b/src/rand_impls.rs index e8c70f523d4..307a683ff3d 100644 --- a/src/rand_impls.rs +++ b/src/rand_impls.rs @@ -12,7 +12,7 @@ use core::{char, mem}; -use {Rand, Rng, SeedableRng}; +use {Rand, Rng, SampleRng, SeedableRng}; impl Rand for isize { #[inline] @@ -255,7 +255,7 @@ impl Rand for T { #[cfg(test)] mod tests { use impls; - use {Rng, Open01, Closed01}; + use {Rng, SampleRng, Open01, Closed01}; struct ConstantRng(u64); impl Rng for ConstantRng { diff --git a/src/read.rs b/src/read.rs index 0590d6fe35e..a9c10ddf775 100644 --- a/src/read.rs +++ b/src/read.rs @@ -25,7 +25,7 @@ use {Rng, Error, ErrorKind, impls}; /// # Example /// /// ```rust -/// use rand::{read, Rng}; +/// use rand::{read, SampleRng}; /// /// let data = vec![1, 2, 3, 4, 5, 6, 7, 8]; /// let mut rng = read::ReadRng::new(&data[..]); diff --git a/src/seq.rs b/src/seq.rs index 7c071afb500..6ef0df01a0e 100644 --- a/src/seq.rs +++ b/src/seq.rs @@ -10,7 +10,7 @@ //! Functions for randomly accessing and sampling sequences. -use super::Rng; +use super::SampleRng; // This crate is only enabled when either std or alloc is available. // BTreeMap is not as fast in tests, but better than nothing. @@ -41,7 +41,7 @@ use super::Rng; /// ``` pub fn sample_iter(rng: &mut R, iterable: I, amount: usize) -> Result, Vec> where I: IntoIterator, - R: Rng, + R: SampleRng, { let mut iter = iterable.into_iter(); let mut reservoir = Vec::with_capacity(amount); @@ -85,7 +85,7 @@ pub fn sample_iter(rng: &mut R, iterable: I, amount: usize) -> Result(rng: &mut R, slice: &[T], amount: usize) -> Vec - where R: Rng, + where R: SampleRng, T: Clone { let indices = sample_indices(rng, slice.len(), amount); @@ -113,7 +113,7 @@ pub fn sample_slice(rng: &mut R, slice: &[T], amount: usize) -> Vec /// println!("{:?}", seq::sample_slice_ref(&mut rng, &values, 3)); /// ``` pub fn sample_slice_ref<'a, R, T>(rng: &mut R, slice: &'a [T], amount: usize) -> Vec<&'a T> - where R: Rng + where R: SampleRng { let indices = sample_indices(rng, slice.len(), amount); @@ -133,7 +133,7 @@ pub fn sample_slice_ref<'a, R, T>(rng: &mut R, slice: &'a [T], amount: usize) -> /// /// Panics if `amount > length` pub fn sample_indices(rng: &mut R, length: usize, amount: usize) -> Vec - where R: Rng, + where R: SampleRng, { if amount > length { panic!("`amount` must be less than or equal to `slice.len()`"); @@ -166,7 +166,7 @@ pub fn sample_indices(rng: &mut R, length: usize, amount: usize) -> Vec= length / 2` since it does not /// require allocating an extra cache and is much faster. fn sample_indices_inplace(rng: &mut R, length: usize, amount: usize) -> Vec - where R: Rng, + where R: SampleRng, { debug_assert!(amount <= length); let mut indices: Vec = Vec::with_capacity(length); @@ -193,7 +193,7 @@ fn sample_indices_cache( length: usize, amount: usize, ) -> Vec - where R: Rng, + where R: SampleRng, { debug_assert!(amount <= length); #[cfg(feature="std")] let mut cache = HashMap::with_capacity(amount); @@ -227,7 +227,7 @@ fn sample_indices_cache( #[cfg(test)] mod test { use super::*; - use {XorShiftRng, SeedableRng}; + use {XorShiftRng, Rng, SeedableRng}; #[cfg(not(feature="std"))] use alloc::Vec; From c73d9f1ba2ebcf28435e73e2e165e8036b087ab6 Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Mon, 29 Jan 2018 18:42:35 +0000 Subject: [PATCH 2/3] SampleRng: fix benchmarks --- benches/generators.rs | 2 +- benches/misc.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/benches/generators.rs b/benches/generators.rs index 044d7b24e89..088a94da2fe 100644 --- a/benches/generators.rs +++ b/benches/generators.rs @@ -9,7 +9,7 @@ const BYTES_LEN: usize = 1024; use std::mem::size_of; use test::{black_box, Bencher}; -use rand::{Rng, NewRng, StdRng, OsRng, JitterRng}; +use rand::{Rng, SampleRng, NewRng, StdRng, OsRng, JitterRng}; use rand::{XorShiftRng, Hc128Rng, IsaacRng, Isaac64Rng, ChaChaRng}; macro_rules! gen_bytes { diff --git a/benches/misc.rs b/benches/misc.rs index 42517617662..41d518c0283 100644 --- a/benches/misc.rs +++ b/benches/misc.rs @@ -5,7 +5,7 @@ extern crate rand; use test::{black_box, Bencher}; -use rand::{Rng, weak_rng}; +use rand::{SampleRng, weak_rng}; use rand::seq::*; #[bench] From a0ea69881b1c600e7beff0a37b61ce71f5ad0240 Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Mon, 29 Jan 2018 19:04:29 +0000 Subject: [PATCH 3/3] Make SampleRng extension trait require Sized All methods already require the bound --- src/lib.rs | 18 +++++++++--------- src/seq.rs | 14 +++++++------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index eaf7d6263c4..161e84cd7b6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -503,7 +503,7 @@ pub trait Rng { /// (converting that randomness to the desired type and distribution). /// /// [`Rng`]: trait.Rng.html -pub trait SampleRng: Rng { +pub trait SampleRng: Rng + Sized { /// Return a random value of a `Rand` type. /// /// # Example @@ -517,7 +517,7 @@ pub trait SampleRng: Rng { /// println!("{:?}", rng.gen::<(f64, bool)>()); /// ``` #[inline(always)] - fn gen(&mut self) -> T where Self: Sized { + fn gen(&mut self) -> T { Rand::rand(self) } @@ -535,7 +535,7 @@ pub trait SampleRng: Rng { /// println!("{:?}", rng.gen_iter::<(f64, bool)>().take(5) /// .collect::>()); /// ``` - fn gen_iter<'a, T: Rand>(&'a mut self) -> Generator<'a, T, Self> where Self: Sized { + fn gen_iter<'a, T: Rand>(&'a mut self) -> Generator<'a, T, Self> { Generator { rng: self, _marker: marker::PhantomData } } @@ -562,7 +562,7 @@ pub trait SampleRng: Rng { /// let m: f64 = rng.gen_range(-40.0f64, 1.3e5f64); /// println!("{}", m); /// ``` - fn gen_range(&mut self, low: T, high: T) -> T where Self: Sized { + fn gen_range(&mut self, low: T, high: T) -> T { assert!(low < high, "SampleRng::gen_range called with low >= high"); Range::new(low, high).ind_sample(self) } @@ -577,7 +577,7 @@ pub trait SampleRng: Rng { /// let mut rng = thread_rng(); /// println!("{}", rng.gen_weighted_bool(3)); /// ``` - fn gen_weighted_bool(&mut self, n: u32) -> bool where Self: Sized { + fn gen_weighted_bool(&mut self, n: u32) -> bool { n <= 1 || self.gen_range(0, n) == 0 } @@ -591,7 +591,7 @@ pub trait SampleRng: Rng { /// let s: String = thread_rng().gen_ascii_chars().take(10).collect(); /// println!("{}", s); /// ``` - fn gen_ascii_chars<'a>(&'a mut self) -> AsciiGenerator<'a, Self> where Self: Sized { + fn gen_ascii_chars<'a>(&'a mut self) -> AsciiGenerator<'a, Self> { AsciiGenerator { rng: self } } @@ -609,7 +609,7 @@ pub trait SampleRng: Rng { /// println!("{:?}", rng.choose(&choices)); /// assert_eq!(rng.choose(&choices[..0]), None); /// ``` - fn choose<'a, T>(&mut self, values: &'a [T]) -> Option<&'a T> where Self: Sized { + fn choose<'a, T>(&mut self, values: &'a [T]) -> Option<&'a T> { if values.is_empty() { None } else { @@ -620,7 +620,7 @@ pub trait SampleRng: Rng { /// Return a mutable pointer to a random element from `values`. /// /// Return `None` if `values` is empty. - fn choose_mut<'a, T>(&mut self, values: &'a mut [T]) -> Option<&'a mut T> where Self: Sized { + fn choose_mut<'a, T>(&mut self, values: &'a mut [T]) -> Option<&'a mut T> { if values.is_empty() { None } else { @@ -646,7 +646,7 @@ pub trait SampleRng: Rng { /// rng.shuffle(&mut y); /// println!("{:?}", y); /// ``` - fn shuffle(&mut self, values: &mut [T]) where Self: Sized { + fn shuffle(&mut self, values: &mut [T]) { let mut i = values.len(); while i >= 2 { // invariant: elements with index >= i have been locked in place. diff --git a/src/seq.rs b/src/seq.rs index 6ef0df01a0e..279fd1d966b 100644 --- a/src/seq.rs +++ b/src/seq.rs @@ -10,7 +10,7 @@ //! Functions for randomly accessing and sampling sequences. -use super::SampleRng; +use super::{Rng, SampleRng}; // This crate is only enabled when either std or alloc is available. // BTreeMap is not as fast in tests, but better than nothing. @@ -41,7 +41,7 @@ use super::SampleRng; /// ``` pub fn sample_iter(rng: &mut R, iterable: I, amount: usize) -> Result, Vec> where I: IntoIterator, - R: SampleRng, + R: Rng, { let mut iter = iterable.into_iter(); let mut reservoir = Vec::with_capacity(amount); @@ -85,7 +85,7 @@ pub fn sample_iter(rng: &mut R, iterable: I, amount: usize) -> Result(rng: &mut R, slice: &[T], amount: usize) -> Vec - where R: SampleRng, + where R: Rng, T: Clone { let indices = sample_indices(rng, slice.len(), amount); @@ -113,7 +113,7 @@ pub fn sample_slice(rng: &mut R, slice: &[T], amount: usize) -> Vec /// println!("{:?}", seq::sample_slice_ref(&mut rng, &values, 3)); /// ``` pub fn sample_slice_ref<'a, R, T>(rng: &mut R, slice: &'a [T], amount: usize) -> Vec<&'a T> - where R: SampleRng + where R: Rng { let indices = sample_indices(rng, slice.len(), amount); @@ -133,7 +133,7 @@ pub fn sample_slice_ref<'a, R, T>(rng: &mut R, slice: &'a [T], amount: usize) -> /// /// Panics if `amount > length` pub fn sample_indices(rng: &mut R, length: usize, amount: usize) -> Vec - where R: SampleRng, + where R: Rng, { if amount > length { panic!("`amount` must be less than or equal to `slice.len()`"); @@ -166,7 +166,7 @@ pub fn sample_indices(rng: &mut R, length: usize, amount: usize) -> Vec= length / 2` since it does not /// require allocating an extra cache and is much faster. fn sample_indices_inplace(rng: &mut R, length: usize, amount: usize) -> Vec - where R: SampleRng, + where R: Rng, { debug_assert!(amount <= length); let mut indices: Vec = Vec::with_capacity(length); @@ -193,7 +193,7 @@ fn sample_indices_cache( length: usize, amount: usize, ) -> Vec - where R: SampleRng, + where R: Rng, { debug_assert!(amount <= length); #[cfg(feature="std")] let mut cache = HashMap::with_capacity(amount);