Skip to content

Commit 22155f1

Browse files
authored
Merge pull request #812 from dhardy/doc
Document generation of array types using fill; support Wrapping types
2 parents 5c7bbea + 4c96015 commit 22155f1

File tree

2 files changed

+76
-31
lines changed

2 files changed

+76
-31
lines changed

src/distributions/mod.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -289,13 +289,15 @@ impl<D, R, T> iter::TrustedLen for DistIter<D, R, T>
289289
/// * Wrapping integers (`Wrapping<T>`), besides the type identical to their
290290
/// normal integer variants.
291291
///
292-
/// The following aggregate types also implement the distribution `Standard` as
293-
/// long as their component types implement it:
292+
/// The `Standard` distribution also supports generation of the following
293+
/// compound types where all component types are supported:
294294
///
295-
/// * Tuples and arrays: Each element of the tuple or array is generated
296-
/// independently, using the `Standard` distribution recursively.
297-
/// * `Option<T>` where `Standard` is implemented for `T`: Returns `None` with
298-
/// probability 0.5; otherwise generates a random `x: T` and returns `Some(x)`.
295+
/// * Tuples (up to 12 elements): each element is generated sequentially.
296+
/// * Arrays (up to 32 elements): each element is generated sequentially;
297+
/// see also [`Rng::fill`] which supports arbitrary array length for integer
298+
/// types and tends to be faster for `u32` and smaller types.
299+
/// * `Option<T>` first generates a `bool`, and if true generates and returns
300+
/// `Some(value)` where `value: T`, otherwise returning `None`.
299301
///
300302
/// ## Custom implementations
301303
///

src/lib.rs

Lines changed: 68 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ pub mod seq;
9292

9393

9494
use core::{mem, slice};
95+
use core::num::Wrapping;
9596
use distributions::{Distribution, Standard};
9697
use distributions::uniform::{SampleUniform, UniformSampler, SampleBorrow};
9798

