Skip to content

Commit 5e20385

Browse files
committed
random: Provide a Distribution<T> trait
This will let people make calls like random(1..=6), and allows for future expansion to non-uniform distributions, as well as floating-point. For now, this is only implemented for `RangeFull`, to get the interface in place. Subsequent commits will implement it for other range types.
1 parent 4c94798 commit 5e20385

File tree

4 files changed

+27
-57
lines changed

4 files changed

+27
-57
lines changed

library/core/src/primitive_docs.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1081,13 +1081,11 @@ mod prim_str {}
10811081
/// * [`Debug`]
10821082
/// * [`Default`]
10831083
/// * [`Hash`]
1084-
/// * [`Random`]
10851084
/// * [`From<[T; N]>`][from]
10861085
///
10871086
/// [from]: convert::From
10881087
/// [`Debug`]: fmt::Debug
10891088
/// [`Hash`]: hash::Hash
1090-
/// [`Random`]: random::Random
10911089
///
10921090
/// The following traits are implemented for tuples of any length. These traits have
10931091
/// implementations that are automatically generated by the compiler, so are not limited by

library/core/src/random.rs

Lines changed: 20 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
//! Random value generation.
2-
//!
3-
//! The [`Random`] trait allows generating a random value for a type using a
4-
//! given [`RandomSource`].
2+
3+
use crate::range::RangeFull;
54

65
/// A source of randomness.
76
#[unstable(feature = "random", issue = "130703")]
@@ -15,39 +14,33 @@ pub trait RandomSource {
1514
fn fill_bytes(&mut self, bytes: &mut [u8]);
1615
}
1716

18-
/// A trait for getting a random value for a type.
19-
///
20-
/// **Warning:** Be careful when manipulating random values! The
21-
/// [`random`](Random::random) method on integers samples them with a uniform
22-
/// distribution, so a value of 1 is just as likely as [`i32::MAX`]. By using
23-
/// modulo operations, some of the resulting values can become more likely than
24-
/// others. Use audited crates when in doubt.
17+
/// A trait representing a distribution of random values for a type.
2518
#[unstable(feature = "random", issue = "130703")]
26-
pub trait Random: Sized {
27-
/// Generates a random value.
28-
fn random(source: &mut (impl RandomSource + ?Sized)) -> Self;
19+
pub trait Distribution<T> {
20+
/// Samples a random value from the distribution, using the specified random source.
21+
fn sample(&self, source: &mut (impl RandomSource + ?Sized)) -> T;
22+
}
23+
24+
impl<T, DT: Distribution<T>> Distribution<T> for &DT {
25+
fn sample(&self, source: &mut (impl RandomSource + ?Sized)) -> T {
26+
(*self).sample(source)
27+
}
2928
}
3029

31-
impl Random for bool {
32-
fn random(source: &mut (impl RandomSource + ?Sized)) -> Self {
33-
u8::random(source) & 1 == 1
30+
impl Distribution<bool> for RangeFull {
31+
fn sample(&self, source: &mut (impl RandomSource + ?Sized)) -> bool {
32+
let byte: u8 = RangeFull.sample(source);
33+
byte & 1 == 1
3434
}
3535
}
3636

3737
macro_rules! impl_primitive {
3838
($t:ty) => {
39-
impl Random for $t {
40-
/// Generates a random value.
41-
///
42-
/// **Warning:** Be careful when manipulating the resulting value! This
43-
/// method samples according to a uniform distribution, so a value of 1 is
44-
/// just as likely as [`MAX`](Self::MAX). By using modulo operations, some
45-
/// values can become more likely than others. Use audited crates when in
46-
/// doubt.
47-
fn random(source: &mut (impl RandomSource + ?Sized)) -> Self {
48-
let mut bytes = (0 as Self).to_ne_bytes();
39+
impl Distribution<$t> for RangeFull {
40+
fn sample(&self, source: &mut (impl RandomSource + ?Sized)) -> $t {
41+
let mut bytes = (0 as $t).to_ne_bytes();
4942
source.fill_bytes(&mut bytes);
50-
Self::from_ne_bytes(bytes)
43+
<$t>::from_ne_bytes(bytes)
5144
}
5245
}
5346
};

library/core/src/tuple.rs

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
use crate::cmp::Ordering::{self, *};
44
use crate::marker::{ConstParamTy_, StructuralPartialEq, UnsizedConstParamTy};
55
use crate::ops::ControlFlow::{self, Break, Continue};
6-
use crate::random::{Random, RandomSource};
76

87
// Recursive macro for implementing n-ary tuple functions and operations
98
//
@@ -131,16 +130,6 @@ macro_rules! tuple_impls {
131130
}
132131
}
133132

134-
maybe_tuple_doc! {
135-
$($T)+ @
136-
#[unstable(feature = "random", issue = "130703")]
137-
impl<$($T: Random),+> Random for ($($T,)+) {
138-
fn random(source: &mut (impl RandomSource + ?Sized)) -> Self {
139-
($({ let x: $T = Random::random(source); x},)+)
140-
}
141-
}
142-
}
143-
144133
maybe_tuple_doc! {
145134
$($T)+ @
146135
#[stable(feature = "array_tuple_conv", since = "1.71.0")]

library/std/src/random.rs

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
11
//! Random value generation.
2-
//!
3-
//! The [`Random`] trait allows generating a random value for a type using a
4-
//! given [`RandomSource`].
52
63
#[unstable(feature = "random", issue = "130703")]
74
pub use core::random::*;
@@ -68,18 +65,11 @@ impl RandomSource for DefaultRandomSource {
6865
}
6966
}
7067

71-
/// Generates a random value with the default random source.
68+
/// Generates a random value from a distribution, using the default random source.
7269
///
73-
/// This is a convenience function for `T::random(&mut DefaultRandomSource)` and
74-
/// will sample according to the same distribution as the underlying [`Random`]
75-
/// trait implementation. See [`DefaultRandomSource`] for more information about
76-
/// how randomness is sourced.
77-
///
78-
/// **Warning:** Be careful when manipulating random values! The
79-
/// [`random`](Random::random) method on integers samples them with a uniform
80-
/// distribution, so a value of 1 is just as likely as [`i32::MAX`]. By using
81-
/// modulo operations, some of the resulting values can become more likely than
82-
/// others. Use audited crates when in doubt.
70+
/// This is a convenience function for `dist.sample(&mut DefaultRandomSource)` and will sample
71+
/// according to the same distribution as the underlying [`Distribution`] trait implementation. See
72+
/// [`DefaultRandomSource`] for more information about how randomness is sourced.
8373
///
8474
/// # Examples
8575
///
@@ -89,7 +79,7 @@ impl RandomSource for DefaultRandomSource {
8979
///
9080
/// use std::random::random;
9181
///
92-
/// let bits: u128 = random();
82+
/// let bits: u128 = random(..);
9383
/// let g1 = (bits >> 96) as u32;
9484
/// let g2 = (bits >> 80) as u16;
9585
/// let g3 = (0x4000 | (bits >> 64) & 0x0fff) as u16;
@@ -101,6 +91,6 @@ impl RandomSource for DefaultRandomSource {
10191
///
10292
/// [version 4/variant 1 UUID]: https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random)
10393
#[unstable(feature = "random", issue = "130703")]
104-
pub fn random<T: Random>() -> T {
105-
T::random(&mut DefaultRandomSource)
94+
pub fn random<T>(dist: impl Distribution<T>) -> T {
95+
dist.sample(&mut DefaultRandomSource)
10696
}

0 commit comments

Comments
 (0)