Skip to content

Commit 73ea9db

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 73ea9db

File tree

3 files changed

+25
-46
lines changed

3 files changed

+25
-46
lines changed

library/core/src/random.rs

Lines changed: 20 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
//! The [`Random`] trait allows generating a random value for a type using a
44
//! given [`RandomSource`].
55
6+
use crate::range::RangeFull;
7+
68
/// A source of randomness.
79
#[unstable(feature = "random", issue = "130703")]
810
pub trait RandomSource {
@@ -15,39 +17,33 @@ pub trait RandomSource {
1517
fn fill_bytes(&mut self, bytes: &mut [u8]);
1618
}
1719

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.
20+
/// A trait representing a distribution of random values for a type.
2521
#[unstable(feature = "random", issue = "130703")]
26-
pub trait Random: Sized {
27-
/// Generates a random value.
28-
fn random(source: &mut (impl RandomSource + ?Sized)) -> Self;
22+
pub trait Distribution<T> {
23+
/// Samples a random value from the distribution, using the specified random source.
24+
fn sample(&self, source: &mut (impl RandomSource + ?Sized)) -> T;
25+
}
26+
27+
impl<T, DT: Distribution<T>> Distribution<T> for &DT {
28+
fn sample(&self, source: &mut (impl RandomSource + ?Sized)) -> T {
29+
(*self).sample(source)
30+
}
2931
}
3032

31-
impl Random for bool {
32-
fn random(source: &mut (impl RandomSource + ?Sized)) -> Self {
33-
u8::random(source) & 1 == 1
33+
impl Distribution<bool> for RangeFull {
34+
fn sample(&self, source: &mut (impl RandomSource + ?Sized)) -> bool {
35+
let byte: u8 = RangeFull.sample(source);
36+
byte & 1 == 1
3437
}
3538
}
3639

3740
macro_rules! impl_primitive {
3841
($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();
42+
impl Distribution<$t> for RangeFull {
43+
fn sample(&self, source: &mut (impl RandomSource + ?Sized)) -> $t {
44+
let mut bytes = (0 as $t).to_ne_bytes();
4945
source.fill_bytes(&mut bytes);
50-
Self::from_ne_bytes(bytes)
46+
<$t>::from_ne_bytes(bytes)
5147
}
5248
}
5349
};

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: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -68,19 +68,13 @@ impl RandomSource for DefaultRandomSource {
6868
}
6969
}
7070

71-
/// Generates a random value with the default random source.
71+
/// Generates a random value from a distribution, using the default random source.
7272
///
73-
/// This is a convenience function for `T::random(&mut DefaultRandomSource)` and
73+
/// This is a convenience function for `dist.sample(&mut DefaultRandomSource)` and
7474
/// will sample according to the same distribution as the underlying [`Random`]
7575
/// trait implementation. See [`DefaultRandomSource`] for more information about
7676
/// how randomness is sourced.
7777
///
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.
83-
///
8478
/// # Examples
8579
///
8680
/// Generating a [version 4/variant 1 UUID] represented as text:
@@ -89,7 +83,7 @@ impl RandomSource for DefaultRandomSource {
8983
///
9084
/// use std::random::random;
9185
///
92-
/// let bits: u128 = random();
86+
/// let bits: u128 = random(..);
9387
/// let g1 = (bits >> 96) as u32;
9488
/// let g2 = (bits >> 80) as u16;
9589
/// let g3 = (0x4000 | (bits >> 64) & 0x0fff) as u16;
@@ -101,6 +95,6 @@ impl RandomSource for DefaultRandomSource {
10195
///
10296
/// [version 4/variant 1 UUID]: https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random)
10397
#[unstable(feature = "random", issue = "130703")]
104-
pub fn random<T: Random>() -> T {
105-
T::random(&mut DefaultRandomSource)
98+
pub fn random<T>(dist: impl Distribution<T>) -> T {
99+
dist.sample(&mut DefaultRandomSource)
106100
}

0 commit comments

Comments
 (0)