diff --git a/rand_chacha/src/chacha.rs b/rand_chacha/src/chacha.rs index a7a28b227e8..a4c9552a909 100644 --- a/rand_chacha/src/chacha.rs +++ b/rand_chacha/src/chacha.rs @@ -114,7 +114,7 @@ macro_rules! chacha_impl { /// except that we use a stream identifier in place of a nonce. A 64-bit counter over 64-byte /// (16 word) blocks allows 1 ZiB of output before cycling, and the stream identifier allows /// 264 unique streams of output per seed. Both counter and stream are initialized - /// to zero but may be set via [`set_word_pos`] and [`set_stream`]. + /// to zero but may be set via the `set_word_pos` and `set_stream` methods. /// /// The word layout is: /// @@ -133,9 +133,6 @@ macro_rules! chacha_impl { /// /// [^2]: [eSTREAM: the ECRYPT Stream Cipher Project]( /// http://www.ecrypt.eu.org/stream/) - /// - /// [`set_word_pos`]: ChaChaXRng::set_word_pos - /// [`set_stream`]: ChaChaXRng::set_stream #[derive(Clone, Debug)] pub struct $ChaChaXRng { rng: BlockRng<$ChaChaXCore>, diff --git a/rand_distr/src/pert.rs b/rand_distr/src/pert.rs index 509d05af139..040cd05cfed 100644 --- a/rand_distr/src/pert.rs +++ b/rand_distr/src/pert.rs @@ -13,9 +13,9 @@ use crate::utils::Float; /// The PERT distribution. /// -/// Similar to the [Triangular] distribution, the PERT distribution is +/// Similar to the [`Triangular`] distribution, the PERT distribution is /// parameterised by a range and a mode within that range. Unlike the -/// [Triangular] distribution, the probability density function of the PERT +/// [`Triangular`] distribution, the probability density function of the PERT /// distribution is smooth, with a configurable weighting around the mode. /// /// # Example @@ -27,6 +27,8 @@ use crate::utils::Float; /// 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 { min: N, diff --git a/rand_distr/src/triangular.rs b/rand_distr/src/triangular.rs index a793669ad40..dd0bbfbdf29 100644 --- a/rand_distr/src/triangular.rs +++ b/rand_distr/src/triangular.rs @@ -17,7 +17,7 @@ use crate::utils::Float; /// (most likely value) within that range. /// /// The probability density function is triangular. For a similar distribution -/// with a smooth PDF, see the [Pert] distribution. +/// with a smooth PDF, see the [`Pert`] distribution. /// /// # Example /// @@ -28,6 +28,8 @@ use crate::utils::Float; /// let v = d.sample(&mut rand::thread_rng()); /// println!("{} is from a triangular distribution", v); /// ``` +/// +/// [`Pert`]: crate::Pert #[derive(Clone, Copy, Debug)] pub struct Triangular { min: N, diff --git a/src/distributions/weighted/mod.rs b/src/distributions/weighted/mod.rs index de2711b1527..5c2cd97c21f 100644 --- a/src/distributions/weighted/mod.rs +++ b/src/distributions/weighted/mod.rs @@ -6,8 +6,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! This module contains different algorithms for sampling random indices with -//! probabilities proportional to a collection of weights. +//! 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 +//! +//! [`alias_method::WeightedIndex`]: alias_method/struct.WeightedIndex.html pub mod alias_method; diff --git a/src/rngs/adapter/read.rs b/src/rngs/adapter/read.rs index 77b2a16d055..c64230f3059 100644 --- a/src/rngs/adapter/read.rs +++ b/src/rngs/adapter/read.rs @@ -41,7 +41,7 @@ use rand_core::{RngCore, Error, impls}; /// println!("{:x}", rng.gen::()); /// ``` /// -/// [`OsRng`]: rngs::OsRng +/// [`OsRng`]: crate::rngs::OsRng /// [`try_fill_bytes`]: RngCore::try_fill_bytes #[derive(Debug)] pub struct ReadRng { diff --git a/src/rngs/adapter/reseeding.rs b/src/rngs/adapter/reseeding.rs index 57c6c7503dd..b05c05247e9 100644 --- a/src/rngs/adapter/reseeding.rs +++ b/src/rngs/adapter/reseeding.rs @@ -72,7 +72,6 @@ use rand_core::block::{BlockRngCore, BlockRng}; /// assert!(reseeding_rng.gen::() != cloned_rng.gen::()); /// ``` /// -/// [`ChaCha20Core`]: ../../../rand_chacha/struct.ChaCha20Core.html /// [`BlockRngCore`]: rand_core::block::BlockRngCore /// [`ReseedingRng::new`]: ReseedingRng::new /// [`reseed()`]: ReseedingRng::reseed diff --git a/src/rngs/entropy.rs b/src/rngs/entropy.rs index fdcc3be52c6..cfb6490fbfe 100644 --- a/src/rngs/entropy.rs +++ b/src/rngs/entropy.rs @@ -18,6 +18,8 @@ use crate::rngs::OsRng; /// 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")] pub struct EntropyRng { diff --git a/src/rngs/mod.rs b/src/rngs/mod.rs index a9a03401c65..6d337e260e6 100644 --- a/src/rngs/mod.rs +++ b/src/rngs/mod.rs @@ -91,7 +91,6 @@ //! [`mock::StepRng`]: rngs::mock::StepRng //! [`adapter::ReadRng`]: rngs::adapter::ReadRng //! [`adapter::ReseedingRng`]: rngs::adapter::ReseedingRng -//! [`ChaCha20Rng`]: ../../rand_chacha/struct.ChaCha20Rng.html //! [`rdrand`]: https://crates.io/crates/rdrand //! [`rand_jitter`]: https://crates.io/crates/rand_jitter //! [`rand_chacha`]: https://crates.io/crates/rand_chacha diff --git a/src/seq/index.rs b/src/seq/index.rs index d524329e31f..0c9a477f24f 100644 --- a/src/seq/index.rs +++ b/src/seq/index.rs @@ -6,7 +6,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Index sampling +//! Low-level API for sampling indices #[cfg(feature="alloc")] use core::slice; diff --git a/src/seq/mod.rs b/src/seq/mod.rs index 0ad0474b5f8..1f3d103d495 100644 --- a/src/seq/mod.rs +++ b/src/seq/mod.rs @@ -6,9 +6,23 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Functions for randomly accessing and sampling sequences. +//! Sequence-related functionality //! -//! TODO: module doc +//! This module provides: +//! +//! * [`seq::SliceRandom`] slice sampling and mutation +//! * [`seq::IteratorRandom`] iterator sampling +//! * [`seq::index::sample`] low-level API to choose multiple indices from +//! `0..length` +//! +//! Also see: +//! +//! * [`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; @@ -23,8 +37,24 @@ use crate::Rng; /// Extension trait on slices, providing random mutation and sampling methods. /// -/// An implementation is provided for slices. This may also be implementable for -/// other types. +/// 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(); +/// bytes.shuffle(&mut rng); +/// let str = String::from_utf8(bytes).unwrap(); +/// println!("{}", str); +/// } +/// ``` +/// Example output (non-deterministic): +/// ```none +/// l,nmroHado !le +/// ``` pub trait SliceRandom { /// The element type. type Item; @@ -32,7 +62,7 @@ pub trait SliceRandom { /// Returns a reference to one random element of the slice, or `None` if the /// slice is empty. /// - /// Depending on the implementation, complexity is expected to be `O(1)`. + /// For slices, complexity is `O(1)`. /// /// # Example /// @@ -51,17 +81,17 @@ pub trait SliceRandom { /// Returns a mutable reference to one random element of the slice, or /// `None` if the slice is empty. /// - /// Depending on the implementation, complexity is expected to be `O(1)`. + /// For slices, complexity is `O(1)`. fn choose_mut(&mut self, rng: &mut R) -> Option<&mut Self::Item> where R: Rng + ?Sized; - /// Produces an iterator that chooses `amount` elements from the slice at - /// random without repeating any, and returns them in random order. + /// Chooses `amount` elements from the slice at random, without repetition, + /// and in random order. The returned iterator is appropriate both for + /// collection into a `Vec` and filling an existing buffer (see example). /// - /// In case this API is not sufficiently flexible, use `index::sample` then - /// apply the indices to the slice. + /// In case this API is not sufficiently flexible, use [`index::sample`]. /// - /// Complexity is expected to be the same as `index::sample`. + /// For slices, complexity is the same as [`index::sample`]. /// /// # Example /// ``` @@ -83,11 +113,16 @@ pub trait SliceRandom { fn choose_multiple(&self, rng: &mut R, amount: usize) -> SliceChooseIter where R: Rng + ?Sized; - /// Similar to [`choose`], where the likelihood of each outcome may be - /// specified. The specified function `weight` maps items `x` to a relative + /// 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)`. /// + /// For slices of length `n`, complexity is `O(n)`. + /// See also [`choose_weighted_mut`], [`distributions::weighted`]. + /// /// # Example /// /// ``` @@ -99,6 +134,8 @@ pub trait SliceRandom { /// println!("{:?}", choices.choose_weighted(&mut rng, |item| item.1).unwrap().0); /// ``` /// [`choose`]: SliceRandom::choose + /// [`choose_weighted_mut`]: SliceRandom::choose_weighted_mut + /// [`distributions::weighted`]: crate::distributions::weighted #[cfg(feature = "alloc")] fn choose_weighted( &self, rng: &mut R, weight: F, @@ -113,15 +150,19 @@ pub trait SliceRandom { + Clone + Default; - /// Similar to [`choose_mut`], where the likelihood of each outcome may be - /// specified. The specified function `weight` maps items `x` to a relative + /// 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)`. /// - /// See also [`choose_weighted`]. + /// For slices of length `n`, complexity is `O(n)`. + /// See also [`choose_weighted`], [`distributions::weighted`]. /// /// [`choose_mut`]: SliceRandom::choose_mut /// [`choose_weighted`]: SliceRandom::choose_weighted + /// [`distributions::weighted`]: crate::distributions::weighted #[cfg(feature = "alloc")] fn choose_weighted_mut( &mut self, rng: &mut R, weight: F, @@ -138,8 +179,7 @@ pub trait SliceRandom { /// Shuffle a mutable slice in place. /// - /// Depending on the implementation, complexity is expected to be `O(n)`, - /// where `n` is the length of the slice. + /// For slices of length `n`, complexity is `O(n)`. /// /// # Example /// @@ -172,7 +212,7 @@ pub trait SliceRandom { /// If `amount` is greater than the number of elements in the slice, this /// will perform a full shuffle. /// - /// Complexity is expected to be `O(m)` where `m = amount`. + /// For slices, complexity is `O(m)` where `m = amount`. fn partial_shuffle( &mut self, rng: &mut R, amount: usize, ) -> (&mut [Self::Item], &mut [Self::Item]) @@ -180,19 +220,37 @@ 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(); +/// +/// let faces = "😀😎😐😕😠😢"; +/// println!("I am {}!", faces.chars().choose(&mut rng).unwrap()); +/// } +/// ``` +/// Example output (non-deterministic): +/// ```none +/// I am 😀! +/// ``` pub trait IteratorRandom: Iterator + Sized { - /// Choose one element at random from the iterator. If you have a slice, - /// it's significantly faster to call the [`choose`] or [`choose_mut`] - /// functions using the slice instead. - /// + /// Choose one element at random from the iterator. + /// /// Returns `None` if and only if the iterator is empty. /// - /// Complexity is `O(n)`, where `n` is the length of the iterator. - /// This likely consumes multiple random numbers, but the exact number - /// is unspecified. - /// - /// [`choose`]: SliceRandom::method.choose - /// [`choose_mut`]: SliceRandom::choose_mut + /// This method uses [`Iterator::size_hint`] for optimisation. With an + /// accurate hint and where [`Iterator::nth`] is a constant-time operation + /// 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 where R: Rng + ?Sized { let (mut lower, mut upper) = self.size_hint(); @@ -251,6 +309,7 @@ pub trait IteratorRandom: Iterator + Sized { /// case this equals the number of elements available. /// /// Complexity is `O(n)` where `n` is the length of the iterator. + /// For slices, prefer [`SliceRandom::choose_multiple`]. fn choose_multiple_fill(mut self, rng: &mut R, buf: &mut [Self::Item]) -> usize where R: Rng + ?Sized { let amount = buf.len(); @@ -288,6 +347,7 @@ pub trait IteratorRandom: Iterator + Sized { /// elements available. /// /// Complexity is `O(n)` where `n` is the length of the iterator. + /// For slices, prefer [`SliceRandom::choose_multiple`]. #[cfg(feature = "alloc")] fn choose_multiple(mut self, rng: &mut R, amount: usize) -> Vec where R: Rng + ?Sized { @@ -418,7 +478,10 @@ impl SliceRandom for [T] { impl IteratorRandom for I where I: Iterator + Sized {} -/// Iterator over multiple choices, as returned by [`SliceRandom::choose_multiple] +/// An iterator over multiple slice elements. +/// +/// This struct is created by +/// [`SliceRandom::choose_multiple`](trait.SliceRandom.html#tymethod.choose_multiple). #[cfg(feature = "alloc")] #[derive(Debug)] pub struct SliceChooseIter<'a, S: ?Sized + 'a, T: 'a> {