From b9e3e95fec1b3d090e91ea17fc31515efcd82b96 Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Tue, 12 Feb 2019 11:47:34 +0000 Subject: [PATCH] Add rustfmt configuration and accept a few of its changes --- examples/monte-carlo.rs | 30 +++---- examples/monty-hall.rs | 7 +- rustfmt.toml | 32 +++++++ src/lib.rs | 19 ++-- src/seq/index.rs | 16 ++-- src/seq/mod.rs | 190 +++++++++++++++++++++------------------- tests/uniformity.rs | 8 +- 7 files changed, 173 insertions(+), 129 deletions(-) create mode 100644 rustfmt.toml diff --git a/examples/monte-carlo.rs b/examples/monte-carlo.rs index 91629968..b79c6a5a 100644 --- a/examples/monte-carlo.rs +++ b/examples/monte-carlo.rs @@ -11,7 +11,7 @@ //! //! Imagine that we have a square with sides of length 2 and a unit circle //! (radius = 1), both centered at the origin. The areas are: -//! +//! //! ```text //! area of circle = πr² = π * r * r = π //! area of square = 2² = 4 @@ -24,7 +24,7 @@ //! the square at random, calculate the fraction that fall within the circle, //! and multiply this fraction by 4. -#![cfg(feature="std")] +#![cfg(feature = "std")] extern crate rand; @@ -32,20 +32,20 @@ extern crate rand; use rand::distributions::{Distribution, Uniform}; fn main() { - let range = Uniform::new(-1.0f64, 1.0); - let mut rng = rand::thread_rng(); + let range = Uniform::new(-1.0f64, 1.0); + let mut rng = rand::thread_rng(); - let total = 1_000_000; - let mut in_circle = 0; + let total = 1_000_000; + let mut in_circle = 0; - for _ in 0..total { - let a = range.sample(&mut rng); - let b = range.sample(&mut rng); - if a*a + b*b <= 1.0 { - in_circle += 1; - } - } + for _ in 0..total { + let a = range.sample(&mut rng); + let b = range.sample(&mut rng); + if a*a + b*b <= 1.0 { + in_circle += 1; + } + } - // prints something close to 3.14159... - println!("π is approximately {}", 4. * (in_circle as f64) / (total as f64)); + // prints something close to 3.14159... + println!("π is approximately {}", 4. * (in_circle as f64) / (total as f64)); } diff --git a/examples/monty-hall.rs b/examples/monty-hall.rs index 0932c5ef..643fbb51 100644 --- a/examples/monty-hall.rs +++ b/examples/monty-hall.rs @@ -26,13 +26,13 @@ //! //! [Monty Hall Problem]: https://en.wikipedia.org/wiki/Monty_Hall_problem -#![cfg(feature="std")] +#![cfg(feature = "std")] extern crate rand; -use rand::Rng; use rand::distributions::{Distribution, Uniform}; +use rand::Rng; struct SimulationResult { win: bool, @@ -40,8 +40,7 @@ struct SimulationResult { } // Run a single simulation of the Monty Hall problem. -fn simulate(random_door: &Uniform, rng: &mut R) - -> SimulationResult { +fn simulate(random_door: &Uniform, rng: &mut R) -> SimulationResult { let car = random_door.sample(rng); // This is our initial choice diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 00000000..4fe708f4 --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1,32 @@ +# This rustfmt file is added for configuration, but in practice much of our +# code is hand-formatted, frequently with more readable results. + +# Comments: +normalize_comments = true +wrap_comments = false +format_doc_comments = true +comment_width = 90 # small excess is okay but prefer 80 + +# Arguments: +use_small_heuristics = "max" +fn_args_density = "compressed" +fn_single_line = false +overflow_delimited_expr = true +where_single_line = true + +# enum_discrim_align_threshold = 20 +# struct_field_align_threshold = 20 + +# Compatibility: +use_try_shorthand = true # stable since Rustc 1.13.0 +use_field_init_shorthand = true # stable since Rustc 1.17.0 +edition = "2015" # we require compatibility back to 1.22.0 + +# Misc: +blank_lines_upper_bound = 2 +reorder_impl_items = true +# report_todo = "Unnumbered" +# report_fixme = "Unnumbered" + +# Ignored files: +ignore = [] diff --git a/src/lib.rs b/src/lib.rs index 9c0482f3..419dd812 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -211,7 +211,8 @@ pub trait Rng: RngCore { /// println!("{:?}", rng.gen::<(f64, bool)>()); /// ``` #[inline] - fn gen(&mut self) -> T where Standard: Distribution { + fn gen(&mut self) -> T + where Standard: Distribution { Standard.sample(self) } @@ -240,8 +241,10 @@ pub trait Rng: RngCore { /// /// [`Uniform`]: distributions::uniform::Uniform fn gen_range(&mut self, low: B1, high: B2) -> T - where B1: SampleBorrow + Sized, - B2: SampleBorrow + Sized { + where + B1: SampleBorrow + Sized, + B2: SampleBorrow + Sized, + { T::Sampler::sample_single(low, high, self) } @@ -290,9 +293,10 @@ pub trait Rng: RngCore { /// println!("Not a 6; rolling again!"); /// } /// ``` - fn sample_iter<'a, T, D: Distribution>(&'a mut self, distr: &'a D) - -> distributions::DistIter<'a, D, Self, T> where Self: Sized - { + fn sample_iter<'a, T, D: Distribution>( + &'a mut self, distr: &'a D, + ) -> distributions::DistIter<'a, D, Self, T> + where Self: Sized { distr.sample_iter(self) } @@ -649,7 +653,8 @@ impl FromEntropy for R { /// [`Standard`]: distributions::Standard #[cfg(feature="std")] #[inline] -pub fn random() -> T where Standard: Distribution { +pub fn random() -> T +where Standard: Distribution { thread_rng().gen() } diff --git a/src/seq/index.rs b/src/seq/index.rs index a70c7367..c64357ac 100644 --- a/src/seq/index.rs +++ b/src/seq/index.rs @@ -173,14 +173,13 @@ impl ExactSizeIterator for IndexVecIntoIter {} /// Note that performance is significantly better over `u32` indices than over /// `u64` indices. Because of this we hide the underlying type behind an /// abstraction, `IndexVec`. -/// +/// /// If an allocation-free `no_std` function is required, it is suggested /// to adapt the internal `sample_floyd` implementation. /// /// Panics if `amount > length`. pub fn sample(rng: &mut R, length: usize, amount: usize) -> IndexVec - where R: Rng + ?Sized, -{ +where R: Rng + ?Sized { if amount > length { panic!("`amount` of samples must be less than or equal to `length`"); } @@ -227,8 +226,7 @@ pub fn sample(rng: &mut R, length: usize, amount: usize) -> IndexVec /// /// This implementation uses `O(amount)` memory and `O(amount^2)` time. fn sample_floyd(rng: &mut R, length: u32, amount: u32) -> IndexVec - where R: Rng + ?Sized, -{ +where R: Rng + ?Sized { // For small amount we use Floyd's fully-shuffled variant. For larger // amounts this is slow due to Vec::insert performance, so we shuffle // afterwards. Benchmarks show little overhead from extra logic. @@ -274,8 +272,7 @@ fn sample_floyd(rng: &mut R, length: u32, amount: u32) -> IndexVec /// /// Set-up is `O(length)` time and memory and shuffling is `O(amount)` time. fn sample_inplace(rng: &mut R, length: u32, amount: u32) -> IndexVec - where R: Rng + ?Sized, -{ +where R: Rng + ?Sized { debug_assert!(amount <= length); let mut indices: Vec = Vec::with_capacity(length as usize); indices.extend(0..length); @@ -290,13 +287,12 @@ fn sample_inplace(rng: &mut R, length: u32, amount: u32) -> IndexVec /// Randomly sample exactly `amount` indices from `0..length`, using rejection /// sampling. -/// +/// /// Since `amount <<< length` there is a low chance of a random sample in /// `0..length` being a duplicate. We test for duplicates and resample where /// necessary. The algorithm is `O(amount)` time and memory. fn sample_rejection(rng: &mut R, length: usize, amount: usize) -> IndexVec - where R: Rng + ?Sized, -{ +where R: Rng + ?Sized { debug_assert!(amount < length); #[cfg(feature="std")] let mut cache = HashSet::with_capacity(amount); #[cfg(not(feature="std"))] let mut cache = BTreeSet::new(); diff --git a/src/seq/mod.rs b/src/seq/mod.rs index d0f83084..eff8a881 100644 --- a/src/seq/mod.rs +++ b/src/seq/mod.rs @@ -46,33 +46,33 @@ pub trait SliceRandom { /// assert_eq!(choices[..0].choose(&mut rng), None); /// ``` fn choose(&self, rng: &mut R) -> Option<&Self::Item> - where R: Rng + ?Sized; + where R: Rng + ?Sized; /// Returns a mutable reference to one random element of the slice, or /// `None` if the slice is empty. - /// + /// /// Depending on the implementation, complexity is expected to be `O(1)`. fn choose_mut(&mut self, rng: &mut R) -> Option<&mut Self::Item> - where R: Rng + ?Sized; + where R: Rng + ?Sized; /// Produces an iterator that chooses `amount` elements from the slice at /// random without repeating any, and returns them in random order. - /// + /// /// In case this API is not sufficiently flexible, use `index::sample` then /// apply the indices to the slice. - /// + /// /// Complexity is expected to be the same as `index::sample`. - /// + /// /// # Example /// ``` /// use rand::seq::SliceRandom; - /// + /// /// let mut rng = &mut rand::thread_rng(); /// let sample = "Hello, audience!".as_bytes(); - /// + /// /// // collect the results into a vector: /// let v: Vec = sample.choose_multiple(&mut rng, 3).cloned().collect(); - /// + /// /// // store in a buffer: /// let mut buf = [0u8; 5]; /// for (b, slot) in sample.choose_multiple(&mut rng, buf.len()).zip(buf.iter_mut()) { @@ -81,7 +81,7 @@ pub trait SliceRandom { /// ``` #[cfg(feature = "alloc")] fn choose_multiple(&self, rng: &mut R, amount: usize) -> SliceChooseIter - where R: Rng + ?Sized; + where R: Rng + ?Sized; /// Similar to [`choose`], where the likelihood of each outcome may be /// specified. The specified function `weight` maps items `x` to a relative @@ -100,15 +100,18 @@ pub trait SliceRandom { /// ``` /// [`choose`]: SliceRandom::choose #[cfg(feature = "alloc")] - fn choose_weighted(&self, rng: &mut R, weight: F) -> Result<&Self::Item, WeightedError> - where R: Rng + ?Sized, - F: Fn(&Self::Item) -> B, - B: SampleBorrow, - X: SampleUniform + - for<'a> ::core::ops::AddAssign<&'a X> + - ::core::cmp::PartialOrd + - Clone + - Default; + fn choose_weighted( + &self, rng: &mut R, weight: F, + ) -> Result<&Self::Item, WeightedError> + where + R: Rng + ?Sized, + F: Fn(&Self::Item) -> B, + B: SampleBorrow, + X: SampleUniform + + for<'a> ::core::ops::AddAssign<&'a X> + + ::core::cmp::PartialOrd + + Clone + + Default; /// Similar to [`choose_mut`], where the likelihood of each outcome may be /// specified. The specified function `weight` maps items `x` to a relative @@ -120,25 +123,28 @@ pub trait SliceRandom { /// [`choose_mut`]: SliceRandom::choose_mut /// [`choose_weighted`]: SliceRandom::choose_weighted #[cfg(feature = "alloc")] - fn choose_weighted_mut(&mut self, rng: &mut R, weight: F) -> Result<&mut Self::Item, WeightedError> - where R: Rng + ?Sized, - F: Fn(&Self::Item) -> B, - B: SampleBorrow, - X: SampleUniform + - for<'a> ::core::ops::AddAssign<&'a X> + - ::core::cmp::PartialOrd + - Clone + - Default; + fn choose_weighted_mut( + &mut self, rng: &mut R, weight: F, + ) -> Result<&mut Self::Item, WeightedError> + where + R: Rng + ?Sized, + F: Fn(&Self::Item) -> B, + B: SampleBorrow, + X: SampleUniform + + for<'a> ::core::ops::AddAssign<&'a X> + + ::core::cmp::PartialOrd + + Clone + + Default; /// Shuffle a mutable slice in place. - /// + /// /// Depending on the implementation, complexity is expected to be `O(1)`. /// /// # Example /// /// ``` - /// use rand::thread_rng; /// use rand::seq::SliceRandom; + /// use rand::thread_rng; /// /// let mut rng = thread_rng(); /// let mut y = [1, 2, 3, 4, 5]; @@ -146,7 +152,8 @@ pub trait SliceRandom { /// y.shuffle(&mut rng); /// println!("Shuffled: {:?}", y); /// ``` - fn shuffle(&mut self, rng: &mut R) where R: Rng + ?Sized; + fn shuffle(&mut self, rng: &mut R) + where R: Rng + ?Sized; /// Shuffle a slice in place, but exit early. /// @@ -165,8 +172,10 @@ pub trait SliceRandom { /// will perform a full shuffle. /// /// Complexity is expected to be `O(m)` where `m = amount`. - fn partial_shuffle(&mut self, rng: &mut R, amount: usize) - -> (&mut [Self::Item], &mut [Self::Item]) where R: Rng + ?Sized; + fn partial_shuffle( + &mut self, rng: &mut R, amount: usize, + ) -> (&mut [Self::Item], &mut [Self::Item]) + where R: Rng + ?Sized; } /// Extension trait on iterators, providing random sampling methods. @@ -176,7 +185,7 @@ pub trait IteratorRandom: Iterator + Sized { /// functions using the slice instead. /// /// Returns `None` if and only if the iterator is empty. - /// + /// /// Complexity is `O(n)`, where `n` is the length of the iterator. /// This likely consumes multiple random numbers, but the exact number /// is unspecified. @@ -184,8 +193,7 @@ pub trait IteratorRandom: Iterator + Sized { /// [`choose`]: SliceRandom::method.choose /// [`choose_mut`]: SliceRandom::choose_mut fn choose(mut self, rng: &mut R) -> Option - where R: Rng + ?Sized - { + where R: Rng + ?Sized { let (mut lower, mut upper) = self.size_hint(); let mut consumed = 0; let mut result = None; @@ -232,19 +240,18 @@ pub trait IteratorRandom: Iterator + Sized { /// Collects `amount` values at random from the iterator into a supplied /// buffer. - /// + /// /// Although the elements are selected randomly, the order of elements in /// the buffer is neither stable nor fully random. If random ordering is /// desired, shuffle the result. - /// + /// /// Returns the number of elements added to the buffer. This equals `amount` /// unless the iterator contains insufficient elements, in which case this /// equals the number of elements available. - /// + /// /// Complexity is `O(n)` where `n` is the length of the iterator. - fn choose_multiple_fill(mut self, rng: &mut R, buf: &mut [Self::Item]) - -> usize where R: Rng + ?Sized - { + fn choose_multiple_fill(mut self, rng: &mut R, buf: &mut [Self::Item]) -> usize + where R: Rng + ?Sized { let amount = buf.len(); let mut len = 0; while len < amount { @@ -274,16 +281,15 @@ pub trait IteratorRandom: Iterator + Sized { /// Although the elements are selected randomly, the order of elements in /// the buffer is neither stable nor fully random. If random ordering is /// desired, shuffle the result. - /// + /// /// The length of the returned vector equals `amount` unless the iterator /// contains insufficient elements, in which case it equals the number of /// elements available. - /// + /// /// Complexity is `O(n)` where `n` is the length of the iterator. #[cfg(feature = "alloc")] fn choose_multiple(mut self, rng: &mut R, amount: usize) -> Vec - where R: Rng + ?Sized - { + where R: Rng + ?Sized { let mut reservoir = Vec::with_capacity(amount); reservoir.extend(self.by_ref().take(amount)); @@ -312,8 +318,7 @@ impl SliceRandom for [T] { type Item = T; fn choose(&self, rng: &mut R) -> Option<&Self::Item> - where R: Rng + ?Sized - { + where R: Rng + ?Sized { if self.is_empty() { None } else { @@ -322,8 +327,7 @@ impl SliceRandom for [T] { } fn choose_mut(&mut self, rng: &mut R) -> Option<&mut Self::Item> - where R: Rng + ?Sized - { + where R: Rng + ?Sized { if self.is_empty() { None } else { @@ -333,10 +337,8 @@ impl SliceRandom for [T] { } #[cfg(feature = "alloc")] - fn choose_multiple(&self, rng: &mut R, amount: usize) - -> SliceChooseIter - where R: Rng + ?Sized - { + fn choose_multiple(&self, rng: &mut R, amount: usize) -> SliceChooseIter + where R: Rng + ?Sized { let amount = ::core::cmp::min(amount, self.len()); SliceChooseIter { slice: self, @@ -346,54 +348,63 @@ impl SliceRandom for [T] { } #[cfg(feature = "alloc")] - fn choose_weighted(&self, rng: &mut R, weight: F) -> Result<&Self::Item, WeightedError> - where R: Rng + ?Sized, - F: Fn(&Self::Item) -> B, - B: SampleBorrow, - X: SampleUniform + - for<'a> ::core::ops::AddAssign<&'a X> + - ::core::cmp::PartialOrd + - Clone + - Default { + fn choose_weighted( + &self, rng: &mut R, weight: F, + ) -> Result<&Self::Item, WeightedError> + where + R: Rng + ?Sized, + F: Fn(&Self::Item) -> B, + B: SampleBorrow, + X: SampleUniform + + for<'a> ::core::ops::AddAssign<&'a X> + + ::core::cmp::PartialOrd + + Clone + + Default, + { use distributions::{Distribution, WeightedIndex}; let distr = WeightedIndex::new(self.iter().map(weight))?; Ok(&self[distr.sample(rng)]) } #[cfg(feature = "alloc")] - fn choose_weighted_mut(&mut self, rng: &mut R, weight: F) -> Result<&mut Self::Item, WeightedError> - where R: Rng + ?Sized, - F: Fn(&Self::Item) -> B, - B: SampleBorrow, - X: SampleUniform + - for<'a> ::core::ops::AddAssign<&'a X> + - ::core::cmp::PartialOrd + - Clone + - Default { + fn choose_weighted_mut( + &mut self, rng: &mut R, weight: F, + ) -> Result<&mut Self::Item, WeightedError> + where + R: Rng + ?Sized, + F: Fn(&Self::Item) -> B, + B: SampleBorrow, + X: SampleUniform + + for<'a> ::core::ops::AddAssign<&'a X> + + ::core::cmp::PartialOrd + + Clone + + Default, + { use distributions::{Distribution, WeightedIndex}; let distr = WeightedIndex::new(self.iter().map(weight))?; Ok(&mut self[distr.sample(rng)]) } - fn shuffle(&mut self, rng: &mut R) where R: Rng + ?Sized - { + fn shuffle(&mut self, rng: &mut R) + where R: Rng + ?Sized { for i in (1..self.len()).rev() { // invariant: elements with index > i have been locked in place. self.swap(i, rng.gen_range(0, i + 1)); } } - fn partial_shuffle(&mut self, rng: &mut R, amount: usize) - -> (&mut [Self::Item], &mut [Self::Item]) where R: Rng + ?Sized - { + fn partial_shuffle( + &mut self, rng: &mut R, amount: usize, + ) -> (&mut [Self::Item], &mut [Self::Item]) + where R: Rng + ?Sized { // This applies Durstenfeld's algorithm for the // [Fisher–Yates shuffle](https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle#The_modern_algorithm) // for an unbiased permutation, but exits early after choosing `amount` // elements. - + let len = self.len(); let end = if amount >= len { 0 } else { len - amount }; - + for i in (end..len).rev() { // invariant: elements with index > i have been locked in place. self.swap(i, rng.gen_range(0, i + 1)); @@ -423,7 +434,7 @@ impl<'a, S: Index + ?Sized + 'a, T: 'a> Iterator for SliceCho // TODO: investigate using SliceIndex::get_unchecked when stable self.indices.next().map(|i| &self.slice[i as usize]) } - + fn size_hint(&self) -> (usize, Option) { (self.indices.len(), Some(self.indices.len())) } @@ -443,10 +454,11 @@ impl<'a, S: Index + ?Sized + 'a, T: 'a> ExactSizeIterator /// /// Deprecated: use [`IteratorRandom::choose_multiple`] instead. #[cfg(feature = "alloc")] -#[deprecated(since="0.6.0", note="use IteratorRandom::choose_multiple instead")] +#[deprecated(since = "0.6.0", note = "use IteratorRandom::choose_multiple instead")] pub fn sample_iter(rng: &mut R, iterable: I, amount: usize) -> Result, Vec> - where I: IntoIterator, - R: Rng + ?Sized, +where + I: IntoIterator, + R: Rng + ?Sized, { use seq::IteratorRandom; let iter = iterable.into_iter(); @@ -468,10 +480,11 @@ pub fn sample_iter(rng: &mut R, iterable: I, amount: usize) -> Result(rng: &mut R, slice: &[T], amount: usize) -> Vec - where R: Rng + ?Sized, - T: Clone +where + R: Rng + ?Sized, + T: Clone, { let indices = index::sample(rng, slice.len(), amount).into_iter(); @@ -490,10 +503,9 @@ pub fn sample_slice(rng: &mut R, slice: &[T], amount: usize) -> Vec /// /// Deprecated: use [`SliceRandom::choose_multiple`] instead. #[cfg(feature = "alloc")] -#[deprecated(since="0.6.0", note="use SliceRandom::choose_multiple instead")] +#[deprecated(since = "0.6.0", note = "use SliceRandom::choose_multiple instead")] pub fn sample_slice_ref<'a, R, T>(rng: &mut R, slice: &'a [T], amount: usize) -> Vec<&'a T> - where R: Rng + ?Sized -{ +where R: Rng + ?Sized { let indices = index::sample(rng, slice.len(), amount).into_iter(); let mut out = Vec::with_capacity(amount); diff --git a/tests/uniformity.rs b/tests/uniformity.rs index b8f74a62..3b9c7493 100644 --- a/tests/uniformity.rs +++ b/tests/uniformity.rs @@ -12,10 +12,10 @@ extern crate average; extern crate rand; -use std as core; -use rand::FromEntropy; -use rand::distributions::Distribution; use average::Histogram; +use rand::distributions::Distribution; +use rand::FromEntropy; +use std as core; const N_BINS: usize = 100; const N_SAMPLES: u32 = 1_000_000; @@ -50,7 +50,7 @@ fn unit_sphere() { #[test] fn unit_circle() { - use ::std::f64::consts::PI; + use std::f64::consts::PI; let mut h = Histogram100::with_const_width(-PI, PI); let dist = rand::distributions::UnitCircle::new(); let mut rng = rand::rngs::SmallRng::from_entropy();