@@ -135,8 +136,6 @@ use distributions::uniform::{SampleUniform, UniformSampler, SampleBorrow};
135136
pub trait Rng: RngCore {
136137
/// Return a random value supporting the [`Standard`] distribution.
137138
///
138-
/// [`Standard`]: distributions::Standard
139-
///
140139
/// # Example
141140
///
142141
/// ```
@@ -147,6 +146,28 @@ pub trait Rng: RngCore {
147146
/// println!("{}", x);
148147
/// println!("{:?}", rng.gen::<(f64, bool)>());
149148
/// ```
149+
///
150+
/// # Arrays and tuples
151+
///
152+
/// The `rng.gen()` method is able to generate arrays (up to 32 elements)
153+
/// and tuples (up to 12 elements), so long as all element types can be
154+
/// generated.
155+
///
156+
/// For arrays of integers, especially for those with small element types
157+
/// (< 64 bit), it will likely be faster to instead use [`Rng::fill`].
158+
///
159+
/// ```
160+
/// use rand::{thread_rng, Rng};
161+
///
162+
/// let mut rng = thread_rng();
163+
/// let tuple: (u8, i32, char) = rng.gen(); // arbitrary tuple support
164+
///
165+
/// let arr1: [f32; 32] = rng.gen(); // array construction
166+
/// let mut arr2 = [0u8; 128];
167+
/// rng.fill(&mut arr2); // array fill
168+
/// ```
169+
///
170+
/// [`Standard`]: distributions::Standard
150171
#[inline]
151172
fn gen<T>(&mut self) -> T
152173
where Standard: Distribution<T> {
@@ -378,6 +399,7 @@ impl AsByteSliceMut for [u8] {
378399
}
379400

380401
macro_rules! impl_as_byte_slice {
402+
() => {};
381403
($t:ty) => {
382404
impl AsByteSliceMut for [$t] {
383405
fn as_byte_slice_mut(&mut self) -> &mut [u8] {
@@ -402,26 +424,47 @@ macro_rules! impl_as_byte_slice {
402424
}
403425
}
404426
}
427+
428+
impl AsByteSliceMut for [Wrapping<$t>] {
429+
fn as_byte_slice_mut(&mut self) -> &mut [u8] {
430+
if self.len() == 0 {
431+
unsafe {
432+
// must not use null pointer
433+
slice::from_raw_parts_mut(0x1 as *mut u8, 0)
434+
}
435+
} else {
436+
unsafe {
437+
slice::from_raw_parts_mut(self.as_mut_ptr()
438+
as *mut u8,
439+
self.len() * mem::size_of::<$t>()
440+
)
441+
}
442+
}
443+
}
444+
445+
fn to_le(&mut self) {
446+
for x in self {
447+
*x = Wrapping(x.0.to_le());
448+
}
449+
}
450+
}
451+
};
452+
($t:ty, $($tt:ty,)*) => {
453+
impl_as_byte_slice!($t);
454+
// TODO: this could replace above impl once Rust #32463 is fixed
455+
// impl_as_byte_slice!(Wrapping<$t>);
456+
impl_as_byte_slice!($($tt,)*);
405457
}
406458
}
407459

408-
impl_as_byte_slice!(u16);
409-
impl_as_byte_slice!(u32);
410-
impl_as_byte_slice!(u64);
460+
impl_as_byte_slice!(u16, u32, u64, usize,);
411461
#[cfg(all(rustc_1_26, not(target_os = "emscripten")))] impl_as_byte_slice!(u128);
412-
impl_as_byte_slice!(usize);
413-
impl_as_byte_slice!(i8);
414-
impl_as_byte_slice!(i16);
415-
impl_as_byte_slice!(i32);
416-
impl_as_byte_slice!(i64);
462+
impl_as_byte_slice!(i8, i16, i32, i64, isize,);
417463
#[cfg(all(rustc_1_26, not(target_os = "emscripten")))] impl_as_byte_slice!(i128);
418-
impl_as_byte_slice!(isize);
419464

420465
macro_rules! impl_as_byte_slice_arrays {
421466
($n:expr,) => {};
422-
($n:expr, $N:ident, $($NN:ident,)*) => {
423-
impl_as_byte_slice_arrays!($n - 1, $($NN,)*);
424-
467+
($n:expr, $N:ident) => {
425468
impl<T> AsByteSliceMut for [T; $n] where [T]: AsByteSliceMut {
426469
fn as_byte_slice_mut(&mut self) -> &mut [u8] {
427470
self[..].as_byte_slice_mut()
@@ -432,25 +475,19 @@ macro_rules! impl_as_byte_slice_arrays {
432475
}
433476
}
434477
};
478+
($n:expr, $N:ident, $($NN:ident,)*) => {
479+
impl_as_byte_slice_arrays!($n, $N);
480+
impl_as_byte_slice_arrays!($n - 1, $($NN,)*);
481+
};
435482
(!div $n:expr,) => {};
436483
(!div $n:expr, $N:ident, $($NN:ident,)*) => {
484+
impl_as_byte_slice_arrays!($n, $N);
437485
impl_as_byte_slice_arrays!(!div $n / 2, $($NN,)*);
438-
439-
impl<T> AsByteSliceMut for [T; $n] where [T]: AsByteSliceMut {
440-
fn as_byte_slice_mut(&mut self) -> &mut [u8] {
441-
self[..].as_byte_slice_mut()
442-
}
443-
444-
fn to_le(&mut self) {
445-
self[..].to_le()
446-
}
447-
}
448486
};
449487
}
450488
impl_as_byte_slice_arrays!(32, N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,);
451489
impl_as_byte_slice_arrays!(!div 4096, N,N,N,N,N,N,N,);
452490

453-
454491
/// Generates a random value using the thread-local random number generator.
455492
///
456493
/// This is simply a shortcut for `thread_rng().gen()`. See [`thread_rng`] for
@@ -548,6 +585,12 @@ mod test {
548585
rng.fill(&mut array[..]);
549586
assert_eq!(array, [x as u32, (x >> 32) as u32]);
550587
assert_eq!(rng.next_u32(), x as u32);
588+
589+
// Check equivalence using wrapped arrays
590+
let mut warray = [Wrapping(0u32); 2];
591+
rng.fill(&mut warray[..]);
592+
assert_eq!(array[0], warray[0].0);
593+
assert_eq!(array[1], warray[1].0);
551594
}
552595

553596
#[test]

0 commit comments

Comments
 (0)