Skip to content

Commit

Permalink
Merge pull request #828 from dhardy/doc
Browse files Browse the repository at this point in the history
Seq module doc
  • Loading branch information
dhardy committed Jun 26, 2019
2 parents 41bc963 + 07361e7 commit b15e9ec
Show file tree
Hide file tree
Showing 10 changed files with 114 additions and 43 deletions.
5 changes: 1 addition & 4 deletions rand_chacha/src/chacha.rs
Expand Up @@ -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
/// 2<sup>64</sup> 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:
///
Expand All @@ -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>,
Expand Down
6 changes: 4 additions & 2 deletions rand_distr/src/pert.rs
Expand Up @@ -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
Expand All @@ -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<N> {
min: N,
Expand Down
4 changes: 3 additions & 1 deletion rand_distr/src/triangular.rs
Expand Up @@ -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
///
Expand All @@ -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<N> {
min: N,
Expand Down
11 changes: 9 additions & 2 deletions src/distributions/weighted/mod.rs
Expand Up @@ -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;

Expand Down
2 changes: 1 addition & 1 deletion src/rngs/adapter/read.rs
Expand Up @@ -41,7 +41,7 @@ use rand_core::{RngCore, Error, impls};
/// println!("{:x}", rng.gen::<u32>());
/// ```
///
/// [`OsRng`]: rngs::OsRng
/// [`OsRng`]: crate::rngs::OsRng
/// [`try_fill_bytes`]: RngCore::try_fill_bytes
#[derive(Debug)]
pub struct ReadRng<R> {
Expand Down
1 change: 0 additions & 1 deletion src/rngs/adapter/reseeding.rs
Expand Up @@ -72,7 +72,6 @@ use rand_core::block::{BlockRngCore, BlockRng};
/// assert!(reseeding_rng.gen::<u64>() != cloned_rng.gen::<u64>());
/// ```
///
/// [`ChaCha20Core`]: ../../../rand_chacha/struct.ChaCha20Core.html
/// [`BlockRngCore`]: rand_core::block::BlockRngCore
/// [`ReseedingRng::new`]: ReseedingRng::new
/// [`reseed()`]: ReseedingRng::reseed
Expand Down
2 changes: 2 additions & 0 deletions src/rngs/entropy.rs
Expand Up @@ -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 {
Expand Down
1 change: 0 additions & 1 deletion src/rngs/mod.rs
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion src/seq/index.rs
Expand Up @@ -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;

Expand Down
123 changes: 93 additions & 30 deletions src/seq/mod.rs
Expand Up @@ -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;
Expand All @@ -23,16 +37,32 @@ 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;

/// 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
///
Expand All @@ -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<R>(&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
/// ```
Expand All @@ -83,11 +113,16 @@ pub trait SliceRandom {
fn choose_multiple<R>(&self, rng: &mut R, amount: usize) -> SliceChooseIter<Self, Self::Item>
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
///
/// ```
Expand All @@ -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<R, F, B, X>(
&self, rng: &mut R, weight: F,
Expand All @@ -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<R, F, B, X>(
&mut self, rng: &mut R, weight: F,
Expand All @@ -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
///
Expand Down Expand Up @@ -172,27 +212,45 @@ 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<R>(
&mut self, rng: &mut R, amount: usize,
) -> (&mut [Self::Item], &mut [Self::Item])
where R: Rng + ?Sized;
}

/// Extension trait on iterators, providing random sampling methods.
///
/// 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<R>(mut self, rng: &mut R) -> Option<Self::Item>
where R: Rng + ?Sized {
let (mut lower, mut upper) = self.size_hint();
Expand Down Expand Up @@ -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<R>(mut self, rng: &mut R, buf: &mut [Self::Item]) -> usize
where R: Rng + ?Sized {
let amount = buf.len();
Expand Down Expand Up @@ -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<R>(mut self, rng: &mut R, amount: usize) -> Vec<Self::Item>
where R: Rng + ?Sized {
Expand Down Expand Up @@ -418,7 +478,10 @@ impl<T> SliceRandom for [T] {
impl<I> 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> {
Expand Down

0 comments on commit b15e9ec

Please sign in to comment.