diff --git a/benches/generators.rs b/benches/generators.rs index 60c0bd08e5c..3e264083d7d 100644 --- a/benches/generators.rs +++ b/benches/generators.rs @@ -19,9 +19,9 @@ use test::{black_box, Bencher}; use rand::prelude::*; use rand::rngs::adapter::ReseedingRng; -use rand::rngs::{OsRng, mock::StepRng}; -use rand_chacha::{ChaCha20Core, ChaCha8Rng, ChaCha12Rng, ChaCha20Rng}; -use rand_hc::{Hc128Rng}; +use rand::rngs::{mock::StepRng, OsRng}; +use rand_chacha::{ChaCha12Rng, ChaCha20Core, ChaCha20Rng, ChaCha8Rng}; +use rand_hc::Hc128Rng; use rand_pcg::{Pcg32, Pcg64, Pcg64Mcg}; macro_rules! gen_bytes { @@ -38,7 +38,7 @@ macro_rules! gen_bytes { }); b.bytes = BYTES_LEN as u64 * RAND_BENCH_N; } - } + }; } gen_bytes!(gen_bytes_step, StepRng::new(0, 1)); @@ -50,7 +50,7 @@ gen_bytes!(gen_bytes_chacha12, ChaCha12Rng::from_entropy()); gen_bytes!(gen_bytes_chacha20, ChaCha20Rng::from_entropy()); gen_bytes!(gen_bytes_hc128, Hc128Rng::from_entropy()); gen_bytes!(gen_bytes_std, StdRng::from_entropy()); -#[cfg(feature="small_rng")] +#[cfg(feature = "small_rng")] gen_bytes!(gen_bytes_small, SmallRng::from_entropy()); gen_bytes!(gen_bytes_os, OsRng); @@ -68,7 +68,7 @@ macro_rules! gen_uint { }); b.bytes = size_of::<$ty>() as u64 * RAND_BENCH_N; } - } + }; } gen_uint!(gen_u32_step, u32, StepRng::new(0, 1)); @@ -80,7 +80,7 @@ gen_uint!(gen_u32_chacha12, u32, ChaCha12Rng::from_entropy()); gen_uint!(gen_u32_chacha20, u32, ChaCha20Rng::from_entropy()); gen_uint!(gen_u32_hc128, u32, Hc128Rng::from_entropy()); gen_uint!(gen_u32_std, u32, StdRng::from_entropy()); -#[cfg(feature="small_rng")] +#[cfg(feature = "small_rng")] gen_uint!(gen_u32_small, u32, SmallRng::from_entropy()); gen_uint!(gen_u32_os, u32, OsRng); @@ -93,7 +93,7 @@ gen_uint!(gen_u64_chacha12, u64, ChaCha12Rng::from_entropy()); gen_uint!(gen_u64_chacha20, u64, ChaCha20Rng::from_entropy()); gen_uint!(gen_u64_hc128, u64, Hc128Rng::from_entropy()); gen_uint!(gen_u64_std, u64, StdRng::from_entropy()); -#[cfg(feature="small_rng")] +#[cfg(feature = "small_rng")] gen_uint!(gen_u64_small, u64, SmallRng::from_entropy()); gen_uint!(gen_u64_os, u64, OsRng); @@ -107,7 +107,7 @@ macro_rules! init_gen { r2 }); } - } + }; } init_gen!(init_pcg32, Pcg32); @@ -123,9 +123,7 @@ macro_rules! reseeding_bytes { ($fnn:ident, $thresh:expr) => { #[bench] fn $fnn(b: &mut Bencher) { - let mut rng = ReseedingRng::new(ChaCha20Core::from_entropy(), - $thresh * 1024, - OsRng); + let mut rng = ReseedingRng::new(ChaCha20Core::from_entropy(), $thresh * 1024, OsRng); let mut buf = [0u8; RESEEDING_BYTES_LEN]; b.iter(|| { for _ in 0..RESEEDING_BENCH_N { @@ -135,7 +133,7 @@ macro_rules! reseeding_bytes { }); b.bytes = RESEEDING_BYTES_LEN as u64 * RESEEDING_BENCH_N; } - } + }; } reseeding_bytes!(reseeding_chacha20_4k, 4); @@ -160,7 +158,7 @@ macro_rules! threadrng_uint { }); b.bytes = size_of::<$ty>() as u64 * RAND_BENCH_N; } - } + }; } threadrng_uint!(thread_rng_u32, u32); diff --git a/benches/misc.rs b/benches/misc.rs index 40986863482..e46137f1981 100644 --- a/benches/misc.rs +++ b/benches/misc.rs @@ -14,8 +14,8 @@ const RAND_BENCH_N: u64 = 1000; use test::Bencher; +use rand::distributions::{Bernoulli, Distribution, Standard}; use rand::prelude::*; -use rand::distributions::{Distribution, Standard, Bernoulli}; use rand_pcg::{Pcg32, Pcg64Mcg}; #[bench] diff --git a/benches/seq.rs b/benches/seq.rs index 4c671b8aad8..7da2ff8a0fd 100644 --- a/benches/seq.rs +++ b/benches/seq.rs @@ -26,7 +26,7 @@ const RAND_BENCH_N: u64 = 1000; #[bench] fn seq_shuffle_100(b: &mut Bencher) { let mut rng = SmallRng::from_rng(thread_rng()).unwrap(); - let x : &mut [usize] = &mut [1; 100]; + let x: &mut [usize] = &mut [1; 100]; b.iter(|| { x.shuffle(&mut rng); x[0] @@ -36,7 +36,7 @@ fn seq_shuffle_100(b: &mut Bencher) { #[bench] fn seq_slice_choose_1_of_1000(b: &mut Bencher) { let mut rng = SmallRng::from_rng(thread_rng()).unwrap(); - let x : &mut [usize] = &mut [1; 1000]; + let x: &mut [usize] = &mut [1; 1000]; for i in 0..1000 { x[i] = i; } @@ -55,19 +55,18 @@ macro_rules! seq_slice_choose_multiple { #[bench] fn $name(b: &mut Bencher) { let mut rng = SmallRng::from_rng(thread_rng()).unwrap(); - let x : &[i32] = &[$amount; $length]; + let x: &[i32] = &[$amount; $length]; let mut result = [0i32; $amount]; b.iter(|| { // Collect full result to prevent unwanted shortcuts getting // first element (in case sample_indices returns an iterator). - for (slot, sample) in result.iter_mut().zip( - x.choose_multiple(&mut rng, $amount)) { + for (slot, sample) in result.iter_mut().zip(x.choose_multiple(&mut rng, $amount)) { *slot = *sample; } - result[$amount-1] + result[$amount - 1] }) } - } + }; } seq_slice_choose_multiple!(seq_slice_choose_multiple_1_of_1000, 1, 1000); @@ -78,7 +77,7 @@ seq_slice_choose_multiple!(seq_slice_choose_multiple_90_of_100, 90, 100); #[bench] fn seq_iter_choose_from_1000(b: &mut Bencher) { let mut rng = SmallRng::from_rng(thread_rng()).unwrap(); - let x : &mut [usize] = &mut [1; 1000]; + let x: &mut [usize] = &mut [1; 1000]; for i in 0..1000 { x[i] = i; } @@ -98,6 +97,7 @@ struct UnhintedIterator { } impl Iterator for UnhintedIterator { type Item = I::Item; + fn next(&mut self) -> Option { self.iter.next() } @@ -110,9 +110,11 @@ struct WindowHintedIterator { } impl Iterator for WindowHintedIterator { type Item = I::Item; + fn next(&mut self) -> Option { self.iter.next() } + fn size_hint(&self) -> (usize, Option) { (std::cmp::min(self.iter.len(), self.window_size), None) } @@ -121,38 +123,40 @@ impl Iterator for WindowHintedIterator< #[bench] fn seq_iter_unhinted_choose_from_1000(b: &mut Bencher) { let mut rng = SmallRng::from_rng(thread_rng()).unwrap(); - let x : &[usize] = &[1; 1000]; + let x: &[usize] = &[1; 1000]; b.iter(|| { - UnhintedIterator { iter: x.iter() }.choose(&mut rng).unwrap() + UnhintedIterator { iter: x.iter() } + .choose(&mut rng) + .unwrap() }) } #[bench] fn seq_iter_window_hinted_choose_from_1000(b: &mut Bencher) { let mut rng = SmallRng::from_rng(thread_rng()).unwrap(); - let x : &[usize] = &[1; 1000]; + let x: &[usize] = &[1; 1000]; b.iter(|| { - WindowHintedIterator { iter: x.iter(), window_size: 7 }.choose(&mut rng) + WindowHintedIterator { + iter: x.iter(), + window_size: 7, + } + .choose(&mut rng) }) } #[bench] fn seq_iter_choose_multiple_10_of_100(b: &mut Bencher) { let mut rng = SmallRng::from_rng(thread_rng()).unwrap(); - let x : &[usize] = &[1; 100]; - b.iter(|| { - x.iter().cloned().choose_multiple(&mut rng, 10) - }) + let x: &[usize] = &[1; 100]; + b.iter(|| x.iter().cloned().choose_multiple(&mut rng, 10)) } #[bench] fn seq_iter_choose_multiple_fill_10_of_100(b: &mut Bencher) { let mut rng = SmallRng::from_rng(thread_rng()).unwrap(); - let x : &[usize] = &[1; 100]; + let x: &[usize] = &[1; 100]; let mut buf = [0; 10]; - b.iter(|| { - x.iter().cloned().choose_multiple_fill(&mut rng, &mut buf) - }) + b.iter(|| x.iter().cloned().choose_multiple_fill(&mut rng, &mut buf)) } macro_rules! sample_indices { @@ -160,11 +164,9 @@ macro_rules! sample_indices { #[bench] fn $name(b: &mut Bencher) { let mut rng = SmallRng::from_rng(thread_rng()).unwrap(); - b.iter(|| { - index::$fn(&mut rng, $length, $amount) - }) + b.iter(|| index::$fn(&mut rng, $length, $amount)) } - } + }; } sample_indices!(misc_sample_indices_1_of_1k, sample, 1, 1000); diff --git a/benches/weighted.rs b/benches/weighted.rs index 5ddca3f2284..68722908a9e 100644 --- a/benches/weighted.rs +++ b/benches/weighted.rs @@ -10,9 +10,9 @@ extern crate test; -use test::Bencher; -use rand::Rng; use rand::distributions::WeightedIndex; +use rand::Rng; +use test::Bencher; #[bench] fn weighted_index_creation(b: &mut Bencher) { diff --git a/examples/monte-carlo.rs b/examples/monte-carlo.rs index 39c779f40cd..70560d0fab9 100644 --- a/examples/monte-carlo.rs +++ b/examples/monte-carlo.rs @@ -38,11 +38,14 @@ fn main() { for _ in 0..total { let a = range.sample(&mut rng); let b = range.sample(&mut rng); - if a*a + b*b <= 1.0 { + 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)); + println!( + "π is approximately {}", + 4. * (in_circle as f64) / (total as f64) + ); } diff --git a/examples/monty-hall.rs b/examples/monty-hall.rs index 9fe58394aef..30e2f44d154 100644 --- a/examples/monty-hall.rs +++ b/examples/monty-hall.rs @@ -52,7 +52,10 @@ fn simulate(random_door: &Uniform, rng: &mut R) -> SimulationResult choice = switch_door(choice, open); } - SimulationResult { win: choice == car, switch } + SimulationResult { + win: choice == car, + switch, + } } // Returns the door the game host opens given our choice and knowledge of @@ -97,16 +100,24 @@ fn main() { let total_switches = switch_wins + switch_losses; let total_keeps = keep_wins + keep_losses; - println!("Switched door {} times with {} wins and {} losses", - total_switches, switch_wins, switch_losses); + println!( + "Switched door {} times with {} wins and {} losses", + total_switches, switch_wins, switch_losses + ); - println!("Kept our choice {} times with {} wins and {} losses", - total_keeps, keep_wins, keep_losses); + println!( + "Kept our choice {} times with {} wins and {} losses", + total_keeps, keep_wins, keep_losses + ); // With a large number of simulations, the values should converge to // 0.667 and 0.333 respectively. - println!("Estimated chance to win if we switch: {}", - switch_wins as f32 / total_switches as f32); - println!("Estimated chance to win if we don't: {}", - keep_wins as f32 / total_keeps as f32); + println!( + "Estimated chance to win if we switch: {}", + switch_wins as f32 / total_switches as f32 + ); + println!( + "Estimated chance to win if we don't: {}", + keep_wins as f32 / total_keeps as f32 + ); } diff --git a/rand_chacha/src/chacha.rs b/rand_chacha/src/chacha.rs index b1b89e0ff59..a40a7d38059 100644 --- a/rand_chacha/src/chacha.rs +++ b/rand_chacha/src/chacha.rs @@ -8,13 +8,11 @@ //! The ChaCha random number generator. -#[cfg(feature = "std")] -use std as core; -#[cfg(not(feature = "std"))] -use core; +#[cfg(not(feature = "std"))] use core; +#[cfg(feature = "std")] use std as core; -use c2_chacha::guts::ChaCha; use self::core::fmt; +use c2_chacha::guts::ChaCha; use rand_core::block::{BlockRng, BlockRngCore}; use rand_core::{CryptoRng, Error, RngCore, SeedableRng}; @@ -22,16 +20,21 @@ const STREAM_PARAM_NONCE: u32 = 1; const STREAM_PARAM_BLOCK: u32 = 0; pub struct Array64([T; 64]); -impl Default for Array64 where T: Default { +impl Default for Array64 +where T: Default +{ + #[rustfmt::skip] fn default() -> Self { - Self([T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), - T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), - T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), - T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), - T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), - T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), - T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), - T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default()]) + Self([ + T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), + T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), + T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), + T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), + T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), + T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), + T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), + T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), T::default(), + ]) } } impl AsRef<[T]> for Array64 { @@ -44,7 +47,9 @@ impl AsMut<[T]> for Array64 { &mut self.0 } } -impl Clone for Array64 where T: Copy + Default { +impl Clone for Array64 +where T: Copy + Default +{ fn clone(&self) -> Self { let mut new = Self::default(); new.0.copy_from_slice(&self.0); diff --git a/rand_chacha/src/lib.rs b/rand_chacha/src/lib.rs index e374bddf321..63f7e2484b5 100644 --- a/rand_chacha/src/lib.rs +++ b/rand_chacha/src/lib.rs @@ -8,21 +8,23 @@ //! The ChaCha random number generator. -#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png", - html_favicon_url = "https://www.rust-lang.org/favicon.ico", - html_root_url = "https://rust-random.github.io/rand/")] - +#![doc( + html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png", + html_favicon_url = "https://www.rust-lang.org/favicon.ico", + html_root_url = "https://rust-random.github.io/rand/" +)] #![deny(missing_docs)] #![deny(missing_debug_implementations)] #![doc(test(attr(allow(unused_variables), deny(warnings))))] - #![cfg_attr(not(feature = "std"), no_std)] pub use rand_core; mod chacha; -pub use crate::chacha::{ChaCha12Core, ChaCha12Rng, ChaCha20Core, ChaCha20Rng, ChaCha8Core, ChaCha8Rng}; +pub use crate::chacha::{ + ChaCha12Core, ChaCha12Rng, ChaCha20Core, ChaCha20Rng, ChaCha8Core, ChaCha8Rng, +}; /// ChaCha with 20 rounds pub type ChaChaRng = ChaCha20Rng; diff --git a/rand_core/src/block.rs b/rand_core/src/block.rs index 0ab7458377f..c686b8f5871 100644 --- a/rand_core/src/block.rs +++ b/rand_core/src/block.rs @@ -50,11 +50,11 @@ //! [`BlockRngCore`]: crate::block::BlockRngCore //! [`fill_bytes`]: RngCore::fill_bytes +use crate::impls::{fill_via_u32_chunks, fill_via_u64_chunks}; +use crate::{CryptoRng, Error, RngCore, SeedableRng}; use core::convert::AsRef; use core::{fmt, ptr}; -#[cfg(feature="serde1")] use serde::{Serialize, Deserialize}; -use crate::{RngCore, CryptoRng, SeedableRng, Error}; -use crate::impls::{fill_via_u32_chunks, fill_via_u64_chunks}; +#[cfg(feature = "serde1")] use serde::{Deserialize, Serialize}; /// A trait for RNGs which do not generate random numbers individually, but in /// blocks (typically `[u32; N]`). This technique is commonly used by @@ -110,7 +110,7 @@ pub trait BlockRngCore { /// [`fill_bytes`]: RngCore::fill_bytes /// [`try_fill_bytes`]: RngCore::try_fill_bytes #[derive(Clone)] -#[cfg_attr(feature="serde1", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] pub struct BlockRng { results: R::Results, index: usize, @@ -122,10 +122,10 @@ pub struct BlockRng { impl fmt::Debug for BlockRng { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fmt.debug_struct("BlockRng") - .field("core", &self.core) - .field("result_len", &self.results.as_ref().len()) - .field("index", &self.index) - .finish() + .field("core", &self.core) + .field("result_len", &self.results.as_ref().len()) + .field("index", &self.index) + .finish() } } @@ -133,7 +133,7 @@ impl BlockRng { /// Create a new `BlockRng` from an existing RNG implementing /// `BlockRngCore`. Results will be generated on first use. #[inline] - pub fn new(core: R) -> BlockRng{ + pub fn new(core: R) -> BlockRng { let results_empty = R::Results::default(); BlockRng { core, @@ -169,7 +169,7 @@ impl BlockRng { } } -impl> RngCore for BlockRng +impl> RngCore for BlockRng where ::Results: AsRef<[u32]> + AsMut<[u32]> { #[inline] @@ -188,7 +188,7 @@ where ::Results: AsRef<[u32]> + AsMut<[u32]> let read_u64 = |results: &[u32], index| { if cfg!(any(target_endian = "little")) { // requires little-endian CPU - #[allow(clippy::cast_ptr_alignment)] // false positive + #[allow(clippy::cast_ptr_alignment)] // false positive let ptr: *const u64 = results[index..=index+1].as_ptr() as *const u64; unsafe { ptr::read_unaligned(ptr) } } else { @@ -201,7 +201,7 @@ where ::Results: AsRef<[u32]> + AsMut<[u32]> let len = self.results.as_ref().len(); let index = self.index; - if index < len-1 { + if index < len - 1 { self.index += 2; // Read an u64 from the current index read_u64(self.results.as_ref(), index) @@ -209,7 +209,7 @@ where ::Results: AsRef<[u32]> + AsMut<[u32]> self.generate_and_set(2); read_u64(self.results.as_ref(), 0) } else { - let x = u64::from(self.results.as_ref()[len-1]); + let x = u64::from(self.results.as_ref()[len - 1]); self.generate_and_set(1); let y = u64::from(self.results.as_ref()[0]); (y << 32) | x @@ -224,8 +224,7 @@ where ::Results: AsRef<[u32]> + AsMut<[u32]> self.generate_and_set(0); } let (consumed_u32, filled_u8) = - fill_via_u32_chunks(&self.results.as_ref()[self.index..], - &mut dest[read_len..]); + fill_via_u32_chunks(&self.results.as_ref()[self.index..], &mut dest[read_len..]); self.index += consumed_u32; read_len += filled_u8; @@ -259,7 +258,6 @@ impl SeedableRng for BlockRng { } - /// A wrapper type implementing [`RngCore`] for some type implementing /// [`BlockRngCore`] with `u64` array buffer; i.e. this can be used to implement /// a full RNG from just a `generate` function. @@ -283,7 +281,7 @@ impl SeedableRng for BlockRng { /// [`fill_bytes`]: RngCore::fill_bytes /// [`try_fill_bytes`]: RngCore::try_fill_bytes #[derive(Clone)] -#[cfg_attr(feature="serde1", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] pub struct BlockRng64 { results: R::Results, index: usize, @@ -296,11 +294,11 @@ pub struct BlockRng64 { impl fmt::Debug for BlockRng64 { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fmt.debug_struct("BlockRng64") - .field("core", &self.core) - .field("result_len", &self.results.as_ref().len()) - .field("index", &self.index) - .field("half_used", &self.half_used) - .finish() + .field("core", &self.core) + .field("result_len", &self.results.as_ref().len()) + .field("index", &self.index) + .field("half_used", &self.half_used) + .finish() } } @@ -308,7 +306,7 @@ impl BlockRng64 { /// Create a new `BlockRng` from an existing RNG implementing /// `BlockRngCore`. Results will be generated on first use. #[inline] - pub fn new(core: R) -> BlockRng64{ + pub fn new(core: R) -> BlockRng64 { let results_empty = R::Results::default(); BlockRng64 { core, @@ -347,7 +345,7 @@ impl BlockRng64 { } } -impl> RngCore for BlockRng64 +impl> RngCore for BlockRng64 where ::Results: AsRef<[u64]> + AsMut<[u64]> { #[inline] @@ -366,8 +364,7 @@ where ::Results: AsRef<[u64]> + AsMut<[u64]> // Index as if this is a u32 slice. unsafe { - let results = - &*(self.results.as_ref() as *const [u64] as *const [u32]); + let results = &*(self.results.as_ref() as *const [u64] as *const [u32]); if cfg!(target_endian = "little") { *results.get_unchecked(index) } else { @@ -399,9 +396,10 @@ where ::Results: AsRef<[u64]> + AsMut<[u64]> self.index = 0; } - let (consumed_u64, filled_u8) = - fill_via_u64_chunks(&self.results.as_ref()[self.index as usize..], - &mut dest[read_len..]); + let (consumed_u64, filled_u8) = fill_via_u64_chunks( + &self.results.as_ref()[self.index as usize..], + &mut dest[read_len..], + ); self.index += consumed_u64; read_len += filled_u8; diff --git a/rand_core/src/error.rs b/rand_core/src/error.rs index 30b095c3cff..b48438153ce 100644 --- a/rand_core/src/error.rs +++ b/rand_core/src/error.rs @@ -18,54 +18,52 @@ use core::num::NonZeroU32; /// possible implementations: with `std` a boxed `Error` trait object is stored, /// while with `no_std` we merely store an error code. pub struct Error { - #[cfg(feature="std")] + #[cfg(feature = "std")] inner: Box, - #[cfg(not(feature="std"))] + #[cfg(not(feature = "std"))] code: NonZeroU32, } impl Error { + /// Codes at or above this point can be used by users to define their own + /// custom errors. + pub const CUSTOM_START: u32 = (1 << 31) + (1 << 30); + /// Codes below this point represent OS Errors (i.e. positive i32 values). + /// Codes at or above this point, but below [`Error::CUSTOM_START`] are + /// reserved for use by the `rand` and `getrandom` crates. + pub const INTERNAL_START: u32 = 1 << 31; + /// Construct from any type supporting `std::error::Error` - /// + /// /// Available only when configured with `std`. - /// + /// /// See also `From`, which is available with and without `std`. - #[cfg(feature="std")] + #[cfg(feature = "std")] #[inline] pub fn new(err: E) -> Self - where E: Into> - { + where E: Into> { Error { inner: err.into() } } - + /// Reference the inner error (`std` only) - /// + /// /// When configured with `std`, this is a trivial operation and never /// panics. Without `std`, this method is simply unavailable. - #[cfg(feature="std")] + #[cfg(feature = "std")] #[inline] pub fn inner(&self) -> &(dyn std::error::Error + Send + Sync + 'static) { &*self.inner } - + /// Unwrap the inner error (`std` only) - /// + /// /// When configured with `std`, this is a trivial operation and never /// panics. Without `std`, this method is simply unavailable. - #[cfg(feature="std")] + #[cfg(feature = "std")] #[inline] pub fn take_inner(self) -> Box { self.inner } - - /// Codes below this point represent OS Errors (i.e. positive i32 values). - /// Codes at or above this point, but below [`Error::CUSTOM_START`] are - /// reserved for use by the `rand` and `getrandom` crates. - pub const INTERNAL_START: u32 = 1 << 31; - - /// Codes at or above this point can be used by users to define their own - /// custom errors. - pub const CUSTOM_START: u32 = (1 << 31) + (1 << 30); /// Extract the raw OS error code (if this error came from the OS) /// @@ -74,29 +72,31 @@ impl Error { /// error value can still be formatted via the `Diplay` implementation. #[inline] pub fn raw_os_error(&self) -> Option { - #[cfg(feature="std")] { + #[cfg(feature = "std")] + { if let Some(e) = self.inner.downcast_ref::() { return e.raw_os_error(); } } match self.code() { - Some(code) if u32::from(code) < Self::INTERNAL_START => - Some(u32::from(code) as i32), + Some(code) if u32::from(code) < Self::INTERNAL_START => Some(u32::from(code) as i32), _ => None, } } /// Retrieve the error code, if any. - /// + /// /// If this `Error` was constructed via `From`, then this method /// will return this `NonZeroU32` code (for `no_std` this is always the /// case). Otherwise, this method will return `None`. #[inline] pub fn code(&self) -> Option { - #[cfg(feature="std")] { + #[cfg(feature = "std")] + { self.inner.downcast_ref::().map(|c| c.0) } - #[cfg(not(feature="std"))] { + #[cfg(not(feature = "std"))] + { Some(self.code) } } @@ -104,13 +104,16 @@ impl Error { impl fmt::Debug for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - #[cfg(feature="std")] { + #[cfg(feature = "std")] + { write!(f, "Error {{ inner: {:?} }}", self.inner) } - #[cfg(all(feature="getrandom", not(feature="std")))] { + #[cfg(all(feature = "getrandom", not(feature = "std")))] + { getrandom::Error::from(self.code).fmt(f) } - #[cfg(not(feature="getrandom"))] { + #[cfg(not(feature = "getrandom"))] + { write!(f, "Error {{ code: {} }}", self.code) } } @@ -118,13 +121,16 @@ impl fmt::Debug for Error { impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - #[cfg(feature="std")] { + #[cfg(feature = "std")] + { write!(f, "{}", self.inner) } - #[cfg(all(feature="getrandom", not(feature="std")))] { + #[cfg(all(feature = "getrandom", not(feature = "std")))] + { getrandom::Error::from(self.code).fmt(f) } - #[cfg(not(feature="getrandom"))] { + #[cfg(not(feature = "getrandom"))] + { write!(f, "error code {}", self.code) } } @@ -133,29 +139,37 @@ impl fmt::Display for Error { impl From for Error { #[inline] fn from(code: NonZeroU32) -> Self { - #[cfg(feature="std")] { - Error { inner: Box::new(ErrorCode(code)) } + #[cfg(feature = "std")] + { + Error { + inner: Box::new(ErrorCode(code)), + } } - #[cfg(not(feature="std"))] { + #[cfg(not(feature = "std"))] + { Error { code } } } } -#[cfg(feature="getrandom")] +#[cfg(feature = "getrandom")] impl From for Error { #[inline] fn from(error: getrandom::Error) -> Self { - #[cfg(feature="std")] { - Error { inner: Box::new(error) } + #[cfg(feature = "std")] + { + Error { + inner: Box::new(error), + } } - #[cfg(not(feature="std"))] { + #[cfg(not(feature = "std"))] + { Error { code: error.code() } } } } -#[cfg(feature="std")] +#[cfg(feature = "std")] impl std::error::Error for Error { #[inline] fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { @@ -163,7 +177,7 @@ impl std::error::Error for Error { } } -#[cfg(feature="std")] +#[cfg(feature = "std")] impl From for std::io::Error { #[inline] fn from(error: Error) -> Self { @@ -175,16 +189,16 @@ impl From for std::io::Error { } } -#[cfg(feature="std")] +#[cfg(feature = "std")] #[derive(Debug, Copy, Clone)] struct ErrorCode(NonZeroU32); -#[cfg(feature="std")] +#[cfg(feature = "std")] impl fmt::Display for ErrorCode { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "error code {}", self.0) } } -#[cfg(feature="std")] +#[cfg(feature = "std")] impl std::error::Error for ErrorCode {} diff --git a/rand_core/src/impls.rs b/rand_core/src/impls.rs index dee4ed11e6b..1231eb4410d 100644 --- a/rand_core/src/impls.rs +++ b/rand_core/src/impls.rs @@ -17,11 +17,11 @@ //! to/from byte sequences, and since its purpose is reproducibility, //! non-reproducible sources (e.g. `OsRng`) need not bother with it. -use core::ptr::copy_nonoverlapping; -use core::slice; +use crate::RngCore; use core::cmp::min; use core::mem::size_of; -use crate::RngCore; +use core::ptr::copy_nonoverlapping; +use core::slice; /// Implement `next_u64` via `next_u32`, little-endian order. @@ -41,7 +41,7 @@ pub fn next_u64_via_u32(rng: &mut R) -> u64 { pub fn fill_bytes_via_next(rng: &mut R, dest: &mut [u8]) { let mut left = dest; while left.len() >= 8 { - let (l, r) = {left}.split_at_mut(8); + let (l, r) = { left }.split_at_mut(8); left = r; let chunk: [u8; 8] = rng.next_u64().to_le_bytes(); l.copy_from_slice(&chunk); @@ -57,7 +57,7 @@ pub fn fill_bytes_via_next(rng: &mut R, dest: &mut [u8]) { } macro_rules! impl_uint_from_fill { - ($rng:expr, $ty:ty, $N:expr) => ({ + ($rng:expr, $ty:ty, $N:expr) => {{ debug_assert!($N == size_of::<$ty>()); let mut int: $ty = 0; @@ -67,14 +67,14 @@ macro_rules! impl_uint_from_fill { $rng.fill_bytes(slice); } int - }); + }}; } macro_rules! fill_via_chunks { - ($src:expr, $dst:expr, $ty:ty, $size:expr) => ({ + ($src:expr, $dst:expr, $ty:ty, $size:expr) => {{ let chunk_size_u8 = min($src.len() * $size, $dst.len()); let chunk_size = (chunk_size_u8 + $size - 1) / $size; - if cfg!(target_endian="little") { + if cfg!(target_endian = "little") { unsafe { copy_nonoverlapping( $src.as_ptr() as *const u8, @@ -94,7 +94,7 @@ macro_rules! fill_via_chunks { } (chunk_size, chunk_size_u8) - }); + }}; } /// Implement `fill_bytes` by reading chunks from the output buffer of a block diff --git a/rand_core/src/le.rs b/rand_core/src/le.rs index 266651f10dc..c247ab7b3ff 100644 --- a/rand_core/src/le.rs +++ b/rand_core/src/le.rs @@ -7,7 +7,7 @@ // except according to those terms. //! Little-Endian utilities -//! +//! //! Little-Endian order has been chosen for internal usage; this makes some //! useful functions available. @@ -46,22 +46,22 @@ pub fn read_u64_into(src: &[u8], dst: &mut [u64]) { #[test] fn test_read() { let bytes = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; - + let mut buf = [0u32; 4]; read_u32_into(&bytes, &mut buf); assert_eq!(buf[0], 0x04030201); assert_eq!(buf[3], 0x100F0E0D); - + let mut buf = [0u32; 3]; - read_u32_into(&bytes[1..13], &mut buf); // unaligned + read_u32_into(&bytes[1..13], &mut buf); // unaligned assert_eq!(buf[0], 0x05040302); assert_eq!(buf[2], 0x0D0C0B0A); - + let mut buf = [0u64; 2]; read_u64_into(&bytes, &mut buf); assert_eq!(buf[0], 0x0807060504030201); assert_eq!(buf[1], 0x100F0E0D0C0B0A09); - + let mut buf = [0u64; 1]; read_u64_into(&bytes[7..15], &mut buf); // unaligned assert_eq!(buf[0], 0x0F0E0D0C0B0A0908); diff --git a/rand_core/src/lib.rs b/rand_core/src/lib.rs index f0a9f9431e3..281bedde745 100644 --- a/rand_core/src/lib.rs +++ b/rand_core/src/lib.rs @@ -27,35 +27,34 @@ //! //! [`rand`]: https://docs.rs/rand -#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png", - html_favicon_url = "https://www.rust-lang.org/favicon.ico", - html_root_url = "https://rust-random.github.io/rand/")] - +#![doc( + html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png", + html_favicon_url = "https://www.rust-lang.org/favicon.ico", + html_root_url = "https://rust-random.github.io/rand/" +)] #![deny(missing_docs)] #![deny(missing_debug_implementations)] #![doc(test(attr(allow(unused_variables), deny(warnings))))] - #![allow(clippy::unreadable_literal)] +#![cfg_attr(not(feature = "std"), no_std)] -#![cfg_attr(not(feature="std"), no_std)] - -use core::default::Default; use core::convert::AsMut; +use core::default::Default; use core::ptr::copy_nonoverlapping; -#[cfg(all(feature="alloc", not(feature="std")))] extern crate alloc; -#[cfg(all(feature="alloc", not(feature="std")))] use alloc::boxed::Box; +#[cfg(all(feature = "alloc", not(feature = "std")))] extern crate alloc; +#[cfg(all(feature = "alloc", not(feature = "std")))] use alloc::boxed::Box; pub use error::Error; -#[cfg(feature="getrandom")] pub use os::OsRng; +#[cfg(feature = "getrandom")] pub use os::OsRng; -mod error; pub mod block; +mod error; pub mod impls; pub mod le; -#[cfg(feature="getrandom")] mod os; +#[cfg(feature = "getrandom")] mod os; /// The core of a random number generator. @@ -369,7 +368,7 @@ pub trait SeedableRng: Sized { /// If [`getrandom`] is unable to provide secure entropy this method will panic. /// /// [`getrandom`]: https://docs.rs/getrandom - #[cfg(feature="getrandom")] + #[cfg(feature = "getrandom")] fn from_entropy() -> Self { let mut seed = Self::Seed::default(); if let Err(err) = getrandom::getrandom(seed.as_mut()) { @@ -407,7 +406,7 @@ impl<'a, R: RngCore + ?Sized> RngCore for &'a mut R { // Implement `RngCore` for boxed references to an `RngCore`. // Force inlining all functions, so that it is up to the `RngCore` // implementation and the optimizer to decide on inlining. -#[cfg(feature="alloc")] +#[cfg(feature = "alloc")] impl RngCore for Box { #[inline(always)] fn next_u32(&mut self) -> u32 { @@ -430,7 +429,7 @@ impl RngCore for Box { } } -#[cfg(feature="std")] +#[cfg(feature = "std")] impl std::io::Read for dyn RngCore { fn read(&mut self, buf: &mut [u8]) -> Result { self.try_fill_bytes(buf)?; @@ -442,7 +441,7 @@ impl std::io::Read for dyn RngCore { impl<'a, R: CryptoRng + ?Sized> CryptoRng for &'a mut R {} // Implement `CryptoRng` for boxed references to an `CryptoRng`. -#[cfg(feature="alloc")] +#[cfg(feature = "alloc")] impl CryptoRng for Box {} #[cfg(test)] @@ -454,6 +453,7 @@ mod test { struct SeedableNum(u64); impl SeedableRng for SeedableNum { type Seed = [u8; 8]; + fn from_seed(seed: Self::Seed) -> Self { let mut x = [0u64; 1]; le::read_u64_into(&seed, &mut x); @@ -477,7 +477,9 @@ mod test { assert!(weight >= 20 && weight <= 44); for (i2, r2) in results.iter().enumerate() { - if i1 == i2 { continue; } + if i1 == i2 { + continue; + } let diff_weight = (r1 ^ r2).count_ones(); assert!(diff_weight >= 20); } diff --git a/rand_core/src/os.rs b/rand_core/src/os.rs index d58c892b5b1..e9c2c0fbc50 100644 --- a/rand_core/src/os.rs +++ b/rand_core/src/os.rs @@ -8,8 +8,8 @@ //! Interface to the random number generator of the operating system. +use crate::{impls, CryptoRng, Error, RngCore}; use getrandom::getrandom; -use crate::{CryptoRng, RngCore, Error, impls}; /// A random number generator that retrieves randomness from from the /// operating system. diff --git a/rand_distr/benches/distributions.rs b/rand_distr/benches/distributions.rs index 893ac4706f0..ac5e03c3ab8 100644 --- a/rand_distr/benches/distributions.rs +++ b/rand_distr/benches/distributions.rs @@ -8,17 +8,20 @@ #![feature(test)] +// Rustfmt slits many macro invocations to shorten lines; in this case longer-lines are more readable +#![rustfmt::skip] + extern crate test; const RAND_BENCH_N: u64 = 1000; use std::mem::size_of; -use std::num::{NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128}; -use test::Bencher; +use std::num::{NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8}; use std::time::Duration; +use test::Bencher; use rand::prelude::*; -use rand_distr::{*, weighted::WeightedIndex}; +use rand_distr::{weighted::WeightedIndex, *}; // At this time, distributions are optimised for 64-bit platforms. use rand_pcg::Pcg64Mcg; @@ -40,7 +43,7 @@ macro_rules! distr_int { }); b.bytes = size_of::<$ty>() as u64 * RAND_BENCH_N; } - } + }; } macro_rules! distr_nz_int { @@ -60,7 +63,7 @@ macro_rules! distr_nz_int { }); b.bytes = size_of::<$ty>() as u64 * RAND_BENCH_N; } - } + }; } macro_rules! distr_float { @@ -80,7 +83,7 @@ macro_rules! distr_float { }); b.bytes = size_of::<$ty>() as u64 * RAND_BENCH_N; } - } + }; } macro_rules! distr_duration { @@ -94,13 +97,15 @@ macro_rules! distr_duration { let mut accum = Duration::new(0, 0); for _ in 0..RAND_BENCH_N { let x: Duration = distr.sample(&mut rng); - accum = accum.checked_add(x).unwrap_or(Duration::new(u64::max_value(), 999_999_999)); + accum = accum + .checked_add(x) + .unwrap_or(Duration::new(u64::max_value(), 999_999_999)); } accum }); b.bytes = size_of::() as u64 * RAND_BENCH_N; } - } + }; } macro_rules! distr { @@ -120,7 +125,7 @@ macro_rules! distr { }); b.bytes = size_of::<$ty>() as u64 * RAND_BENCH_N; } - } + }; } macro_rules! distr_arr { @@ -140,7 +145,7 @@ macro_rules! distr_arr { }); b.bytes = size_of::<$ty>() as u64 * RAND_BENCH_N; } - } + }; } // uniform @@ -245,7 +250,7 @@ macro_rules! gen_range_int { }); b.bytes = size_of::<$ty>() as u64 * RAND_BENCH_N; } - } + }; } gen_range_int!(gen_range_i8, i8, -20i8, 100); @@ -275,7 +280,7 @@ macro_rules! gen_range_float { }); b.bytes = size_of::<$ty>() as u64 * RAND_BENCH_N; } - } + }; } gen_range_float!(gen_range_f32, f32, -20000.0f32, 100000.0); @@ -308,7 +313,7 @@ macro_rules! sample_binomial { rng.sample(d) }) } - } + }; } sample_binomial!(misc_binomial_1, 1, 0.9); diff --git a/rand_distr/src/binomial.rs b/rand_distr/src/binomial.rs index 29919c88a06..ea58ddf7ebe 100644 --- a/rand_distr/src/binomial.rs +++ b/rand_distr/src/binomial.rs @@ -9,8 +9,8 @@ //! The binomial distribution. -use rand::Rng; use crate::{Distribution, Uniform}; +use rand::Rng; use std::{error, fmt}; /// The binomial distribution `Binomial(n, p)`. @@ -77,7 +77,7 @@ fn f64_to_i64(x: f64) -> i64 { } impl Distribution for Binomial { - #[allow(clippy::many_single_char_names)] // Same names as in the reference. + #[allow(clippy::many_single_char_names)] // Same names as in the reference. fn sample(&self, rng: &mut R) -> u64 { // Handle these values directly. if self.p == 0.0 { @@ -89,11 +89,7 @@ impl Distribution for Binomial { // The binomial distribution is symmetrical with respect to p -> 1-p, // k -> n-k switch p so that it is less than 0.5 - this allows for lower // expected values we will just invert the result at the end - let p = if self.p <= 0.5 { - self.p - } else { - 1.0 - self.p - }; + let p = if self.p <= 0.5 { self.p } else { 1.0 - self.p }; let result; let q = 1. - p; @@ -110,8 +106,7 @@ impl Distribution for Binomial { // Ranlib uses 30, and GSL uses 14. const BINV_THRESHOLD: f64 = 10.; - if (self.n as f64) * p < BINV_THRESHOLD && - self.n <= (::std::i32::MAX as u64) { + if (self.n as f64) * p < BINV_THRESHOLD && self.n <= (::std::i32::MAX as u64) { // Use the BINV algorithm. let s = p / q; let a = ((self.n + 1) as f64) * s; @@ -243,8 +238,8 @@ impl Distribution for Binomial { // Step 5.2: Squeezing. Check the value of ln(v) againts upper and // lower bound of ln(f(y)). let k = k as f64; - let rho = (k / npq) * ((k * (k / 3. + 0.625) + 1./6.) / npq + 0.5); - let t = -0.5 * k*k / npq; + let rho = (k / npq) * ((k * (k / 3. + 0.625) + 1. / 6.) / npq + 0.5); + let t = -0.5 * k * k / npq; let alpha = v.ln(); if alpha < t - rho { break; @@ -264,15 +259,19 @@ impl Distribution for Binomial { (13860. - (462. - (132. - (99. - 140. / a2) / a2) / a2) / a2) / a / 166320. } - if alpha > x_m * (f1 / x1).ln() - + (n - (m as f64) + 0.5) * (z / w).ln() - + ((y - m) as f64) * (w * p / (x1 * q)).ln() - // We use the signs from the GSL implementation, which are - // different than the ones in the reference. According to - // the GSL authors, the new signs were verified to be - // correct by one of the original designers of the - // algorithm. - + stirling(f1) + stirling(z) - stirling(x1) - stirling(w) + if alpha + > x_m * (f1 / x1).ln() + + (n - (m as f64) + 0.5) * (z / w).ln() + + ((y - m) as f64) * (w * p / (x1 * q)).ln() + // We use the signs from the GSL implementation, which are + // different than the ones in the reference. According to + // the GSL authors, the new signs were verified to be + // correct by one of the original designers of the + // algorithm. + + stirling(f1) + + stirling(z) + - stirling(x1) + - stirling(w) { continue; } @@ -294,9 +293,9 @@ impl Distribution for Binomial { #[cfg(test)] mod test { - use rand::Rng; - use crate::Distribution; use super::Binomial; + use crate::Distribution; + use rand::Rng; fn test_binomial_mean_and_variance(n: u64, p: f64, rng: &mut R) { let binomial = Binomial::new(n, p).unwrap(); @@ -305,14 +304,15 @@ mod test { let expected_variance = n as f64 * p * (1.0 - p); let mut results = [0.0; 1000]; - for i in results.iter_mut() { *i = binomial.sample(rng) as f64; } + for i in results.iter_mut() { + *i = binomial.sample(rng) as f64; + } let mean = results.iter().sum::() / results.len() as f64; assert!((mean as f64 - expected_mean).abs() < expected_mean / 50.0); let variance = - results.iter().map(|x| (x - mean) * (x - mean)).sum::() - / results.len() as f64; + results.iter().map(|x| (x - mean) * (x - mean)).sum::() / results.len() as f64; assert!((variance - expected_variance).abs() < expected_variance / 10.0); } @@ -338,7 +338,7 @@ mod test { fn test_binomial_invalid_lambda_neg() { Binomial::new(20, -10.0).unwrap(); } - + #[test] fn value_stability() { fn test_samples(n: u64, p: f64, expected: &[u64]) { @@ -350,7 +350,7 @@ mod test { } assert_eq!(buf, expected); } - + // We have multiple code paths: np < 10, p > 0.5 test_samples(2, 0.7, &[1, 1, 2, 1]); test_samples(20, 0.3, &[7, 7, 5, 7]); diff --git a/rand_distr/src/cauchy.rs b/rand_distr/src/cauchy.rs index 297c19e6d9c..3e1b1b5ec72 100644 --- a/rand_distr/src/cauchy.rs +++ b/rand_distr/src/cauchy.rs @@ -9,9 +9,9 @@ //! The Cauchy distribution. -use rand::Rng; -use crate::{Distribution, Standard}; use crate::utils::Float; +use crate::{Distribution, Standard}; +use rand::Rng; use std::{error, fmt}; /// The Cauchy distribution `Cauchy(median, scale)`. @@ -63,10 +63,7 @@ where Standard: Distribution if !(scale > N::from(0.0)) { return Err(Error::ScaleTooSmall); } - Ok(Cauchy { - median, - scale - }) + Ok(Cauchy { median, scale }) } } @@ -130,7 +127,7 @@ mod test { fn test_cauchy_invalid_scale_neg() { Cauchy::new(0.0, -10.0).unwrap(); } - + #[test] fn value_stability() { fn gen_samples(m: N, s: N, buf: &mut [N]) @@ -141,19 +138,23 @@ mod test { *x = rng.sample(&distr); } } - + let mut buf = [0.0; 4]; gen_samples(100f64, 10.0, &mut buf); - assert_eq!(&buf, &[77.93369152808678, 90.1606912098641, - 125.31516221323625, 86.10217834773925]); - + assert_eq!(&buf, &[ + 77.93369152808678, + 90.1606912098641, + 125.31516221323625, + 86.10217834773925 + ]); + // Unfortunately this test is not fully portable due to reliance on the // system's implementation of tanf (see doc on Cauchy struct). let mut buf = [0.0; 4]; gen_samples(10f32, 7.0, &mut buf); let expected = [15.023088, -5.446413, 3.7092876, 3.112482]; - for (a,b) in buf.iter().zip(expected.iter()) { - let (a,b) = (*a, *b); + for (a, b) in buf.iter().zip(expected.iter()) { + let (a, b) = (*a, *b); assert!((a - b).abs() < 1e-6, "expected: {} = {}", a, b); } } diff --git a/rand_distr/src/dirichlet.rs b/rand_distr/src/dirichlet.rs index 7edfad312fd..84c7c933915 100644 --- a/rand_distr/src/dirichlet.rs +++ b/rand_distr/src/dirichlet.rs @@ -9,9 +9,9 @@ //! The dirichlet distribution. -use rand::Rng; -use crate::{Distribution, Gamma, StandardNormal, Exp1, Open01}; use crate::utils::Float; +use crate::{Distribution, Exp1, Gamma, Open01, StandardNormal}; +use rand::Rng; use std::{error, fmt}; /// The Dirichlet distribution `Dirichlet(alpha)`. @@ -61,7 +61,10 @@ impl fmt::Display for Error { impl error::Error for Error {} impl Dirichlet -where StandardNormal: Distribution, Exp1: Distribution, Open01: Distribution +where + StandardNormal: Distribution, + Exp1: Distribution, + Open01: Distribution, { /// Construct a new `Dirichlet` with the given alpha parameter `alpha`. /// @@ -99,7 +102,10 @@ where StandardNormal: Distribution, Exp1: Distribution, Open01: Distributi } impl Distribution> for Dirichlet -where StandardNormal: Distribution, Exp1: Distribution, Open01: Distribution +where + StandardNormal: Distribution, + Exp1: Distribution, + Open01: Distribution, { fn sample(&self, rng: &mut R) -> Vec { let n = self.alpha.len(); @@ -164,14 +170,20 @@ mod test { fn test_dirichlet_invalid_alpha() { Dirichlet::new_with_size(0.0f64, 2).unwrap(); } - + #[test] fn value_stability() { let mut rng = crate::test::rng(223); - assert_eq!(rng.sample(Dirichlet::new(vec![1.0, 2.0, 3.0]).unwrap()), - vec![0.12941567177708177, 0.4702121891675036, 0.4003721390554146]); - assert_eq!(rng.sample(Dirichlet::new_with_size(8.0, 5).unwrap()), - vec![0.17684200044809556, 0.29915953935953055, - 0.1832858056608014, 0.1425623503573967, 0.19815030417417595]); + assert_eq!( + rng.sample(Dirichlet::new(vec![1.0, 2.0, 3.0]).unwrap()), + vec![0.12941567177708177, 0.4702121891675036, 0.4003721390554146] + ); + assert_eq!(rng.sample(Dirichlet::new_with_size(8.0, 5).unwrap()), vec![ + 0.17684200044809556, + 0.29915953935953055, + 0.1832858056608014, + 0.1425623503573967, + 0.19815030417417595 + ]); } } diff --git a/rand_distr/src/exponential.rs b/rand_distr/src/exponential.rs index ecd39beedb0..87fb29f5a8e 100644 --- a/rand_distr/src/exponential.rs +++ b/rand_distr/src/exponential.rs @@ -9,9 +9,9 @@ //! The exponential distribution. -use rand::Rng; -use crate::{ziggurat_tables, Distribution}; use crate::utils::{ziggurat, Float}; +use crate::{ziggurat_tables, Distribution}; +use rand::Rng; use std::{error, fmt}; /// Samples floating-point numbers according to the exponential distribution, @@ -62,10 +62,14 @@ impl Distribution for Exp1 { ziggurat_tables::ZIG_EXP_R - rng.gen::().ln() } - ziggurat(rng, false, - &ziggurat_tables::ZIG_EXP_X, - &ziggurat_tables::ZIG_EXP_F, - pdf, zero_case) + ziggurat( + rng, + false, + &ziggurat_tables::ZIG_EXP_X, + &ziggurat_tables::ZIG_EXP_F, + pdf, + zero_case, + ) } } @@ -73,7 +77,7 @@ impl Distribution for Exp1 { /// /// This distribution has density function: `f(x) = lambda * exp(-lambda * x)` /// for `x > 0`. -/// +/// /// Note that [`Exp1`](crate::Exp1) is an optimised implementation for `lambda = 1`. /// /// # Example @@ -88,7 +92,7 @@ impl Distribution for Exp1 { #[derive(Clone, Copy, Debug)] pub struct Exp { /// `lambda` stored as `1/lambda`, since this is what we scale by. - lambda_inverse: N + lambda_inverse: N, } /// Error type returned from `Exp::new`. @@ -118,7 +122,9 @@ where Exp1: Distribution if !(lambda > N::from(0.0)) { return Err(Error::LambdaTooSmall); } - Ok(Exp { lambda_inverse: N::from(1.0) / lambda }) + Ok(Exp { + lambda_inverse: N::from(1.0) / lambda, + }) } } @@ -152,12 +158,12 @@ mod test { fn test_exp_invalid_lambda_neg() { Exp::new(-10.0).unwrap(); } - + #[test] fn value_stability() { - fn test_samples> - (distr: D, zero: N, expected: &[N]) - { + fn test_samples>( + distr: D, zero: N, expected: &[N], + ) { let mut rng = crate::test::rng(223); let mut buf = [zero; 4]; for x in &mut buf { @@ -165,15 +171,23 @@ mod test { } assert_eq!(buf, expected); } - + test_samples(Exp1, 0f32, &[1.079617, 1.8325565, 0.04601166, 0.34471703]); - test_samples(Exp1, 0f64, &[1.0796170642388276, 1.8325565304274, - 0.04601166186842716, 0.3447170217100157]); - - test_samples(Exp::new(2.0).unwrap(), 0f32, - &[0.5398085, 0.91627824, 0.02300583, 0.17235851]); + test_samples(Exp1, 0f64, &[ + 1.0796170642388276, + 1.8325565304274, + 0.04601166186842716, + 0.3447170217100157, + ]); + + test_samples(Exp::new(2.0).unwrap(), 0f32, &[ + 0.5398085, 0.91627824, 0.02300583, 0.17235851, + ]); test_samples(Exp::new(1.0).unwrap(), 0f64, &[ - 1.0796170642388276, 1.8325565304274, - 0.04601166186842716, 0.3447170217100157]); + 1.0796170642388276, + 1.8325565304274, + 0.04601166186842716, + 0.3447170217100157, + ]); } } diff --git a/rand_distr/src/gamma.rs b/rand_distr/src/gamma.rs index 555a1a0c48c..ba8e4e0eb31 100644 --- a/rand_distr/src/gamma.rs +++ b/rand_distr/src/gamma.rs @@ -9,13 +9,13 @@ //! The Gamma and derived distributions. -use self::GammaRepr::*; use self::ChiSquaredRepr::*; +use self::GammaRepr::*; -use rand::Rng; use crate::normal::StandardNormal; -use crate::{Distribution, Exp1, Exp, Open01}; use crate::utils::Float; +use crate::{Distribution, Exp, Exp1, Open01}; +use rand::Rng; use std::{error, fmt}; /// The Gamma distribution `Gamma(shape, scale)` distribution. @@ -80,7 +80,7 @@ impl error::Error for Error {} enum GammaRepr { Large(GammaLargeShape), One(Exp), - Small(GammaSmallShape) + Small(GammaSmallShape), } // These two helpers could be made public, but saving the @@ -100,7 +100,7 @@ enum GammaRepr { #[derive(Clone, Copy, Debug)] struct GammaSmallShape { inv_shape: N, - large_shape: GammaLargeShape + large_shape: GammaLargeShape, } /// Gamma distribution where the shape parameter is larger than 1. @@ -111,11 +111,14 @@ struct GammaSmallShape { struct GammaLargeShape { scale: N, c: N, - d: N + d: N, } impl Gamma -where StandardNormal: Distribution, Exp1: Distribution, Open01: Distribution +where + StandardNormal: Distribution, + Exp1: Distribution, + Open01: Distribution, { /// Construct an object representing the `Gamma(shape, scale)` /// distribution. @@ -140,31 +143,38 @@ where StandardNormal: Distribution, Exp1: Distribution, Open01: Distributi } impl GammaSmallShape -where StandardNormal: Distribution, Open01: Distribution +where + StandardNormal: Distribution, + Open01: Distribution, { fn new_raw(shape: N, scale: N) -> GammaSmallShape { GammaSmallShape { inv_shape: N::from(1.0) / shape, - large_shape: GammaLargeShape::new_raw(shape + N::from(1.0), scale) + large_shape: GammaLargeShape::new_raw(shape + N::from(1.0), scale), } } } impl GammaLargeShape -where StandardNormal: Distribution, Open01: Distribution +where + StandardNormal: Distribution, + Open01: Distribution, { fn new_raw(shape: N, scale: N) -> GammaLargeShape { let d = shape - N::from(1. / 3.); GammaLargeShape { scale, c: N::from(1.0) / (N::from(9.) * d).sqrt(), - d + d, } } } impl Distribution for Gamma -where StandardNormal: Distribution, Exp1: Distribution, Open01: Distribution +where + StandardNormal: Distribution, + Exp1: Distribution, + Open01: Distribution, { fn sample(&self, rng: &mut R) -> N { match self.repr { @@ -175,7 +185,9 @@ where StandardNormal: Distribution, Exp1: Distribution, Open01: Distributi } } impl Distribution for GammaSmallShape -where StandardNormal: Distribution, Open01: Distribution +where + StandardNormal: Distribution, + Open01: Distribution, { fn sample(&self, rng: &mut R) -> N { let u: N = rng.sample(Open01); @@ -184,25 +196,28 @@ where StandardNormal: Distribution, Open01: Distribution } } impl Distribution for GammaLargeShape -where StandardNormal: Distribution, Open01: Distribution +where + StandardNormal: Distribution, + Open01: Distribution, { fn sample(&self, rng: &mut R) -> N { // Marsaglia & Tsang method, 2000 loop { let x: N = rng.sample(StandardNormal); let v_cbrt = N::from(1.0) + self.c * x; - if v_cbrt <= N::from(0.0) { // a^3 <= 0 iff a <= 0 - continue + if v_cbrt <= N::from(0.0) { + // a^3 <= 0 iff a <= 0 + continue; } let v = v_cbrt * v_cbrt * v_cbrt; let u: N = rng.sample(Open01); let x_sqr = x * x; - if u < N::from(1.0) - N::from(0.0331) * x_sqr * x_sqr || - u.ln() < N::from(0.5) * x_sqr + self.d * (N::from(1.0) - v + v.ln()) + if u < N::from(1.0) - N::from(0.0331) * x_sqr * x_sqr + || u.ln() < N::from(0.5) * x_sqr + self.d * (N::from(1.0) - v + v.ln()) { - return self.d * v * self.scale + return self.d * v * self.scale; } } } @@ -259,7 +274,10 @@ enum ChiSquaredRepr { } impl ChiSquared -where StandardNormal: Distribution, Exp1: Distribution, Open01: Distribution +where + StandardNormal: Distribution, + Exp1: Distribution, + Open01: Distribution, { /// Create a new chi-squared distribution with degrees-of-freedom /// `k`. @@ -276,7 +294,10 @@ where StandardNormal: Distribution, Exp1: Distribution, Open01: Distributi } } impl Distribution for ChiSquared -where StandardNormal: Distribution, Exp1: Distribution, Open01: Distribution +where + StandardNormal: Distribution, + Exp1: Distribution, + Open01: Distribution, { fn sample(&self, rng: &mut R) -> N { match self.repr { @@ -285,7 +306,7 @@ where StandardNormal: Distribution, Exp1: Distribution, Open01: Distributi let norm: N = rng.sample(StandardNormal); norm * norm } - DoFAnythingElse(ref g) => g.sample(rng) + DoFAnythingElse(ref g) => g.sample(rng), } } } @@ -335,7 +356,10 @@ impl fmt::Display for FisherFError { impl error::Error for FisherFError {} impl FisherF -where StandardNormal: Distribution, Exp1: Distribution, Open01: Distribution +where + StandardNormal: Distribution, + Exp1: Distribution, + Open01: Distribution, { /// Create a new `FisherF` distribution, with the given parameter. pub fn new(m: N, n: N) -> Result, FisherFError> { @@ -349,12 +373,15 @@ where StandardNormal: Distribution, Exp1: Distribution, Open01: Distributi Ok(FisherF { numer: ChiSquared::new(m).unwrap(), denom: ChiSquared::new(n).unwrap(), - dof_ratio: n / m + dof_ratio: n / m, }) } } impl Distribution for FisherF -where StandardNormal: Distribution, Exp1: Distribution, Open01: Distribution +where + StandardNormal: Distribution, + Exp1: Distribution, + Open01: Distribution, { fn sample(&self, rng: &mut R) -> N { self.numer.sample(rng) / self.denom.sample(rng) * self.dof_ratio @@ -376,23 +403,29 @@ where StandardNormal: Distribution, Exp1: Distribution, Open01: Distributi #[derive(Clone, Copy, Debug)] pub struct StudentT { chi: ChiSquared, - dof: N + dof: N, } impl StudentT -where StandardNormal: Distribution, Exp1: Distribution, Open01: Distribution +where + StandardNormal: Distribution, + Exp1: Distribution, + Open01: Distribution, { /// Create a new Student t distribution with `n` degrees of /// freedom. pub fn new(n: N) -> Result, ChiSquaredError> { Ok(StudentT { chi: ChiSquared::new(n)?, - dof: n + dof: n, }) } } impl Distribution for StudentT -where StandardNormal: Distribution, Exp1: Distribution, Open01: Distribution +where + StandardNormal: Distribution, + Exp1: Distribution, + Open01: Distribution, { fn sample(&self, rng: &mut R) -> N { let norm: N = rng.sample(StandardNormal); @@ -438,22 +471,26 @@ impl fmt::Display for BetaError { impl error::Error for BetaError {} impl Beta -where StandardNormal: Distribution, Exp1: Distribution, Open01: Distribution +where + StandardNormal: Distribution, + Exp1: Distribution, + Open01: Distribution, { /// Construct an object representing the `Beta(alpha, beta)` /// distribution. pub fn new(alpha: N, beta: N) -> Result, BetaError> { Ok(Beta { - gamma_a: Gamma::new(alpha, N::from(1.)) - .map_err(|_| BetaError::AlphaTooSmall)?, - gamma_b: Gamma::new(beta, N::from(1.)) - .map_err(|_| BetaError::BetaTooSmall)?, + gamma_a: Gamma::new(alpha, N::from(1.)).map_err(|_| BetaError::AlphaTooSmall)?, + gamma_b: Gamma::new(beta, N::from(1.)).map_err(|_| BetaError::BetaTooSmall)?, }) } } impl Distribution for Beta -where StandardNormal: Distribution, Exp1: Distribution, Open01: Distribution +where + StandardNormal: Distribution, + Exp1: Distribution, + Open01: Distribution, { fn sample(&self, rng: &mut R) -> N { let x = self.gamma_a.sample(rng); @@ -528,12 +565,12 @@ mod test { fn test_beta_invalid_dof() { Beta::new(0., 0.).unwrap(); } - + #[test] fn value_stability() { - fn test_samples> - (distr: D, zero: N, expected: &[N]) - { + fn test_samples>( + distr: D, zero: N, expected: &[N], + ) { let mut rng = crate::test::rng(223); let mut buf = [zero; 4]; for x in &mut buf { @@ -541,47 +578,78 @@ mod test { } assert_eq!(buf, expected); } - + // Gamma has 3 cases: shape == 1, shape < 1, shape > 1 - test_samples(Gamma::new(1.0, 5.0).unwrap(), 0f32, - &[5.398085, 9.162783, 0.2300583, 1.7235851]); - test_samples(Gamma::new(0.8, 5.0).unwrap(), 0f32, - &[0.5051203, 0.9048302, 3.095812, 1.8566116]); + test_samples(Gamma::new(1.0, 5.0).unwrap(), 0f32, &[ + 5.398085, 9.162783, 0.2300583, 1.7235851, + ]); + test_samples(Gamma::new(0.8, 5.0).unwrap(), 0f32, &[ + 0.5051203, 0.9048302, 3.095812, 1.8566116, + ]); test_samples(Gamma::new(1.1, 5.0).unwrap(), 0f64, &[ - 7.783878094584059, 1.4939528171618057, - 8.638017638857592, 3.0949337228829004]); - + 7.783878094584059, + 1.4939528171618057, + 8.638017638857592, + 3.0949337228829004, + ]); + // ChiSquared has 2 cases: k == 1, k != 1 test_samples(ChiSquared::new(1.0).unwrap(), 0f64, &[ - 0.4893526200348249, 1.635249736808788, - 0.5013580219361969, 0.1457735613733489]); + 0.4893526200348249, + 1.635249736808788, + 0.5013580219361969, + 0.1457735613733489, + ]); test_samples(ChiSquared::new(0.1).unwrap(), 0f64, &[ - 0.014824404726978617, 0.021602123937134326, - 0.0000003431429746851693, 0.00000002291755769542258]); - test_samples(ChiSquared::new(10.0).unwrap(), 0f32, - &[12.693656, 6.812016, 11.082001, 12.436167]); - + 0.014824404726978617, + 0.021602123937134326, + 0.0000003431429746851693, + 0.00000002291755769542258, + ]); + test_samples(ChiSquared::new(10.0).unwrap(), 0f32, &[ + 12.693656, 6.812016, 11.082001, 12.436167, + ]); + // FisherF has same special cases as ChiSquared on each param - test_samples(FisherF::new(1.0, 13.5).unwrap(), 0f32, - &[0.32283646, 0.048049655, 0.0788893, 1.817178]); - test_samples(FisherF::new(1.0, 1.0).unwrap(), 0f32, - &[0.29925257, 3.4392934, 9.567652, 0.020074]); + test_samples(FisherF::new(1.0, 13.5).unwrap(), 0f32, &[ + 0.32283646, + 0.048049655, + 0.0788893, + 1.817178, + ]); + test_samples(FisherF::new(1.0, 1.0).unwrap(), 0f32, &[ + 0.29925257, 3.4392934, 9.567652, 0.020074, + ]); test_samples(FisherF::new(0.7, 13.5).unwrap(), 0f64, &[ - 3.3196593155045124, 0.3409169916262829, - 0.03377989856426519, 0.00004041672861036937]); - + 3.3196593155045124, + 0.3409169916262829, + 0.03377989856426519, + 0.00004041672861036937, + ]); + // StudentT has same special cases as ChiSquared - test_samples(StudentT::new(1.0).unwrap(), 0f32, - &[0.54703987, -1.8545331, 3.093162, -0.14168274]); + test_samples(StudentT::new(1.0).unwrap(), 0f32, &[ + 0.54703987, + -1.8545331, + 3.093162, + -0.14168274, + ]); test_samples(StudentT::new(1.1).unwrap(), 0f64, &[ - 0.7729195887949754, 1.2606210611616204, - -1.7553606501113175, -2.377641221169782]); - + 0.7729195887949754, + 1.2606210611616204, + -1.7553606501113175, + -2.377641221169782, + ]); + // Beta has same special cases as Gamma on each param - test_samples(Beta::new(1.0, 0.8).unwrap(), 0f32, - &[0.6444564, 0.357635, 0.4110078, 0.7347192]); + test_samples(Beta::new(1.0, 0.8).unwrap(), 0f32, &[ + 0.6444564, 0.357635, 0.4110078, 0.7347192, + ]); test_samples(Beta::new(0.7, 1.2).unwrap(), 0f64, &[ - 0.6433129944095513, 0.5373371199711573, - 0.10313293199269491, 0.002472280249144378]); + 0.6433129944095513, + 0.5373371199711573, + 0.10313293199269491, + 0.002472280249144378, + ]); } } diff --git a/rand_distr/src/lib.rs b/rand_distr/src/lib.rs index 454e93ede90..0e7beb91b5d 100644 --- a/rand_distr/src/lib.rs +++ b/rand_distr/src/lib.rs @@ -6,15 +6,19 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png", - html_favicon_url = "https://www.rust-lang.org/favicon.ico", - html_root_url = "https://rust-random.github.io/rand/")] - +#![doc( + html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png", + html_favicon_url = "https://www.rust-lang.org/favicon.ico", + html_root_url = "https://rust-random.github.io/rand/" +)] #![deny(missing_docs)] #![deny(missing_debug_implementations)] - -#![allow(clippy::excessive_precision, clippy::float_cmp, clippy::unreadable_literal)] -#![allow(clippy::neg_cmp_op_on_partial_ord)] // suggested fix too verbose +#![allow( + clippy::excessive_precision, + clippy::float_cmp, + clippy::unreadable_literal +)] +#![allow(clippy::neg_cmp_op_on_partial_ord)] // suggested fix too verbose //! Generating random samples from probability distributions. //! @@ -25,7 +29,7 @@ //! [`Distribution`] trait and implementations. //! //! The following are re-exported: -//! +//! //! - The [`Distribution`] trait and [`DistIter`] helper type //! - The [`Standard`], [`Alphanumeric`], [`Uniform`], [`OpenClosed01`], [`Open01`] and [`Bernoulli`] distributions //! - The [`weighted`] sub-module @@ -63,53 +67,56 @@ //! - [`UnitCircle`] distribution //! - [`UnitDisc`] distribution -pub use rand::distributions::{Distribution, DistIter, Standard, - Alphanumeric, Uniform, OpenClosed01, Open01, Bernoulli, BernoulliError, - uniform, weighted}; +pub use rand::distributions::{ + uniform, weighted, Alphanumeric, Bernoulli, BernoulliError, DistIter, Distribution, Open01, + OpenClosed01, Standard, Uniform, +}; -pub use self::unit_sphere::UnitSphere; -pub use self::unit_ball::UnitBall; -pub use self::unit_circle::UnitCircle; -pub use self::unit_disc::UnitDisc; -pub use self::gamma::{Gamma, Error as GammaError, ChiSquared, ChiSquaredError, - FisherF, FisherFError, StudentT, Beta, BetaError}; -pub use self::normal::{Normal, Error as NormalError, LogNormal, StandardNormal}; -pub use self::exponential::{Exp, Error as ExpError, Exp1}; -pub use self::pareto::{Pareto, Error as ParetoError}; -pub use self::pert::{Pert, PertError}; -pub use self::poisson::{Poisson, Error as PoissonError}; pub use self::binomial::{Binomial, Error as BinomialError}; pub use self::cauchy::{Cauchy, Error as CauchyError}; pub use self::dirichlet::{Dirichlet, Error as DirichletError}; +pub use self::exponential::{Error as ExpError, Exp, Exp1}; +pub use self::gamma::{ + Beta, BetaError, ChiSquared, ChiSquaredError, Error as GammaError, FisherF, FisherFError, + Gamma, StudentT, +}; +pub use self::normal::{Error as NormalError, LogNormal, Normal, StandardNormal}; +pub use self::pareto::{Error as ParetoError, Pareto}; +pub use self::pert::{Pert, PertError}; +pub use self::poisson::{Error as PoissonError, Poisson}; pub use self::triangular::{Triangular, TriangularError}; -pub use self::weibull::{Weibull, Error as WeibullError}; +pub use self::unit_ball::UnitBall; +pub use self::unit_circle::UnitCircle; +pub use self::unit_disc::UnitDisc; +pub use self::unit_sphere::UnitSphere; pub use self::utils::Float; +pub use self::weibull::{Error as WeibullError, Weibull}; -mod unit_sphere; -mod unit_ball; -mod unit_circle; -mod unit_disc; +mod binomial; +mod cauchy; +mod dirichlet; +mod exponential; mod gamma; mod normal; -mod exponential; mod pareto; mod pert; mod poisson; -mod binomial; -mod cauchy; -mod dirichlet; mod triangular; -mod weibull; +mod unit_ball; +mod unit_circle; +mod unit_disc; +mod unit_sphere; mod utils; +mod weibull; mod ziggurat_tables; #[cfg(test)] mod test { // Notes on testing - // + // // Testing random number distributions correctly is hard. The following // testing is desired: - // + // // - Construction: test initialisation with a few valid parameter sets. // - Erroneous usage: test that incorrect usage generates an error. // - Vector: test that usage with fixed inputs (including RNG) generates a diff --git a/rand_distr/src/normal.rs b/rand_distr/src/normal.rs index e2148d8302d..39f9402ec04 100644 --- a/rand_distr/src/normal.rs +++ b/rand_distr/src/normal.rs @@ -9,9 +9,9 @@ //! The normal and derived distributions. -use rand::Rng; -use crate::{ziggurat_tables, Distribution, Open01}; use crate::utils::{ziggurat, Float}; +use crate::{ziggurat_tables, Distribution, Open01}; +use rand::Rng; use std::{error, fmt}; /// Samples floating-point numbers according to the normal distribution @@ -51,7 +51,7 @@ impl Distribution for StandardNormal { fn sample(&self, rng: &mut R) -> f64 { #[inline] fn pdf(x: f64) -> f64 { - (-x*x/2.0).exp() + (-x * x / 2.0).exp() } #[inline] fn zero_case(rng: &mut R, u: f64) -> f64 { @@ -72,13 +72,21 @@ impl Distribution for StandardNormal { y = y_.ln(); } - if u < 0.0 { x - ziggurat_tables::ZIG_NORM_R } else { ziggurat_tables::ZIG_NORM_R - x } + if u < 0.0 { + x - ziggurat_tables::ZIG_NORM_R + } else { + ziggurat_tables::ZIG_NORM_R - x + } } - ziggurat(rng, true, // this is symmetric - &ziggurat_tables::ZIG_NORM_X, - &ziggurat_tables::ZIG_NORM_F, - pdf, zero_case) + ziggurat( + rng, + true, // this is symmetric + &ziggurat_tables::ZIG_NORM_X, + &ziggurat_tables::ZIG_NORM_F, + pdf, + zero_case, + ) } } @@ -86,7 +94,7 @@ impl Distribution for StandardNormal { /// /// This uses the ZIGNOR variant of the Ziggurat method, see [`StandardNormal`] /// for more details. -/// +/// /// Note that [`StandardNormal`] is an optimised implementation for mean 0, and /// standard deviation 1. /// @@ -135,10 +143,7 @@ where StandardNormal: Distribution if !(std_dev >= N::from(0.0)) { return Err(Error::StdDevTooSmall); } - Ok(Normal { - mean, - std_dev - }) + Ok(Normal { mean, std_dev }) } } @@ -169,7 +174,7 @@ where StandardNormal: Distribution /// ``` #[derive(Clone, Copy, Debug)] pub struct LogNormal { - norm: Normal + norm: Normal, } impl LogNormal @@ -182,7 +187,9 @@ where StandardNormal: Distribution if !(std_dev >= N::from(0.0)) { return Err(Error::StdDevTooSmall); } - Ok(LogNormal { norm: Normal::new(mean, std_dev).unwrap() }) + Ok(LogNormal { + norm: Normal::new(mean, std_dev).unwrap(), + }) } } @@ -226,12 +233,12 @@ mod tests { fn test_log_normal_invalid_sd() { LogNormal::new(10.0, -1.0).unwrap(); } - + #[test] fn value_stability() { - fn test_samples> - (distr: D, zero: N, expected: &[N]) - { + fn test_samples>( + distr: D, zero: N, expected: &[N], + ) { let mut rng = crate::test::rng(213); let mut buf = [zero; 4]; for x in &mut buf { @@ -239,23 +246,41 @@ mod tests { } assert_eq!(buf, expected); } - - test_samples(StandardNormal, 0f32, - &[-0.11844189, 0.781378, 0.06563994, -1.1932899]); + + test_samples(StandardNormal, 0f32, &[ + -0.11844189, + 0.781378, + 0.06563994, + -1.1932899, + ]); test_samples(StandardNormal, 0f64, &[ - -0.11844188827977231, 0.7813779637772346, - 0.06563993969580051, -1.1932899004186373]); - - test_samples(Normal::new(0.0, 1.0).unwrap(), 0f32, - &[-0.11844189, 0.781378, 0.06563994, -1.1932899]); + -0.11844188827977231, + 0.7813779637772346, + 0.06563993969580051, + -1.1932899004186373, + ]); + + test_samples(Normal::new(0.0, 1.0).unwrap(), 0f32, &[ + -0.11844189, + 0.781378, + 0.06563994, + -1.1932899, + ]); test_samples(Normal::new(2.0, 0.5).unwrap(), 0f64, &[ - 1.940779055860114, 2.3906889818886174, - 2.0328199698479, 1.4033550497906813]); - - test_samples(LogNormal::new(0.0, 1.0).unwrap(), 0f32, - &[0.88830346, 2.1844804, 1.0678421, 0.30322206]); + 1.940779055860114, + 2.3906889818886174, + 2.0328199698479, + 1.4033550497906813, + ]); + + test_samples(LogNormal::new(0.0, 1.0).unwrap(), 0f32, &[ + 0.88830346, 2.1844804, 1.0678421, 0.30322206, + ]); test_samples(LogNormal::new(2.0, 0.5).unwrap(), 0f64, &[ - 6.964174338639032, 10.921015733601452, - 7.6355881556915906, 4.068828213584092]); + 6.964174338639032, + 10.921015733601452, + 7.6355881556915906, + 4.068828213584092, + ]); } } diff --git a/rand_distr/src/pareto.rs b/rand_distr/src/pareto.rs index 75842c5fb92..fd427514c4d 100644 --- a/rand_distr/src/pareto.rs +++ b/rand_distr/src/pareto.rs @@ -8,9 +8,9 @@ //! The Pareto distribution. -use rand::Rng; -use crate::{Distribution, OpenClosed01}; use crate::utils::Float; +use crate::{Distribution, OpenClosed01}; +use rand::Rng; use std::{error, fmt}; /// Samples floating-point numbers according to the Pareto distribution @@ -63,7 +63,10 @@ where OpenClosed01: Distribution if !(shape > N::from(0.0)) { return Err(Error::ShapeTooSmall); } - Ok(Pareto { scale, inv_neg_shape: N::from(-1.0) / shape }) + Ok(Pareto { + scale, + inv_neg_shape: N::from(-1.0) / shape, + }) } } @@ -97,12 +100,12 @@ mod tests { assert!(r >= scale); } } - + #[test] fn value_stability() { - fn test_samples> - (distr: D, zero: N, expected: &[N]) - { + fn test_samples>( + distr: D, zero: N, expected: &[N], + ) { let mut rng = crate::test::rng(213); let mut buf = [zero; 4]; for x in &mut buf { @@ -110,11 +113,15 @@ mod tests { } assert_eq!(buf, expected); } - - test_samples(Pareto::new(1.0, 1.0).unwrap(), 0f32, - &[1.0423688, 2.1235929, 4.132709, 1.4679428]); + + test_samples(Pareto::new(1.0, 1.0).unwrap(), 0f32, &[ + 1.0423688, 2.1235929, 4.132709, 1.4679428, + ]); test_samples(Pareto::new(2.0, 0.5).unwrap(), 0f64, &[ - 9.019295276219136, 4.3097126018270595, - 6.837815045397157, 105.8826669383772]); + 9.019295276219136, + 4.3097126018270595, + 6.837815045397157, + 105.8826669383772, + ]); } } diff --git a/rand_distr/src/pert.rs b/rand_distr/src/pert.rs index bd8a0c40121..2a00a8c27fb 100644 --- a/rand_distr/src/pert.rs +++ b/rand_distr/src/pert.rs @@ -7,9 +7,9 @@ // except according to those terms. //! The PERT distribution. -use rand::Rng; -use crate::{Distribution, Beta, StandardNormal, Exp1, Open01}; use crate::utils::Float; +use crate::{Beta, Distribution, Exp1, Open01, StandardNormal}; +use rand::Rng; use std::{error, fmt}; /// The PERT distribution. @@ -28,7 +28,7 @@ use std::{error, fmt}; /// let v = d.sample(&mut rand::thread_rng()); /// println!("{} is from a PERT distribution", v); /// ``` -/// +/// /// [`Triangular`]: crate::Triangular #[derive(Clone, Copy, Debug)] pub struct Pert { @@ -61,7 +61,10 @@ impl fmt::Display for PertError { impl error::Error for PertError {} impl Pert -where StandardNormal: Distribution, Exp1: Distribution, Open01: Distribution +where + StandardNormal: Distribution, + Exp1: Distribution, + Open01: Distribution, { /// Set up the PERT distribution with defined `min`, `max` and `mode`. /// @@ -70,7 +73,7 @@ where StandardNormal: Distribution, Exp1: Distribution, Open01: Distributi pub fn new(min: N, max: N, mode: N) -> Result, PertError> { Pert::new_with_shape(min, max, mode, N::from(4.)) } - + /// Set up the PERT distribution with defined `min`, `max`, `mode` and /// `shape`. pub fn new_with_shape(min: N, max: N, mode: N, shape: N) -> Result, PertError> { @@ -83,23 +86,25 @@ where StandardNormal: Distribution, Exp1: Distribution, Open01: Distributi if !(shape >= N::from(0.)) { return Err(PertError::ShapeTooSmall); } - + let range = max - min; let mu = (min + max + shape * mode) / (shape + N::from(2.)); let v = if mu == mode { shape * N::from(0.5) + N::from(1.) } else { - (mu - min) * (N::from(2.) * mode - min - max) - / ((mode - mu) * (max - min)) + (mu - min) * (N::from(2.) * mode - min - max) / ((mode - mu) * (max - min)) }; let w = v * (max - mu) / (mu - min); let beta = Beta::new(v, w).map_err(|_| PertError::RangeTooSmall)?; - Ok(Pert{ min, range, beta }) + Ok(Pert { min, range, beta }) } } impl Distribution for Pert -where StandardNormal: Distribution, Exp1: Distribution, Open01: Distribution +where + StandardNormal: Distribution, + Exp1: Distribution, + Open01: Distribution, { #[inline] fn sample(&self, rng: &mut R) -> N { @@ -109,8 +114,8 @@ where StandardNormal: Distribution, Exp1: Distribution, Open01: Distributi #[cfg(test)] mod test { - use std::f64; use super::*; + use std::f64; #[test] fn test_pert() { @@ -131,15 +136,20 @@ mod test { assert!(Pert::new(min, max, mode).is_err()); } } - + #[test] fn value_stability() { let rng = crate::test::rng(860); - let distr = Pert::new(2., 10., 3.).unwrap(); // mean = 4, var = 12/7 + let distr = Pert::new(2., 10., 3.).unwrap(); // mean = 4, var = 12/7 let seq = distr.sample_iter(rng).take(5).collect::>(); println!("seq: {:?}", seq); - let expected = vec![4.631484136029422, 3.307201472321789, - 3.29995019556348, 3.66835483991721, 3.514246139933899]; + let expected = vec![ + 4.631484136029422, + 3.307201472321789, + 3.29995019556348, + 3.66835483991721, + 3.514246139933899, + ]; assert!(seq == expected); } } diff --git a/rand_distr/src/poisson.rs b/rand_distr/src/poisson.rs index 504677e484f..28f835ab7b8 100644 --- a/rand_distr/src/poisson.rs +++ b/rand_distr/src/poisson.rs @@ -9,9 +9,9 @@ //! The Poisson distribution. -use rand::Rng; -use crate::{Distribution, Cauchy, Standard}; use crate::utils::Float; +use crate::{Cauchy, Distribution, Standard}; +use rand::Rng; use std::{error, fmt}; /// The Poisson distribution `Poisson(lambda)`. @@ -120,8 +120,12 @@ where Standard: Distribution // the magic value scales the distribution function to a range of approximately 0-1 // since it is not exact, we multiply the ratio by 0.9 to avoid ratios greater than 1 // this doesn't change the resulting distribution, only increases the rate of failed drawings - let check = N::from(0.9) * (N::from(1.0) + comp_dev * comp_dev) - * (result * self.log_lambda - (N::from(1.0) + result).log_gamma() - self.magic_val).exp(); + let check = N::from(0.9) + * (N::from(1.0) + comp_dev * comp_dev) + * (result * self.log_lambda + - (N::from(1.0) + result).log_gamma() + - self.magic_val) + .exp(); // check with uniform random value - if below the threshold, we are within the target distribution if rng.gen::() <= check { @@ -240,12 +244,12 @@ mod test { fn test_poisson_invalid_lambda_neg() { Poisson::new(-10.0).unwrap(); } - + #[test] fn value_stability() { - fn test_samples> - (distr: D, zero: N, expected: &[N]) - { + fn test_samples>( + distr: D, zero: N, expected: &[N], + ) { let mut rng = crate::test::rng(223); let mut buf = [zero; 4]; for x in &mut buf { @@ -253,7 +257,7 @@ mod test { } assert_eq!(buf, expected); } - + // Special cases: < 12, >= 12 test_samples(Poisson::new(7.0).unwrap(), 0f32, &[5.0, 11.0, 6.0, 5.0]); test_samples(Poisson::new(7.0).unwrap(), 0f64, &[9.0, 5.0, 7.0, 6.0]); diff --git a/rand_distr/src/triangular.rs b/rand_distr/src/triangular.rs index 15e7e2662e8..f290f030765 100644 --- a/rand_distr/src/triangular.rs +++ b/rand_distr/src/triangular.rs @@ -7,13 +7,13 @@ // except according to those terms. //! The triangular distribution. -use rand::Rng; -use crate::{Distribution, Standard}; use crate::utils::Float; +use crate::{Distribution, Standard}; +use rand::Rng; use std::{error, fmt}; /// The triangular distribution. -/// +/// /// A continuous probability distribution parameterised by a range, and a mode /// (most likely value) within that range. /// @@ -95,9 +95,9 @@ where Standard: Distribution #[cfg(test)] mod test { - use std::f64; - use rand::{Rng, rngs::mock}; use super::*; + use rand::{rngs::mock, Rng}; + use std::f64; #[test] fn test_triangular() { @@ -125,15 +125,20 @@ mod test { assert!(Triangular::new(min, max, mode).is_err()); } } - + #[test] fn value_stability() { let rng = crate::test::rng(860); let distr = Triangular::new(2., 10., 3.).unwrap(); let seq = distr.sample_iter(rng).take(5).collect::>(); println!("seq: {:?}", seq); - let expected = vec![5.74373257511361, 7.890059162791258, - 4.7256280652553455, 2.9474808121184077, 3.058301946314053]; + let expected = vec![ + 5.74373257511361, + 7.890059162791258, + 4.7256280652553455, + 2.9474808121184077, + 3.058301946314053, + ]; assert!(seq == expected); } } diff --git a/rand_distr/src/unit_ball.rs b/rand_distr/src/unit_ball.rs index 9d61627a3ef..616a25161ae 100644 --- a/rand_distr/src/unit_ball.rs +++ b/rand_distr/src/unit_ball.rs @@ -6,9 +6,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use rand::Rng; -use crate::{Distribution, Uniform, uniform::SampleUniform}; use crate::utils::Float; +use crate::{uniform::SampleUniform, Distribution, Uniform}; +use rand::Rng; /// Samples uniformly from the unit ball (surface and interior) in three /// dimensions. @@ -38,7 +38,7 @@ impl Distribution<[N; 3]> for UnitBall { x1 = uniform.sample(rng); x2 = uniform.sample(rng); x3 = uniform.sample(rng); - if x1*x1 + x2*x2 + x3*x3 <= N::from(1.) { + if x1 * x1 + x2 * x2 + x3 * x3 <= N::from(1.) { break; } } @@ -48,22 +48,22 @@ impl Distribution<[N; 3]> for UnitBall { #[cfg(test)] mod tests { - use crate::Distribution; use super::UnitBall; + use crate::Distribution; #[test] fn value_stability() { let mut rng = crate::test::rng(2); let expected = [ - [0.018035709265959987, -0.4348771383120438, -0.07982762085055706], - [0.10588569388223945, -0.4734350111375454, -0.7392104908825501], - [0.11060237642041049, -0.16065642822852677, -0.8444043930440075] - ]; + [0.018035709265959987, -0.4348771383120438, -0.07982762085055706], + [0.10588569388223945, -0.4734350111375454, -0.7392104908825501], + [0.11060237642041049, -0.16065642822852677, -0.8444043930440075] + ]; let samples: [[f64; 3]; 3] = [ - UnitBall.sample(&mut rng), - UnitBall.sample(&mut rng), - UnitBall.sample(&mut rng), - ]; + UnitBall.sample(&mut rng), + UnitBall.sample(&mut rng), + UnitBall.sample(&mut rng), + ]; assert_eq!(samples, expected); } } diff --git a/rand_distr/src/unit_circle.rs b/rand_distr/src/unit_circle.rs index 5863a1a0ff9..9f9844a5536 100644 --- a/rand_distr/src/unit_circle.rs +++ b/rand_distr/src/unit_circle.rs @@ -6,9 +6,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use rand::Rng; -use crate::{Distribution, Uniform, uniform::SampleUniform}; use crate::utils::Float; +use crate::{uniform::SampleUniform, Distribution, Uniform}; +use rand::Rng; /// Samples uniformly from the edge of the unit circle in two dimensions. /// @@ -41,35 +41,36 @@ impl Distribution<[N; 2]> for UnitCircle { loop { x1 = uniform.sample(rng); x2 = uniform.sample(rng); - sum = x1*x1 + x2*x2; + sum = x1 * x1 + x2 * x2; if sum < N::from(1.) { break; } } - let diff = x1*x1 - x2*x2; - [diff / sum, N::from(2.)*x1*x2 / sum] + let diff = x1 * x1 - x2 * x2; + [diff / sum, N::from(2.) * x1 * x2 / sum] } } #[cfg(test)] mod tests { - use crate::Distribution; use super::UnitCircle; + use crate::Distribution; /// Assert that two numbers are almost equal to each other. /// /// On panic, this macro will print the values of the expressions with their /// debug representations. macro_rules! assert_almost_eq { - ($a:expr, $b:expr, $prec:expr) => ( + ($a:expr, $b:expr, $prec:expr) => { let diff = ($a - $b).abs(); if diff > $prec { panic!(format!( "assertion failed: `abs(left - right) = {:.1e} < {:e}`, \ (left: `{}`, right: `{}`)", - diff, $prec, $a, $b)); + diff, $prec, $a, $b + )); } - ); + }; } #[test] @@ -77,7 +78,7 @@ mod tests { let mut rng = crate::test::rng(1); for _ in 0..1000 { let x: [f64; 2] = UnitCircle.sample(&mut rng); - assert_almost_eq!(x[0]*x[0] + x[1]*x[1], 1., 1e-15); + assert_almost_eq!(x[0] * x[0] + x[1] * x[1], 1., 1e-15); } } @@ -85,15 +86,15 @@ mod tests { fn value_stability() { let mut rng = crate::test::rng(2); let expected = [ - [-0.9965658683520504, -0.08280380447614634], - [-0.9790853270389644, -0.20345004884984505], - [-0.8449189758898707, 0.5348943112253227], - ]; + [-0.9965658683520504, -0.08280380447614634], + [-0.9790853270389644, -0.20345004884984505], + [-0.8449189758898707, 0.5348943112253227], + ]; let samples: [[f64; 2]; 3] = [ - UnitCircle.sample(&mut rng), - UnitCircle.sample(&mut rng), - UnitCircle.sample(&mut rng), - ]; + UnitCircle.sample(&mut rng), + UnitCircle.sample(&mut rng), + UnitCircle.sample(&mut rng), + ]; assert_eq!(samples, expected); } } diff --git a/rand_distr/src/unit_disc.rs b/rand_distr/src/unit_disc.rs index 97abc2f206e..dc37c129cb9 100644 --- a/rand_distr/src/unit_disc.rs +++ b/rand_distr/src/unit_disc.rs @@ -6,9 +6,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use rand::Rng; -use crate::{Distribution, Uniform, uniform::SampleUniform}; use crate::utils::Float; +use crate::{uniform::SampleUniform, Distribution, Uniform}; +use rand::Rng; /// Samples uniformly from the unit disc in two dimensions. /// @@ -35,7 +35,7 @@ impl Distribution<[N; 2]> for UnitDisc { loop { x1 = uniform.sample(rng); x2 = uniform.sample(rng); - if x1*x1 + x2*x2 <= N::from(1.) { + if x1 * x1 + x2 * x2 <= N::from(1.) { break; } } @@ -45,22 +45,22 @@ impl Distribution<[N; 2]> for UnitDisc { #[cfg(test)] mod tests { - use crate::Distribution; use super::UnitDisc; + use crate::Distribution; #[test] fn value_stability() { let mut rng = crate::test::rng(2); let expected = [ - [0.018035709265959987, -0.4348771383120438], - [-0.07982762085055706, 0.7765329819820659], - [0.21450745997299503, 0.7398636984333291] - ]; + [0.018035709265959987, -0.4348771383120438], + [-0.07982762085055706, 0.7765329819820659], + [0.21450745997299503, 0.7398636984333291], + ]; let samples: [[f64; 2]; 3] = [ - UnitDisc.sample(&mut rng), - UnitDisc.sample(&mut rng), - UnitDisc.sample(&mut rng), - ]; + UnitDisc.sample(&mut rng), + UnitDisc.sample(&mut rng), + UnitDisc.sample(&mut rng), + ]; assert_eq!(samples, expected); } } diff --git a/rand_distr/src/unit_sphere.rs b/rand_distr/src/unit_sphere.rs index 8e0c3612594..54539cc9e41 100644 --- a/rand_distr/src/unit_sphere.rs +++ b/rand_distr/src/unit_sphere.rs @@ -6,9 +6,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use rand::Rng; -use crate::{Distribution, Uniform, uniform::SampleUniform}; use crate::utils::Float; +use crate::{uniform::SampleUniform, Distribution, Uniform}; +use rand::Rng; /// Samples uniformly from the surface of the unit sphere in three dimensions. /// @@ -36,35 +36,36 @@ impl Distribution<[N; 3]> for UnitSphere { let uniform = Uniform::new(N::from(-1.), N::from(1.)); loop { let (x1, x2) = (uniform.sample(rng), uniform.sample(rng)); - let sum = x1*x1 + x2*x2; + let sum = x1 * x1 + x2 * x2; if sum >= N::from(1.) { continue; } let factor = N::from(2.) * (N::from(1.0) - sum).sqrt(); - return [x1 * factor, x2 * factor, N::from(1.) - N::from(2.)*sum]; + return [x1 * factor, x2 * factor, N::from(1.) - N::from(2.) * sum]; } } } #[cfg(test)] mod tests { - use crate::Distribution; use super::UnitSphere; + use crate::Distribution; /// Assert that two numbers are almost equal to each other. /// /// On panic, this macro will print the values of the expressions with their /// debug representations. macro_rules! assert_almost_eq { - ($a:expr, $b:expr, $prec:expr) => ( + ($a:expr, $b:expr, $prec:expr) => { let diff = ($a - $b).abs(); if diff > $prec { panic!(format!( "assertion failed: `abs(left - right) = {:.1e} < {:e}`, \ (left: `{}`, right: `{}`)", - diff, $prec, $a, $b)); + diff, $prec, $a, $b + )); } - ); + }; } #[test] @@ -72,7 +73,7 @@ mod tests { let mut rng = crate::test::rng(1); for _ in 0..1000 { let x: [f64; 3] = UnitSphere.sample(&mut rng); - assert_almost_eq!(x[0]*x[0] + x[1]*x[1] + x[2]*x[2], 1., 1e-15); + assert_almost_eq!(x[0] * x[0] + x[1] * x[1] + x[2] * x[2], 1., 1e-15); } } @@ -80,15 +81,15 @@ mod tests { fn value_stability() { let mut rng = crate::test::rng(2); let expected = [ - [0.03247542860231647, -0.7830477442152738, 0.6211131755296027], - [-0.09978440840914075, 0.9706650829833128, -0.21875184231323952], - [0.2735582468624679, 0.9435374242279655, -0.1868234852870203], - ]; + [0.03247542860231647, -0.7830477442152738, 0.6211131755296027], + [-0.09978440840914075, 0.9706650829833128, -0.21875184231323952], + [0.2735582468624679, 0.9435374242279655, -0.1868234852870203], + ]; let samples: [[f64; 3]; 3] = [ - UnitSphere.sample(&mut rng), - UnitSphere.sample(&mut rng), - UnitSphere.sample(&mut rng), - ]; + UnitSphere.sample(&mut rng), + UnitSphere.sample(&mut rng), + UnitSphere.sample(&mut rng), + ]; assert_eq!(samples, expected); } } diff --git a/rand_distr/src/utils.rs b/rand_distr/src/utils.rs index 75b350053f3..478aacf7625 100644 --- a/rand_distr/src/utils.rs +++ b/rand_distr/src/utils.rs @@ -8,26 +8,32 @@ //! Math helper functions -use rand::Rng; use crate::ziggurat_tables; -use rand::distributions::hidden_export::IntoFloat; use core::{cmp, ops}; +use rand::distributions::hidden_export::IntoFloat; +use rand::Rng; /// Trait for floating-point scalar types -/// +/// /// This allows many distributions to work with `f32` or `f64` parameters and is /// potentially extensible. Note however that the `Exp1` and `StandardNormal` /// distributions are implemented exclusively for `f32` and `f64`. -/// +/// /// The bounds and methods are based purely on internal /// requirements, and will change as needed. -pub trait Float: Copy + Sized + cmp::PartialOrd +pub trait Float: + Copy + + Sized + + cmp::PartialOrd + ops::Neg + ops::Add + ops::Sub + ops::Mul + ops::Div - + ops::AddAssign + ops::SubAssign + ops::MulAssign + ops::DivAssign + + ops::AddAssign + + ops::SubAssign + + ops::MulAssign + + ops::DivAssign { /// The constant π fn pi() -> Self; @@ -35,12 +41,12 @@ pub trait Float: Copy + Sized + cmp::PartialOrd fn from(x: f64) -> Self; /// Support converting to an unsigned integer. fn to_u64(self) -> Option; - + /// Take the absolute value of self fn abs(self) -> Self; /// Take the largest integer less than or equal to self fn floor(self) -> Self; - + /// Take the exponential of self fn exp(self) -> Self; /// Take the natural logarithm of self @@ -49,7 +55,7 @@ pub trait Float: Copy + Sized + cmp::PartialOrd fn sqrt(self) -> Self; /// Take self to a floating-point power fn powf(self, power: Self) -> Self; - + /// Take the tangent of self fn tan(self) -> Self; /// Take the logarithm of the gamma function of self @@ -58,9 +64,15 @@ pub trait Float: Copy + Sized + cmp::PartialOrd impl Float for f32 { #[inline] - fn pi() -> Self { core::f32::consts::PI } + fn pi() -> Self { + core::f32::consts::PI + } + #[inline] - fn from(x: f64) -> Self { x as f32 } + fn from(x: f64) -> Self { + x as f32 + } + #[inline] fn to_u64(self) -> Option { if self >= 0. && self <= ::core::u64::MAX as f32 { @@ -69,23 +81,42 @@ impl Float for f32 { None } } - + #[inline] - fn abs(self) -> Self { self.abs() } + fn abs(self) -> Self { + self.abs() + } + #[inline] - fn floor(self) -> Self { self.floor() } - + fn floor(self) -> Self { + self.floor() + } + #[inline] - fn exp(self) -> Self { self.exp() } + fn exp(self) -> Self { + self.exp() + } + #[inline] - fn ln(self) -> Self { self.ln() } + fn ln(self) -> Self { + self.ln() + } + #[inline] - fn sqrt(self) -> Self { self.sqrt() } + fn sqrt(self) -> Self { + self.sqrt() + } + #[inline] - fn powf(self, power: Self) -> Self { self.powf(power) } - + fn powf(self, power: Self) -> Self { + self.powf(power) + } + #[inline] - fn tan(self) -> Self { self.tan() } + fn tan(self) -> Self { + self.tan() + } + #[inline] fn log_gamma(self) -> Self { let result = log_gamma(self.into()); @@ -97,9 +128,15 @@ impl Float for f32 { impl Float for f64 { #[inline] - fn pi() -> Self { core::f64::consts::PI } + fn pi() -> Self { + core::f64::consts::PI + } + #[inline] - fn from(x: f64) -> Self { x } + fn from(x: f64) -> Self { + x + } + #[inline] fn to_u64(self) -> Option { if self >= 0. && self <= ::core::u64::MAX as f64 { @@ -108,25 +145,46 @@ impl Float for f64 { None } } - + #[inline] - fn abs(self) -> Self { self.abs() } + fn abs(self) -> Self { + self.abs() + } + #[inline] - fn floor(self) -> Self { self.floor() } - + fn floor(self) -> Self { + self.floor() + } + #[inline] - fn exp(self) -> Self { self.exp() } + fn exp(self) -> Self { + self.exp() + } + #[inline] - fn ln(self) -> Self { self.ln() } + fn ln(self) -> Self { + self.ln() + } + #[inline] - fn sqrt(self) -> Self { self.sqrt() } + fn sqrt(self) -> Self { + self.sqrt() + } + #[inline] - fn powf(self, power: Self) -> Self { self.powf(power) } - + fn powf(self, power: Self) -> Self { + self.powf(power) + } + #[inline] - fn tan(self) -> Self { self.tan() } + fn tan(self) -> Self { + self.tan() + } + #[inline] - fn log_gamma(self) -> Self { log_gamma(self) } + fn log_gamma(self) -> Self { + log_gamma(self) + } } /// Calculates ln(gamma(x)) (natural logarithm of the gamma @@ -188,13 +246,17 @@ pub(crate) fn log_gamma(x: f64) -> f64 { // size from force-inlining. #[inline(always)] pub(crate) fn ziggurat( - rng: &mut R, - symmetric: bool, - x_tab: ziggurat_tables::ZigTable, - f_tab: ziggurat_tables::ZigTable, - mut pdf: P, - mut zero_case: Z) - -> f64 where P: FnMut(f64) -> f64, Z: FnMut(&mut R, f64) -> f64 { + rng: &mut R, + symmetric: bool, + x_tab: ziggurat_tables::ZigTable, + f_tab: ziggurat_tables::ZigTable, + mut pdf: P, + mut zero_case: Z +) -> f64 +where + P: FnMut(f64) -> f64, + Z: FnMut(&mut R, f64) -> f64, +{ loop { // As an optimisation we re-implement the conversion to a f64. // From the remaining 12 most significant bits we use 8 to construct `i`. @@ -212,12 +274,11 @@ pub(crate) fn ziggurat( (bits >> 12).into_float_with_exponent(1) - 3.0 } else { // Convert to a value in the range [1,2) and substract to get (0,1) - (bits >> 12).into_float_with_exponent(0) - - (1.0 - std::f64::EPSILON / 2.0) + (bits >> 12).into_float_with_exponent(0) - (1.0 - std::f64::EPSILON / 2.0) }; let x = u * x_tab[i]; - let test_x = if symmetric { x.abs() } else {x}; + let test_x = if symmetric { x.abs() } else { x }; // algebraically equivalent to |u| < x_tab[i+1]/x_tab[i] (or u < x_tab[i+1]/x_tab[i]) if test_x < x_tab[i + 1] { diff --git a/rand_distr/src/weibull.rs b/rand_distr/src/weibull.rs index 84380419c92..6ef3e553363 100644 --- a/rand_distr/src/weibull.rs +++ b/rand_distr/src/weibull.rs @@ -8,9 +8,9 @@ //! The Weibull distribution. -use rand::Rng; -use crate::{Distribution, OpenClosed01}; use crate::utils::Float; +use crate::{Distribution, OpenClosed01}; +use rand::Rng; use std::{error, fmt}; /// Samples floating-point numbers according to the Weibull distribution @@ -60,7 +60,10 @@ where OpenClosed01: Distribution if !(shape > N::from(0.0)) { return Err(Error::ShapeTooSmall); } - Ok(Weibull { inv_shape: N::from(1.)/shape, scale }) + Ok(Weibull { + inv_shape: N::from(1.) / shape, + scale, + }) } } @@ -94,12 +97,12 @@ mod tests { assert!(r >= 0.); } } - + #[test] fn value_stability() { - fn test_samples> - (distr: D, zero: N, expected: &[N]) - { + fn test_samples>( + distr: D, zero: N, expected: &[N], + ) { let mut rng = crate::test::rng(213); let mut buf = [zero; 4]; for x in &mut buf { @@ -107,11 +110,18 @@ mod tests { } assert_eq!(buf, expected); } - - test_samples(Weibull::new(1.0, 1.0).unwrap(), 0f32, - &[0.041495778, 0.7531094, 1.4189332, 0.38386202]); + + test_samples(Weibull::new(1.0, 1.0).unwrap(), 0f32, &[ + 0.041495778, + 0.7531094, + 1.4189332, + 0.38386202, + ]); test_samples(Weibull::new(2.0, 0.5).unwrap(), 0f64, &[ - 1.1343478702739669, 0.29470010050655226, - 0.7556151370284702, 7.877212340241561]); + 1.1343478702739669, + 0.29470010050655226, + 0.7556151370284702, + 7.877212340241561, + ]); } } diff --git a/rand_distr/src/ziggurat_tables.rs b/rand_distr/src/ziggurat_tables.rs index ca1ce30410f..f830a601bdd 100644 --- a/rand_distr/src/ziggurat_tables.rs +++ b/rand_distr/src/ziggurat_tables.rs @@ -12,6 +12,7 @@ pub type ZigTable = &'static [f64; 257]; pub const ZIG_NORM_R: f64 = 3.654152885361008796; +#[rustfmt::skip] pub static ZIG_NORM_X: [f64; 257] = [3.910757959537090045, 3.654152885361008796, 3.449278298560964462, 3.320244733839166074, 3.224575052047029100, 3.147889289517149969, 3.083526132001233044, 3.027837791768635434, @@ -78,6 +79,7 @@ pub static ZIG_NORM_X: [f64; 257] = 0.487443966121754335, 0.463634336771763245, 0.437518402186662658, 0.408389134588000746, 0.375121332850465727, 0.335737519180459465, 0.286174591747260509, 0.215241895913273806, 0.000000000000000000]; +#[rustfmt::skip] pub static ZIG_NORM_F: [f64; 257] = [0.000477467764586655, 0.001260285930498598, 0.002609072746106363, 0.004037972593371872, 0.005522403299264754, 0.007050875471392110, 0.008616582769422917, 0.010214971439731100, @@ -145,6 +147,7 @@ pub static ZIG_NORM_F: [f64; 257] = 0.932060075968990209, 0.945198953453078028, 0.959879091812415930, 0.977101701282731328, 1.000000000000000000]; pub const ZIG_EXP_R: f64 = 7.697117470131050077; +#[rustfmt::skip] pub static ZIG_EXP_X: [f64; 257] = [8.697117470131052741, 7.697117470131050077, 6.941033629377212577, 6.478378493832569696, 6.144164665772472667, 5.882144315795399869, 5.666410167454033697, 5.482890627526062488, @@ -211,6 +214,7 @@ pub static ZIG_EXP_X: [f64; 257] = 0.253658363385912022, 0.233790483059674731, 0.212671510630966620, 0.189958689622431842, 0.165127622564187282, 0.137304980940012589, 0.104838507565818778, 0.063852163815001570, 0.000000000000000000]; +#[rustfmt::skip] pub static ZIG_EXP_F: [f64; 257] = [0.000167066692307963, 0.000454134353841497, 0.000967269282327174, 0.001536299780301573, 0.002145967743718907, 0.002788798793574076, 0.003460264777836904, 0.004157295120833797, diff --git a/rand_distr/tests/uniformity.rs b/rand_distr/tests/uniformity.rs index d0d9d976ed3..7d359c7d733 100644 --- a/rand_distr/tests/uniformity.rs +++ b/rand_distr/tests/uniformity.rs @@ -25,9 +25,13 @@ fn unit_sphere() { for _ in 0..N_SAMPLES { let v: [f64; 3] = dist.sample(&mut rng); for i in 0..N_DIM { - histograms[i].add(v[i]).map_err( - |e| { println!("v: {}", v[i]); e } - ).unwrap(); + histograms[i] + .add(v[i]) + .map_err(|e| { + println!("v: {}", v[i]); + e + }) + .unwrap(); } } for h in &histograms { diff --git a/rand_hc/src/hc128.rs b/rand_hc/src/hc128.rs index a320f48f441..8bc85f917fe 100644 --- a/rand_hc/src/hc128.rs +++ b/rand_hc/src/hc128.rs @@ -9,8 +9,8 @@ //! The HC-128 random number generator. use core::fmt; -use rand_core::{CryptoRng, RngCore, SeedableRng, Error, le}; -use rand_core::block::{BlockRngCore, BlockRng}; +use rand_core::block::{BlockRng, BlockRngCore}; +use rand_core::{le, CryptoRng, Error, RngCore, SeedableRng}; const SEED_WORDS: usize = 8; // 128 bit key followed by 128 bit iv @@ -173,9 +173,7 @@ impl BlockRngCore for Hc128Core { impl Hc128Core { // One step of HC-128, update P and generate 32 bits keystream #[inline(always)] - fn step_p(&mut self, i: usize, i511: usize, i3: usize, i10: usize, i12: usize) - -> u32 - { + fn step_p(&mut self, i: usize, i511: usize, i3: usize, i10: usize, i12: usize) -> u32 { let (p, q) = self.t.split_at_mut(512); // FIXME: it would be great if we the bounds checks here could be // optimized out, and we would not need unsafe. @@ -184,9 +182,10 @@ impl Hc128Core { let temp0 = p.get_unchecked(i511).rotate_right(23); let temp1 = p.get_unchecked(i3).rotate_right(10); let temp2 = p.get_unchecked(i10).rotate_right(8); - *p.get_unchecked_mut(i) = p.get_unchecked(i) - .wrapping_add(temp2) - .wrapping_add(temp0 ^ temp1); + *p.get_unchecked_mut(i) = p + .get_unchecked(i) + .wrapping_add(temp2) + .wrapping_add(temp0 ^ temp1); let temp3 = { // The h1 function in HC-128 let a = *p.get_unchecked(i12) as u8; @@ -201,17 +200,16 @@ impl Hc128Core { // Similar to `step_p`, but `p` and `q` are swapped, and the rotates are to // the left instead of to the right. #[inline(always)] - fn step_q(&mut self, i: usize, i511: usize, i3: usize, i10: usize, i12: usize) - -> u32 - { + fn step_q(&mut self, i: usize, i511: usize, i3: usize, i10: usize, i12: usize) -> u32 { let (p, q) = self.t.split_at_mut(512); unsafe { let temp0 = q.get_unchecked(i511).rotate_left(23); let temp1 = q.get_unchecked(i3).rotate_left(10); let temp2 = q.get_unchecked(i10).rotate_left(8); - *q.get_unchecked_mut(i) = q.get_unchecked(i) - .wrapping_add(temp2) - .wrapping_add(temp0 ^ temp1); + *q.get_unchecked_mut(i) = q + .get_unchecked(i) + .wrapping_add(temp2) + .wrapping_add(temp0 ^ temp1); let temp3 = { // The h2 function in HC-128 let a = *q.get_unchecked(i12) as u8; @@ -272,7 +270,7 @@ impl Hc128Core { // Initialize an HC-128 random number generator. The seed has to be // 256 bits in length (`[u32; 8]`), matching the 128 bit `key` followed by // 128 bit `iv` when HC-128 where to be used as a stream cipher. - #[inline(always)] // single use: SeedableRng::from_seed + #[inline(always)] // single use: SeedableRng::from_seed fn init(seed: [u32; SEED_WORDS]) -> Self { #[inline] fn f1(x: u32) -> u32 { @@ -295,9 +293,12 @@ impl Hc128Core { // Generate the 256 intermediate values W[16] ... W[256+16-1], and // copy the last 16 generated values to the start op P. - for i in 16..256+16 { - t[i] = f2(t[i-2]).wrapping_add(t[i-7]).wrapping_add(f1(t[i-15])) - .wrapping_add(t[i-16]).wrapping_add(i as u32); + for i in 16..256 + 16 { + t[i] = f2(t[i - 2]) + .wrapping_add(t[i - 7]) + .wrapping_add(f1(t[i - 15])) + .wrapping_add(t[i - 16]) + .wrapping_add(i as u32); } { let (p1, p2) = t.split_at_mut(256); @@ -306,21 +307,26 @@ impl Hc128Core { // Generate both the P and Q tables for i in 16..1024 { - t[i] = f2(t[i-2]).wrapping_add(t[i-7]).wrapping_add(f1(t[i-15])) - .wrapping_add(t[i-16]).wrapping_add(256 + i as u32); + t[i] = f2(t[i - 2]) + .wrapping_add(t[i - 7]) + .wrapping_add(f1(t[i - 15])) + .wrapping_add(t[i - 16]) + .wrapping_add(256 + i as u32); } let mut core = Self { t, counter1024: 0 }; // run the cipher 1024 steps - for _ in 0..64 { core.sixteen_steps() }; + for _ in 0..64 { + core.sixteen_steps() + } core.counter1024 = 0; core } } impl SeedableRng for Hc128Core { - type Seed = [u8; SEED_WORDS*4]; + type Seed = [u8; SEED_WORDS * 4]; /// Create an HC-128 random number generator with a seed. The seed has to be /// 256 bits in length, matching the 128 bit `key` followed by 128 bit `iv` @@ -336,18 +342,22 @@ impl CryptoRng for Hc128Core {} #[cfg(test)] mod test { - use ::rand_core::{RngCore, SeedableRng}; use super::Hc128Rng; + use ::rand_core::{RngCore, SeedableRng}; #[test] // Test vector 1 from the paper "The Stream Cipher HC-128" fn test_hc128_true_values_a() { + #[rustfmt::skip] let seed = [0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // key 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0]; // iv let mut rng = Hc128Rng::from_seed(seed); let mut results = [0u32; 16]; - for i in results.iter_mut() { *i = rng.next_u32(); } + for i in results.iter_mut() { + *i = rng.next_u32(); + } + #[rustfmt::skip] let expected = [0x73150082, 0x3bfd03a0, 0xfb2fd77f, 0xaa63af0e, 0xde122fc6, 0xa7dc29b6, 0x62a68527, 0x8b75ec68, 0x9036db1e, 0x81896005, 0x00ade078, 0x491fbf9a, @@ -358,12 +368,16 @@ mod test { #[test] // Test vector 2 from the paper "The Stream Cipher HC-128" fn test_hc128_true_values_b() { + #[rustfmt::skip] let seed = [0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // key 1,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0]; // iv let mut rng = Hc128Rng::from_seed(seed); let mut results = [0u32; 16]; - for i in results.iter_mut() { *i = rng.next_u32(); } + for i in results.iter_mut() { + *i = rng.next_u32(); + } + #[rustfmt::skip] let expected = [0xc01893d5, 0xb7dbe958, 0x8f65ec98, 0x64176604, 0x36fc6724, 0xc82c6eec, 0x1b1c38a7, 0xc9b42a95, 0x323ef123, 0x0a6a908b, 0xce757b68, 0x9f14f7bb, @@ -374,12 +388,16 @@ mod test { #[test] // Test vector 3 from the paper "The Stream Cipher HC-128" fn test_hc128_true_values_c() { + #[rustfmt::skip] let seed = [0x55,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // key 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0]; // iv let mut rng = Hc128Rng::from_seed(seed); let mut results = [0u32; 16]; - for i in results.iter_mut() { *i = rng.next_u32(); } + for i in results.iter_mut() { + *i = rng.next_u32(); + } + #[rustfmt::skip] let expected = [0x518251a4, 0x04b4930a, 0xb02af931, 0x0639f032, 0xbcb4a47a, 0x5722480b, 0x2bf99f72, 0xcdc0e566, 0x310f0c56, 0xd3cc83e8, 0x663db8ef, 0x62dfe07f, @@ -389,12 +407,16 @@ mod test { #[test] fn test_hc128_true_values_u64() { + #[rustfmt::skip] let seed = [0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // key 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0]; // iv let mut rng = Hc128Rng::from_seed(seed); let mut results = [0u64; 8]; - for i in results.iter_mut() { *i = rng.next_u64(); } + for i in results.iter_mut() { + *i = rng.next_u64(); + } + #[rustfmt::skip] let expected = [0x3bfd03a073150082, 0xaa63af0efb2fd77f, 0xa7dc29b6de122fc6, 0x8b75ec6862a68527, 0x818960059036db1e, 0x491fbf9a00ade078, @@ -404,9 +426,14 @@ mod test { // The RNG operates in a P block of 512 results and next a Q block. // After skipping 2*800 u32 results we end up somewhere in the Q block // of the second round - for _ in 0..800 { rng.next_u64(); } + for _ in 0..800 { + rng.next_u64(); + } - for i in results.iter_mut() { *i = rng.next_u64(); } + for i in results.iter_mut() { + *i = rng.next_u64(); + } + #[rustfmt::skip] let expected = [0xd8c4d6ca84d0fc10, 0xf16a5d91dc66e8e7, 0xd800de5bc37a8653, 0x7bae1f88c0dfbb4c, 0x3bfe1f374e6d4d14, 0x424b55676be3fa06, @@ -416,9 +443,11 @@ mod test { #[test] fn test_hc128_true_values_bytes() { + #[rustfmt::skip] let seed = [0x55,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // key 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0]; // iv let mut rng = Hc128Rng::from_seed(seed); + #[rustfmt::skip] let expected = [0x31, 0xf9, 0x2a, 0xb0, 0x32, 0xf0, 0x39, 0x06, 0x7a, 0xa4, 0xb4, 0xbc, 0x0b, 0x48, 0x22, 0x57, 0x72, 0x9f, 0xf9, 0x2b, 0x66, 0xe5, 0xc0, 0xcd, @@ -439,7 +468,7 @@ mod test { // Pick a somewhat large buffer so we can test filling with the // remainder from `state.results`, directly filling the buffer, and // filling the remainder of the buffer. - let mut buffer = [0u8; 16*4*2]; + let mut buffer = [0u8; 16 * 4 * 2]; // Consume a value so that we have a remainder. assert!(rng.next_u64() == 0x04b4930a518251a4); rng.fill_bytes(&mut buffer); @@ -453,6 +482,7 @@ mod test { #[test] fn test_hc128_clone() { + #[rustfmt::skip] let seed = [0x55,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // key 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0]; // iv let mut rng1 = Hc128Rng::from_seed(seed); diff --git a/rand_hc/src/lib.rs b/rand_hc/src/lib.rs index c1ae665147b..995cb1d043d 100644 --- a/rand_hc/src/lib.rs +++ b/rand_hc/src/lib.rs @@ -8,16 +8,16 @@ //! The HC128 random number generator. -#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png", - html_favicon_url = "https://www.rust-lang.org/favicon.ico", - html_root_url = "https://rust-random.github.io/rand/")] - +#![doc( + html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png", + html_favicon_url = "https://www.rust-lang.org/favicon.ico", + html_root_url = "https://rust-random.github.io/rand/" +)] #![deny(missing_docs)] #![deny(missing_debug_implementations)] #![doc(test(attr(allow(unused_variables), deny(warnings))))] - #![no_std] mod hc128; -pub use hc128::{Hc128Rng, Hc128Core}; +pub use hc128::{Hc128Core, Hc128Rng}; diff --git a/rand_pcg/src/lib.rs b/rand_pcg/src/lib.rs index 22ba4a05d32..2ffa0b878f5 100644 --- a/rand_pcg/src/lib.rs +++ b/rand_pcg/src/lib.rs @@ -28,22 +28,19 @@ //! value-stable (i.e. any change affecting the output given a fixed seed would //! be considered a breaking change to the crate). -#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png", - html_favicon_url = "https://www.rust-lang.org/favicon.ico", - html_root_url = "https://rust-random.github.io/rand/")] - +#![doc( + html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png", + html_favicon_url = "https://www.rust-lang.org/favicon.ico", + html_root_url = "https://rust-random.github.io/rand/" +)] #![deny(missing_docs)] #![deny(missing_debug_implementations)] - #![allow(clippy::unreadable_literal)] - #![no_std] -mod pcg64; #[cfg(not(target_os = "emscripten"))] mod pcg128; +mod pcg64; -pub use self::pcg64::{Pcg32, Lcg64Xsh32}; -#[cfg(not(target_os = "emscripten"))] pub use self::pcg128::{ - Pcg64, Lcg128Xsl64, - Pcg64Mcg, Mcg128Xsl64, -}; +#[cfg(not(target_os = "emscripten"))] +pub use self::pcg128::{Lcg128Xsl64, Mcg128Xsl64, Pcg64, Pcg64Mcg}; +pub use self::pcg64::{Lcg64Xsh32, Pcg32}; diff --git a/rand_pcg/src/pcg128.rs b/rand_pcg/src/pcg128.rs index 8de9e20e01e..63f03b47cba 100644 --- a/rand_pcg/src/pcg128.rs +++ b/rand_pcg/src/pcg128.rs @@ -14,8 +14,8 @@ const MULTIPLIER: u128 = 0x2360_ED05_1FC6_5DA4_4385_DF64_9FCC_F645; use core::fmt; -use rand_core::{RngCore, SeedableRng, Error, le}; -#[cfg(feature="serde1")] use serde::{Serialize, Deserialize}; +use rand_core::{le, Error, RngCore, SeedableRng}; +#[cfg(feature = "serde1")] use serde::{Deserialize, Serialize}; /// A PCG random number generator (XSL RR 128/64 (LCG) variant). /// @@ -30,7 +30,7 @@ use rand_core::{RngCore, SeedableRng, Error, le}; /// comprising 128 bits of state and 128 bits stream selector. These are both /// set by `SeedableRng`, using a 256-bit seed. #[derive(Clone)] -#[cfg_attr(feature="serde1", derive(Serialize,Deserialize))] +#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] pub struct Lcg128Xsl64 { state: u128, increment: u128, @@ -64,7 +64,8 @@ impl Lcg128Xsl64 { #[inline] fn step(&mut self) { // prepare the LCG for the next round - self.state = self.state + self.state = self + .state .wrapping_mul(MULTIPLIER) .wrapping_add(self.increment); } @@ -130,7 +131,7 @@ impl RngCore for Lcg128Xsl64 { /// output function), this RNG is faster, also has a long cycle, and still has /// good performance on statistical tests. #[derive(Clone)] -#[cfg_attr(feature="serde1", derive(Serialize,Deserialize))] +#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] pub struct Mcg128Xsl64 { state: u128, } @@ -200,8 +201,8 @@ impl RngCore for Mcg128Xsl64 { fn output_xsl_rr(state: u128) -> u64 { // Output function XSL RR ("xorshift low (bits), random rotation") // Constants are for 128-bit state, 64-bit output - const XSHIFT: u32 = 64; // (128 - 64 + 64) / 2 - const ROTATE: u32 = 122; // 128 - 6 + const XSHIFT: u32 = 64; // (128 - 64 + 64) / 2 + const ROTATE: u32 = 122; // 128 - 6 let rot = (state >> ROTATE) as u32; let xsl = ((state >> XSHIFT) as u64) ^ (state as u64); @@ -212,7 +213,7 @@ fn output_xsl_rr(state: u128) -> u64 { fn fill_bytes_impl(rng: &mut R, dest: &mut [u8]) { let mut left = dest; while left.len() >= 8 { - let (l, r) = {left}.split_at_mut(8); + let (l, r) = { left }.split_at_mut(8); left = r; let chunk: [u8; 8] = rng.next_u64().to_le_bytes(); l.copy_from_slice(&chunk); diff --git a/rand_pcg/src/pcg64.rs b/rand_pcg/src/pcg64.rs index 39231d3c4f6..ad7dee2f77d 100644 --- a/rand_pcg/src/pcg64.rs +++ b/rand_pcg/src/pcg64.rs @@ -11,8 +11,8 @@ //! PCG random number generators use core::fmt; -use rand_core::{RngCore, SeedableRng, Error, le, impls}; -#[cfg(feature="serde1")] use serde::{Serialize, Deserialize}; +use rand_core::{impls, le, Error, RngCore, SeedableRng}; +#[cfg(feature = "serde1")] use serde::{Deserialize, Serialize}; // This is the default multiplier used by PCG for 64-bit state. const MULTIPLIER: u64 = 6364136223846793005; @@ -30,7 +30,7 @@ const MULTIPLIER: u64 = 6364136223846793005; /// comprising 64 bits of state and 64 bits stream selector. These are both set /// by `SeedableRng`, using a 128-bit seed. #[derive(Clone)] -#[cfg_attr(feature="serde1", derive(Serialize,Deserialize))] +#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] pub struct Lcg64Xsh32 { state: u64, increment: u64, @@ -65,7 +65,8 @@ impl Lcg64Xsh32 { #[inline] fn step(&mut self) { // prepare the LCG for the next round - self.state = self.state + self.state = self + .state .wrapping_mul(MULTIPLIER) .wrapping_add(self.increment); } @@ -102,7 +103,7 @@ impl RngCore for Lcg64Xsh32 { // Constants are for 64-bit state, 32-bit output const ROTATE: u32 = 59; // 64 - 5 const XSHIFT: u32 = 18; // (5 + 32) / 2 - const SPARE: u32 = 27; // 64 - 32 - 5 + const SPARE: u32 = 27; // 64 - 32 - 5 let rot = (state >> ROTATE) as u32; let xsh = (((state >> XSHIFT) ^ state) >> SPARE) as u32; diff --git a/rand_pcg/tests/lcg128xsl64.rs b/rand_pcg/tests/lcg128xsl64.rs index efc72fffd57..ac238b51623 100644 --- a/rand_pcg/tests/lcg128xsl64.rs +++ b/rand_pcg/tests/lcg128xsl64.rs @@ -4,6 +4,7 @@ use rand_pcg::{Lcg128Xsl64, Pcg64}; #[test] fn test_lcg128xsl64_construction() { // Test that various construction techniques produce a working RNG. + #[rustfmt::skip] let seed = [1,2,3,4, 5,6,7,8, 9,10,11,12, 13,14,15,16, 17,18,19,20, 21,22,23,24, 25,26,27,28, 29,30,31,32]; let mut rng1 = Lcg128Xsl64::from_seed(seed); @@ -26,17 +27,25 @@ fn test_lcg128xsl64_true_values() { let mut rng = Lcg128Xsl64::new(42, 54); let mut results = [0u64; 6]; - for i in results.iter_mut() { *i = rng.next_u64(); } - let expected: [u64; 6] = [0x86b1da1d72062b68, 0x1304aa46c9853d39, - 0xa3670e9e0dd50358, 0xf9090e529a7dae00, 0xc85b9fd837996f2c, 0x606121f8e3919196]; + for i in results.iter_mut() { + *i = rng.next_u64(); + } + let expected: [u64; 6] = [ + 0x86b1da1d72062b68, + 0x1304aa46c9853d39, + 0xa3670e9e0dd50358, + 0xf9090e529a7dae00, + 0xc85b9fd837996f2c, + 0x606121f8e3919196, + ]; assert_eq!(results, expected); } -#[cfg(feature="serde1")] +#[cfg(feature = "serde1")] #[test] fn test_lcg128xsl64_serde() { use bincode; - use std::io::{BufWriter, BufReader}; + use std::io::{BufReader, BufWriter}; let mut rng = Lcg128Xsl64::seed_from_u64(0); @@ -46,8 +55,8 @@ fn test_lcg128xsl64_serde() { let buf = buf.into_inner().unwrap(); let mut read = BufReader::new(&buf[..]); - let mut deserialized: Lcg128Xsl64 = bincode::deserialize_from(&mut read) - .expect("Could not deserialize"); + let mut deserialized: Lcg128Xsl64 = + bincode::deserialize_from(&mut read).expect("Could not deserialize"); for _ in 0..16 { assert_eq!(rng.next_u64(), deserialized.next_u64()); diff --git a/rand_pcg/tests/lcg64xsh32.rs b/rand_pcg/tests/lcg64xsh32.rs index e05bcc1dfa3..24a06d32483 100644 --- a/rand_pcg/tests/lcg64xsh32.rs +++ b/rand_pcg/tests/lcg64xsh32.rs @@ -4,7 +4,7 @@ use rand_pcg::{Lcg64Xsh32, Pcg32}; #[test] fn test_lcg64xsh32_construction() { // Test that various construction techniques produce a working RNG. - let seed = [1,2,3,4, 5,6,7,8, 9,10,11,12, 13,14,15,16]; + let seed = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; let mut rng1 = Lcg64Xsh32::from_seed(seed); assert_eq!(rng1.next_u64(), 1204678643940597513); @@ -25,17 +25,20 @@ fn test_lcg64xsh32_true_values() { let mut rng = Lcg64Xsh32::new(42, 54); let mut results = [0u32; 6]; - for i in results.iter_mut() { *i = rng.next_u32(); } - let expected: [u32; 6] = [0xa15c02b7, 0x7b47f409, 0xba1d3330, - 0x83d2f293, 0xbfa4784b, 0xcbed606e]; + for i in results.iter_mut() { + *i = rng.next_u32(); + } + let expected: [u32; 6] = [ + 0xa15c02b7, 0x7b47f409, 0xba1d3330, 0x83d2f293, 0xbfa4784b, 0xcbed606e, + ]; assert_eq!(results, expected); } -#[cfg(feature="serde1")] +#[cfg(feature = "serde1")] #[test] fn test_lcg64xsh32_serde() { use bincode; - use std::io::{BufWriter, BufReader}; + use std::io::{BufReader, BufWriter}; let mut rng = Lcg64Xsh32::seed_from_u64(0); @@ -45,8 +48,8 @@ fn test_lcg64xsh32_serde() { let buf = buf.into_inner().unwrap(); let mut read = BufReader::new(&buf[..]); - let mut deserialized: Lcg64Xsh32 = bincode::deserialize_from(&mut read) - .expect("Could not deserialize"); + let mut deserialized: Lcg64Xsh32 = + bincode::deserialize_from(&mut read).expect("Could not deserialize"); for _ in 0..16 { assert_eq!(rng.next_u64(), deserialized.next_u64()); diff --git a/rand_pcg/tests/mcg128xsl64.rs b/rand_pcg/tests/mcg128xsl64.rs index d58fa752599..32f363f350f 100644 --- a/rand_pcg/tests/mcg128xsl64.rs +++ b/rand_pcg/tests/mcg128xsl64.rs @@ -4,7 +4,7 @@ use rand_pcg::{Mcg128Xsl64, Pcg64Mcg}; #[test] fn test_mcg128xsl64_construction() { // Test that various construction techniques produce a working RNG. - let seed = [1,2,3,4, 5,6,7,8, 9,10,11,12, 13,14,15,16]; + let seed = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; let mut rng1 = Mcg128Xsl64::from_seed(seed); assert_eq!(rng1.next_u64(), 7071994460355047496); @@ -25,17 +25,25 @@ fn test_mcg128xsl64_true_values() { let mut rng = Mcg128Xsl64::new(42); let mut results = [0u64; 6]; - for i in results.iter_mut() { *i = rng.next_u64(); } - let expected: [u64; 6] = [0x63b4a3a813ce700a, 0x382954200617ab24, - 0xa7fd85ae3fe950ce, 0xd715286aa2887737, 0x60c92fee2e59f32c, 0x84c4e96beff30017]; + for i in results.iter_mut() { + *i = rng.next_u64(); + } + let expected: [u64; 6] = [ + 0x63b4a3a813ce700a, + 0x382954200617ab24, + 0xa7fd85ae3fe950ce, + 0xd715286aa2887737, + 0x60c92fee2e59f32c, + 0x84c4e96beff30017, + ]; assert_eq!(results, expected); } -#[cfg(feature="serde1")] +#[cfg(feature = "serde1")] #[test] fn test_mcg128xsl64_serde() { use bincode; - use std::io::{BufWriter, BufReader}; + use std::io::{BufReader, BufWriter}; let mut rng = Mcg128Xsl64::seed_from_u64(0); @@ -45,8 +53,8 @@ fn test_mcg128xsl64_serde() { let buf = buf.into_inner().unwrap(); let mut read = BufReader::new(&buf[..]); - let mut deserialized: Mcg128Xsl64 = bincode::deserialize_from(&mut read) - .expect("Could not deserialize"); + let mut deserialized: Mcg128Xsl64 = + bincode::deserialize_from(&mut read).expect("Could not deserialize"); for _ in 0..16 { assert_eq!(rng.next_u64(), deserialized.next_u64()); diff --git a/rustfmt.toml b/rustfmt.toml index 6b2aba35178..6a2d9d48215 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -4,13 +4,14 @@ # 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" +use_small_heuristics = "Default" +# TODO: single line functions only where short, please? +# https://github.com/rust-lang/rustfmt/issues/3358 fn_single_line = false +fn_args_layout = "Compressed" overflow_delimited_expr = true where_single_line = true @@ -21,6 +22,7 @@ where_single_line = true edition = "2018" # we require compatibility back to 1.32.0 # Misc: +inline_attribute_width = 80 blank_lines_upper_bound = 2 reorder_impl_items = true # report_todo = "Unnumbered" diff --git a/src/distributions/bernoulli.rs b/src/distributions/bernoulli.rs index 024233a53b2..a1fa86e14d4 100644 --- a/src/distributions/bernoulli.rs +++ b/src/distributions/bernoulli.rs @@ -8,8 +8,8 @@ //! The Bernoulli distribution. -use crate::Rng; use crate::distributions::Distribution; +use crate::Rng; use core::{fmt, u64}; /// The Bernoulli distribution. @@ -94,10 +94,14 @@ impl Bernoulli { #[inline] pub fn new(p: f64) -> Result { if !(p >= 0.0 && p < 1.0) { - if p == 1.0 { return Ok(Bernoulli { p_int: ALWAYS_TRUE }) } + if p == 1.0 { + return Ok(Bernoulli { p_int: ALWAYS_TRUE }); + } return Err(BernoulliError::InvalidProbability); } - Ok(Bernoulli { p_int: (p * SCALE) as u64 }) + Ok(Bernoulli { + p_int: (p * SCALE) as u64, + }) } /// Construct a new `Bernoulli` with the probability of success of @@ -114,7 +118,7 @@ impl Bernoulli { return Err(BernoulliError::InvalidProbability); } if numerator == denominator { - return Ok(Bernoulli { p_int: ALWAYS_TRUE }) + return Ok(Bernoulli { p_int: ALWAYS_TRUE }); } let p_int = ((f64::from(numerator) / f64::from(denominator)) * SCALE) as u64; Ok(Bernoulli { p_int }) @@ -125,7 +129,9 @@ impl Distribution for Bernoulli { #[inline] fn sample(&self, rng: &mut R) -> bool { // Make sure to always return true for p = 1.0. - if self.p_int == ALWAYS_TRUE { return true; } + if self.p_int == ALWAYS_TRUE { + return true; + } let v: u64 = rng.gen(); v < self.p_int } @@ -133,9 +139,9 @@ impl Distribution for Bernoulli { #[cfg(test)] mod test { - use crate::Rng; - use crate::distributions::Distribution; use super::Bernoulli; + use crate::distributions::Distribution; + use crate::Rng; #[test] fn test_trivial() { @@ -175,9 +181,9 @@ mod test { assert!((avg1 - P).abs() < 5e-3); let avg2 = (sum2 as f64) / (N as f64); - assert!((avg2 - (NUM as f64)/(DENOM as f64)).abs() < 5e-3); + assert!((avg2 - (NUM as f64) / (DENOM as f64)).abs() < 5e-3); } - + #[test] fn value_stability() { let mut rng = crate::test::rng(3); @@ -186,6 +192,8 @@ mod test { for x in &mut buf { *x = rng.sample(&distr); } - assert_eq!(buf, [true, false, false, true, false, false, true, true, true, true]); + assert_eq!(buf, [ + true, false, false, true, false, false, true, true, true, true + ]); } } diff --git a/src/distributions/binomial.rs b/src/distributions/binomial.rs index 310b9dfb94d..c096e4a8629 100644 --- a/src/distributions/binomial.rs +++ b/src/distributions/binomial.rs @@ -11,14 +11,14 @@ #![allow(deprecated)] #![allow(clippy::all)] -use crate::Rng; use crate::distributions::{Distribution, Uniform}; +use crate::Rng; /// The binomial distribution `Binomial(n, p)`. /// /// This distribution has density function: /// `f(k) = n!/(k! (n-k)!) p^k (1-p)^(n-k)` for `k >= 0`. -#[deprecated(since="0.7.0", note="moved to rand_distr crate")] +#[deprecated(since = "0.7.0", note = "moved to rand_distr crate")] #[derive(Clone, Copy, Debug)] pub struct Binomial { /// Number of trials. @@ -58,11 +58,7 @@ impl Distribution for Binomial { // The binomial distribution is symmetrical with respect to p -> 1-p, // k -> n-k switch p so that it is less than 0.5 - this allows for lower // expected values we will just invert the result at the end - let p = if self.p <= 0.5 { - self.p - } else { - 1.0 - self.p - }; + let p = if self.p <= 0.5 { self.p } else { 1.0 - self.p }; let result; let q = 1. - p; @@ -79,8 +75,7 @@ impl Distribution for Binomial { // Ranlib uses 30, and GSL uses 14. const BINV_THRESHOLD: f64 = 10.; - if (self.n as f64) * p < BINV_THRESHOLD && - self.n <= (::std::i32::MAX as u64) { + if (self.n as f64) * p < BINV_THRESHOLD && self.n <= (::std::i32::MAX as u64) { // Use the BINV algorithm. let s = p / q; let a = ((self.n + 1) as f64) * s; @@ -212,8 +207,8 @@ impl Distribution for Binomial { // Step 5.2: Squeezing. Check the value of ln(v) againts upper and // lower bound of ln(f(y)). let k = k as f64; - let rho = (k / npq) * ((k * (k / 3. + 0.625) + 1./6.) / npq + 0.5); - let t = -0.5 * k*k / npq; + let rho = (k / npq) * ((k * (k / 3. + 0.625) + 1. / 6.) / npq + 0.5); + let t = -0.5 * k * k / npq; let alpha = v.ln(); if alpha < t - rho { break; @@ -233,15 +228,19 @@ impl Distribution for Binomial { (13860. - (462. - (132. - (99. - 140. / a2) / a2) / a2) / a2) / a / 166320. } - if alpha > x_m * (f1 / x1).ln() - + (n - (m as f64) + 0.5) * (z / w).ln() - + ((y - m) as f64) * (w * p / (x1 * q)).ln() - // We use the signs from the GSL implementation, which are - // different than the ones in the reference. According to - // the GSL authors, the new signs were verified to be - // correct by one of the original designers of the - // algorithm. - + stirling(f1) + stirling(z) - stirling(x1) - stirling(w) + if alpha + > x_m * (f1 / x1).ln() + + (n - (m as f64) + 0.5) * (z / w).ln() + + ((y - m) as f64) * (w * p / (x1 * q)).ln() + // We use the signs from the GSL implementation, which are + // different than the ones in the reference. According to + // the GSL authors, the new signs were verified to be + // correct by one of the original designers of the + // algorithm. + + stirling(f1) + + stirling(z) + - stirling(x1) + - stirling(w) { continue; } @@ -263,9 +262,9 @@ impl Distribution for Binomial { #[cfg(test)] mod test { - use crate::Rng; - use crate::distributions::Distribution; use super::Binomial; + use crate::distributions::Distribution; + use crate::Rng; fn test_binomial_mean_and_variance(n: u64, p: f64, rng: &mut R) { let binomial = Binomial::new(n, p); @@ -274,17 +273,26 @@ mod test { let expected_variance = n as f64 * p * (1.0 - p); let mut results = [0.0; 1000]; - for i in results.iter_mut() { *i = binomial.sample(rng) as f64; } + for i in results.iter_mut() { + *i = binomial.sample(rng) as f64; + } let mean = results.iter().sum::() / results.len() as f64; - assert!((mean as f64 - expected_mean).abs() < expected_mean / 50.0, - "mean: {}, expected_mean: {}", mean, expected_mean); + assert!( + (mean as f64 - expected_mean).abs() < expected_mean / 50.0, + "mean: {}, expected_mean: {}", + mean, + expected_mean + ); let variance = - results.iter().map(|x| (x - mean) * (x - mean)).sum::() - / results.len() as f64; - assert!((variance - expected_variance).abs() < expected_variance / 10.0, - "variance: {}, expected_variance: {}", variance, expected_variance); + results.iter().map(|x| (x - mean) * (x - mean)).sum::() / results.len() as f64; + assert!( + (variance - expected_variance).abs() < expected_variance / 10.0, + "variance: {}, expected_variance: {}", + variance, + expected_variance + ); } #[test] diff --git a/src/distributions/cauchy.rs b/src/distributions/cauchy.rs index 8f30fcc0419..dc54c98a35b 100644 --- a/src/distributions/cauchy.rs +++ b/src/distributions/cauchy.rs @@ -11,19 +11,19 @@ #![allow(deprecated)] #![allow(clippy::all)] -use crate::Rng; use crate::distributions::Distribution; +use crate::Rng; use std::f64::consts::PI; /// The Cauchy distribution `Cauchy(median, scale)`. /// /// This distribution has a density function: /// `f(x) = 1 / (pi * scale * (1 + ((x - median) / scale)^2))` -#[deprecated(since="0.7.0", note="moved to rand_distr crate")] +#[deprecated(since = "0.7.0", note = "moved to rand_distr crate")] #[derive(Clone, Copy, Debug)] pub struct Cauchy { median: f64, - scale: f64 + scale: f64, } impl Cauchy { @@ -32,10 +32,7 @@ impl Cauchy { /// Panics if `scale <= 0`. pub fn new(median: f64, scale: f64) -> Cauchy { assert!(scale > 0.0, "Cauchy::new called with scale factor <= 0"); - Cauchy { - median, - scale - } + Cauchy { median, scale } } } @@ -54,8 +51,8 @@ impl Distribution for Cauchy { #[cfg(test)] mod test { - use crate::distributions::Distribution; use super::Cauchy; + use crate::distributions::Distribution; fn median(mut numbers: &mut [f64]) -> f64 { sort(&mut numbers); diff --git a/src/distributions/dirichlet.rs b/src/distributions/dirichlet.rs index 1ce01fdd0f2..a75678a8504 100644 --- a/src/distributions/dirichlet.rs +++ b/src/distributions/dirichlet.rs @@ -11,16 +11,16 @@ #![allow(deprecated)] #![allow(clippy::all)] -use crate::Rng; -use crate::distributions::Distribution; use crate::distributions::gamma::Gamma; +use crate::distributions::Distribution; +use crate::Rng; /// The dirichelet distribution `Dirichlet(alpha)`. /// /// The Dirichlet distribution is a family of continuous multivariate /// probability distributions parameterized by a vector alpha of positive reals. /// It is a multivariate generalization of the beta distribution. -#[deprecated(since="0.7.0", note="moved to rand_distr crate")] +#[deprecated(since = "0.7.0", note = "moved to rand_distr crate")] #[derive(Clone, Debug)] pub struct Dirichlet { /// Concentration parameters (alpha) @@ -32,7 +32,6 @@ impl Dirichlet { /// /// # Panics /// - if `alpha.len() < 2` - /// #[inline] pub fn new>>(alpha: V) -> Dirichlet { let a = alpha.into(); @@ -49,7 +48,6 @@ impl Dirichlet { /// # Panics /// - if `alpha <= 0.0` /// - if `size < 2` - /// #[inline] pub fn new_with_param(alpha: f64, size: usize) -> Dirichlet { assert!(alpha > 0.0); diff --git a/src/distributions/exponential.rs b/src/distributions/exponential.rs index 0278248a708..5fdf7aa74fb 100644 --- a/src/distributions/exponential.rs +++ b/src/distributions/exponential.rs @@ -10,9 +10,9 @@ //! The exponential distribution. #![allow(deprecated)] -use crate::{Rng}; -use crate::distributions::{ziggurat_tables, Distribution}; use crate::distributions::utils::ziggurat; +use crate::distributions::{ziggurat_tables, Distribution}; +use crate::Rng; /// Samples floating-point numbers according to the exponential distribution, /// with rate parameter `λ = 1`. This is equivalent to `Exp::new(1.0)` or @@ -28,7 +28,7 @@ use crate::distributions::utils::ziggurat; /// Generate Normal Random Samples*]( /// https://www.doornik.com/research/ziggurat.pdf). /// Nuffield College, Oxford -#[deprecated(since="0.7.0", note="moved to rand_distr crate")] +#[deprecated(since = "0.7.0", note = "moved to rand_distr crate")] #[derive(Clone, Copy, Debug)] pub struct Exp1; @@ -45,10 +45,14 @@ impl Distribution for Exp1 { ziggurat_tables::ZIG_EXP_R - rng.gen::().ln() } - ziggurat(rng, false, - &ziggurat_tables::ZIG_EXP_X, - &ziggurat_tables::ZIG_EXP_F, - pdf, zero_case) + ziggurat( + rng, + false, + &ziggurat_tables::ZIG_EXP_X, + &ziggurat_tables::ZIG_EXP_F, + pdf, + zero_case, + ) } } @@ -56,13 +60,13 @@ impl Distribution for Exp1 { /// /// This distribution has density function: `f(x) = lambda * exp(-lambda * x)` /// for `x > 0`. -/// +/// /// Note that [`Exp1`](crate::distributions::Exp1) is an optimised implementation for `lambda = 1`. -#[deprecated(since="0.7.0", note="moved to rand_distr crate")] +#[deprecated(since = "0.7.0", note = "moved to rand_distr crate")] #[derive(Clone, Copy, Debug)] pub struct Exp { /// `lambda` stored as `1/lambda`, since this is what we scale by. - lambda_inverse: f64 + lambda_inverse: f64, } impl Exp { @@ -71,7 +75,9 @@ impl Exp { #[inline] pub fn new(lambda: f64) -> Exp { assert!(lambda > 0.0, "Exp::new called with `lambda` <= 0"); - Exp { lambda_inverse: 1.0 / lambda } + Exp { + lambda_inverse: 1.0 / lambda, + } } } @@ -84,8 +90,8 @@ impl Distribution for Exp { #[cfg(test)] mod test { - use crate::distributions::Distribution; use super::Exp; + use crate::distributions::Distribution; #[test] fn test_exp() { diff --git a/src/distributions/float.rs b/src/distributions/float.rs index 3f36a5822b5..0a45f397743 100644 --- a/src/distributions/float.rs +++ b/src/distributions/float.rs @@ -8,12 +8,11 @@ //! Basic floating-point number distributions -use core::mem; -use crate::Rng; -use crate::distributions::{Distribution, Standard}; use crate::distributions::utils::FloatSIMDUtils; -#[cfg(feature="simd_support")] -use packed_simd::*; +use crate::distributions::{Distribution, Standard}; +use crate::Rng; +use core::mem; +#[cfg(feature = "simd_support")] use packed_simd::*; /// A distribution to sample floating point numbers uniformly in the half-open /// interval `(0, 1]`, i.e. including 1 but not 0. @@ -149,20 +148,20 @@ macro_rules! float_impls { float_impls! { f32, u32, f32, u32, 23, 127 } float_impls! { f64, u64, f64, u64, 52, 1023 } -#[cfg(feature="simd_support")] +#[cfg(feature = "simd_support")] float_impls! { f32x2, u32x2, f32, u32, 23, 127 } -#[cfg(feature="simd_support")] +#[cfg(feature = "simd_support")] float_impls! { f32x4, u32x4, f32, u32, 23, 127 } -#[cfg(feature="simd_support")] +#[cfg(feature = "simd_support")] float_impls! { f32x8, u32x8, f32, u32, 23, 127 } -#[cfg(feature="simd_support")] +#[cfg(feature = "simd_support")] float_impls! { f32x16, u32x16, f32, u32, 23, 127 } -#[cfg(feature="simd_support")] +#[cfg(feature = "simd_support")] float_impls! { f64x2, u64x2, f64, u64, 52, 1023 } -#[cfg(feature="simd_support")] +#[cfg(feature = "simd_support")] float_impls! { f64x4, u64x4, f64, u64, 52, 1023 } -#[cfg(feature="simd_support")] +#[cfg(feature = "simd_support")] float_impls! { f64x8, u64x8, f64, u64, 52, 1023 } @@ -188,8 +187,7 @@ mod tests { // OpenClosed01 let mut zeros = StepRng::new(0, 0); - assert_eq!(zeros.sample::<$ty, _>(OpenClosed01), - 0.0 + $EPSILON / 2.0); + assert_eq!(zeros.sample::<$ty, _>(OpenClosed01), 0.0 + $EPSILON / 2.0); let mut one = StepRng::new(1 << 8 | 1 << (8 + 32), 0); assert_eq!(one.sample::<$ty, _>(OpenClosed01), $EPSILON); let mut max = StepRng::new(!0, 0); @@ -203,16 +201,16 @@ mod tests { let mut max = StepRng::new(!0, 0); assert_eq!(max.sample::<$ty, _>(Open01), 1.0 - $EPSILON / 2.0); } - } + }; } test_f32! { f32_edge_cases, f32, 0.0, EPSILON32 } - #[cfg(feature="simd_support")] + #[cfg(feature = "simd_support")] test_f32! { f32x2_edge_cases, f32x2, f32x2::splat(0.0), f32x2::splat(EPSILON32) } - #[cfg(feature="simd_support")] + #[cfg(feature = "simd_support")] test_f32! { f32x4_edge_cases, f32x4, f32x4::splat(0.0), f32x4::splat(EPSILON32) } - #[cfg(feature="simd_support")] + #[cfg(feature = "simd_support")] test_f32! { f32x8_edge_cases, f32x8, f32x8::splat(0.0), f32x8::splat(EPSILON32) } - #[cfg(feature="simd_support")] + #[cfg(feature = "simd_support")] test_f32! { f32x16_edge_cases, f32x16, f32x16::splat(0.0), f32x16::splat(EPSILON32) } macro_rules! test_f64 { @@ -229,8 +227,7 @@ mod tests { // OpenClosed01 let mut zeros = StepRng::new(0, 0); - assert_eq!(zeros.sample::<$ty, _>(OpenClosed01), - 0.0 + $EPSILON / 2.0); + assert_eq!(zeros.sample::<$ty, _>(OpenClosed01), 0.0 + $EPSILON / 2.0); let mut one = StepRng::new(1 << 11, 0); assert_eq!(one.sample::<$ty, _>(OpenClosed01), $EPSILON); let mut max = StepRng::new(!0, 0); @@ -244,20 +241,20 @@ mod tests { let mut max = StepRng::new(!0, 0); assert_eq!(max.sample::<$ty, _>(Open01), 1.0 - $EPSILON / 2.0); } - } + }; } test_f64! { f64_edge_cases, f64, 0.0, EPSILON64 } - #[cfg(feature="simd_support")] + #[cfg(feature = "simd_support")] test_f64! { f64x2_edge_cases, f64x2, f64x2::splat(0.0), f64x2::splat(EPSILON64) } - #[cfg(feature="simd_support")] + #[cfg(feature = "simd_support")] test_f64! { f64x4_edge_cases, f64x4, f64x4::splat(0.0), f64x4::splat(EPSILON64) } - #[cfg(feature="simd_support")] + #[cfg(feature = "simd_support")] test_f64! { f64x8_edge_cases, f64x8, f64x8::splat(0.0), f64x8::splat(EPSILON64) } - + #[test] fn value_stability() { fn test_samples>( - distr: &D, zero: T, expected: &[T] + distr: &D, zero: T, expected: &[T], ) { let mut rng = crate::test::rng(0x6f44f5646c2a7334); let mut buf = [zero; 3]; @@ -266,33 +263,45 @@ mod tests { } assert_eq!(&buf, expected); } - + test_samples(&Standard, 0f32, &[0.0035963655, 0.7346052, 0.09778172]); - test_samples(&Standard, 0f64, &[0.7346051961657583, - 0.20298547462974248, 0.8166436635290655]); - + test_samples(&Standard, 0f64, &[ + 0.7346051961657583, + 0.20298547462974248, + 0.8166436635290655, + ]); + test_samples(&OpenClosed01, 0f32, &[0.003596425, 0.73460525, 0.09778178]); - test_samples(&OpenClosed01, 0f64, &[0.7346051961657584, - 0.2029854746297426, 0.8166436635290656]); - + test_samples(&OpenClosed01, 0f64, &[ + 0.7346051961657584, + 0.2029854746297426, + 0.8166436635290656, + ]); + test_samples(&Open01, 0f32, &[0.0035963655, 0.73460525, 0.09778172]); - test_samples(&Open01, 0f64, &[0.7346051961657584, - 0.20298547462974248, 0.8166436635290656]); - - #[cfg(feature="simd_support")] { + test_samples(&Open01, 0f64, &[ + 0.7346051961657584, + 0.20298547462974248, + 0.8166436635290656, + ]); + + #[cfg(feature = "simd_support")] + { // We only test a sub-set of types here. Values are identical to // non-SIMD types; we assume this pattern continues across all // SIMD types. - + test_samples(&Standard, f32x2::new(0.0, 0.0), &[ - f32x2::new(0.0035963655, 0.7346052), - f32x2::new(0.09778172, 0.20298547), - f32x2::new(0.34296435, 0.81664366)]); - + f32x2::new(0.0035963655, 0.7346052), + f32x2::new(0.09778172, 0.20298547), + f32x2::new(0.34296435, 0.81664366), + ]); + test_samples(&Standard, f64x2::new(0.0, 0.0), &[ - f64x2::new(0.7346051961657583, 0.20298547462974248), - f64x2::new(0.8166436635290655, 0.7423708925400552), - f64x2::new(0.16387782224016323, 0.9087068770169618)]); + f64x2::new(0.7346051961657583, 0.20298547462974248), + f64x2::new(0.8166436635290655, 0.7423708925400552), + f64x2::new(0.16387782224016323, 0.9087068770169618), + ]); } } } diff --git a/src/distributions/gamma.rs b/src/distributions/gamma.rs index b5a97f52fad..f19738dbe8e 100644 --- a/src/distributions/gamma.rs +++ b/src/distributions/gamma.rs @@ -10,12 +10,12 @@ //! The Gamma and derived distributions. #![allow(deprecated)] -use self::GammaRepr::*; use self::ChiSquaredRepr::*; +use self::GammaRepr::*; -use crate::Rng; use crate::distributions::normal::StandardNormal; use crate::distributions::{Distribution, Exp, Open01}; +use crate::Rng; /// The Gamma distribution `Gamma(shape, scale)` distribution. /// @@ -37,7 +37,7 @@ use crate::distributions::{Distribution, Exp, Open01}; /// Generating Gamma Variables" *ACM Trans. Math. Softw.* 26, 3 /// (September 2000), 363-372. /// DOI:[10.1145/358407.358414](https://doi.acm.org/10.1145/358407.358414) -#[deprecated(since="0.7.0", note="moved to rand_distr crate")] +#[deprecated(since = "0.7.0", note = "moved to rand_distr crate")] #[derive(Clone, Copy, Debug)] pub struct Gamma { repr: GammaRepr, @@ -47,7 +47,7 @@ pub struct Gamma { enum GammaRepr { Large(GammaLargeShape), One(Exp), - Small(GammaSmallShape) + Small(GammaSmallShape), } // These two helpers could be made public, but saving the @@ -67,7 +67,7 @@ enum GammaRepr { #[derive(Clone, Copy, Debug)] struct GammaSmallShape { inv_shape: f64, - large_shape: GammaLargeShape + large_shape: GammaLargeShape, } /// Gamma distribution where the shape parameter is larger than 1. @@ -78,7 +78,7 @@ struct GammaSmallShape { struct GammaLargeShape { scale: f64, c: f64, - d: f64 + d: f64, } impl Gamma { @@ -106,7 +106,7 @@ impl GammaSmallShape { fn new_raw(shape: f64, scale: f64) -> GammaSmallShape { GammaSmallShape { inv_shape: 1. / shape, - large_shape: GammaLargeShape::new_raw(shape + 1.0, scale) + large_shape: GammaLargeShape::new_raw(shape + 1.0, scale), } } } @@ -117,7 +117,7 @@ impl GammaLargeShape { GammaLargeShape { scale, c: 1. / (9. * d).sqrt(), - d + d, } } } @@ -143,17 +143,19 @@ impl Distribution for GammaLargeShape { loop { let x = rng.sample(StandardNormal); let v_cbrt = 1.0 + self.c * x; - if v_cbrt <= 0.0 { // a^3 <= 0 iff a <= 0 - continue + if v_cbrt <= 0.0 { + // a^3 <= 0 iff a <= 0 + continue; } let v = v_cbrt * v_cbrt * v_cbrt; let u: f64 = rng.sample(Open01); let x_sqr = x * x; - if u < 1.0 - 0.0331 * x_sqr * x_sqr || - u.ln() < 0.5 * x_sqr + self.d * (1.0 - v + v.ln()) { - return self.d * v * self.scale + if u < 1.0 - 0.0331 * x_sqr * x_sqr + || u.ln() < 0.5 * x_sqr + self.d * (1.0 - v + v.ln()) + { + return self.d * v * self.scale; } } } @@ -166,7 +168,7 @@ impl Distribution for GammaLargeShape { /// of `k` independent standard normal random variables. For other /// `k`, this uses the equivalent characterisation /// `χ²(k) = Gamma(k/2, 2)`. -#[deprecated(since="0.7.0", note="moved to rand_distr crate")] +#[deprecated(since = "0.7.0", note = "moved to rand_distr crate")] #[derive(Clone, Copy, Debug)] pub struct ChiSquared { repr: ChiSquaredRepr, @@ -202,7 +204,7 @@ impl Distribution for ChiSquared { let norm = rng.sample(StandardNormal); norm * norm } - DoFAnythingElse(ref g) => g.sample(rng) + DoFAnythingElse(ref g) => g.sample(rng), } } } @@ -212,7 +214,7 @@ impl Distribution for ChiSquared { /// This distribution is equivalent to the ratio of two normalised /// chi-squared distributions, that is, `F(m,n) = (χ²(m)/m) / /// (χ²(n)/n)`. -#[deprecated(since="0.7.0", note="moved to rand_distr crate")] +#[deprecated(since = "0.7.0", note = "moved to rand_distr crate")] #[derive(Clone, Copy, Debug)] pub struct FisherF { numer: ChiSquared, @@ -232,7 +234,7 @@ impl FisherF { FisherF { numer: ChiSquared::new(m), denom: ChiSquared::new(n), - dof_ratio: n / m + dof_ratio: n / m, } } } @@ -244,11 +246,11 @@ impl Distribution for FisherF { /// The Student t distribution, `t(nu)`, where `nu` is the degrees of /// freedom. -#[deprecated(since="0.7.0", note="moved to rand_distr crate")] +#[deprecated(since = "0.7.0", note = "moved to rand_distr crate")] #[derive(Clone, Copy, Debug)] pub struct StudentT { chi: ChiSquared, - dof: f64 + dof: f64, } impl StudentT { @@ -258,7 +260,7 @@ impl StudentT { assert!(n > 0.0, "StudentT::new called with `n <= 0`"); StudentT { chi: ChiSquared::new(n), - dof: n + dof: n, } } } @@ -270,7 +272,7 @@ impl Distribution for StudentT { } /// The Beta distribution with shape parameters `alpha` and `beta`. -#[deprecated(since="0.7.0", note="moved to rand_distr crate")] +#[deprecated(since = "0.7.0", note = "moved to rand_distr crate")] #[derive(Clone, Copy, Debug)] pub struct Beta { gamma_a: Gamma, @@ -301,8 +303,8 @@ impl Distribution for Beta { #[cfg(test)] mod test { + use super::{Beta, ChiSquared, FisherF, StudentT}; use crate::distributions::Distribution; - use super::{Beta, ChiSquared, StudentT, FisherF}; const N: u32 = 100; diff --git a/src/distributions/integer.rs b/src/distributions/integer.rs index 63cd3b9489b..f2db1f1c623 100644 --- a/src/distributions/integer.rs +++ b/src/distributions/integer.rs @@ -8,16 +8,14 @@ //! The implementations of the `Standard` distribution for integer types. -use crate::{Rng}; use crate::distributions::{Distribution, Standard}; -use core::num::{NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroUsize}; -#[cfg(not(target_os = "emscripten"))] use core::num::NonZeroU128; -#[cfg(feature="simd_support")] -use packed_simd::*; -#[cfg(all(target_arch = "x86", feature="nightly"))] -use core::arch::x86::*; -#[cfg(all(target_arch = "x86_64", feature="nightly"))] +use crate::Rng; +#[cfg(all(target_arch = "x86", feature = "nightly"))] use core::arch::x86::*; +#[cfg(all(target_arch = "x86_64", feature = "nightly"))] use core::arch::x86_64::*; +#[cfg(not(target_os = "emscripten"))] use core::num::NonZeroU128; +use core::num::{NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize}; +#[cfg(feature = "simd_support")] use packed_simd::*; impl Distribution for Standard { #[inline] @@ -80,14 +78,15 @@ macro_rules! impl_int_from_uint { rng.gen::<$uty>() as $ty } } - } + }; } impl_int_from_uint! { i8, u8 } impl_int_from_uint! { i16, u16 } impl_int_from_uint! { i32, u32 } impl_int_from_uint! { i64, u64 } -#[cfg(not(target_os = "emscripten"))] impl_int_from_uint! { i128, u128 } +#[cfg(not(target_os = "emscripten"))] +impl_int_from_uint! { i128, u128 } impl_int_from_uint! { isize, usize } macro_rules! impl_nzint { @@ -101,17 +100,18 @@ macro_rules! impl_nzint { } } } - } + }; } impl_nzint!(NonZeroU8, NonZeroU8::new); impl_nzint!(NonZeroU16, NonZeroU16::new); impl_nzint!(NonZeroU32, NonZeroU32::new); impl_nzint!(NonZeroU64, NonZeroU64::new); -#[cfg(not(target_os = "emscripten"))] impl_nzint!(NonZeroU128, NonZeroU128::new); +#[cfg(not(target_os = "emscripten"))] +impl_nzint!(NonZeroU128, NonZeroU128::new); impl_nzint!(NonZeroUsize, NonZeroUsize::new); -#[cfg(feature="simd_support")] +#[cfg(feature = "simd_support")] macro_rules! simd_impl { ($(($intrinsic:ident, $vec:ty),)+) => {$( impl Distribution<$intrinsic> for Standard { @@ -141,29 +141,33 @@ macro_rules! simd_impl { }; } -#[cfg(feature="simd_support")] +#[cfg(feature = "simd_support")] simd_impl!(16, u8x2, i8x2,); -#[cfg(feature="simd_support")] +#[cfg(feature = "simd_support")] simd_impl!(32, u8x4, i8x4, u16x2, i16x2,); -#[cfg(feature="simd_support")] +#[cfg(feature = "simd_support")] simd_impl!(64, u8x8, i8x8, u16x4, i16x4, u32x2, i32x2,); -#[cfg(feature="simd_support")] +#[cfg(feature = "simd_support")] simd_impl!(128, u8x16, i8x16, u16x8, i16x8, u32x4, i32x4, u64x2, i64x2,); -#[cfg(feature="simd_support")] +#[cfg(feature = "simd_support")] simd_impl!(256, u8x32, i8x32, u16x16, i16x16, u32x8, i32x8, u64x4, i64x4,); -#[cfg(feature="simd_support")] +#[cfg(feature = "simd_support")] simd_impl!(512, u8x64, i8x64, u16x32, i16x32, u32x16, i32x16, u64x8, i64x8,); -#[cfg(all(feature="simd_support", feature="nightly", any(target_arch="x86", target_arch="x86_64")))] +#[cfg(all( + feature = "simd_support", + feature = "nightly", + any(target_arch = "x86", target_arch = "x86_64") +))] simd_impl!((__m64, u8x8), (__m128i, u8x16), (__m256i, u8x32),); #[cfg(test)] mod tests { use super::*; - + #[test] fn test_integers() { let mut rng = crate::test::rng(806); - + rng.sample::(Standard); rng.sample::(Standard); rng.sample::(Standard); @@ -171,7 +175,7 @@ mod tests { rng.sample::(Standard); #[cfg(not(target_os = "emscripten"))] rng.sample::(Standard); - + rng.sample::(Standard); rng.sample::(Standard); rng.sample::(Standard); @@ -180,14 +184,11 @@ mod tests { #[cfg(not(target_os = "emscripten"))] rng.sample::(Standard); } - + #[test] fn value_stability() { - fn test_samples( - zero: T, expected: &[T] - ) - where Standard: Distribution - { + fn test_samples(zero: T, expected: &[T]) + where Standard: Distribution { let mut rng = crate::test::rng(807); let mut buf = [zero; 3]; for x in &mut buf { @@ -195,49 +196,84 @@ mod tests { } assert_eq!(&buf, expected); } - + test_samples(0u8, &[9, 247, 111]); test_samples(0u16, &[32265, 42999, 38255]); test_samples(0u32, &[2220326409, 2575017975, 2018088303]); - test_samples(0u64, &[11059617991457472009, - 16096616328739788143, 1487364411147516184]); - test_samples(0u128, &[296930161868957086625409848350820761097, - 145644820879247630242265036535529306392, - 111087889832015897993126088499035356354]); + test_samples(0u64, &[ + 11059617991457472009, + 16096616328739788143, + 1487364411147516184, + ]); + test_samples(0u128, &[ + 296930161868957086625409848350820761097, + 145644820879247630242265036535529306392, + 111087889832015897993126088499035356354, + ]); #[cfg(any(target_pointer_width = "32", target_pointer_width = "16"))] test_samples(0usize, &[2220326409, 2575017975, 2018088303]); #[cfg(target_pointer_width = "64")] - test_samples(0usize, &[11059617991457472009, - 16096616328739788143, 1487364411147516184]); - + test_samples(0usize, &[ + 11059617991457472009, + 16096616328739788143, + 1487364411147516184, + ]); + test_samples(0i8, &[9, -9, 111]); // Skip further i* types: they are simple reinterpretation of u* samples - - #[cfg(feature="simd_support")] { + + #[cfg(feature = "simd_support")] + { // We only test a sub-set of types here and make assumptions about the rest. - - test_samples(u8x2::default(), &[u8x2::new(9, 126), - u8x2::new(247, 167), u8x2::new(111, 149)]); - test_samples(u8x4::default(), &[u8x4::new(9, 126, 87, 132), - u8x4::new(247, 167, 123, 153), u8x4::new(111, 149, 73, 120)]); + + test_samples(u8x2::default(), &[ + u8x2::new(9, 126), + u8x2::new(247, 167), + u8x2::new(111, 149), + ]); + test_samples(u8x4::default(), &[ + u8x4::new(9, 126, 87, 132), + u8x4::new(247, 167, 123, 153), + u8x4::new(111, 149, 73, 120), + ]); test_samples(u8x8::default(), &[ - u8x8::new(9, 126, 87, 132, 247, 167, 123, 153), - u8x8::new(111, 149, 73, 120, 68, 171, 98, 223), - u8x8::new(24, 121, 1, 50, 13, 46, 164, 20)]); - + u8x8::new(9, 126, 87, 132, 247, 167, 123, 153), + u8x8::new(111, 149, 73, 120, 68, 171, 98, 223), + u8x8::new(24, 121, 1, 50, 13, 46, 164, 20), + ]); + test_samples(i64x8::default(), &[ - i64x8::new(-7387126082252079607, -2350127744969763473, - 1487364411147516184, 7895421560427121838, - 602190064936008898, 6022086574635100741, - -5080089175222015595, -4066367846667249123), - i64x8::new(9180885022207963908, 3095981199532211089, - 6586075293021332726, 419343203796414657, - 3186951873057035255, 5287129228749947252, - 444726432079249540, -1587028029513790706), - i64x8::new(6075236523189346388, 1351763722368165432, - -6192309979959753740, -7697775502176768592, - -4482022114172078123, 7522501477800909500, - -1837258847956201231, -586926753024886735)]); + i64x8::new( + -7387126082252079607, + -2350127744969763473, + 1487364411147516184, + 7895421560427121838, + 602190064936008898, + 6022086574635100741, + -5080089175222015595, + -4066367846667249123, + ), + i64x8::new( + 9180885022207963908, + 3095981199532211089, + 6586075293021332726, + 419343203796414657, + 3186951873057035255, + 5287129228749947252, + 444726432079249540, + -1587028029513790706, + ), + i64x8::new( + 6075236523189346388, + 1351763722368165432, + -6192309979959753740, + -7697775502176768592, + -4482022114172078123, + 7522501477800909500, + -1837258847956201231, + -586926753024886735, + ), + ]); } } } diff --git a/src/distributions/mod.rs b/src/distributions/mod.rs index 7a1e7629aa0..4e1b1a6e3a0 100644 --- a/src/distributions/mod.rs +++ b/src/distributions/mod.rs @@ -41,7 +41,7 @@ //! with the [`random`] function. //! //! ## Random characters -//! +//! //! [`Alphanumeric`] is a simple distribution to sample random letters and //! numbers of the `char` type; in contrast [`Standard`] may sample any valid //! `char`. @@ -93,66 +93,79 @@ //! [`rand_distr`]: https://crates.io/crates/rand_distr //! [`statrs`]: https://crates.io/crates/statrs -use core::iter; use crate::Rng; +use core::iter; +pub use self::bernoulli::{Bernoulli, BernoulliError}; +pub use self::float::{Open01, OpenClosed01}; pub use self::other::Alphanumeric; #[doc(inline)] pub use self::uniform::Uniform; -pub use self::float::{OpenClosed01, Open01}; -pub use self::bernoulli::{Bernoulli, BernoulliError}; -#[cfg(feature="alloc")] pub use self::weighted::{WeightedIndex, WeightedError}; +#[cfg(feature = "alloc")] +pub use self::weighted::{WeightedError, WeightedIndex}; // The following are all deprecated after being moved to rand_distr #[allow(deprecated)] -#[cfg(feature="std")] pub use self::unit_sphere::UnitSphereSurface; +#[cfg(feature = "std")] +pub use self::binomial::Binomial; #[allow(deprecated)] -#[cfg(feature="std")] pub use self::unit_circle::UnitCircle; +#[cfg(feature = "std")] +pub use self::cauchy::Cauchy; #[allow(deprecated)] -#[cfg(feature="std")] pub use self::gamma::{Gamma, ChiSquared, FisherF, - StudentT, Beta}; +#[cfg(feature = "std")] +pub use self::dirichlet::Dirichlet; #[allow(deprecated)] -#[cfg(feature="std")] pub use self::normal::{Normal, LogNormal, StandardNormal}; +#[cfg(feature = "std")] +pub use self::exponential::{Exp, Exp1}; #[allow(deprecated)] -#[cfg(feature="std")] pub use self::exponential::{Exp, Exp1}; +#[cfg(feature = "std")] +pub use self::gamma::{Beta, ChiSquared, FisherF, Gamma, StudentT}; #[allow(deprecated)] -#[cfg(feature="std")] pub use self::pareto::Pareto; +#[cfg(feature = "std")] +pub use self::normal::{LogNormal, Normal, StandardNormal}; #[allow(deprecated)] -#[cfg(feature="std")] pub use self::poisson::Poisson; +#[cfg(feature = "std")] +pub use self::pareto::Pareto; #[allow(deprecated)] -#[cfg(feature="std")] pub use self::binomial::Binomial; +#[cfg(feature = "std")] +pub use self::poisson::Poisson; #[allow(deprecated)] -#[cfg(feature="std")] pub use self::cauchy::Cauchy; +#[cfg(feature = "std")] +pub use self::triangular::Triangular; #[allow(deprecated)] -#[cfg(feature="std")] pub use self::dirichlet::Dirichlet; +#[cfg(feature = "std")] +pub use self::unit_circle::UnitCircle; #[allow(deprecated)] -#[cfg(feature="std")] pub use self::triangular::Triangular; +#[cfg(feature = "std")] +pub use self::unit_sphere::UnitSphereSurface; #[allow(deprecated)] -#[cfg(feature="std")] pub use self::weibull::Weibull; +#[cfg(feature = "std")] +pub use self::weibull::Weibull; -pub mod uniform; mod bernoulli; -#[cfg(feature="alloc")] pub mod weighted; -#[cfg(feature="std")] mod unit_sphere; -#[cfg(feature="std")] mod unit_circle; -#[cfg(feature="std")] mod gamma; -#[cfg(feature="std")] mod normal; -#[cfg(feature="std")] mod exponential; -#[cfg(feature="std")] mod pareto; -#[cfg(feature="std")] mod poisson; -#[cfg(feature="std")] mod binomial; -#[cfg(feature="std")] mod cauchy; -#[cfg(feature="std")] mod dirichlet; -#[cfg(feature="std")] mod triangular; -#[cfg(feature="std")] mod weibull; +#[cfg(feature = "std")] mod binomial; +#[cfg(feature = "std")] mod cauchy; +#[cfg(feature = "std")] mod dirichlet; +#[cfg(feature = "std")] mod exponential; +#[cfg(feature = "std")] mod gamma; +#[cfg(feature = "std")] mod normal; +#[cfg(feature = "std")] mod pareto; +#[cfg(feature = "std")] mod poisson; +#[cfg(feature = "std")] mod triangular; +pub mod uniform; +#[cfg(feature = "std")] mod unit_circle; +#[cfg(feature = "std")] mod unit_sphere; +#[cfg(feature = "std")] mod weibull; +#[cfg(feature = "alloc")] pub mod weighted; mod float; -#[doc(hidden)] pub mod hidden_export { - pub use super::float::IntoFloat; // used by rand_distr +#[doc(hidden)] +pub mod hidden_export { + pub use super::float::IntoFloat; // used by rand_distr } mod integer; mod other; mod utils; -#[cfg(feature="std")] mod ziggurat_tables; +#[cfg(feature = "std")] mod ziggurat_tables; /// Types (distributions) that can be used to create a random instance of `T`. /// @@ -207,7 +220,9 @@ pub trait Distribution { /// } /// ``` fn sample_iter(self, rng: R) -> DistIter - where R: Rng, Self: Sized + where + R: Rng, + Self: Sized, { DistIter { distr: self, @@ -239,7 +254,9 @@ pub struct DistIter { } impl Iterator for DistIter - where D: Distribution, R: Rng +where + D: Distribution, + R: Rng, { type Item = T; @@ -257,11 +274,19 @@ impl Iterator for DistIter } impl iter::FusedIterator for DistIter - where D: Distribution, R: Rng {} +where + D: Distribution, + R: Rng, +{ +} #[cfg(features = "nightly")] impl iter::TrustedLen for DistIter - where D: Distribution, R: Rng {} +where + D: Distribution, + R: Rng, +{ +} /// A generic random value distribution, implemented for many primitive types. @@ -347,8 +372,8 @@ pub struct Standard; #[cfg(all(test, feature = "std"))] mod tests { - use crate::Rng; use super::{Distribution, Uniform}; + use crate::Rng; #[test] fn test_distributions_iter() { @@ -358,16 +383,18 @@ mod tests { let results: Vec = distr.sample_iter(&mut rng).take(100).collect(); println!("{:?}", results); } - + #[test] fn test_make_an_iter() { - fn ten_dice_rolls_other_than_five<'a, R: Rng>(rng: &'a mut R) -> impl Iterator + 'a { + fn ten_dice_rolls_other_than_five<'a, R: Rng>( + rng: &'a mut R, + ) -> impl Iterator + 'a { Uniform::new_inclusive(1, 6) .sample_iter(rng) .filter(|x| *x != 5) .take(10) } - + let mut rng = crate::test::rng(211); let mut count = 0; for val in ten_dice_rolls_other_than_five(&mut rng) { diff --git a/src/distributions/normal.rs b/src/distributions/normal.rs index 7808bafee83..ec62fa9abe9 100644 --- a/src/distributions/normal.rs +++ b/src/distributions/normal.rs @@ -10,9 +10,9 @@ //! The normal and derived distributions. #![allow(deprecated)] -use crate::Rng; -use crate::distributions::{ziggurat_tables, Distribution, Open01}; use crate::distributions::utils::ziggurat; +use crate::distributions::{ziggurat_tables, Distribution, Open01}; +use crate::Rng; /// Samples floating-point numbers according to the normal distribution /// `N(0, 1)` (a.k.a. a standard normal, or Gaussian). This is equivalent to @@ -26,7 +26,7 @@ use crate::distributions::utils::ziggurat; /// Generate Normal Random Samples*]( /// https://www.doornik.com/research/ziggurat.pdf). /// Nuffield College, Oxford -#[deprecated(since="0.7.0", note="moved to rand_distr crate")] +#[deprecated(since = "0.7.0", note = "moved to rand_distr crate")] #[derive(Clone, Copy, Debug)] pub struct StandardNormal; @@ -34,7 +34,7 @@ impl Distribution for StandardNormal { fn sample(&self, rng: &mut R) -> f64 { #[inline] fn pdf(x: f64) -> f64 { - (-x*x/2.0).exp() + (-x * x / 2.0).exp() } #[inline] fn zero_case(rng: &mut R, u: f64) -> f64 { @@ -55,13 +55,21 @@ impl Distribution for StandardNormal { y = y_.ln(); } - if u < 0.0 { x - ziggurat_tables::ZIG_NORM_R } else { ziggurat_tables::ZIG_NORM_R - x } + if u < 0.0 { + x - ziggurat_tables::ZIG_NORM_R + } else { + ziggurat_tables::ZIG_NORM_R - x + } } - ziggurat(rng, true, // this is symmetric - &ziggurat_tables::ZIG_NORM_X, - &ziggurat_tables::ZIG_NORM_F, - pdf, zero_case) + ziggurat( + rng, + true, // this is symmetric + &ziggurat_tables::ZIG_NORM_X, + &ziggurat_tables::ZIG_NORM_F, + pdf, + zero_case, + ) } } @@ -69,12 +77,12 @@ impl Distribution for StandardNormal { /// /// This uses the ZIGNOR variant of the Ziggurat method, see [`StandardNormal`] /// for more details. -/// +/// /// Note that [`StandardNormal`] is an optimised implementation for mean 0, and /// standard deviation 1. /// /// [`StandardNormal`]: crate::distributions::StandardNormal -#[deprecated(since="0.7.0", note="moved to rand_distr crate")] +#[deprecated(since = "0.7.0", note = "moved to rand_distr crate")] #[derive(Clone, Copy, Debug)] pub struct Normal { mean: f64, @@ -91,10 +99,7 @@ impl Normal { #[inline] pub fn new(mean: f64, std_dev: f64) -> Normal { assert!(std_dev >= 0.0, "Normal::new called with `std_dev` < 0"); - Normal { - mean, - std_dev - } + Normal { mean, std_dev } } } impl Distribution for Normal { @@ -109,10 +114,10 @@ impl Distribution for Normal { /// /// If `X` is log-normal distributed, then `ln(X)` is `N(mean, std_dev**2)` /// distributed. -#[deprecated(since="0.7.0", note="moved to rand_distr crate")] +#[deprecated(since = "0.7.0", note = "moved to rand_distr crate")] #[derive(Clone, Copy, Debug)] pub struct LogNormal { - norm: Normal + norm: Normal, } impl LogNormal { @@ -125,7 +130,9 @@ impl LogNormal { #[inline] pub fn new(mean: f64, std_dev: f64) -> LogNormal { assert!(std_dev >= 0.0, "LogNormal::new called with `std_dev` < 0"); - LogNormal { norm: Normal::new(mean, std_dev) } + LogNormal { + norm: Normal::new(mean, std_dev), + } } } impl Distribution for LogNormal { @@ -136,8 +143,8 @@ impl Distribution for LogNormal { #[cfg(test)] mod tests { + use super::{LogNormal, Normal}; use crate::distributions::Distribution; - use super::{Normal, LogNormal}; #[test] fn test_normal() { diff --git a/src/distributions/other.rs b/src/distributions/other.rs index 334b6f81a5b..c95060e5104 100644 --- a/src/distributions/other.rs +++ b/src/distributions/other.rs @@ -11,21 +11,21 @@ use core::char; use core::num::Wrapping; -use crate::Rng; use crate::distributions::{Distribution, Standard, Uniform}; +use crate::Rng; // ----- Sampling distributions ----- /// Sample a `char`, uniformly distributed over ASCII letters and numbers: /// a-z, A-Z and 0-9. -/// +/// /// # Example /// /// ``` /// use std::iter; /// use rand::{Rng, thread_rng}; /// use rand::distributions::Alphanumeric; -/// +/// /// let mut rng = thread_rng(); /// let chars: String = iter::repeat(()) /// .map(|()| rng.sample(Alphanumeric)) @@ -63,8 +63,7 @@ impl Distribution for Standard { impl Distribution for Alphanumeric { fn sample(&self, rng: &mut R) -> char { const RANGE: u32 = 26 + 26 + 10; - const GEN_ASCII_STR_CHARSET: &[u8] = - b"ABCDEFGHIJKLMNOPQRSTUVWXYZ\ + const GEN_ASCII_STR_CHARSET: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ\ abcdefghijklmnopqrstuvwxyz\ 0123456789"; // We can pick from 62 characters. This is so close to a power of 2, 64, @@ -74,7 +73,7 @@ impl Distribution for Alphanumeric { loop { let var = rng.next_u32() >> (32 - 6); if var < RANGE { - return GEN_ASCII_STR_CHARSET[var as usize] as char + return GEN_ASCII_STR_CHARSET[var as usize] as char; } } } @@ -118,20 +117,22 @@ macro_rules! tuple_impl { impl Distribution<()> for Standard { #[allow(clippy::unused_unit)] #[inline] - fn sample(&self, _: &mut R) -> () { () } + fn sample(&self, _: &mut R) -> () { + () + } } -tuple_impl!{A} -tuple_impl!{A, B} -tuple_impl!{A, B, C} -tuple_impl!{A, B, C, D} -tuple_impl!{A, B, C, D, E} -tuple_impl!{A, B, C, D, E, F} -tuple_impl!{A, B, C, D, E, F, G} -tuple_impl!{A, B, C, D, E, F, G, H} -tuple_impl!{A, B, C, D, E, F, G, H, I} -tuple_impl!{A, B, C, D, E, F, G, H, I, J} -tuple_impl!{A, B, C, D, E, F, G, H, I, J, K} -tuple_impl!{A, B, C, D, E, F, G, H, I, J, K, L} +tuple_impl! {A} +tuple_impl! {A, B} +tuple_impl! {A, B, C} +tuple_impl! {A, B, C, D} +tuple_impl! {A, B, C, D, E} +tuple_impl! {A, B, C, D, E, F} +tuple_impl! {A, B, C, D, E, F, G} +tuple_impl! {A, B, C, D, E, F, G, H} +tuple_impl! {A, B, C, D, E, F, G, H, I} +tuple_impl! {A, B, C, D, E, F, G, H, I, J} +tuple_impl! {A, B, C, D, E, F, G, H, I, J, K} +tuple_impl! {A, B, C, D, E, F, G, H, I, J, K, L} macro_rules! array_impl { // recursive, given at least one type parameter: @@ -153,9 +154,11 @@ macro_rules! array_impl { }; } -array_impl!{32, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,} +array_impl! {32, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,} -impl Distribution> for Standard where Standard: Distribution { +impl Distribution> for Standard +where Standard: Distribution +{ #[inline] fn sample(&self, rng: &mut R) -> Option { // UFCS is needed here: https://github.com/rust-lang/rust/issues/24066 @@ -167,7 +170,9 @@ impl Distribution> for Standard where Standard: Distribution { } } -impl Distribution> for Standard where Standard: Distribution { +impl Distribution> for Standard +where Standard: Distribution +{ #[inline] fn sample(&self, rng: &mut R) -> Wrapping { Wrapping(rng.gen()) @@ -179,17 +184,17 @@ impl Distribution> for Standard where Standard: Distribution { mod tests { use super::*; use crate::RngCore; - #[cfg(all(not(feature="std"), feature="alloc"))] use alloc::string::String; + #[cfg(all(not(feature = "std"), feature = "alloc"))] use alloc::string::String; #[test] fn test_misc() { let rng: &mut dyn RngCore = &mut crate::test::rng(820); - + rng.sample::(Standard); rng.sample::(Standard); } - - #[cfg(feature="alloc")] + + #[cfg(feature = "alloc")] #[test] fn test_chars() { use core::iter; @@ -198,7 +203,9 @@ mod tests { // Test by generating a relatively large number of chars, so we also // take the rejection sampling path. let word: String = iter::repeat(()) - .map(|()| rng.gen::()).take(1000).collect(); + .map(|()| rng.gen::()) + .take(1000) + .collect(); assert!(word.len() != 0); } @@ -217,11 +224,12 @@ mod tests { } assert!(incorrect == false); } - + #[test] fn value_stability() { fn test_samples>( - distr: &D, zero: T, expected: &[T]) { + distr: &D, zero: T, expected: &[T], + ) { let mut rng = crate::test::rng(807); let mut buf = [zero; 5]; for x in &mut buf { @@ -229,25 +237,55 @@ mod tests { } assert_eq!(&buf, expected); } - - test_samples(&Standard, 'a', &['\u{8cdac}', '\u{a346a}', '\u{80120}', '\u{ed692}', '\u{35888}']); + + test_samples(&Standard, 'a', &[ + '\u{8cdac}', + '\u{a346a}', + '\u{80120}', + '\u{ed692}', + '\u{35888}', + ]); test_samples(&Alphanumeric, 'a', &['h', 'm', 'e', '3', 'M']); test_samples(&Standard, false, &[true, true, false, true, false]); - test_samples(&Standard, None as Option, - &[Some(true), None, Some(false), None, Some(false)]); - test_samples(&Standard, Wrapping(0i32), &[Wrapping(-2074640887), - Wrapping(-1719949321), Wrapping(2018088303), - Wrapping(-547181756), Wrapping(838957336)]); - + test_samples(&Standard, None as Option, &[ + Some(true), + None, + Some(false), + None, + Some(false), + ]); + test_samples(&Standard, Wrapping(0i32), &[ + Wrapping(-2074640887), + Wrapping(-1719949321), + Wrapping(2018088303), + Wrapping(-547181756), + Wrapping(838957336), + ]); + // We test only sub-sets of tuple and array impls test_samples(&Standard, (), &[(), (), (), (), ()]); - test_samples(&Standard, (false,), &[(true,), (true,), (false,), (true,), (false,)]); - test_samples(&Standard, (false,false), &[(true,true), (false,true), - (false,false), (true,false), (false,false)]); - + test_samples(&Standard, (false,), &[ + (true,), + (true,), + (false,), + (true,), + (false,), + ]); + test_samples(&Standard, (false, false), &[ + (true, true), + (false, true), + (false, false), + (true, false), + (false, false), + ]); + test_samples(&Standard, [0u8; 0], &[[], [], [], [], []]); - test_samples(&Standard, [0u8; 3], &[[9, 247, 111], - [68, 24, 13], [174, 19, 194], - [172, 69, 213], [149, 207, 29]]); + test_samples(&Standard, [0u8; 3], &[ + [9, 247, 111], + [68, 24, 13], + [174, 19, 194], + [172, 69, 213], + [149, 207, 29], + ]); } } diff --git a/src/distributions/pareto.rs b/src/distributions/pareto.rs index edc91223295..ac5473b8c84 100644 --- a/src/distributions/pareto.rs +++ b/src/distributions/pareto.rs @@ -9,11 +9,11 @@ //! The Pareto distribution. #![allow(deprecated)] -use crate::Rng; use crate::distributions::{Distribution, OpenClosed01}; +use crate::Rng; /// Samples floating-point numbers according to the Pareto distribution -#[deprecated(since="0.7.0", note="moved to rand_distr crate")] +#[deprecated(since = "0.7.0", note = "moved to rand_distr crate")] #[derive(Clone, Copy, Debug)] pub struct Pareto { scale: f64, @@ -31,7 +31,10 @@ impl Pareto { /// `scale` and `shape` have to be non-zero and positive. pub fn new(scale: f64, shape: f64) -> Pareto { assert!((scale > 0.) & (shape > 0.)); - Pareto { scale, inv_neg_shape: -1.0 / shape } + Pareto { + scale, + inv_neg_shape: -1.0 / shape, + } } } @@ -44,8 +47,8 @@ impl Distribution for Pareto { #[cfg(test)] mod tests { - use crate::distributions::Distribution; use super::Pareto; + use crate::distributions::Distribution; #[test] #[should_panic] diff --git a/src/distributions/poisson.rs b/src/distributions/poisson.rs index 63d132bea68..ce94d7542b3 100644 --- a/src/distributions/poisson.rs +++ b/src/distributions/poisson.rs @@ -10,15 +10,15 @@ //! The Poisson distribution. #![allow(deprecated)] -use crate::Rng; -use crate::distributions::{Distribution, Cauchy}; use crate::distributions::utils::log_gamma; +use crate::distributions::{Cauchy, Distribution}; +use crate::Rng; /// The Poisson distribution `Poisson(lambda)`. /// /// This distribution has a density function: /// `f(k) = lambda^k * exp(-lambda) / k!` for `k >= 0`. -#[deprecated(since="0.7.0", note="moved to rand_distr crate")] +#[deprecated(since = "0.7.0", note = "moved to rand_distr crate")] #[derive(Clone, Copy, Debug)] pub struct Poisson { lambda: f64, @@ -90,7 +90,8 @@ impl Distribution for Poisson { // the magic value scales the distribution function to a range of approximately 0-1 // since it is not exact, we multiply the ratio by 0.9 to avoid ratios greater than 1 // this doesn't change the resulting distribution, only increases the rate of failed drawings - let check = 0.9 * (1.0 + comp_dev * comp_dev) + let check = 0.9 + * (1.0 + comp_dev * comp_dev) * (result * self.log_lambda - log_gamma(1.0 + result) - self.magic_val).exp(); // check with uniform random value - if below the threshold, we are within the target distribution @@ -105,8 +106,8 @@ impl Distribution for Poisson { #[cfg(test)] mod test { - use crate::distributions::Distribution; use super::Poisson; + use crate::distributions::Distribution; #[test] #[cfg_attr(miri, ignore)] // Miri is too slow diff --git a/src/distributions/triangular.rs b/src/distributions/triangular.rs index 3e8f8b03eff..37be19867e8 100644 --- a/src/distributions/triangular.rs +++ b/src/distributions/triangular.rs @@ -9,11 +9,11 @@ //! The triangular distribution. #![allow(deprecated)] -use crate::Rng; use crate::distributions::{Distribution, Standard}; +use crate::Rng; /// The triangular distribution. -#[deprecated(since="0.7.0", note="moved to rand_distr crate")] +#[deprecated(since = "0.7.0", note = "moved to rand_distr crate")] #[derive(Clone, Copy, Debug)] pub struct Triangular { min: f64, @@ -28,7 +28,6 @@ impl Triangular { /// # Panics /// /// If `max < mode`, `mode < max` or `max == min`. - /// #[inline] pub fn new(min: f64, max: f64, mode: f64) -> Triangular { assert!(max >= mode); @@ -54,14 +53,19 @@ impl Distribution for Triangular { #[cfg(test)] mod test { - use crate::distributions::Distribution; use super::Triangular; + use crate::distributions::Distribution; #[test] fn test_new() { for &(min, max, mode) in &[ - (-1., 1., 0.), (1., 2., 1.), (5., 25., 25.), (1e-5, 1e5, 1e-3), - (0., 1., 0.9), (-4., -0.5, -2.), (-13.039, 8.41, 1.17), + (-1., 1., 0.), + (1., 2., 1.), + (5., 25., 25.), + (1e-5, 1e5, 1e-3), + (0., 1., 0.9), + (-4., -0.5, -2.), + (-13.039, 8.41, 1.17), ] { println!("{} {} {}", min, max, mode); let _ = Triangular::new(min, max, mode); diff --git a/src/distributions/uniform.rs b/src/distributions/uniform.rs index c9eed587c3c..8584152f039 100644 --- a/src/distributions/uniform.rs +++ b/src/distributions/uniform.rs @@ -103,23 +103,20 @@ //! [`UniformDuration`]: crate::distributions::uniform::UniformDuration //! [`SampleBorrow::borrow`]: crate::distributions::uniform::SampleBorrow::borrow -#[cfg(feature = "std")] -use std::time::Duration; -#[cfg(not(feature = "std"))] -use core::time::Duration; +#[cfg(not(feature = "std"))] use core::time::Duration; +#[cfg(feature = "std")] use std::time::Duration; -use crate::Rng; -use crate::distributions::Distribution; use crate::distributions::float::IntoFloat; -use crate::distributions::utils::{WideningMultiply, FloatSIMDUtils, FloatAsSIMD, BoolAsSIMD}; +use crate::distributions::utils::{BoolAsSIMD, FloatAsSIMD, FloatSIMDUtils, WideningMultiply}; +use crate::distributions::Distribution; +use crate::Rng; #[cfg(not(feature = "std"))] #[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::*; /// Sample values uniformly between two bounds. /// @@ -168,8 +165,9 @@ impl Uniform { /// Create a new `Uniform` instance which samples uniformly from the half /// open range `[low, high)` (excluding `high`). Panics if `low >= high`. pub fn new(low: B1, high: B2) -> Uniform - where B1: SampleBorrow + Sized, - B2: SampleBorrow + Sized + where + B1: SampleBorrow + Sized, + B2: SampleBorrow + Sized, { Uniform(X::Sampler::new(low, high)) } @@ -177,8 +175,9 @@ impl Uniform { /// Create a new `Uniform` instance which samples uniformly from the closed /// range `[low, high]` (inclusive). Panics if `low > high`. pub fn new_inclusive(low: B1, high: B2) -> Uniform - where B1: SampleBorrow + Sized, - B2: SampleBorrow + Sized + where + B1: SampleBorrow + Sized, + B2: SampleBorrow + Sized, { Uniform(X::Sampler::new_inclusive(low, high)) } @@ -222,8 +221,9 @@ pub trait UniformSampler: Sized { /// Usually users should not call this directly but instead use /// `Uniform::new`, which asserts that `low < high` before calling this. fn new(low: B1, high: B2) -> Self - where B1: SampleBorrow + Sized, - B2: SampleBorrow + Sized; + where + B1: SampleBorrow + Sized, + B2: SampleBorrow + Sized; /// Construct self, with inclusive bounds `[low, high]`. /// @@ -231,8 +231,9 @@ pub trait UniformSampler: Sized { /// `Uniform::new_inclusive`, which asserts that `low <= high` before /// calling this. fn new_inclusive(low: B1, high: B2) -> Self - where B1: SampleBorrow + Sized, - B2: SampleBorrow + Sized; + where + B1: SampleBorrow + Sized, + B2: SampleBorrow + Sized; /// Sample a value. fn sample(&self, rng: &mut R) -> Self::X; @@ -256,10 +257,10 @@ pub trait UniformSampler: Sized { /// ::Sampler::sample_single(lb, ub, &mut rng) /// } /// ``` - fn sample_single(low: B1, high: B2, rng: &mut R) - -> Self::X - where B1: SampleBorrow + Sized, - B2: SampleBorrow + Sized + fn sample_single(low: B1, high: B2, rng: &mut R) -> Self::X + where + B1: SampleBorrow + Sized, + B2: SampleBorrow + Sized, { let uniform: Self = UniformSampler::new(low, high); uniform.sample(rng) @@ -289,13 +290,21 @@ pub trait SampleBorrow { /// [`Borrow::borrow`]: std::borrow::Borrow::borrow fn borrow(&self) -> &Borrowed; } -impl SampleBorrow for Borrowed where Borrowed: SampleUniform { +impl SampleBorrow for Borrowed +where Borrowed: SampleUniform +{ #[inline(always)] - fn borrow(&self) -> &Borrowed { self } + fn borrow(&self) -> &Borrowed { + self + } } -impl<'a, Borrowed> SampleBorrow for &'a Borrowed where Borrowed: SampleUniform { +impl<'a, Borrowed> SampleBorrow for &'a Borrowed +where Borrowed: SampleUniform +{ #[inline(always)] - fn borrow(&self) -> &Borrowed { *self } + fn borrow(&self) -> &Borrowed { + *self + } } //////////////////////////////////////////////////////////////////////////////// @@ -341,7 +350,7 @@ impl<'a, Borrowed> SampleBorrow for &'a Borrowed where Borrowed: Sampl pub struct UniformInt { low: X, range: X, - z: X, // either ints_to_reject or zone depending on implementation + z: X, // either ints_to_reject or zone depending on implementation } macro_rules! uniform_int_impl { @@ -361,8 +370,9 @@ macro_rules! uniform_int_impl { #[inline] // if the range is constant, this helps LLVM to do the // calculations at compile-time. fn new(low_b: B1, high_b: B2) -> Self - where B1: SampleBorrow + Sized, - B2: SampleBorrow + Sized + where + B1: SampleBorrow + Sized, + B2: SampleBorrow + Sized, { let low = *low_b.borrow(); let high = *high_b.borrow(); @@ -373,29 +383,31 @@ macro_rules! uniform_int_impl { #[inline] // if the range is constant, this helps LLVM to do the // calculations at compile-time. fn new_inclusive(low_b: B1, high_b: B2) -> Self - where B1: SampleBorrow + Sized, - B2: SampleBorrow + Sized + where + B1: SampleBorrow + Sized, + B2: SampleBorrow + Sized, { let low = *low_b.borrow(); let high = *high_b.borrow(); - assert!(low <= high, - "Uniform::new_inclusive called with `low > high`"); + assert!( + low <= high, + "Uniform::new_inclusive called with `low > high`" + ); let unsigned_max = ::core::$u_large::MAX; let range = high.wrapping_sub(low).wrapping_add(1) as $unsigned; - let ints_to_reject = - if range > 0 { - let range = $u_large::from(range); - (unsigned_max - range + 1) % range - } else { - 0 - }; + let ints_to_reject = if range > 0 { + let range = $u_large::from(range); + (unsigned_max - range + 1) % range + } else { + 0 + }; UniformInt { low: low, // These are really $unsigned values, but store as $ty: range: range as $ty, - z: ints_to_reject as $unsigned as $ty + z: ints_to_reject as $unsigned as $ty, } } @@ -417,29 +429,27 @@ macro_rules! uniform_int_impl { } } - fn sample_single(low_b: B1, high_b: B2, rng: &mut R) - -> Self::X - where B1: SampleBorrow + Sized, - B2: SampleBorrow + Sized + fn sample_single(low_b: B1, high_b: B2, rng: &mut R) -> Self::X + where + B1: SampleBorrow + Sized, + B2: SampleBorrow + Sized, { let low = *low_b.borrow(); let high = *high_b.borrow(); - assert!(low < high, - "UniformSampler::sample_single: low >= high"); + assert!(low < high, "UniformSampler::sample_single: low >= high"); let range = high.wrapping_sub(low) as $unsigned as $u_large; - let zone = - if ::core::$unsigned::MAX <= ::core::u16::MAX as $unsigned { - // Using a modulus is faster than the approximation for - // i8 and i16. I suppose we trade the cost of one - // modulus for near-perfect branch prediction. - let unsigned_max: $u_large = ::core::$u_large::MAX; - let ints_to_reject = (unsigned_max - range + 1) % range; - unsigned_max - ints_to_reject - } else { - // conservative but fast approximation. `- 1` is necessary to allow the - // same comparison without bias. - (range << range.leading_zeros()).wrapping_sub(1) - }; + let zone = if ::core::$unsigned::MAX <= ::core::u16::MAX as $unsigned { + // Using a modulus is faster than the approximation for + // i8 and i16. I suppose we trade the cost of one + // modulus for near-perfect branch prediction. + let unsigned_max: $u_large = ::core::$u_large::MAX; + let ints_to_reject = (unsigned_max - range + 1) % range; + unsigned_max - ints_to_reject + } else { + // conservative but fast approximation. `- 1` is necessary to allow the + // same comparison without bias. + (range << range.leading_zeros()).wrapping_sub(1) + }; loop { let v: $u_large = rng.gen(); @@ -450,7 +460,7 @@ macro_rules! uniform_int_impl { } } } - } + }; } uniform_int_impl! { i8, u8, u32 } @@ -649,17 +659,20 @@ macro_rules! uniform_float_impl { type X = $ty; fn new(low_b: B1, high_b: B2) -> Self - where B1: SampleBorrow + Sized, - B2: SampleBorrow + Sized + where + B1: SampleBorrow + Sized, + B2: SampleBorrow + Sized, { let low = *low_b.borrow(); let high = *high_b.borrow(); - assert!(low.all_lt(high), - "Uniform::new called with `low >= high`"); - assert!(low.all_finite() && high.all_finite(), - "Uniform::new called with non-finite boundaries"); - let max_rand = <$ty>::splat((::core::$u_scalar::MAX >> $bits_to_discard) - .into_float_with_exponent(0) - 1.0); + assert!(low.all_lt(high), "Uniform::new called with `low >= high`"); + assert!( + low.all_finite() && high.all_finite(), + "Uniform::new called with non-finite boundaries" + ); + let max_rand = <$ty>::splat( + (::core::$u_scalar::MAX >> $bits_to_discard).into_float_with_exponent(0) - 1.0, + ); let mut scale = high - low; @@ -677,17 +690,23 @@ macro_rules! uniform_float_impl { } fn new_inclusive(low_b: B1, high_b: B2) -> Self - where B1: SampleBorrow + Sized, - B2: SampleBorrow + Sized + where + B1: SampleBorrow + Sized, + B2: SampleBorrow + Sized, { let low = *low_b.borrow(); let high = *high_b.borrow(); - assert!(low.all_le(high), - "Uniform::new_inclusive called with `low > high`"); - assert!(low.all_finite() && high.all_finite(), - "Uniform::new_inclusive called with non-finite boundaries"); - let max_rand = <$ty>::splat((::core::$u_scalar::MAX >> $bits_to_discard) - .into_float_with_exponent(0) - 1.0); + assert!( + low.all_le(high), + "Uniform::new_inclusive called with `low > high`" + ); + assert!( + low.all_finite() && high.all_finite(), + "Uniform::new_inclusive called with non-finite boundaries" + ); + let max_rand = <$ty>::splat( + (::core::$u_scalar::MAX >> $bits_to_discard).into_float_with_exponent(0) - 1.0, + ); let mut scale = (high - low) / max_rand; @@ -706,8 +725,7 @@ macro_rules! uniform_float_impl { fn sample(&self, rng: &mut R) -> Self::X { // Generate a value in the range [1, 2) - let value1_2 = (rng.gen::<$uty>() >> $bits_to_discard) - .into_float_with_exponent(0); + let value1_2 = (rng.gen::<$uty>() >> $bits_to_discard).into_float_with_exponent(0); // Get a value in the range [0, 1) in order to avoid // overflowing into infinity when multiplying with scale @@ -722,21 +740,23 @@ macro_rules! uniform_float_impl { } #[inline] - fn sample_single(low_b: B1, high_b: B2, rng: &mut R) - -> Self::X - where B1: SampleBorrow + Sized, - B2: SampleBorrow + Sized + fn sample_single(low_b: B1, high_b: B2, rng: &mut R) -> Self::X + where + B1: SampleBorrow + Sized, + B2: SampleBorrow + Sized, { let low = *low_b.borrow(); let high = *high_b.borrow(); - assert!(low.all_lt(high), - "UniformSampler::sample_single: low >= high"); + assert!( + low.all_lt(high), + "UniformSampler::sample_single: low >= high" + ); let mut scale = high - low; loop { // Generate a value in the range [1, 2) - let value1_2 = (rng.gen::<$uty>() >> $bits_to_discard) - .into_float_with_exponent(0); + let value1_2 = + (rng.gen::<$uty>() >> $bits_to_discard).into_float_with_exponent(0); // Get a value in the range [0, 1) in order to avoid // overflowing into infinity when multiplying with scale @@ -780,37 +800,38 @@ macro_rules! uniform_float_impl { // rare, so handle it here after the common case. let mask = !scale.finite_mask(); if mask.any() { - assert!(low.all_finite() && high.all_finite(), - "Uniform::sample_single: low and high must be finite"); + assert!( + low.all_finite() && high.all_finite(), + "Uniform::sample_single: low and high must be finite" + ); scale = scale.decrease_masked(mask); } } } } - } + }; } uniform_float_impl! { f32, u32, f32, u32, 32 - 23 } uniform_float_impl! { f64, u64, f64, u64, 64 - 52 } -#[cfg(feature="simd_support")] +#[cfg(feature = "simd_support")] uniform_float_impl! { f32x2, u32x2, f32, u32, 32 - 23 } -#[cfg(feature="simd_support")] +#[cfg(feature = "simd_support")] uniform_float_impl! { f32x4, u32x4, f32, u32, 32 - 23 } -#[cfg(feature="simd_support")] +#[cfg(feature = "simd_support")] uniform_float_impl! { f32x8, u32x8, f32, u32, 32 - 23 } -#[cfg(feature="simd_support")] +#[cfg(feature = "simd_support")] uniform_float_impl! { f32x16, u32x16, f32, u32, 32 - 23 } -#[cfg(feature="simd_support")] +#[cfg(feature = "simd_support")] uniform_float_impl! { f64x2, u64x2, f64, u64, 64 - 52 } -#[cfg(feature="simd_support")] +#[cfg(feature = "simd_support")] uniform_float_impl! { f64x4, u64x4, f64, u64, 64 - 52 } -#[cfg(feature="simd_support")] +#[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 @@ -834,7 +855,7 @@ enum UniformDurationMode { max_secs: u64, max_nanos: u32, secs: Uniform, - } + }, } impl SampleUniform for Duration { @@ -846,8 +867,9 @@ impl UniformSampler for UniformDuration { #[inline] fn new(low_b: B1, high_b: B2) -> Self - where B1: SampleBorrow + Sized, - B2: SampleBorrow + Sized + where + B1: SampleBorrow + Sized, + B2: SampleBorrow + Sized, { let low = *low_b.borrow(); let high = *high_b.borrow(); @@ -857,12 +879,16 @@ impl UniformSampler for UniformDuration { #[inline] fn new_inclusive(low_b: B1, high_b: B2) -> Self - where B1: SampleBorrow + Sized, - B2: SampleBorrow + Sized + where + B1: SampleBorrow + Sized, + B2: SampleBorrow + Sized, { let low = *low_b.borrow(); let high = *high_b.borrow(); - assert!(low <= high, "Uniform::new_inclusive called with `low > high`"); + assert!( + low <= high, + "Uniform::new_inclusive called with `low > high`" + ); let low_s = low.as_secs(); let low_n = low.subsec_nanos(); @@ -916,7 +942,11 @@ impl UniformSampler for UniformDuration { let nanos = nanos.sample(rng); Duration::new(nanos / 1_000_000_000, (nanos % 1_000_000_000) as u32) } - UniformDurationMode::Large { max_secs, max_nanos, secs } => { + UniformDurationMode::Large { + max_secs, + max_nanos, + secs, + } => { // constant folding means this is at least as fast as `gen_range` let nano_range = Uniform::new(0, 1_000_000_000); loop { @@ -961,10 +991,9 @@ mod tests { #[test] #[cfg_attr(miri, ignore)] // Miri is too slow fn test_integers() { - use core::{i8, i16, i32, i64, isize}; - use core::{u8, u16, u32, u64, usize}; - #[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}; let mut rng = crate::test::rng(251); macro_rules! t { @@ -1025,8 +1054,7 @@ mod tests { );)* }}; } - t!(i8, i16, i32, i64, isize, - u8, u16, u32, u64, usize); + t!(i8, i16, i32, i64, isize, u8, u16, u32, u64, usize); #[cfg(not(target_os = "emscripten"))] t!(i128, u128); @@ -1051,22 +1079,22 @@ mod tests { let mut max_rng = StepRng::new(0xffff_ffff_ffff_ffff, 0); macro_rules! t { ($ty:ty, $f_scalar:ident, $bits_shifted:expr) => {{ - let v: &[($f_scalar, $f_scalar)]= - &[(0.0, 100.0), - (-1e35, -1e25), - (1e-35, 1e-25), - (-1e35, 1e35), - (<$f_scalar>::from_bits(0), <$f_scalar>::from_bits(3)), - (-<$f_scalar>::from_bits(10), -<$f_scalar>::from_bits(1)), - (-<$f_scalar>::from_bits(5), 0.0), - (-<$f_scalar>::from_bits(7), -0.0), - (10.0, ::core::$f_scalar::MAX), - (-100.0, ::core::$f_scalar::MAX), - (-::core::$f_scalar::MAX / 5.0, ::core::$f_scalar::MAX), - (-::core::$f_scalar::MAX, ::core::$f_scalar::MAX / 5.0), - (-::core::$f_scalar::MAX * 0.8, ::core::$f_scalar::MAX * 0.7), - (-::core::$f_scalar::MAX, ::core::$f_scalar::MAX), - ]; + let v: &[($f_scalar, $f_scalar)] = &[ + (0.0, 100.0), + (-1e35, -1e25), + (1e-35, 1e-25), + (-1e35, 1e35), + (<$f_scalar>::from_bits(0), <$f_scalar>::from_bits(3)), + (-<$f_scalar>::from_bits(10), -<$f_scalar>::from_bits(1)), + (-<$f_scalar>::from_bits(5), 0.0), + (-<$f_scalar>::from_bits(7), -0.0), + (10.0, ::core::$f_scalar::MAX), + (-100.0, ::core::$f_scalar::MAX), + (-::core::$f_scalar::MAX / 5.0, ::core::$f_scalar::MAX), + (-::core::$f_scalar::MAX, ::core::$f_scalar::MAX / 5.0), + (-::core::$f_scalar::MAX * 0.8, ::core::$f_scalar::MAX * 0.7), + (-::core::$f_scalar::MAX, ::core::$f_scalar::MAX), + ]; for &(low_scalar, high_scalar) in v.iter() { for lane in 0..<$ty>::lanes() { let low = <$ty>::splat(0.0 as $f_scalar).replace(lane, low_scalar); @@ -1082,7 +1110,10 @@ mod tests { assert!(low_scalar <= v && v < high_scalar); } - assert_eq!(rng.sample(Uniform::new_inclusive(low, low)).extract(lane), low_scalar); + assert_eq!( + rng.sample(Uniform::new_inclusive(low, low)).extract(lane), + low_scalar + ); assert_eq!(zero_rng.sample(my_uniform).extract(lane), low_scalar); assert_eq!(zero_rng.sample(my_incl_uniform).extract(lane), low_scalar); @@ -1094,26 +1125,37 @@ mod tests { // since for those rounding might result in selecting high for a very // long time. if (high_scalar - low_scalar) > 0.0001 { - let mut lowering_max_rng = - StepRng::new(0xffff_ffff_ffff_ffff, - (-1i64 << $bits_shifted) as u64); - assert!(lowering_max_rng.gen_range(low, high).extract(lane) < high_scalar); + let mut lowering_max_rng = StepRng::new( + 0xffff_ffff_ffff_ffff, + (-1i64 << $bits_shifted) as u64, + ); + assert!( + lowering_max_rng.gen_range(low, high).extract(lane) < high_scalar + ); } } } - assert_eq!(rng.sample(Uniform::new_inclusive(::core::$f_scalar::MAX, - ::core::$f_scalar::MAX)), - ::core::$f_scalar::MAX); - assert_eq!(rng.sample(Uniform::new_inclusive(-::core::$f_scalar::MAX, - -::core::$f_scalar::MAX)), - -::core::$f_scalar::MAX); - }} + assert_eq!( + rng.sample(Uniform::new_inclusive( + ::core::$f_scalar::MAX, + ::core::$f_scalar::MAX + )), + ::core::$f_scalar::MAX + ); + assert_eq!( + rng.sample(Uniform::new_inclusive( + -::core::$f_scalar::MAX, + -::core::$f_scalar::MAX + )), + -::core::$f_scalar::MAX + ); + }}; } t!(f32, f32, 32 - 23); t!(f64, f64, 64 - 52); - #[cfg(feature="simd_support")] + #[cfg(feature = "simd_support")] { t!(f32x2, f32, 32 - 23); t!(f32x4, f32, 32 - 23); @@ -1126,12 +1168,14 @@ mod tests { } #[test] - #[cfg(all(feature="std", - not(target_arch = "wasm32"), - not(target_arch = "asmjs")))] + #[cfg(all( + feature = "std", + not(target_arch = "wasm32"), + not(target_arch = "asmjs") + ))] fn test_float_assertions() { - use std::panic::catch_unwind; use super::SampleUniform; + use std::panic::catch_unwind; fn range(low: T, high: T) { let mut rng = crate::test::rng(253); rng.gen_range(low, high); @@ -1139,20 +1183,23 @@ mod tests { macro_rules! t { ($ty:ident, $f_scalar:ident) => {{ - let v: &[($f_scalar, $f_scalar)] = - &[(::std::$f_scalar::NAN, 0.0), - (1.0, ::std::$f_scalar::NAN), - (::std::$f_scalar::NAN, ::std::$f_scalar::NAN), - (1.0, 0.5), - (::std::$f_scalar::MAX, -::std::$f_scalar::MAX), - (::std::$f_scalar::INFINITY, ::std::$f_scalar::INFINITY), - (::std::$f_scalar::NEG_INFINITY, ::std::$f_scalar::NEG_INFINITY), - (::std::$f_scalar::NEG_INFINITY, 5.0), - (5.0, ::std::$f_scalar::INFINITY), - (::std::$f_scalar::NAN, ::std::$f_scalar::INFINITY), - (::std::$f_scalar::NEG_INFINITY, ::std::$f_scalar::NAN), - (::std::$f_scalar::NEG_INFINITY, ::std::$f_scalar::INFINITY), - ]; + let v: &[($f_scalar, $f_scalar)] = &[ + (::std::$f_scalar::NAN, 0.0), + (1.0, ::std::$f_scalar::NAN), + (::std::$f_scalar::NAN, ::std::$f_scalar::NAN), + (1.0, 0.5), + (::std::$f_scalar::MAX, -::std::$f_scalar::MAX), + (::std::$f_scalar::INFINITY, ::std::$f_scalar::INFINITY), + ( + ::std::$f_scalar::NEG_INFINITY, + ::std::$f_scalar::NEG_INFINITY, + ), + (::std::$f_scalar::NEG_INFINITY, 5.0), + (5.0, ::std::$f_scalar::INFINITY), + (::std::$f_scalar::NAN, ::std::$f_scalar::INFINITY), + (::std::$f_scalar::NEG_INFINITY, ::std::$f_scalar::NAN), + (::std::$f_scalar::NEG_INFINITY, ::std::$f_scalar::INFINITY), + ]; for &(low_scalar, high_scalar) in v.iter() { for lane in 0..<$ty>::lanes() { let low = <$ty>::splat(0.0 as $f_scalar).replace(lane, low_scalar); @@ -1164,12 +1211,12 @@ mod tests { assert!(catch_unwind(|| Uniform::new(low, low)).is_err()); } } - }} + }}; } t!(f32, f32); t!(f64, f64); - #[cfg(feature="simd_support")] + #[cfg(feature = "simd_support")] { t!(f32x2, f32); t!(f32x4, f32); @@ -1185,16 +1232,19 @@ mod tests { #[test] #[cfg_attr(miri, ignore)] // Miri is too slow fn test_durations() { - #[cfg(feature = "std")] - use std::time::Duration; - #[cfg(not(feature = "std"))] - use core::time::Duration; + #[cfg(not(feature = "std"))] use core::time::Duration; + #[cfg(feature = "std")] use std::time::Duration; let mut rng = crate::test::rng(253); - let v = &[(Duration::new(10, 50000), Duration::new(100, 1234)), - (Duration::new(0, 100), Duration::new(1, 50)), - (Duration::new(0, 0), Duration::new(u64::max_value(), 999_999_999))]; + let v = &[ + (Duration::new(10, 50000), Duration::new(100, 1234)), + (Duration::new(0, 100), Duration::new(1, 50)), + ( + Duration::new(0, 0), + Duration::new(u64::max_value(), 999_999_999), + ), + ]; for &(low, high) in v.iter() { let my_uniform = Uniform::new(low, high); for _ in 0..1000 { @@ -1206,7 +1256,9 @@ mod tests { #[test] fn test_custom_uniform() { - use crate::distributions::uniform::{UniformSampler, UniformFloat, SampleUniform, SampleBorrow}; + use crate::distributions::uniform::{ + SampleBorrow, SampleUniform, UniformFloat, UniformSampler, + }; #[derive(Clone, Copy, PartialEq, PartialOrd)] struct MyF32 { x: f32, @@ -1215,27 +1267,34 @@ mod tests { struct UniformMyF32(UniformFloat); impl UniformSampler for UniformMyF32 { type X = MyF32; + fn new(low: B1, high: B2) -> Self - where B1: SampleBorrow + Sized, - B2: SampleBorrow + Sized + where + B1: SampleBorrow + Sized, + B2: SampleBorrow + Sized, { UniformMyF32(UniformFloat::::new(low.borrow().x, high.borrow().x)) } + fn new_inclusive(low: B1, high: B2) -> Self - where B1: SampleBorrow + Sized, - B2: SampleBorrow + Sized + where + B1: SampleBorrow + Sized, + B2: SampleBorrow + Sized, { UniformSampler::new(low, high) } + fn sample(&self, rng: &mut R) -> Self::X { - MyF32 { x: self.0.sample(rng) } + MyF32 { + x: self.0.sample(rng), + } } } impl SampleUniform for MyF32 { type Sampler = UniformMyF32; } - let (low, high) = (MyF32{ x: 17.0f32 }, MyF32{ x: 22.0f32 }); + let (low, high) = (MyF32 { x: 17.0f32 }, MyF32 { x: 22.0f32 }); let uniform = Uniform::new(low, high); let mut rng = crate::test::rng(804); for _ in 0..100 { @@ -1264,42 +1323,58 @@ mod tests { assert!(r.0.scale > 5.0); assert!(r.0.scale < 5.0 + 1e-14); } - + #[test] fn value_stability() { fn test_samples( - lb: T, ub: T, expected_single: &[T], expected_multiple: &[T] - ) - where Uniform: Distribution - { + lb: T, ub: T, expected_single: &[T], expected_multiple: &[T], + ) where Uniform: Distribution { let mut rng = crate::test::rng(897); let mut buf = [lb; 3]; - + for x in &mut buf { *x = T::Sampler::sample_single(lb, ub, &mut rng); } assert_eq!(&buf, expected_single); - + let distr = Uniform::new(lb, ub); for x in &mut buf { *x = rng.sample(&distr); } assert_eq!(&buf, expected_multiple); } - + // We test on a sub-set of types; possibly we should do more. // TODO: SIMD types - + 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(-1e10f64, 1e10f64, - &[-4673848682.871551, 6388267422.932352, 4857075081.198343], - &[1173375212.1808167, 1917642852.109581, 2365076174.3153973]); - - test_samples(Duration::new(2, 0), Duration::new(4, 0), - &[Duration::new(2,532615131), Duration::new(3,638826742), Duration::new(3,485707508)], &[Duration::new(3,117337521), Duration::new(3,191764285), Duration::new(3,236507617)]); + + test_samples(0f32, 1e-2f32, &[0.0003070104, 0.0026630748, 0.00979833], &[ + 0.008194133, + 0.00398172, + 0.007428536, + ]); + test_samples( + -1e10f64, + 1e10f64, + &[-4673848682.871551, 6388267422.932352, 4857075081.198343], + &[1173375212.1808167, 1917642852.109581, 2365076174.3153973], + ); + + test_samples( + Duration::new(2, 0), + Duration::new(4, 0), + &[ + Duration::new(2, 532615131), + Duration::new(3, 638826742), + Duration::new(3, 485707508), + ], + &[ + Duration::new(3, 117337521), + Duration::new(3, 191764285), + Duration::new(3, 236507617), + ], + ); } } diff --git a/src/distributions/unit_circle.rs b/src/distributions/unit_circle.rs index 56e75b600cd..37885d8eb8e 100644 --- a/src/distributions/unit_circle.rs +++ b/src/distributions/unit_circle.rs @@ -9,8 +9,8 @@ #![allow(deprecated)] #![allow(clippy::all)] -use crate::Rng; use crate::distributions::{Distribution, Uniform}; +use crate::Rng; /// Samples uniformly from the edge of the unit circle in two dimensions. /// @@ -20,7 +20,7 @@ use crate::distributions::{Distribution, Uniform}; /// Random Digits.*](https://mcnp.lanl.gov/pdf_files/nbs_vonneumann.pdf) /// NBS Appl. Math. Ser., No. 12. Washington, DC: U.S. Government Printing /// Office, pp. 36-38. -#[deprecated(since="0.7.0", note="moved to rand_distr crate")] +#[deprecated(since = "0.7.0", note = "moved to rand_distr crate")] #[derive(Clone, Copy, Debug)] pub struct UnitCircle; @@ -42,35 +42,36 @@ impl Distribution<[f64; 2]> for UnitCircle { loop { x1 = uniform.sample(rng); x2 = uniform.sample(rng); - sum = x1*x1 + x2*x2; + sum = x1 * x1 + x2 * x2; if sum < 1. { break; } } - let diff = x1*x1 - x2*x2; - [diff / sum, 2.*x1*x2 / sum] + let diff = x1 * x1 - x2 * x2; + [diff / sum, 2. * x1 * x2 / sum] } } #[cfg(test)] mod tests { - use crate::distributions::Distribution; use super::UnitCircle; + use crate::distributions::Distribution; /// Assert that two numbers are almost equal to each other. /// /// On panic, this macro will print the values of the expressions with their /// debug representations. macro_rules! assert_almost_eq { - ($a:expr, $b:expr, $prec:expr) => ( + ($a:expr, $b:expr, $prec:expr) => { let diff = ($a - $b).abs(); if diff > $prec { panic!(format!( "assertion failed: `abs(left - right) = {:.1e} < {:e}`, \ (left: `{}`, right: `{}`)", - diff, $prec, $a, $b)); + diff, $prec, $a, $b + )); } - ); + }; } #[test] @@ -79,7 +80,7 @@ mod tests { let dist = UnitCircle::new(); for _ in 0..1000 { let x = dist.sample(&mut rng); - assert_almost_eq!(x[0]*x[0] + x[1]*x[1], 1., 1e-15); + assert_almost_eq!(x[0] * x[0] + x[1] * x[1], 1., 1e-15); } } @@ -87,15 +88,15 @@ mod tests { fn value_stability() { let mut rng = crate::test::rng(2); let expected = [ - [-0.9965658683520504, -0.08280380447614634], - [-0.9790853270389644, -0.20345004884984505], - [-0.8449189758898707, 0.5348943112253227], - ]; + [-0.9965658683520504, -0.08280380447614634], + [-0.9790853270389644, -0.20345004884984505], + [-0.8449189758898707, 0.5348943112253227], + ]; let samples = [ - UnitCircle.sample(&mut rng), - UnitCircle.sample(&mut rng), - UnitCircle.sample(&mut rng), - ]; + UnitCircle.sample(&mut rng), + UnitCircle.sample(&mut rng), + UnitCircle.sample(&mut rng), + ]; assert_eq!(samples, expected); } } diff --git a/src/distributions/unit_sphere.rs b/src/distributions/unit_sphere.rs index 188f48ca19a..5b8c8ad55f8 100644 --- a/src/distributions/unit_sphere.rs +++ b/src/distributions/unit_sphere.rs @@ -9,8 +9,8 @@ #![allow(deprecated)] #![allow(clippy::all)] -use crate::Rng; use crate::distributions::{Distribution, Uniform}; +use crate::Rng; /// Samples uniformly from the surface of the unit sphere in three dimensions. /// @@ -19,7 +19,7 @@ use crate::distributions::{Distribution, Uniform}; /// [^1]: Marsaglia, George (1972). [*Choosing a Point from the Surface of a /// Sphere.*](https://doi.org/10.1214/aoms/1177692644) /// Ann. Math. Statist. 43, no. 2, 645--646. -#[deprecated(since="0.7.0", note="moved to rand_distr crate")] +#[deprecated(since = "0.7.0", note = "moved to rand_distr crate")] #[derive(Clone, Copy, Debug)] pub struct UnitSphereSurface; @@ -37,35 +37,36 @@ impl Distribution<[f64; 3]> for UnitSphereSurface { let uniform = Uniform::new(-1., 1.); loop { let (x1, x2) = (uniform.sample(rng), uniform.sample(rng)); - let sum = x1*x1 + x2*x2; + let sum = x1 * x1 + x2 * x2; if sum >= 1. { continue; } let factor = 2. * (1.0_f64 - sum).sqrt(); - return [x1 * factor, x2 * factor, 1. - 2.*sum]; + return [x1 * factor, x2 * factor, 1. - 2. * sum]; } } } #[cfg(test)] mod tests { - use crate::distributions::Distribution; use super::UnitSphereSurface; + use crate::distributions::Distribution; /// Assert that two numbers are almost equal to each other. /// /// On panic, this macro will print the values of the expressions with their /// debug representations. macro_rules! assert_almost_eq { - ($a:expr, $b:expr, $prec:expr) => ( + ($a:expr, $b:expr, $prec:expr) => { let diff = ($a - $b).abs(); if diff > $prec { panic!(format!( "assertion failed: `abs(left - right) = {:.1e} < {:e}`, \ (left: `{}`, right: `{}`)", - diff, $prec, $a, $b)); + diff, $prec, $a, $b + )); } - ); + }; } #[test] @@ -74,7 +75,7 @@ mod tests { let dist = UnitSphereSurface::new(); for _ in 0..1000 { let x = dist.sample(&mut rng); - assert_almost_eq!(x[0]*x[0] + x[1]*x[1] + x[2]*x[2], 1., 1e-15); + assert_almost_eq!(x[0] * x[0] + x[1] * x[1] + x[2] * x[2], 1., 1e-15); } } @@ -82,15 +83,15 @@ mod tests { fn value_stability() { let mut rng = crate::test::rng(2); let expected = [ - [0.03247542860231647, -0.7830477442152738, 0.6211131755296027], - [-0.09978440840914075, 0.9706650829833128, -0.21875184231323952], - [0.2735582468624679, 0.9435374242279655, -0.1868234852870203], - ]; + [0.03247542860231647, -0.7830477442152738, 0.6211131755296027], + [-0.09978440840914075, 0.9706650829833128, -0.21875184231323952], + [0.2735582468624679, 0.9435374242279655, -0.1868234852870203], + ]; let samples = [ - UnitSphereSurface.sample(&mut rng), - UnitSphereSurface.sample(&mut rng), - UnitSphereSurface.sample(&mut rng), - ]; + UnitSphereSurface.sample(&mut rng), + UnitSphereSurface.sample(&mut rng), + UnitSphereSurface.sample(&mut rng), + ]; assert_eq!(samples, expected); } } diff --git a/src/distributions/utils.rs b/src/distributions/utils.rs index f7ddecbb9cd..2d36b022658 100644 --- a/src/distributions/utils.rs +++ b/src/distributions/utils.rs @@ -8,12 +8,9 @@ //! Math helper functions -#[cfg(feature="simd_support")] -use packed_simd::*; -#[cfg(feature="std")] -use crate::distributions::ziggurat_tables; -#[cfg(feature="std")] -use crate::Rng; +#[cfg(feature = "std")] use crate::distributions::ziggurat_tables; +#[cfg(feature = "std")] use crate::Rng; +#[cfg(feature = "simd_support")] use packed_simd::*; pub trait WideningMultiply { @@ -141,7 +138,7 @@ macro_rules! wmul_impl_usize { (high as usize, low as usize) } } - } + }; } #[cfg(target_pointer_width = "32")] wmul_impl_usize! { u32 } @@ -150,11 +147,9 @@ wmul_impl_usize! { u64 } #[cfg(all(feature = "simd_support", feature = "nightly"))] mod simd_wmul { - #[cfg(target_arch = "x86")] - use core::arch::x86::*; - #[cfg(target_arch = "x86_64")] - use core::arch::x86_64::*; use super::*; + #[cfg(target_arch = "x86")] use core::arch::x86::*; + #[cfg(target_arch = "x86_64")] use core::arch::x86_64::*; wmul_impl! { (u8x2, u16x2), @@ -248,25 +243,35 @@ pub(crate) trait FloatSIMDUtils { /// Implement functions available in std builds but missing from core primitives #[cfg(not(std))] -pub(crate) trait Float : Sized { +pub(crate) trait Float: Sized { fn is_nan(self) -> bool; fn is_infinite(self) -> bool; fn is_finite(self) -> bool; } /// Implement functions on f32/f64 to give them APIs similar to SIMD types -pub(crate) trait FloatAsSIMD : Sized { +pub(crate) trait FloatAsSIMD: Sized { #[inline(always)] - fn lanes() -> usize { 1 } + fn lanes() -> usize { + 1 + } #[inline(always)] - fn splat(scalar: Self) -> Self { scalar } + fn splat(scalar: Self) -> Self { + scalar + } #[inline(always)] - fn extract(self, index: usize) -> Self { debug_assert_eq!(index, 0); self } + fn extract(self, index: usize) -> Self { + debug_assert_eq!(index, 0); + self + } #[inline(always)] - fn replace(self, index: usize, new_value: Self) -> Self { debug_assert_eq!(index, 0); new_value } + fn replace(self, index: usize, new_value: Self) -> Self { + debug_assert_eq!(index, 0); + new_value + } } -pub(crate) trait BoolAsSIMD : Sized { +pub(crate) trait BoolAsSIMD: Sized { fn any(self) -> bool; fn all(self) -> bool; fn none(self) -> bool; @@ -274,11 +279,19 @@ pub(crate) trait BoolAsSIMD : Sized { impl BoolAsSIMD for bool { #[inline(always)] - fn any(self) -> bool { self } + fn any(self) -> bool { + self + } + #[inline(always)] - fn all(self) -> bool { self } + fn all(self) -> bool { + self + } + #[inline(always)] - fn none(self) -> bool { !self } + fn none(self) -> bool { + !self + } } macro_rules! scalar_float_impl { @@ -303,47 +316,80 @@ macro_rules! scalar_float_impl { impl FloatSIMDUtils for $ty { type Mask = bool; + type UInt = $uty; + #[inline(always)] - fn all_lt(self, other: Self) -> bool { self < other } + fn all_lt(self, other: Self) -> bool { + self < other + } + #[inline(always)] - fn all_le(self, other: Self) -> bool { self <= other } + fn all_le(self, other: Self) -> bool { + self <= other + } + #[inline(always)] - fn all_finite(self) -> bool { self.is_finite() } + fn all_finite(self) -> bool { + self.is_finite() + } + #[inline(always)] - fn finite_mask(self) -> Self::Mask { self.is_finite() } + fn finite_mask(self) -> Self::Mask { + self.is_finite() + } + #[inline(always)] - fn gt_mask(self, other: Self) -> Self::Mask { self > other } + fn gt_mask(self, other: Self) -> Self::Mask { + self > other + } + #[inline(always)] - fn ge_mask(self, other: Self) -> Self::Mask { self >= other } + fn ge_mask(self, other: Self) -> Self::Mask { + self >= other + } + #[inline(always)] fn decrease_masked(self, mask: Self::Mask) -> Self { debug_assert!(mask, "At least one lane must be set"); <$ty>::from_bits(self.to_bits() - 1) } - type UInt = $uty; + #[inline] - fn cast_from_int(i: Self::UInt) -> Self { i as $ty } + fn cast_from_int(i: Self::UInt) -> Self { + i as $ty + } } impl FloatAsSIMD for $ty {} - } + }; } scalar_float_impl!(f32, u32); scalar_float_impl!(f64, u64); -#[cfg(feature="simd_support")] +#[cfg(feature = "simd_support")] macro_rules! simd_impl { ($ty:ident, $f_scalar:ident, $mty:ident, $uty:ident) => { impl FloatSIMDUtils for $ty { type Mask = $mty; + type UInt = $uty; + #[inline(always)] - fn all_lt(self, other: Self) -> bool { self.lt(other).all() } + fn all_lt(self, other: Self) -> bool { + self.lt(other).all() + } + #[inline(always)] - fn all_le(self, other: Self) -> bool { self.le(other).all() } + fn all_le(self, other: Self) -> bool { + self.le(other).all() + } + #[inline(always)] - fn all_finite(self) -> bool { self.finite_mask().all() } + fn all_finite(self) -> bool { + self.finite_mask().all() + } + #[inline(always)] fn finite_mask(self) -> Self::Mask { // This can possibly be done faster by checking bit patterns @@ -351,10 +397,17 @@ macro_rules! simd_impl { let pos_inf = $ty::splat(::core::$f_scalar::INFINITY); self.gt(neg_inf) & self.lt(pos_inf) } + #[inline(always)] - fn gt_mask(self, other: Self) -> Self::Mask { self.gt(other) } + fn gt_mask(self, other: Self) -> Self::Mask { + self.gt(other) + } + #[inline(always)] - fn ge_mask(self, other: Self) -> Self::Mask { self.ge(other) } + fn ge_mask(self, other: Self) -> Self::Mask { + self.ge(other) + } + #[inline(always)] fn decrease_masked(self, mask: Self::Mask) -> Self { // Casting a mask into ints will produce all bits set for @@ -366,11 +419,13 @@ macro_rules! simd_impl { debug_assert!(mask.any(), "At least one lane must be set"); <$ty>::from_bits(<$uty>::from_bits(self) + <$uty>::from_bits(mask)) } - type UInt = $uty; + #[inline] - fn cast_from_int(i: Self::UInt) -> Self { i.cast() } + fn cast_from_int(i: Self::UInt) -> Self { + i.cast() + } } - } + }; } #[cfg(feature="simd_support")] simd_impl! { f32x2, f32, m32x2, u32x2 } @@ -394,7 +449,7 @@ macro_rules! simd_impl { /// `Ag(z)` is an infinite series with coefficients that can be calculated /// ahead of time - we use just the first 6 terms, which is good enough /// for most purposes. -#[cfg(feature="std")] +#[cfg(feature = "std")] pub fn log_gamma(x: f64) -> f64 { // precalculated 6 coefficients for the first 6 terms of the series let coefficients: [f64; 6] = [ @@ -439,16 +494,20 @@ pub fn log_gamma(x: f64) -> f64 { // the perf improvement (25-50%) is definitely worth the extra code // size from force-inlining. -#[cfg(feature="std")] +#[cfg(feature = "std")] #[inline(always)] pub fn ziggurat( - rng: &mut R, - symmetric: bool, - x_tab: ziggurat_tables::ZigTable, - f_tab: ziggurat_tables::ZigTable, - mut pdf: P, - mut zero_case: Z) - -> f64 where P: FnMut(f64) -> f64, Z: FnMut(&mut R, f64) -> f64 { + rng: &mut R, + symmetric: bool, + x_tab: ziggurat_tables::ZigTable, + f_tab: ziggurat_tables::ZigTable, + mut pdf: P, + mut zero_case: Z +) -> f64 +where + P: FnMut(f64) -> f64, + Z: FnMut(&mut R, f64) -> f64, +{ use crate::distributions::float::IntoFloat; loop { // As an optimisation we re-implement the conversion to a f64. @@ -467,12 +526,11 @@ pub fn ziggurat( (bits >> 12).into_float_with_exponent(1) - 3.0 } else { // Convert to a value in the range [1,2) and substract to get (0,1) - (bits >> 12).into_float_with_exponent(0) - - (1.0 - ::core::f64::EPSILON / 2.0) + (bits >> 12).into_float_with_exponent(0) - (1.0 - ::core::f64::EPSILON / 2.0) }; let x = u * x_tab[i]; - let test_x = if symmetric { x.abs() } else {x}; + let test_x = if symmetric { x.abs() } else { x }; // algebraically equivalent to |u| < x_tab[i+1]/x_tab[i] (or u < x_tab[i+1]/x_tab[i]) if test_x < x_tab[i + 1] { diff --git a/src/distributions/weibull.rs b/src/distributions/weibull.rs index 483714f9bf5..ffbc93b0156 100644 --- a/src/distributions/weibull.rs +++ b/src/distributions/weibull.rs @@ -9,11 +9,11 @@ //! The Weibull distribution. #![allow(deprecated)] -use crate::Rng; use crate::distributions::{Distribution, OpenClosed01}; +use crate::Rng; /// Samples floating-point numbers according to the Weibull distribution -#[deprecated(since="0.7.0", note="moved to rand_distr crate")] +#[deprecated(since = "0.7.0", note = "moved to rand_distr crate")] #[derive(Clone, Copy, Debug)] pub struct Weibull { inv_shape: f64, @@ -28,7 +28,10 @@ impl Weibull { /// `scale` and `shape` have to be non-zero and positive. pub fn new(scale: f64, shape: f64) -> Weibull { assert!((scale > 0.) & (shape > 0.)); - Weibull { inv_shape: 1./shape, scale } + Weibull { + inv_shape: 1. / shape, + scale, + } } } @@ -41,8 +44,8 @@ impl Distribution for Weibull { #[cfg(test)] mod tests { - use crate::distributions::Distribution; use super::Weibull; + use crate::distributions::Distribution; #[test] #[should_panic] diff --git a/src/distributions/weighted/alias_method.rs b/src/distributions/weighted/alias_method.rs index 506b289f4e8..7d42a35267b 100644 --- a/src/distributions/weighted/alias_method.rs +++ b/src/distributions/weighted/alias_method.rs @@ -2,17 +2,15 @@ //! indices with probabilities proportional to a collection of weights. use super::WeightedError; -#[cfg(not(feature = "std"))] -use crate::alloc::vec::Vec; -#[cfg(not(feature = "std"))] -use crate::alloc::vec; -use core::fmt; -use core::iter::Sum; -use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign}; +#[cfg(not(feature = "std"))] use crate::alloc::vec; +#[cfg(not(feature = "std"))] use crate::alloc::vec::Vec; use crate::distributions::uniform::SampleUniform; use crate::distributions::Distribution; use crate::distributions::Uniform; use crate::Rng; +use core::fmt; +use core::iter::Sum; +use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign}; /// A distribution using weighted sampling to pick a discretely selected item. /// @@ -192,9 +190,8 @@ impl WeightedIndex { let b = aliases.pop_big(); aliases.set_alias(s, b); - no_alias_odds[b as usize] = no_alias_odds[b as usize] - - weight_sum - + no_alias_odds[s as usize]; + no_alias_odds[b as usize] = + no_alias_odds[b as usize] - weight_sum + no_alias_odds[s as usize]; if no_alias_odds[b as usize] < weight_sum { aliases.push_small(b); @@ -253,8 +250,7 @@ where } impl Clone for WeightedIndex -where - Uniform: Clone, +where Uniform: Clone { fn clone(&self) -> Self { Self { @@ -444,9 +440,7 @@ mod test { } fn test_weighted_index f64>(w_to_f64: F) - where - WeightedIndex: fmt::Debug, - { + where WeightedIndex: fmt::Debug { const NUM_WEIGHTS: u32 = 10; const ZERO_WEIGHT_INDEX: u32 = 3; const NUM_SAMPLES: u32 = 15000; @@ -496,7 +490,7 @@ mod test { WeightedError::InvalidWeight ); } - + #[test] fn value_stability() { fn test_samples(weights: Vec, buf: &mut [usize], expected: &[usize]) { @@ -508,10 +502,16 @@ mod test { } assert_eq!(buf, expected); } - + let mut buf = [0; 10]; - test_samples(vec![1i32,1,1,1,1,1,1,1,1], &mut buf, &[6, 5, 7, 5, 8, 7, 6, 2, 3, 7]); - test_samples(vec![0.7f32, 0.1, 0.1, 0.1], &mut buf, &[2, 0, 0, 0, 0, 0, 0, 0, 1, 3]); - test_samples(vec![1.0f64, 0.999, 0.998, 0.997], &mut buf, &[2, 1, 2, 3, 2, 1, 3, 2, 1, 1]); + test_samples(vec![1i32, 1, 1, 1, 1, 1, 1, 1, 1], &mut buf, &[ + 6, 5, 7, 5, 8, 7, 6, 2, 3, 7, + ]); + test_samples(vec![0.7f32, 0.1, 0.1, 0.1], &mut buf, &[ + 2, 0, 0, 0, 0, 0, 0, 0, 1, 3, + ]); + test_samples(vec![1.0f64, 0.999, 0.998, 0.997], &mut buf, &[ + 2, 1, 2, 3, 2, 1, 3, 2, 1, 1, + ]); } } diff --git a/src/distributions/weighted/mod.rs b/src/distributions/weighted/mod.rs index efa31d59b73..357e3a9f024 100644 --- a/src/distributions/weighted/mod.rs +++ b/src/distributions/weighted/mod.rs @@ -7,9 +7,9 @@ // except according to those terms. //! Weighted index sampling -//! +//! //! This module provides two implementations for sampling indices: -//! +//! //! * [`WeightedIndex`] allows `O(log N)` sampling //! * [`alias_method::WeightedIndex`] allows `O(1)` sampling, but with //! much greater set-up cost @@ -18,14 +18,14 @@ pub mod alias_method; -use crate::Rng; +use crate::distributions::uniform::{SampleBorrow, SampleUniform, UniformSampler}; use crate::distributions::Distribution; -use crate::distributions::uniform::{UniformSampler, SampleUniform, SampleBorrow}; +use crate::Rng; 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; /// A distribution using weighted sampling to pick a discretely selected /// item. @@ -98,16 +98,13 @@ impl WeightedIndex { /// /// [`Uniform`]: crate::distributions::uniform::Uniform pub fn new(weights: I) -> Result, WeightedError> - where I: IntoIterator, - I::Item: SampleBorrow, - X: for<'a> ::core::ops::AddAssign<&'a X> + - Clone + - Default { + where + I: IntoIterator, + I::Item: SampleBorrow, + X: for<'a> ::core::ops::AddAssign<&'a X> + Clone + Default, + { let mut iter = weights.into_iter(); - let mut total_weight: X = iter.next() - .ok_or(WeightedError::NoItem)? - .borrow() - .clone(); + let mut total_weight: X = iter.next().ok_or(WeightedError::NoItem)?.borrow().clone(); let zero = ::default(); if total_weight < zero { @@ -128,7 +125,11 @@ impl WeightedIndex { } let distr = X::Sampler::new(zero, total_weight.clone()); - Ok(WeightedIndex { cumulative_weights: weights, total_weight, weight_distribution: distr }) + Ok(WeightedIndex { + cumulative_weights: weights, + total_weight, + weight_distribution: distr, + }) } /// Update a subset of weights, without changing the number of weights. @@ -141,10 +142,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> + - for<'a> ::core::ops::SubAssign<&'a X> + - Clone + - Default { + where X: for<'a> ::core::ops::AddAssign<&'a X> + + for<'a> ::core::ops::SubAssign<&'a X> + + Clone + + Default { if new_weights.is_empty() { return Ok(()); } @@ -196,17 +197,17 @@ impl WeightedIndex { let mut cumulative_weight = if first_new_index > 0 { self.cumulative_weights[first_new_index - 1].clone() } else { - zero.clone() + zero.clone() }; for i in first_new_index..self.cumulative_weights.len() { match next_new_weight { Some(&(j, w)) if i == j => { cumulative_weight += w; next_new_weight = iter.next(); - }, + } _ => { let mut tmp = self.cumulative_weights[i].clone(); - tmp -= &prev_weight; // We know this is positive. + tmp -= &prev_weight; // We know this is positive. cumulative_weight += &tmp; } } @@ -221,14 +222,22 @@ impl WeightedIndex { } } -impl Distribution for WeightedIndex where - X: SampleUniform + PartialOrd { +impl Distribution for WeightedIndex +where X: SampleUniform + PartialOrd +{ fn sample(&self, rng: &mut R) -> usize { use ::core::cmp::Ordering; let chosen_weight = self.weight_distribution.sample(rng); // Find the first item which has a weight *higher* than the chosen weight. - self.cumulative_weights.binary_search_by( - |w| if *w <= chosen_weight { Ordering::Less } else { Ordering::Greater }).unwrap_err() + self.cumulative_weights + .binary_search_by(|w| { + if *w <= chosen_weight { + Ordering::Less + } else { + Ordering::Greater + } + }) + .unwrap_err() } } @@ -282,25 +291,49 @@ mod test { for _ in 0..5 { assert_eq!(WeightedIndex::new(&[0, 1]).unwrap().sample(&mut r), 1); assert_eq!(WeightedIndex::new(&[1, 0]).unwrap().sample(&mut r), 0); - assert_eq!(WeightedIndex::new(&[0, 0, 0, 0, 10, 0]).unwrap().sample(&mut r), 4); + assert_eq!( + WeightedIndex::new(&[0, 0, 0, 0, 10, 0]) + .unwrap() + .sample(&mut r), + 4 + ); } - assert_eq!(WeightedIndex::new(&[10][0..0]).unwrap_err(), WeightedError::NoItem); - assert_eq!(WeightedIndex::new(&[0]).unwrap_err(), WeightedError::AllWeightsZero); - assert_eq!(WeightedIndex::new(&[10, 20, -1, 30]).unwrap_err(), WeightedError::InvalidWeight); - assert_eq!(WeightedIndex::new(&[-10, 20, 1, 30]).unwrap_err(), WeightedError::InvalidWeight); - assert_eq!(WeightedIndex::new(&[-10]).unwrap_err(), WeightedError::InvalidWeight); + assert_eq!( + WeightedIndex::new(&[10][0..0]).unwrap_err(), + WeightedError::NoItem + ); + assert_eq!( + WeightedIndex::new(&[0]).unwrap_err(), + WeightedError::AllWeightsZero + ); + assert_eq!( + WeightedIndex::new(&[10, 20, -1, 30]).unwrap_err(), + WeightedError::InvalidWeight + ); + assert_eq!( + WeightedIndex::new(&[-10, 20, 1, 30]).unwrap_err(), + WeightedError::InvalidWeight + ); + assert_eq!( + WeightedIndex::new(&[-10]).unwrap_err(), + WeightedError::InvalidWeight + ); } #[test] fn test_update_weights() { let data = [ - (&[10u32, 2, 3, 4][..], - &[(1, &100), (2, &4)][..], // positive change - &[10, 100, 4, 4][..]), - (&[1u32, 2, 3, 0, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7][..], - &[(2, &1), (5, &1), (13, &100)][..], // negative change and last element - &[1u32, 2, 1, 0, 5, 1, 7, 1, 2, 3, 4, 5, 6, 100][..]), + ( + &[10u32, 2, 3, 4][..], + &[(1, &100), (2, &4)][..], // positive change + &[10, 100, 4, 4][..], + ), + ( + &[1u32, 2, 3, 0, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7][..], + &[(2, &1), (5, &1), (13, &100)][..], // negative change and last element + &[1u32, 2, 1, 0, 5, 1, 7, 1, 2, 3, 4, 5, 6, 100][..], + ), ]; for (weights, update, expected_weights) in data.iter() { @@ -316,20 +349,15 @@ mod test { assert_eq!(distr.cumulative_weights, expected_distr.cumulative_weights); } } - + #[test] fn value_stability() { - fn test_samples - ( - weights: I, - buf: &mut [usize], - expected: &[usize] - ) - where I: IntoIterator, - I::Item: SampleBorrow, - X: for<'a> ::core::ops::AddAssign<&'a X> + - Clone + - Default + fn test_samples( + weights: I, buf: &mut [usize], expected: &[usize], + ) where + I: IntoIterator, + I::Item: SampleBorrow, + X: for<'a> ::core::ops::AddAssign<&'a X> + Clone + Default, { assert_eq!(buf.len(), expected.len()); let distr = WeightedIndex::new(weights).unwrap(); @@ -339,11 +367,17 @@ mod test { } assert_eq!(buf, expected); } - + 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, + ]); } } @@ -359,12 +393,12 @@ pub enum WeightedError { /// All items in the provided weight collection are zero. AllWeightsZero, - + /// Too many weights are provided (length greater than `u32::MAX`) TooMany, } -#[cfg(feature="std")] +#[cfg(feature = "std")] impl ::std::error::Error for WeightedError {} impl fmt::Display for WeightedError { diff --git a/src/distributions/ziggurat_tables.rs b/src/distributions/ziggurat_tables.rs index ca1ce30410f..f830a601bdd 100644 --- a/src/distributions/ziggurat_tables.rs +++ b/src/distributions/ziggurat_tables.rs @@ -12,6 +12,7 @@ pub type ZigTable = &'static [f64; 257]; pub const ZIG_NORM_R: f64 = 3.654152885361008796; +#[rustfmt::skip] pub static ZIG_NORM_X: [f64; 257] = [3.910757959537090045, 3.654152885361008796, 3.449278298560964462, 3.320244733839166074, 3.224575052047029100, 3.147889289517149969, 3.083526132001233044, 3.027837791768635434, @@ -78,6 +79,7 @@ pub static ZIG_NORM_X: [f64; 257] = 0.487443966121754335, 0.463634336771763245, 0.437518402186662658, 0.408389134588000746, 0.375121332850465727, 0.335737519180459465, 0.286174591747260509, 0.215241895913273806, 0.000000000000000000]; +#[rustfmt::skip] pub static ZIG_NORM_F: [f64; 257] = [0.000477467764586655, 0.001260285930498598, 0.002609072746106363, 0.004037972593371872, 0.005522403299264754, 0.007050875471392110, 0.008616582769422917, 0.010214971439731100, @@ -145,6 +147,7 @@ pub static ZIG_NORM_F: [f64; 257] = 0.932060075968990209, 0.945198953453078028, 0.959879091812415930, 0.977101701282731328, 1.000000000000000000]; pub const ZIG_EXP_R: f64 = 7.697117470131050077; +#[rustfmt::skip] pub static ZIG_EXP_X: [f64; 257] = [8.697117470131052741, 7.697117470131050077, 6.941033629377212577, 6.478378493832569696, 6.144164665772472667, 5.882144315795399869, 5.666410167454033697, 5.482890627526062488, @@ -211,6 +214,7 @@ pub static ZIG_EXP_X: [f64; 257] = 0.253658363385912022, 0.233790483059674731, 0.212671510630966620, 0.189958689622431842, 0.165127622564187282, 0.137304980940012589, 0.104838507565818778, 0.063852163815001570, 0.000000000000000000]; +#[rustfmt::skip] pub static ZIG_EXP_F: [f64; 257] = [0.000167066692307963, 0.000454134353841497, 0.000967269282327174, 0.001536299780301573, 0.002145967743718907, 0.002788798793574076, 0.003460264777836904, 0.004157295120833797, diff --git a/src/lib.rs b/src/lib.rs index 5e124d61680..d42a79fb124 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -40,22 +40,23 @@ //! For the user guide and futher documentation, please read //! [The Rust Rand Book](https://rust-random.github.io/book). - -#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png", - html_favicon_url = "https://www.rust-lang.org/favicon.ico", - html_root_url = "https://rust-random.github.io/rand/")] - +#![doc( + html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png", + html_favicon_url = "https://www.rust-lang.org/favicon.ico", + html_root_url = "https://rust-random.github.io/rand/" +)] #![deny(missing_docs)] #![deny(missing_debug_implementations)] #![doc(test(attr(allow(unused_variables), deny(warnings))))] +#![cfg_attr(not(feature = "std"), no_std)] +#![cfg_attr(all(feature = "simd_support", feature = "nightly"), feature(stdsimd))] +#![allow( + clippy::excessive_precision, + clippy::unreadable_literal, + clippy::float_cmp +)] -#![cfg_attr(not(feature="std"), no_std)] -#![cfg_attr(all(feature="simd_support", feature="nightly"), feature(stdsimd))] - -#![allow(clippy::excessive_precision, clippy::unreadable_literal, clippy::float_cmp)] - -#[cfg(all(feature="alloc", not(feature="std")))] -extern crate alloc; +#[cfg(all(feature = "alloc", not(feature = "std")))] extern crate alloc; #[allow(unused)] macro_rules! trace { ($($x:tt)*) => ( @@ -89,10 +90,10 @@ macro_rules! error { ($($x:tt)*) => ( ) } // Re-exports from rand_core -pub use rand_core::{RngCore, CryptoRng, SeedableRng, Error}; +pub use rand_core::{CryptoRng, Error, RngCore, SeedableRng}; // Public exports -#[cfg(feature="std")] pub use crate::rngs::thread::thread_rng; +#[cfg(feature = "std")] pub use crate::rngs::thread::thread_rng; // Public modules pub mod distributions; @@ -101,10 +102,10 @@ pub mod rngs; pub mod seq; -use core::{mem, slice}; -use core::num::Wrapping; +use crate::distributions::uniform::{SampleBorrow, SampleUniform, UniformSampler}; use crate::distributions::{Distribution, Standard}; -use crate::distributions::uniform::{SampleUniform, UniformSampler, SampleBorrow}; +use core::num::Wrapping; +use core::{mem, slice}; /// An automatically-implemented extension trait on [`RngCore`] providing high-level /// generic methods for sampling values and other convenience methods. @@ -268,7 +269,10 @@ pub trait Rng: RngCore { /// } /// ``` fn sample_iter(self, distr: D) -> distributions::DistIter - where D: Distribution, Self: Sized { + where + D: Distribution, + Self: Sized, + { distr.sample_iter(self) } @@ -468,9 +472,11 @@ macro_rules! impl_as_byte_slice { } impl_as_byte_slice!(u16, u32, u64, usize,); -#[cfg(not(target_os = "emscripten"))] impl_as_byte_slice!(u128); +#[cfg(not(target_os = "emscripten"))] +impl_as_byte_slice!(u128); impl_as_byte_slice!(i8, i16, i32, i64, isize,); -#[cfg(not(target_os = "emscripten"))] impl_as_byte_slice!(i128); +#[cfg(not(target_os = "emscripten"))] +impl_as_byte_slice!(i128); macro_rules! impl_as_byte_slice_arrays { ($n:expr,) => {}; @@ -495,6 +501,7 @@ macro_rules! impl_as_byte_slice_arrays { impl_as_byte_slice_arrays!(!div $n / 2, $($NN,)*); }; } +#[rustfmt::skip] impl_as_byte_slice_arrays!(32, N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,); impl_as_byte_slice_arrays!(!div 4096, N,N,N,N,N,N,N,); @@ -540,7 +547,7 @@ impl_as_byte_slice_arrays!(!div 4096, N,N,N,N,N,N,N,); /// ``` /// /// [`Standard`]: distributions::Standard -#[cfg(feature="std")] +#[cfg(feature = "std")] #[inline] pub fn random() -> T where Standard: Distribution { @@ -549,9 +556,9 @@ where Standard: Distribution { #[cfg(test)] mod test { - use crate::rngs::mock::StepRng; use super::*; - #[cfg(all(not(feature="std"), feature="alloc"))] use alloc::boxed::Box; + use crate::rngs::mock::StepRng; + #[cfg(all(not(feature = "std"), feature = "alloc"))] use alloc::boxed::Box; /// Construct a deterministic RNG with the given seed pub fn rng(seed: u64) -> impl RngCore { @@ -566,8 +573,7 @@ mod test { let mut r = StepRng::new(0x11_22_33_44_55_66_77_88, 0); // check every remainder mod 8, both in small and big vectors. - let lengths = [0, 1, 2, 3, 4, 5, 6, 7, - 80, 81, 82, 83, 84, 85, 86, 87]; + let lengths = [0, 1, 2, 3, 4, 5, 6, 7, 80, 81, 82, 83, 84, 85, 86, 87]; for &n in lengths.iter() { let mut buffer = [0u8; 87]; let v = &mut buffer[0..n]; @@ -584,7 +590,7 @@ mod test { #[test] fn test_fill() { - let x = 9041086907909331047; // a random u64 + let x = 9041086907909331047; // a random u64 let mut rng = StepRng::new(x, 0); // Convert to byte sequence and back to u64; byte-swap twice if BE. @@ -670,7 +676,7 @@ mod test { } #[test] - #[cfg(feature="alloc")] + #[cfg(feature = "alloc")] fn test_rng_boxed_trait() { use crate::distributions::{Distribution, Standard}; let rng = rng(110); @@ -682,18 +688,18 @@ mod test { } #[test] - #[cfg(feature="std")] + #[cfg(feature = "std")] fn test_random() { // not sure how to test this aside from just getting some values - let _n : usize = random(); - let _f : f32 = random(); - let _o : Option> = random(); - let _many : ((), - (usize, - isize, - Option<(u32, (bool,))>), - (u8, i8, u16, i16, u32, i32, u64, i64), - (f32, (f64, (f64,)))) = random(); + let _n: usize = random(); + let _f: f32 = random(); + let _o: Option> = random(); + let _many: ( + (), + (usize, isize, Option<(u32, (bool,))>), + (u8, i8, u16, i16, u32, i32, u64, i64), + (f32, (f64, (f64,))), + ) = random(); } #[test] @@ -711,7 +717,7 @@ mod test { } } // Have Binomial(N, NUM/DENOM) distribution - let expected = (NUM * N) / DENOM; // exact integer + let expected = (NUM * N) / DENOM; // exact integer assert!(((sum - expected) as i32).abs() < 500); } } diff --git a/src/prelude.rs b/src/prelude.rs index 3c386e8629c..98ae3bb4315 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -19,10 +19,15 @@ //! ``` #[doc(no_inline)] pub use crate::distributions::Distribution; +#[cfg(feature = "small_rng")] +#[doc(no_inline)] +pub use crate::rngs::SmallRng; #[doc(no_inline)] pub use crate::rngs::StdRng; -#[cfg(feature="small_rng")] -#[doc(no_inline)] pub use crate::rngs::SmallRng; -#[doc(no_inline)] #[cfg(feature="std")] pub use crate::rngs::ThreadRng; -#[doc(no_inline)] pub use crate::{Rng, RngCore, CryptoRng, SeedableRng}; -#[doc(no_inline)] #[cfg(feature="std")] pub use crate::{random, thread_rng}; -#[doc(no_inline)] pub use crate::seq::{SliceRandom, IteratorRandom}; +#[doc(no_inline)] +#[cfg(feature = "std")] +pub use crate::rngs::ThreadRng; +#[doc(no_inline)] pub use crate::seq::{IteratorRandom, SliceRandom}; +#[doc(no_inline)] +#[cfg(feature = "std")] +pub use crate::{random, thread_rng}; +#[doc(no_inline)] pub use crate::{CryptoRng, Rng, RngCore, SeedableRng}; diff --git a/src/rngs/adapter/mod.rs b/src/rngs/adapter/mod.rs index 659ff26218d..45e56af7266 100644 --- a/src/rngs/adapter/mod.rs +++ b/src/rngs/adapter/mod.rs @@ -8,8 +8,8 @@ //! Wrappers / adapters forming RNGs -#[cfg(feature="std")] mod read; +#[cfg(feature = "std")] mod read; mod reseeding; -#[cfg(feature="std")] pub use self::read::{ReadRng, ReadError}; +#[cfg(feature = "std")] pub use self::read::{ReadError, ReadRng}; pub use self::reseeding::ReseedingRng; diff --git a/src/rngs/adapter/read.rs b/src/rngs/adapter/read.rs index 901462ea7ca..9a4b55d4e78 100644 --- a/src/rngs/adapter/read.rs +++ b/src/rngs/adapter/read.rs @@ -9,10 +9,10 @@ //! A wrapper around any Read to treat it as an RNG. -use std::io::Read; use std::fmt; +use std::io::Read; -use rand_core::{RngCore, Error, impls}; +use rand_core::{impls, Error, RngCore}; /// An RNG that reads random bytes straight from any type supporting @@ -45,15 +45,13 @@ use rand_core::{RngCore, Error, impls}; /// [`try_fill_bytes`]: RngCore::try_fill_bytes #[derive(Debug)] pub struct ReadRng { - reader: R + reader: R, } impl ReadRng { /// Create a new `ReadRng` from a `Read`. pub fn new(r: R) -> ReadRng { - ReadRng { - reader: r - } + ReadRng { reader: r } } } @@ -67,14 +65,22 @@ impl RngCore for ReadRng { } fn fill_bytes(&mut self, dest: &mut [u8]) { - self.try_fill_bytes(dest).unwrap_or_else(|err| - panic!("reading random bytes from Read implementation failed; error: {}", err)); + self.try_fill_bytes(dest).unwrap_or_else(|err| { + panic!( + "reading random bytes from Read implementation failed; error: {}", + err + ) + }); } fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { - if dest.is_empty() { return Ok(()); } + if dest.is_empty() { + return Ok(()); + } // Use `std::io::read_exact`, which retries on `ErrorKind::Interrupted`. - self.reader.read_exact(dest).map_err(|e| Error::new(ReadError(e))) + self.reader + .read_exact(dest) + .map_err(|e| Error::new(ReadError(e))) } } @@ -103,6 +109,7 @@ mod test { #[test] fn test_reader_rng_u64() { // transmute from the target to avoid endianness concerns. + #[rustfmt::skip] let v = vec![0u8, 0, 0, 0, 0, 0, 0, 1, 0 , 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3]; diff --git a/src/rngs/adapter/reseeding.rs b/src/rngs/adapter/reseeding.rs index ec88efe218f..f7a694f2211 100644 --- a/src/rngs/adapter/reseeding.rs +++ b/src/rngs/adapter/reseeding.rs @@ -12,8 +12,8 @@ use core::mem::size_of; -use rand_core::{RngCore, CryptoRng, SeedableRng, Error}; -use rand_core::block::{BlockRngCore, BlockRng}; +use rand_core::block::{BlockRng, BlockRngCore}; +use rand_core::{CryptoRng, Error, RngCore, SeedableRng}; /// A wrapper around any PRNG that implements [`BlockRngCore`], that adds the /// ability to reseed it. @@ -77,12 +77,14 @@ use rand_core::block::{BlockRngCore, BlockRng}; /// [`reseed()`]: ReseedingRng::reseed #[derive(Debug)] pub struct ReseedingRng(BlockRng>) -where R: BlockRngCore + SeedableRng, - Rsdr: RngCore; +where + R: BlockRngCore + SeedableRng, + Rsdr: RngCore; impl ReseedingRng -where R: BlockRngCore + SeedableRng, - Rsdr: RngCore +where + R: BlockRngCore + SeedableRng, + Rsdr: RngCore, { /// Create a new `ReseedingRng` from an existing PRNG, combined with a RNG /// to use as reseeder. @@ -103,8 +105,9 @@ where R: BlockRngCore + SeedableRng, // TODO: this should be implemented for any type where the inner type // implements RngCore, but we can't specify that because ReseedingCore is private impl RngCore for ReseedingRng -where R: BlockRngCore + SeedableRng, - ::Results: AsRef<[u32]> + AsMut<[u32]> +where + R: BlockRngCore + SeedableRng, + ::Results: AsRef<[u32]> + AsMut<[u32]>, { #[inline(always)] fn next_u32(&mut self) -> u32 { @@ -126,8 +129,9 @@ where R: BlockRngCore + SeedableRng, } impl Clone for ReseedingRng -where R: BlockRngCore + SeedableRng + Clone, - Rsdr: RngCore + Clone +where + R: BlockRngCore + SeedableRng + Clone, + Rsdr: RngCore + Clone, { fn clone(&self) -> ReseedingRng { // Recreating `BlockRng` seems easier than cloning it and resetting @@ -137,8 +141,11 @@ where R: BlockRngCore + SeedableRng + Clone, } impl CryptoRng for ReseedingRng -where R: BlockRngCore + SeedableRng + CryptoRng, - Rsdr: RngCore + CryptoRng {} +where + R: BlockRngCore + SeedableRng + CryptoRng, + Rsdr: RngCore + CryptoRng, +{ +} #[derive(Debug)] struct ReseedingCore { @@ -150,16 +157,16 @@ struct ReseedingCore { } impl BlockRngCore for ReseedingCore -where R: BlockRngCore + SeedableRng, - Rsdr: RngCore +where + R: BlockRngCore + SeedableRng, + Rsdr: RngCore, { type Item = ::Item; type Results = ::Results; fn generate(&mut self, results: &mut Self::Results) { let global_fork_counter = fork::get_fork_counter(); - if self.bytes_until_reseed <= 0 || - self.is_forked(global_fork_counter) { + if self.bytes_until_reseed <= 0 || self.is_forked(global_fork_counter) { // We get better performance by not calling only `reseed` here // and continuing with the rest of the function, but by directly // returning from a non-inlined function. @@ -172,8 +179,9 @@ where R: BlockRngCore + SeedableRng, } impl ReseedingCore -where R: BlockRngCore + SeedableRng, - Rsdr: RngCore +where + R: BlockRngCore + SeedableRng, + Rsdr: RngCore, { /// Create a new `ReseedingCore`. fn new(rng: R, threshold: u64, reseeder: Rsdr) -> Self { @@ -184,10 +192,13 @@ where R: BlockRngCore + SeedableRng, // current hardware, we just clamp to that value. // Also we set a threshold of 0, which indicates no limit, to that // value. - let threshold = - if threshold == 0 { MAX } - else if threshold <= MAX as u64 { threshold as i64 } - else { MAX }; + let threshold = if threshold == 0 { + MAX + } else if threshold <= MAX as u64 { + threshold as i64 + } else { + MAX + }; ReseedingCore { inner: rng, @@ -221,19 +232,17 @@ where R: BlockRngCore + SeedableRng, } #[inline(never)] - fn reseed_and_generate(&mut self, - results: &mut ::Results, - global_fork_counter: usize) - { - #![allow(clippy::if_same_then_else)] // false positive + fn reseed_and_generate( + &mut self, results: &mut ::Results, global_fork_counter: usize, + ) { + #![allow(clippy::if_same_then_else)] // false positive if self.is_forked(global_fork_counter) { info!("Fork detected, reseeding RNG"); } else { trace!("Reseeding RNG (periodic reseed)"); } - let num_bytes = - results.as_ref().len() * size_of::<::Item>(); + let num_bytes = results.as_ref().len() * size_of::<::Item>(); if let Err(e) = self.reseed() { warn!("Reseeding RNG failed: {}", e); @@ -247,8 +256,9 @@ where R: BlockRngCore + SeedableRng, } impl Clone for ReseedingCore -where R: BlockRngCore + SeedableRng + Clone, - Rsdr: RngCore + Clone +where + R: BlockRngCore + SeedableRng + Clone, + Rsdr: RngCore + Clone, { fn clone(&self) -> ReseedingCore { ReseedingCore { @@ -262,15 +272,18 @@ where R: BlockRngCore + SeedableRng + Clone, } impl CryptoRng for ReseedingCore -where R: BlockRngCore + SeedableRng + CryptoRng, - Rsdr: RngCore + CryptoRng {} +where + R: BlockRngCore + SeedableRng + CryptoRng, + Rsdr: RngCore + CryptoRng, +{ +} -#[cfg(all(unix, not(target_os="emscripten")))] +#[cfg(all(unix, not(target_os = "emscripten")))] mod fork { - use core::sync::atomic::{AtomicUsize, AtomicBool, Ordering}; - #[allow(deprecated)] // Required for compatibility with Rust < 1.24. - use core::sync::atomic::{ATOMIC_USIZE_INIT, ATOMIC_BOOL_INIT}; + use core::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; + #[allow(deprecated)] // Required for compatibility with Rust < 1.24. + use core::sync::atomic::{ATOMIC_BOOL_INIT, ATOMIC_USIZE_INIT}; // Fork protection // @@ -294,7 +307,7 @@ mod fork { #[allow(deprecated)] static FORK_HANDLER_REGISTERED: AtomicBool = ATOMIC_BOOL_INIT; - extern fn fork_handler() { + extern "C" fn fork_handler() { // Note: fetch_add is defined to wrap on overflow // (which is what we want). RESEEDING_RNG_FORK_COUNTER.fetch_add(1, Ordering::Relaxed); @@ -308,19 +321,21 @@ mod fork { } } -#[cfg(not(all(unix, not(target_os="emscripten"))))] +#[cfg(not(all(unix, not(target_os = "emscripten"))))] mod fork { - pub fn get_fork_counter() -> usize { 0 } + pub fn get_fork_counter() -> usize { + 0 + } pub fn register_fork_handler() {} } #[cfg(test)] mod test { - use crate::{Rng, SeedableRng}; - use crate::rngs::std::Core; - use crate::rngs::mock::StepRng; use super::ReseedingRng; + use crate::rngs::mock::StepRng; + use crate::rngs::std::Core; + use crate::{Rng, SeedableRng}; #[test] fn test_reseeding() { @@ -346,10 +361,12 @@ mod test { fn test_clone_reseeding() { let mut zero = StepRng::new(0, 0); let rng = Core::from_rng(&mut zero).unwrap(); - let mut rng1 = ReseedingRng::new(rng, 32*4, zero); + let mut rng1 = ReseedingRng::new(rng, 32 * 4, zero); let first: u32 = rng1.gen(); - for _ in 0..10 { let _ = rng1.gen::(); } + for _ in 0..10 { + let _ = rng1.gen::(); + } let mut rng2 = rng1.clone(); assert_eq!(first, rng2.gen::()); diff --git a/src/rngs/entropy.rs b/src/rngs/entropy.rs index 1ed59ab1503..9ad0d71e0cd 100644 --- a/src/rngs/entropy.rs +++ b/src/rngs/entropy.rs @@ -8,19 +8,19 @@ //! Entropy generator, or wrapper around external generators -#![allow(deprecated)] // whole module is deprecated +#![allow(deprecated)] // whole module is deprecated -use rand_core::{RngCore, CryptoRng, Error}; use crate::rngs::OsRng; +use rand_core::{CryptoRng, Error, RngCore}; /// An interface returning random data from external source(s), provided /// specifically for securely seeding algorithmic generators (PRNGs). /// /// This is deprecated. It is suggested you use [`rngs::OsRng`] instead. -/// +/// /// [`rngs::OsRng`]: crate::rngs::OsRng #[derive(Debug)] -#[deprecated(since="0.7.0", note="use rngs::OsRng instead")] +#[deprecated(since = "0.7.0", note = "use rngs::OsRng instead")] pub struct EntropyRng { source: OsRng, } @@ -71,6 +71,6 @@ mod test { fn test_entropy() { let mut rng = EntropyRng::new(); let n = (rng.next_u32() ^ rng.next_u32()).count_ones(); - assert!(n >= 2); // p(failure) approx 1e-7 + assert!(n >= 2); // p(failure) approx 1e-7 } } diff --git a/src/rngs/mock.rs b/src/rngs/mock.rs index b4081daf355..9a47264a762 100644 --- a/src/rngs/mock.rs +++ b/src/rngs/mock.rs @@ -8,18 +8,18 @@ //! Mock random number generator -use rand_core::{RngCore, Error, impls}; +use rand_core::{impls, Error, RngCore}; /// A simple implementation of `RngCore` for testing purposes. -/// +/// /// This generates an arithmetic sequence (i.e. adds a constant each step) /// over a `u64` number, using wrapping arithmetic. If the increment is 0 /// the generator yields a constant. -/// +/// /// ``` /// use rand::Rng; /// use rand::rngs::mock::StepRng; -/// +/// /// let mut my_rng = StepRng::new(2, 1); /// let sample: [u64; 3] = my_rng.gen(); /// assert_eq!(sample, [2, 3, 4]); @@ -34,7 +34,10 @@ impl StepRng { /// Create a `StepRng`, yielding an arithmetic sequence starting with /// `initial` and incremented by `increment` each time. pub fn new(initial: u64, increment: u64) -> Self { - StepRng { v: initial, a: increment } + StepRng { + v: initial, + a: increment, + } } } diff --git a/src/rngs/mod.rs b/src/rngs/mod.rs index 1d9f5185d6e..11121960255 100644 --- a/src/rngs/mod.rs +++ b/src/rngs/mod.rs @@ -98,20 +98,19 @@ pub mod adapter; -#[cfg(feature="std")] mod entropy; -pub mod mock; // Public so we don't export `StepRng` directly, making it a bit - // more clear it is intended for testing. -#[cfg(feature="small_rng")] -mod small; +#[cfg(feature = "std")] mod entropy; +pub mod mock; // Public so we don't export `StepRng` directly, making it a bit + // more clear it is intended for testing. +#[cfg(feature = "small_rng")] mod small; mod std; -#[cfg(feature="std")] pub(crate) mod thread; +#[cfg(feature = "std")] pub(crate) mod thread; #[allow(deprecated)] -#[cfg(feature="std")] pub use self::entropy::EntropyRng; +#[cfg(feature = "std")] +pub use self::entropy::EntropyRng; -#[cfg(feature="small_rng")] -pub use self::small::SmallRng; +#[cfg(feature = "small_rng")] pub use self::small::SmallRng; pub use self::std::StdRng; -#[cfg(feature="std")] pub use self::thread::ThreadRng; +#[cfg(feature = "std")] pub use self::thread::ThreadRng; -#[cfg(feature="getrandom")] pub use rand_core::OsRng; +#[cfg(feature = "getrandom")] pub use rand_core::OsRng; diff --git a/src/rngs/small.rs b/src/rngs/small.rs index 2b0b0df69f6..d676898149c 100644 --- a/src/rngs/small.rs +++ b/src/rngs/small.rs @@ -8,7 +8,7 @@ //! A small fast RNG -use rand_core::{RngCore, SeedableRng, Error}; +use rand_core::{Error, RngCore, SeedableRng}; #[cfg(all(not(target_os = "emscripten"), target_pointer_width = "64"))] type Rng = rand_pcg::Pcg64Mcg; diff --git a/src/rngs/std.rs b/src/rngs/std.rs index 6d02c2d3891..8b07081a048 100644 --- a/src/rngs/std.rs +++ b/src/rngs/std.rs @@ -8,15 +8,15 @@ //! The standard RNG -use crate::{RngCore, CryptoRng, Error, SeedableRng}; +use crate::{CryptoRng, Error, RngCore, SeedableRng}; -#[cfg(all(any(test, feature = "std"), target_os = "emscripten"))] -pub(crate) use rand_hc::Hc128Core as Core; #[cfg(all(any(test, feature = "std"), not(target_os = "emscripten")))] pub(crate) use rand_chacha::ChaCha20Core as Core; +#[cfg(all(any(test, feature = "std"), target_os = "emscripten"))] +pub(crate) use rand_hc::Hc128Core as Core; -#[cfg(target_os = "emscripten")] use rand_hc::Hc128Rng as Rng; #[cfg(not(target_os = "emscripten"))] use rand_chacha::ChaCha20Rng as Rng; +#[cfg(target_os = "emscripten")] use rand_hc::Hc128Rng as Rng; /// The standard RNG. The PRNG algorithm in `StdRng` is chosen to be efficient /// on the current platform, to be statistically strong and unpredictable @@ -76,21 +76,22 @@ impl CryptoRng for StdRng {} #[cfg(test)] mod test { - use crate::{RngCore, SeedableRng}; use crate::rngs::StdRng; + use crate::{RngCore, SeedableRng}; #[test] fn test_stdrng_construction() { // Test value-stability of StdRng. This is expected to break any time // the algorithm is changed. + #[rustfmt::skip] let seed = [1,0,0,0, 23,0,0,0, 200,1,0,0, 210,30,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0]; - #[cfg(any(feature="stdrng_strong", not(feature="stdrng_fast")))] + #[cfg(any(feature = "stdrng_strong", not(feature = "stdrng_fast")))] let target = [3950704604716924505, 5573172343717151650]; - #[cfg(all(not(feature="stdrng_strong"), feature="stdrng_fast"))] + #[cfg(all(not(feature = "stdrng_strong"), feature = "stdrng_fast"))] let target = [10719222850664546238, 14064965282130556830]; - + let mut rng0 = StdRng::from_seed(seed); let x0 = rng0.next_u64(); diff --git a/src/rngs/thread.rs b/src/rngs/thread.rs index 2006f4176fa..91ed4c30a8e 100644 --- a/src/rngs/thread.rs +++ b/src/rngs/thread.rs @@ -11,10 +11,10 @@ use std::cell::UnsafeCell; use std::ptr::NonNull; -use crate::{RngCore, CryptoRng, SeedableRng, Error}; +use super::std::Core; use crate::rngs::adapter::ReseedingRng; use crate::rngs::OsRng; -use super::std::Core; +use crate::{CryptoRng, Error, RngCore, SeedableRng}; // Rationale for using `UnsafeCell` in `ThreadRng`: // diff --git a/src/seq/index.rs b/src/seq/index.rs index 3287c6c5dae..551d409e71c 100644 --- a/src/seq/index.rs +++ b/src/seq/index.rs @@ -8,15 +8,18 @@ //! Low-level API for sampling indices -#[cfg(feature="alloc")] use core::slice; +#[cfg(feature = "alloc")] use core::slice; -#[cfg(feature="std")] use std::vec; -#[cfg(all(feature="alloc", not(feature="std")))] use crate::alloc::vec::{self, Vec}; +#[cfg(all(feature = "alloc", not(feature = "std")))] +use crate::alloc::vec::{self, Vec}; +#[cfg(feature = "std")] use std::vec; // BTreeMap is not as fast in tests, but better than nothing. -#[cfg(feature="std")] use std::collections::{HashSet}; -#[cfg(all(feature="alloc", not(feature="std")))] use crate::alloc::collections::BTreeSet; +#[cfg(all(feature = "alloc", not(feature = "std")))] +use crate::alloc::collections::BTreeSet; +#[cfg(feature = "std")] use std::collections::HashSet; -#[cfg(feature="alloc")] use crate::distributions::{Distribution, Uniform, uniform::SampleUniform}; +#[cfg(feature = "alloc")] +use crate::distributions::{uniform::SampleUniform, Distribution, Uniform}; use crate::Rng; /// A vector of indices. @@ -24,8 +27,10 @@ use crate::Rng; /// Multiple internal representations are possible. #[derive(Clone, Debug)] pub enum IndexVec { - #[doc(hidden)] U32(Vec), - #[doc(hidden)] USize(Vec), + #[doc(hidden)] + U32(Vec), + #[doc(hidden)] + USize(Vec), } impl IndexVec { @@ -93,10 +98,12 @@ impl PartialEq for IndexVec { match (self, other) { (&U32(ref v1), &U32(ref v2)) => v1 == v2, (&USize(ref v1), &USize(ref v2)) => v1 == v2, - (&U32(ref v1), &USize(ref v2)) => (v1.len() == v2.len()) - && (v1.iter().zip(v2.iter()).all(|(x, y)| *x as usize == *y)), - (&USize(ref v1), &U32(ref v2)) => (v1.len() == v2.len()) - && (v1.iter().zip(v2.iter()).all(|(x, y)| *x == *y as usize)), + (&U32(ref v1), &USize(ref v2)) => { + (v1.len() == v2.len()) && (v1.iter().zip(v2.iter()).all(|(x, y)| *x as usize == *y)) + } + (&USize(ref v1), &U32(ref v2)) => { + (v1.len() == v2.len()) && (v1.iter().zip(v2.iter()).all(|(x, y)| *x == *y as usize)) + } } } } @@ -118,12 +125,15 @@ impl From> for IndexVec { /// Return type of `IndexVec::iter`. #[derive(Debug)] pub enum IndexVecIter<'a> { - #[doc(hidden)] U32(slice::Iter<'a, u32>), - #[doc(hidden)] USize(slice::Iter<'a, usize>), + #[doc(hidden)] + U32(slice::Iter<'a, u32>), + #[doc(hidden)] + USize(slice::Iter<'a, usize>), } impl<'a> Iterator for IndexVecIter<'a> { type Item = usize; + #[inline] fn next(&mut self) -> Option { use self::IndexVecIter::*; @@ -147,8 +157,10 @@ impl<'a> ExactSizeIterator for IndexVecIter<'a> {} /// Return type of `IndexVec::into_iter`. #[derive(Clone, Debug)] pub enum IndexVecIntoIter { - #[doc(hidden)] U32(vec::IntoIter), - #[doc(hidden)] USize(vec::IntoIter), + #[doc(hidden)] + U32(vec::IntoIter), + #[doc(hidden)] + USize(vec::IntoIter), } impl Iterator for IndexVecIntoIter { @@ -216,7 +228,7 @@ where R: Rng + ?Sized { // We do some calculations with f32. Accuracy is not very important. if amount < 163 { - const C: [[f32; 2]; 2] = [[1.6, 8.0/45.0], [10.0, 70.0/9.0]]; + const C: [[f32; 2]; 2] = [[1.6, 8.0 / 45.0], [10.0, 70.0 / 9.0]]; let j = if length < 500_000 { 0 } else { 1 }; let amount_fp = amount as f32; let m4 = C[0][j] * amount_fp; @@ -227,7 +239,7 @@ where R: Rng + ?Sized { sample_floyd(rng, length, amount) } } else { - const C: [f32; 2] = [270.0, 330.0/9.0]; + const C: [f32; 2] = [270.0, 330.0 / 9.0]; let j = if length < 500_000 { 0 } else { 1 }; if (length as f32) < C[j] * (amount as f32) { sample_inplace(rng, length, amount) @@ -252,7 +264,7 @@ where R: Rng + ?Sized { debug_assert!(amount <= length); let mut indices = Vec::with_capacity(amount as usize); - for j in length - amount .. length { + for j in length - amount..length { let t = rng.gen_range(0, j + 1); if floyd_shuffle { if let Some(pos) = indices.iter().position(|&x| x == t) { @@ -306,12 +318,26 @@ trait UInt: Copy + PartialOrd + Ord + PartialEq + Eq + SampleUniform + core::has fn as_usize(self) -> usize; } impl UInt for u32 { - #[inline] fn zero() -> Self { 0 } - #[inline] fn as_usize(self) -> usize { self as usize } + #[inline] + fn zero() -> Self { + 0 + } + + #[inline] + fn as_usize(self) -> usize { + self as usize + } } impl UInt for usize { - #[inline] fn zero() -> Self { 0 } - #[inline] fn as_usize(self) -> usize { self } + #[inline] + fn zero() -> Self { + 0 + } + + #[inline] + fn as_usize(self) -> usize { + self + } } /// Randomly sample exactly `amount` indices from `0..length`, using rejection @@ -320,14 +346,19 @@ impl UInt for usize { /// 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. -/// +/// /// This function is generic over X primarily so that results are value-stable /// over 32-bit and 64-bit platforms. fn sample_rejection(rng: &mut R, length: X, amount: X) -> IndexVec -where R: Rng + ?Sized, IndexVec: From> { +where + R: Rng + ?Sized, + IndexVec: From>, +{ debug_assert!(amount < length); - #[cfg(feature="std")] let mut cache = HashSet::with_capacity(amount.as_usize()); - #[cfg(not(feature="std"))] let mut cache = BTreeSet::new(); + #[cfg(feature = "std")] + let mut cache = HashSet::with_capacity(amount.as_usize()); + #[cfg(not(feature = "std"))] + let mut cache = BTreeSet::new(); let distr = Uniform::new(X::zero(), length); let mut indices = Vec::with_capacity(amount.as_usize()); for _ in 0..amount.as_usize() { @@ -344,9 +375,9 @@ where R: Rng + ?Sized, IndexVec: From> { #[cfg(test)] mod test { - #[cfg(feature="std")] use std::vec; - #[cfg(all(feature="alloc", not(feature="std")))] use crate::alloc::vec; use super::*; + #[cfg(all(feature = "alloc", not(feature = "std")))] use crate::alloc::vec; + #[cfg(feature = "std")] use std::vec; #[test] fn test_sample_boundaries() { @@ -363,12 +394,10 @@ mod test { assert_eq!(sample_floyd(&mut r, 1, 1).into_vec(), vec![0]); // These algorithms should be fast with big numbers. Test average. - let sum: usize = sample_rejection(&mut r, 1 << 25, 10u32) - .into_iter().sum(); + let sum: usize = sample_rejection(&mut r, 1 << 25, 10u32).into_iter().sum(); assert!(1 << 25 < sum && sum < (1 << 25) * 25); - let sum: usize = sample_floyd(&mut r, 1 << 25, 10) - .into_iter().sum(); + let sum: usize = sample_floyd(&mut r, 1 << 25, 10).into_iter().sum(); assert!(1 << 25 < sum && sum < (1 << 25) * 25); } @@ -393,14 +422,14 @@ mod test { assert!(v1 != v3); // A large length and small amount should use Floyd - let (length, amount): (usize, usize) = (1<<20, 50); + let (length, amount): (usize, usize) = (1 << 20, 50); let v1 = sample(&mut seed_rng(421), length, amount); let v2 = sample_floyd(&mut seed_rng(421), length as u32, amount as u32); assert!(v1.iter().all(|e| e < length)); assert_eq!(v1, v2); // A large length and larger amount should use cache - let (length, amount): (usize, usize) = (1<<20, 600); + let (length, amount): (usize, usize) = (1 << 20, 600); let v1 = sample(&mut seed_rng(422), length, amount); let v2 = sample_rejection(&mut seed_rng(422), length as u32, amount as u32); assert!(v1.iter().all(|e| e < length)); diff --git a/src/seq/mod.rs b/src/seq/mod.rs index 91f6c2808f1..dabf3292794 100644 --- a/src/seq/mod.rs +++ b/src/seq/mod.rs @@ -7,42 +7,43 @@ // except according to those terms. //! Sequence-related functionality -//! +//! //! This module provides: -//! +//! //! * [`SliceRandom`] slice sampling and mutation //! * [`IteratorRandom`] iterator sampling //! * [`index::sample`] low-level API to choose multiple indices from //! `0..length` -//! +//! //! Also see: -//! +//! //! * [`crate::distributions::weighted`] module which provides //! implementations of weighted index sampling. -//! +//! //! In order to make results reproducible across 32-64 bit architectures, all //! `usize` indices are sampled as a `u32` where possible (also providing a //! small performance boost in some cases). -#[cfg(feature="alloc")] pub mod index; +#[cfg(feature = "alloc")] pub mod index; -#[cfg(feature="alloc")] use core::ops::Index; +#[cfg(feature = "alloc")] use core::ops::Index; -#[cfg(all(feature="alloc", not(feature="std")))] use crate::alloc::vec::Vec; +#[cfg(all(feature = "alloc", not(feature = "std")))] use crate::alloc::vec::Vec; +#[cfg(feature = "alloc")] +use crate::distributions::uniform::{SampleBorrow, SampleUniform}; +#[cfg(feature = "alloc")] use crate::distributions::WeightedError; use crate::Rng; -#[cfg(feature="alloc")] use crate::distributions::WeightedError; -#[cfg(feature="alloc")] use crate::distributions::uniform::{SampleUniform, SampleBorrow}; /// Extension trait on slices, providing random mutation and sampling methods. -/// +/// /// This trait is implemented on all `[T]` slice types, providing several /// methods for choosing and shuffling elements. You must `use` this trait: -/// +/// /// ``` /// use rand::seq::SliceRandom; -/// +/// /// fn main() { /// let mut rng = rand::thread_rng(); /// let mut bytes = "Hello, random!".to_string().into_bytes(); @@ -61,7 +62,7 @@ pub trait SliceRandom { /// Returns a reference to one random element of the slice, or `None` if the /// slice is empty. - /// + /// /// For slices, complexity is `O(1)`. /// /// # Example @@ -115,7 +116,7 @@ pub trait SliceRandom { /// Similar to [`choose`], but where the likelihood of each outcome may be /// specified. - /// + /// /// The specified function `weight` maps each item `x` to a relative /// likelihood `weight(x)`. The probability of each item being selected is /// therefore `weight(x) / s`, where `s` is the sum of all `weight(x)`. @@ -152,7 +153,7 @@ pub trait SliceRandom { /// Similar to [`choose_mut`], but where the likelihood of each outcome may /// be specified. - /// + /// /// The specified function `weight` maps each item `x` to a relative /// likelihood `weight(x)`. The probability of each item being selected is /// therefore `weight(x) / s`, where `s` is the sum of all `weight(x)`. @@ -220,13 +221,13 @@ pub trait SliceRandom { } /// Extension trait on iterators, providing random sampling methods. -/// +/// /// This trait is implemented on all sized iterators, providing methods for /// choosing one or more elements. You must `use` this trait: -/// +/// /// ``` /// use rand::seq::IteratorRandom; -/// +/// /// fn main() { /// let mut rng = rand::thread_rng(); /// @@ -240,7 +241,7 @@ pub trait SliceRandom { /// ``` pub trait IteratorRandom: Iterator + Sized { /// Choose one element at random from the iterator. - /// + /// /// Returns `None` if and only if the iterator is empty. /// /// This method uses [`Iterator::size_hint`] for optimisation. With an @@ -248,7 +249,7 @@ pub trait IteratorRandom: Iterator + Sized { /// this method can offer `O(1)` performance. Where no size hint is /// available, complexity is `O(n)` where `n` is the iterator length. /// Partial hints (where `lower > 0`) also improve performance. - /// + /// /// For slices, prefer [`SliceRandom::choose`] which guarantees `O(1)` /// performance. fn choose(mut self, rng: &mut R) -> Option @@ -258,7 +259,11 @@ pub trait IteratorRandom: Iterator + Sized { let mut result = None; if upper == Some(lower) { - return if lower == 0 { None } else { self.nth(gen_index(rng, lower)) }; + return if lower == 0 { + None + } else { + self.nth(gen_index(rng, lower)) + }; } // Continue until the iterator is exhausted @@ -478,7 +483,7 @@ impl IteratorRandom for I where I: Iterator + Sized {} /// An iterator over multiple slice elements. -/// +/// /// This struct is created by /// [`SliceRandom::choose_multiple`](trait.SliceRandom.html#tymethod.choose_multiple). #[cfg(feature = "alloc")] @@ -530,13 +535,14 @@ fn gen_index(rng: &mut R, ubound: usize) -> usize { mod test { use super::*; #[cfg(feature = "alloc")] use crate::Rng; - #[cfg(all(feature="alloc", not(feature="std")))] - use alloc::vec::Vec; + #[cfg(all(feature = "alloc", not(feature = "std")))] use alloc::vec::Vec; #[test] fn test_slice_choose() { let mut r = crate::test::rng(107); - let chars = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n']; + let chars = [ + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', + ]; let mut chosen = [0i32; 14]; // The below all use a binomial distribution with n=1000, p=1/14. // binocdf(40, 1000, 1/14) ~= 2e-5; 1-binocdf(106, ..) ~= 2e-5 @@ -567,6 +573,7 @@ mod test { } impl Iterator for UnhintedIterator { type Item = I::Item; + fn next(&mut self) -> Option { self.iter.next() } @@ -581,18 +588,25 @@ mod test { } impl Iterator for ChunkHintedIterator { type Item = I::Item; + fn next(&mut self) -> Option { if self.chunk_remaining == 0 { - self.chunk_remaining = ::core::cmp::min(self.chunk_size, - self.iter.len()); + self.chunk_remaining = ::core::cmp::min(self.chunk_size, self.iter.len()); } self.chunk_remaining = self.chunk_remaining.saturating_sub(1); self.iter.next() } + fn size_hint(&self) -> (usize, Option) { - (self.chunk_remaining, - if self.hint_total_size { Some(self.iter.len()) } else { None }) + ( + self.chunk_remaining, + if self.hint_total_size { + Some(self.iter.len()) + } else { + None + }, + ) } } @@ -604,12 +618,20 @@ mod test { } impl Iterator for WindowHintedIterator { type Item = I::Item; + fn next(&mut self) -> Option { self.iter.next() } + fn size_hint(&self) -> (usize, Option) { - (::core::cmp::min(self.iter.len(), self.window_size), - if self.hint_total_size { Some(self.iter.len()) } else { None }) + ( + ::core::cmp::min(self.iter.len(), self.window_size), + if self.hint_total_size { + Some(self.iter.len()) + } else { + None + }, + ) } } @@ -617,7 +639,7 @@ mod test { #[cfg_attr(miri, ignore)] // Miri is too slow fn test_iterator_choose() { let r = &mut crate::test::rng(109); - fn test_iter + Clone>(r: &mut R, iter: Iter) { + fn test_iter + Clone>(r: &mut R, iter: Iter) { let mut chosen = [0i32; 9]; for _ in 0..1000 { let picked = iter.clone().choose(r).unwrap(); @@ -627,7 +649,11 @@ mod test { // Samples should follow Binomial(1000, 1/9) // Octave: binopdf(x, 1000, 1/9) gives the prob of *count == x // Note: have seen 153, which is unlikely but not impossible. - assert!(72 < *count && *count < 154, "count not close to 1000/9: {}", count); + assert!( + 72 < *count && *count < 154, + "count not close to 1000/9: {}", + count + ); } } @@ -636,13 +662,31 @@ mod test { #[cfg(feature = "alloc")] test_iter(r, (0..9).collect::>().into_iter()); test_iter(r, UnhintedIterator { iter: 0..9 }); - test_iter(r, ChunkHintedIterator { iter: 0..9, chunk_size: 4, chunk_remaining: 4, hint_total_size: false }); - test_iter(r, ChunkHintedIterator { iter: 0..9, chunk_size: 4, chunk_remaining: 4, hint_total_size: true }); - test_iter(r, WindowHintedIterator { iter: 0..9, window_size: 2, hint_total_size: false }); - test_iter(r, WindowHintedIterator { iter: 0..9, window_size: 2, hint_total_size: true }); + test_iter(r, ChunkHintedIterator { + iter: 0..9, + chunk_size: 4, + chunk_remaining: 4, + hint_total_size: false, + }); + test_iter(r, ChunkHintedIterator { + iter: 0..9, + chunk_size: 4, + chunk_remaining: 4, + hint_total_size: true, + }); + test_iter(r, WindowHintedIterator { + iter: 0..9, + window_size: 2, + hint_total_size: false, + }); + test_iter(r, WindowHintedIterator { + iter: 0..9, + window_size: 2, + hint_total_size: true, + }); assert_eq!((0..0).choose(r), None); - assert_eq!(UnhintedIterator{ iter: 0..0 }.choose(r), None); + assert_eq!(UnhintedIterator { iter: 0..0 }.choose(r), None); } #[test] @@ -694,15 +738,15 @@ mod test { assert!(352 <= *count && *count <= 483, "count: {}", count); } } - + #[test] fn test_partial_shuffle() { let mut r = crate::test::rng(118); - + let mut empty: [u32; 0] = []; let res = empty.partial_shuffle(&mut r, 10); assert_eq!((res.0.len(), res.1.len()), (0, 0)); - + let mut v = [1, 2, 3, 4, 5]; let res = v.partial_shuffle(&mut r, 2); assert_eq!((res.0.len(), res.1.len()), (2, 3)); @@ -727,11 +771,11 @@ mod test { // no randomization happens when amount >= len assert_eq!(large_sample, vals.iter().collect::>()); - assert!(small_sample.iter().all(|e| { - **e >= min_val && **e <= max_val - })); + assert!(small_sample + .iter() + .all(|e| { **e >= min_val && **e <= max_val })); } - + #[test] #[cfg(feature = "alloc")] #[cfg_attr(miri, ignore)] // Miri is too slow @@ -782,10 +826,25 @@ mod test { // Check error cases let empty_slice = &mut [10][0..0]; - assert_eq!(empty_slice.choose_weighted(&mut r, |_| 1), Err(WeightedError::NoItem)); - assert_eq!(empty_slice.choose_weighted_mut(&mut r, |_| 1), Err(WeightedError::NoItem)); - assert_eq!(['x'].choose_weighted_mut(&mut r, |_| 0), Err(WeightedError::AllWeightsZero)); - assert_eq!([0, -1].choose_weighted_mut(&mut r, |x| *x), Err(WeightedError::InvalidWeight)); - assert_eq!([-1, 0].choose_weighted_mut(&mut r, |x| *x), Err(WeightedError::InvalidWeight)); + assert_eq!( + empty_slice.choose_weighted(&mut r, |_| 1), + Err(WeightedError::NoItem) + ); + assert_eq!( + empty_slice.choose_weighted_mut(&mut r, |_| 1), + Err(WeightedError::NoItem) + ); + assert_eq!( + ['x'].choose_weighted_mut(&mut r, |_| 0), + Err(WeightedError::AllWeightsZero) + ); + assert_eq!( + [0, -1].choose_weighted_mut(&mut r, |x| *x), + Err(WeightedError::InvalidWeight) + ); + assert_eq!( + [-1, 0].choose_weighted_mut(&mut r, |x| *x), + Err(WeightedError::InvalidWeight) + ); } }