diff --git a/CHANGELOG.md b/CHANGELOG.md index 15347e017d..3300b9ad9f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,7 @@ You may also find the [Upgrade Guide](https://rust-random.github.io/book/update. - Require `Clone` and `AsRef` bound for `SeedableRng::Seed`. (#1491) - Implement `Distribution` for `Poisson` (#1498) - Limit the maximal acceptable lambda for `Poisson` to solve (#1312) (#1498) +- Rename `Rng::gen_iter` to `random_iter` (#1500) ## [0.9.0-alpha.1] - 2024-03-18 - Add the `Slice::num_choices` method to the Slice distribution (#1402) diff --git a/README.md b/README.md index 18f22a89eb..25341ac2d0 100644 --- a/README.md +++ b/README.md @@ -6,26 +6,31 @@ [![API](https://img.shields.io/badge/api-master-yellow.svg)](https://rust-random.github.io/rand/rand) [![API](https://docs.rs/rand/badge.svg)](https://docs.rs/rand) -A Rust library for random number generation, featuring: +Rand is a Rust library supporting random generators: -- Easy random value generation and usage via the [`Rng`](https://docs.rs/rand/*/rand/trait.Rng.html), - [`SliceRandom`](https://docs.rs/rand/*/rand/seq/trait.SliceRandom.html) and - [`IteratorRandom`](https://docs.rs/rand/*/rand/seq/trait.IteratorRandom.html) traits -- Secure seeding via the [`getrandom` crate](https://crates.io/crates/getrandom) - and fast, convenient generation via [`thread_rng`](https://docs.rs/rand/*/rand/fn.thread_rng.html) -- A modular design built over [`rand_core`](https://crates.io/crates/rand_core) - ([see the book](https://rust-random.github.io/book/crates.html)) +- A standard RNG trait: [`rand_core::RngCore`](https://docs.rs/rand_core/latest/rand_core/trait.RngCore.html) - Fast implementations of the best-in-class [cryptographic](https://rust-random.github.io/book/guide-rngs.html#cryptographically-secure-pseudo-random-number-generators-csprngs) and - [non-cryptographic](https://rust-random.github.io/book/guide-rngs.html#basic-pseudo-random-number-generators-prngs) generators + [non-cryptographic](https://rust-random.github.io/book/guide-rngs.html#basic-pseudo-random-number-generators-prngs) generators: [`rand::rngs`](https://docs.rs/rand/latest/rand/rngs/index.html), and more RNGs: [`rand_chacha`](https://docs.rs/rand_chacha), [`rand_xoshiro`](https://docs.rs/rand_xoshiro/), [`rand_pcg`](https://docs.rs/rand_pcg/), [rngs repo](https://github.com/rust-random/rngs/) +- [`rand::thread_rng`](https://docs.rs/rand/latest/rand/fn.thread_rng.html) is an asymtotically-fast, reasonably secure generator available on all `std` targets +- Secure seeding via the [`getrandom` crate](https://crates.io/crates/getrandom) + +Supporting random value generation and random processes: + +- [`Standard`](https://docs.rs/rand/latest/rand/distributions/struct.Standard.html) random value generation +- Ranged [`Uniform`](https://docs.rs/rand/latest/rand/distributions/struct.Uniform.html) number generation for many types - A flexible [`distributions`](https://docs.rs/rand/*/rand/distr/index.html) module - Samplers for a large number of random number distributions via our own [`rand_distr`](https://docs.rs/rand_distr) and via the [`statrs`](https://docs.rs/statrs/0.13.0/statrs/) +- Random processes (mostly choose and shuffle) via [`rand::seq`](https://docs.rs/rand/latest/rand/seq/index.html) traits + +All with: + - [Portably reproducible output](https://rust-random.github.io/book/portability.html) - `#[no_std]` compatibility (partial) - *Many* performance optimisations -It's also worth pointing out what `rand` *is not*: +It's also worth pointing out what Rand *is not*: - Small. Most low-level crates are small, but the higher-level `rand` and `rand_distr` each contain a lot of functionality. @@ -73,8 +78,7 @@ Rand is built with these features enabled by default: - `alloc` (implied by `std`) enables functionality requiring an allocator - `getrandom` (implied by `std`) is an optional dependency providing the code behind `rngs::OsRng` -- `std_rng` enables inclusion of `StdRng`, `thread_rng` and `random` - (the latter two *also* require that `std` be enabled) +- `std_rng` enables inclusion of `StdRng`, `thread_rng` Optionally, the following dependencies can be enabled: @@ -94,8 +98,7 @@ experimental `simd_support` feature. Rand supports limited functionality in `no_std` mode (enabled via `default-features = false`). In this case, `OsRng` and `from_os_rng` are unavailable (unless `getrandom` is enabled), large parts of `seq` are -unavailable (unless `alloc` is enabled), and `thread_rng` and `random` are -unavailable. +unavailable (unless `alloc` is enabled), and `thread_rng` is unavailable. ## Portability and platform support diff --git a/benches/benches/seq_choose.rs b/benches/benches/seq_choose.rs index f418f9cc4d..58c4f894ea 100644 --- a/benches/benches/seq_choose.rs +++ b/benches/benches/seq_choose.rs @@ -19,7 +19,7 @@ criterion_group!( criterion_main!(benches); pub fn bench(c: &mut Criterion) { - c.bench_function("seq_slice_choose_1_of_1000", |b| { + c.bench_function("seq_slice_choose_1_of_100", |b| { let mut rng = Pcg32::from_rng(thread_rng()); let mut buf = [0i32; 100]; rng.fill(&mut buf); diff --git a/rand_core/src/lib.rs b/rand_core/src/lib.rs index 3c16a9767c..39e95d95db 100644 --- a/rand_core/src/lib.rs +++ b/rand_core/src/lib.rs @@ -54,11 +54,11 @@ pub use getrandom; #[cfg(feature = "getrandom")] pub use os::OsRng; -/// The core of a random number generator. +/// Implementation-level interface for RNGs /// /// This trait encapsulates the low-level functionality common to all /// generators, and is the "back end", to be implemented by generators. -/// End users should normally use the `Rng` trait from the [`rand`] crate, +/// End users should normally use the [`rand::Rng`] trait /// which is automatically implemented for every type implementing `RngCore`. /// /// Three different methods for generating random data are provided since the @@ -129,7 +129,7 @@ pub use os::OsRng; /// rand_core::impl_try_rng_from_rng_core!(CountingRng); /// ``` /// -/// [`rand`]: https://docs.rs/rand +/// [`rand::Rng`]: https://docs.rs/rand/latest/rand/trait.Rng.html /// [`fill_bytes`]: RngCore::fill_bytes /// [`next_u32`]: RngCore::next_u32 /// [`next_u64`]: RngCore::next_u64 diff --git a/rand_distr/src/weighted_alias.rs b/rand_distr/src/weighted_alias.rs index 593219cafd..537060f388 100644 --- a/rand_distr/src/weighted_alias.rs +++ b/rand_distr/src/weighted_alias.rs @@ -275,9 +275,10 @@ where } } -/// Trait that must be implemented for weights, that are used with -/// [`WeightedAliasIndex`]. Currently no guarantees on the correctness of -/// [`WeightedAliasIndex`] are given for custom implementations of this trait. +/// Weight bound for [`WeightedAliasIndex`] +/// +/// Currently no guarantees on the correctness of [`WeightedAliasIndex`] are +/// given for custom implementations of this trait. pub trait AliasableWeight: Sized + Copy diff --git a/src/lib.rs b/src/lib.rs index 3abbc5a266..958c15d481 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,25 +14,24 @@ //! //! # Quick Start //! -//! To get you started quickly, the easiest and highest-level way to get -//! a random value is to use [`random()`]; alternatively you can use -//! [`thread_rng()`]. The [`Rng`] trait provides a useful API on all RNGs, while -//! the [`distr`] and [`seq`] modules provide further -//! functionality on top of RNGs. -//! //! ``` +//! // The prelude import enables methods we use below, specifically +//! // Rng::random, Rng::sample, SliceRandom::shuffle and IndexedRandom::choose. //! use rand::prelude::*; //! -//! if rand::random() { // generates a boolean -//! // Try printing a random unicode code point (probably a bad idea)! -//! println!("char: {}", rand::random::()); -//! } -//! +//! // Get an RNG: //! let mut rng = rand::thread_rng(); -//! let y: f64 = rng.random(); // generates a float between 0 and 1 //! +//! // Try printing a random unicode code point (probably a bad idea)! +//! println!("char: '{}'", rng.random::()); +//! // Try printing a random alphanumeric value instead! +//! println!("alpha: '{}'", rng.sample(rand::distr::Alphanumeric) as char); +//! +//! // Generate and shuffle a sequence: //! let mut nums: Vec = (1..100).collect(); //! nums.shuffle(&mut rng); +//! // And take a random pick (yes, we didn't need to shuffle first!): +//! let _ = nums.choose(&mut rng); //! ``` //! //! # The Book diff --git a/src/rng.rs b/src/rng.rs index 9190747a29..7c9e887a2d 100644 --- a/src/rng.rs +++ b/src/rng.rs @@ -15,10 +15,14 @@ use core::num::Wrapping; use core::{mem, slice}; use rand_core::RngCore; -/// An automatically-implemented extension trait on [`RngCore`] providing high-level -/// generic methods for sampling values and other convenience methods. +/// User-level interface for RNGs /// -/// This is the primary trait to use when generating random values. +/// [`RngCore`] is the `dyn`-safe implementation-level interface for Random +/// (Number) Generators. This trait, `Rng`, provides a user-level interface on +/// RNGs. It is implemented automatically for any `R: RngCore`. +/// +/// This trait must usually be brought into scope via `use rand::Rng;` or +/// `use rand::prelude::*;`. /// /// # Generic usage /// @@ -96,55 +100,13 @@ pub trait Rng: RngCore { Standard.sample(self) } - /// Generate a random value in the given range. - /// - /// This function is optimised for the case that only a single sample is - /// made from the given range. See also the [`Uniform`] distribution - /// type which may be faster if sampling from the same range repeatedly. - /// - /// All types support `low..high_exclusive` and `low..=high` range syntax. - /// Unsigned integer types also support `..high_exclusive` and `..=high` syntax. - /// - /// # Panics - /// - /// Panics if the range is empty, or if `high - low` overflows for floats. - /// - /// # Example - /// - /// ``` - /// use rand::{thread_rng, Rng}; - /// - /// let mut rng = thread_rng(); - /// - /// // Exclusive range - /// let n: u32 = rng.gen_range(..10); - /// println!("{}", n); - /// let m: f64 = rng.gen_range(-40.0..1.3e5); - /// println!("{}", m); - /// - /// // Inclusive range - /// let n: u32 = rng.gen_range(..=10); - /// println!("{}", n); - /// ``` - /// - /// [`Uniform`]: distr::uniform::Uniform - #[track_caller] - fn gen_range(&mut self, range: R) -> T - where - T: SampleUniform, - R: SampleRange, - { - assert!(!range.is_empty(), "cannot sample empty range"); - range.sample_single(self).unwrap() - } - - /// Generate values via an iterator + /// Return an iterator over [`random`](Self::random) variates /// /// This is a just a wrapper over [`Rng::sample_iter`] using /// [`distr::Standard`]. /// /// Note: this method consumes its argument. Use - /// `(&mut rng).gen_iter()` to avoid consuming the RNG. + /// `(&mut rng).random_iter()` to avoid consuming the RNG. /// /// # Example /// @@ -152,11 +114,11 @@ pub trait Rng: RngCore { /// use rand::{rngs::mock::StepRng, Rng}; /// /// let rng = StepRng::new(1, 1); - /// let v: Vec = rng.gen_iter().take(5).collect(); + /// let v: Vec = rng.random_iter().take(5).collect(); /// assert_eq!(&v, &[1, 2, 3, 4, 5]); /// ``` #[inline] - fn gen_iter(self) -> distr::DistIter + fn random_iter(self) -> distr::DistIter where Self: Sized, Standard: Distribution, @@ -247,6 +209,48 @@ pub trait Rng: RngCore { dest.fill(self) } + /// Generate a random value in the given range. + /// + /// This function is optimised for the case that only a single sample is + /// made from the given range. See also the [`Uniform`] distribution + /// type which may be faster if sampling from the same range repeatedly. + /// + /// All types support `low..high_exclusive` and `low..=high` range syntax. + /// Unsigned integer types also support `..high_exclusive` and `..=high` syntax. + /// + /// # Panics + /// + /// Panics if the range is empty, or if `high - low` overflows for floats. + /// + /// # Example + /// + /// ``` + /// use rand::{thread_rng, Rng}; + /// + /// let mut rng = thread_rng(); + /// + /// // Exclusive range + /// let n: u32 = rng.gen_range(..10); + /// println!("{}", n); + /// let m: f64 = rng.gen_range(-40.0..1.3e5); + /// println!("{}", m); + /// + /// // Inclusive range + /// let n: u32 = rng.gen_range(..=10); + /// println!("{}", n); + /// ``` + /// + /// [`Uniform`]: distr::uniform::Uniform + #[track_caller] + fn gen_range(&mut self, range: R) -> T + where + T: SampleUniform, + R: SampleRange, + { + assert!(!range.is_empty(), "cannot sample empty range"); + range.sample_single(self).unwrap() + } + /// Return a bool with a probability `p` of being true. /// /// See also the [`Bernoulli`] distribution, which may be faster if @@ -316,7 +320,7 @@ pub trait Rng: RngCore { since = "0.9.0", note = "Renamed to `random` to avoid conflict with the new `gen` keyword in Rust 2024." )] - fn gen(&mut self) -> T + fn r#gen(&mut self) -> T where Standard: Distribution, { @@ -474,8 +478,8 @@ mod test { // Check equivalence for generated floats let mut array = [0f32; 2]; rng.fill(&mut array); - let gen: [f32; 2] = rng.random(); - assert_eq!(array, gen); + let arr2: [f32; 2] = rng.random(); + assert_eq!(array, arr2); } #[test] diff --git a/src/seq/index.rs b/src/seq/index.rs index 5bb1a7597f..e66b503988 100644 --- a/src/seq/index.rs +++ b/src/seq/index.rs @@ -282,10 +282,12 @@ where } } -/// Randomly sample exactly `amount` distinct indices from `0..length`, and -/// return them in an arbitrary order (there is no guarantee of shuffling or -/// ordering). The weights are to be provided by the input function `weights`, -/// which will be called once for each index. +/// Randomly sample exactly `amount` distinct indices from `0..length` +/// +/// Results are in arbitrary order (there is no guarantee of shuffling or +/// ordering). +/// +/// Function `weight` is called once for each index to provide weights. /// /// This method is used internally by the slice sampling methods, but it can /// sometimes be useful to have the indices themselves so this is provided as