rand/seq/mod.rs
1// Copyright 2018-2023 Developers of the Rand project.
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9//! Sequence-related functionality
10//!
11//! This module provides:
12//!
13//! * [`IndexedRandom`] for sampling slices and other indexable lists
14//! * [`IndexedMutRandom`] for sampling slices and other mutably indexable lists
15//! * [`SliceRandom`] for mutating slices
16//! * [`IteratorRandom`] for sampling iterators
17//! * [`index::sample`] low-level API to choose multiple indices from
18//! `0..length`
19//!
20//! Also see:
21//!
22//! * [`crate::distr::weighted::WeightedIndex`] distribution which provides
23//! weighted index sampling.
24//!
25//! In order to make results reproducible across 32-64 bit architectures, all
26//! `usize` indices are sampled as a `u32` where possible (also providing a
27//! small performance boost in some cases).
28
29mod coin_flipper;
30mod increasing_uniform;
31mod iterator;
32mod slice;
33
34#[cfg(feature = "alloc")]
35#[path = "index.rs"]
36mod index_;
37
38#[cfg(feature = "alloc")]
39#[doc(no_inline)]
40pub use crate::distr::weighted::Error as WeightError;
41pub use iterator::IteratorRandom;
42#[cfg(feature = "alloc")]
43pub use slice::IndexedSamples;
44#[allow(deprecated)]
45#[cfg(feature = "alloc")]
46pub use slice::SliceChooseIter;
47pub use slice::{IndexedMutRandom, IndexedRandom, SliceRandom};
48
49/// Low-level API for sampling indices
50pub mod index {
51 use crate::Rng;
52
53 #[cfg(feature = "alloc")]
54 #[doc(inline)]
55 pub use super::index_::*;
56
57 /// Randomly sample exactly `N` distinct indices from `0..len`, and
58 /// return them in random order (fully shuffled).
59 ///
60 /// This is implemented via Floyd's algorithm. Time complexity is `O(N^2)`
61 /// and memory complexity is `O(N)`.
62 ///
63 /// Returns `None` if (and only if) `N > len`.
64 pub fn sample_array<R, const N: usize>(rng: &mut R, len: usize) -> Option<[usize; N]>
65 where
66 R: Rng + ?Sized,
67 {
68 if N > len {
69 return None;
70 }
71
72 // Floyd's algorithm
73 let mut indices = [0; N];
74 for (i, j) in (len - N..len).enumerate() {
75 let t = rng.random_range(..j + 1);
76 if let Some(pos) = indices[0..i].iter().position(|&x| x == t) {
77 indices[pos] = j;
78 }
79 indices[i] = t;
80 }
81 Some(indices)
82 }
83}