Skip to content

Commit 58350a9

Browse files
committed
Merge branch 'master' into isaac_init
2 parents 130b64c + d511022 commit 58350a9

15 files changed

+288
-169
lines changed

benches/distributions.rs

+6-20
Original file line numberDiff line numberDiff line change
@@ -25,25 +25,12 @@ fn distr_baseline(b: &mut Bencher) {
2525
b.bytes = size_of::<u64>() as u64 * ::RAND_BENCH_N;
2626
}
2727

28-
#[bench]
29-
fn distr_range_int(b: &mut Bencher) {
30-
let mut rng = XorShiftRng::new().unwrap();
31-
let distr = Range::new(3i64, 134217671i64);
32-
33-
b.iter(|| {
34-
for _ in 0..::RAND_BENCH_N {
35-
black_box(distr.sample(&mut rng));
36-
}
37-
});
38-
b.bytes = size_of::<i64>() as u64 * ::RAND_BENCH_N;
39-
}
40-
41-
macro_rules! distr_range2_int {
28+
macro_rules! distr_range_int {
4229
($fnn:ident, $ty:ty, $low:expr, $high:expr) => {
4330
#[bench]
4431
fn $fnn(b: &mut Bencher) {
4532
let mut rng = XorShiftRng::new().unwrap();
46-
let distr = range2::Range::new($low, $high);
33+
let distr = Range::new($low, $high);
4734

4835
b.iter(|| {
4936
for _ in 0..::RAND_BENCH_N {
@@ -56,10 +43,10 @@ macro_rules! distr_range2_int {
5643
}
5744
}
5845

59-
distr_range2_int!(distr_range2_i8, i8, 20i8, 100);
60-
distr_range2_int!(distr_range2_i16, i16, -500i16, 2000);
61-
distr_range2_int!(distr_range2_i32, i32, -200_000_000i32, 800_000_000);
62-
distr_range2_int!(distr_range2_i64, i64, 3i64, 134217671);
46+
distr_range_int!(distr_range_i8, i8, 20i8, 100);
47+
distr_range_int!(distr_range_i16, i16, -500i16, 2000);
48+
distr_range_int!(distr_range_i32, i32, -200_000_000i32, 800_000_000);
49+
distr_range_int!(distr_range_i64, i64, 3i64, 134217671);
6350

6451
macro_rules! distr_float {
6552
($fnn:ident, $distr:expr) => {
@@ -83,7 +70,6 @@ distr_float!(distr_uniform01_float, Uniform01);
8370
distr_float!(distr_closed01_float, Closed01);
8471
distr_float!(distr_open01_float, Open01);
8572
distr_float!(distr_range_float, Range::new(2.26f64, 2.319f64));
86-
distr_float!(distr_range2_float, range2::Range::new(2.26f64, 2.319f64));
8773
distr_float!(distr_exp, Exp::new(2.71828 * 3.14159));
8874
distr_float!(distr_normal, Normal::new(-2.71828, 3.14159));
8975
distr_float!(distr_log_normal, LogNormal::new(-2.71828, 3.14159));

rand_core/src/impls.rs

+34-12
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
//! TODO: should we add more implementations?
2525
2626
use core::intrinsics::transmute;
27-
use {Rng, Result};
27+
use Rng;
2828

2929
/// Implement `next_u64` via `next_u32`, little-endian order.
3030
pub fn next_u64_via_u32<R: Rng+?Sized>(rng: &mut R) -> u64 {
@@ -45,7 +45,7 @@ pub fn next_u128_via_u64<R: Rng+?Sized>(rng: &mut R) -> u128 {
4545
(y << 64) | x
4646
}
4747

48-
macro_rules! try_fill_via {
48+
macro_rules! fill_bytes_via {
4949
($rng:ident, $next_u:ident, $BYTES:expr, $dest:ident) => {{
5050
let mut left = $dest;
5151
while left.len() >= $BYTES {
@@ -63,24 +63,46 @@ macro_rules! try_fill_via {
6363
};
6464
left.copy_from_slice(&chunk[..n]);
6565
}
66-
Ok(())
6766
}}
6867
}
6968

70-
/// Implement `try_fill` via `next_u32`, little-endian order.
71-
pub fn try_fill_via_u32<R: Rng+?Sized>(rng: &mut R, dest: &mut [u8]) -> Result<()> {
72-
try_fill_via!(rng, next_u32, 4, dest)
69+
/// Implement `fill_bytes` via `next_u32`, little-endian order.
70+
pub fn fill_bytes_via_u32<R: Rng+?Sized>(rng: &mut R, dest: &mut [u8]) {
71+
fill_bytes_via!(rng, next_u32, 4, dest)
7372
}
7473

75-
/// Implement `try_fill` via `next_u64`, little-endian order.
76-
pub fn try_fill_via_u64<R: Rng+?Sized>(rng: &mut R, dest: &mut [u8]) -> Result<()> {
77-
try_fill_via!(rng, next_u64, 8, dest)
74+
/// Implement `fill_bytes` via `next_u64`, little-endian order.
75+
pub fn fill_bytes_via_u64<R: Rng+?Sized>(rng: &mut R, dest: &mut [u8]) {
76+
fill_bytes_via!(rng, next_u64, 8, dest)
7877
}
7978

80-
/// Implement `try_fill` via `next_u128`, little-endian order.
79+
/// Implement `fill_bytes` via `next_u128`, little-endian order.
8180
#[cfg(feature = "i128_support")]
82-
pub fn try_fill_via_u128<R: Rng+?Sized>(rng: &mut R, dest: &mut [u8]) -> Result<()> {
83-
try_fill_via!(rng, next_u128, 16, dest)
81+
pub fn fill_bytes_via_u128<R: Rng+?Sized>(rng: &mut R, dest: &mut [u8]) {
82+
fill_bytes_via!(rng, next_u128, 16, dest)
83+
}
84+
85+
macro_rules! impl_uint_from_fill {
86+
($self:expr, $ty:ty, $N:expr) => ({
87+
// Transmute and convert from LE (i.e. byte-swap on BE)
88+
debug_assert!($N == ::core::mem::size_of::<$ty>());
89+
let mut buf = [0u8; $N];
90+
$self.fill_bytes(&mut buf);
91+
unsafe{ *(buf.as_ptr() as *const $ty) }.to_le()
92+
});
93+
}
94+
95+
pub fn next_u32_via_fill<R: Rng+?Sized>(rng: &mut R) -> u32 {
96+
impl_uint_from_fill!(rng, u32, 4)
97+
}
98+
99+
pub fn next_u64_via_fill<R: Rng+?Sized>(rng: &mut R) -> u64 {
100+
impl_uint_from_fill!(rng, u64, 8)
101+
}
102+
103+
#[cfg(feature = "i128_support")]
104+
pub fn next_u128_via_fill<R: Rng+?Sized>(rng: &mut R) -> u128 {
105+
impl_uint_from_fill!(rng, u128, 16)
84106
}
85107

86108
// TODO: implement tests for the above

rand_core/src/lib.rs

+93-21
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@
2020
//! `SeedFromRng` and `SeedableRng` are extension traits for construction and
2121
//! reseeding.
2222
//!
23-
//! `Error` and `Result` are provided for error-handling. They are safe to use
24-
//! in `no_std` environments.
23+
//! `Error` is provided for error-handling. It is safe to use in `no_std`
24+
//! environments.
2525
//!
2626
//! The `impls` sub-module includes a few small functions to assist
2727
//! implementation of `Rng`. Since this module is only of interest to `Rng`
@@ -43,6 +43,8 @@
4343
#[cfg(feature="std")]
4444
extern crate core;
4545

46+
use core::fmt;
47+
4648
pub mod impls;
4749
pub mod mock;
4850

@@ -89,16 +91,29 @@ pub trait Rng {
8991
/// Return the next random u128.
9092
#[cfg(feature = "i128_support")]
9193
fn next_u128(&mut self) -> u128;
92-
94+
95+
/// Fill `dest` entirely with random data.
96+
///
97+
/// This method does *not* have any requirement on how much of the
98+
/// generated random number stream is consumed; e.g. `fill_bytes_via_u64`
99+
/// implementation uses `next_u64` thus consuming 8 bytes even when only
100+
/// 1 is required. A different implementation might use `next_u32` and
101+
/// only consume 4 bytes; *however* any change affecting *reproducibility*
102+
/// of output must be considered a breaking change.
103+
fn fill_bytes(&mut self, dest: &mut [u8]);
104+
93105
/// Fill `dest` entirely with random data.
94106
///
107+
/// If a RNG can encounter an error, this is the only method that reports
108+
/// it. The other methods either handle the error, or panic.
109+
///
95110
/// This method does *not* have any requirement on how much of the
96111
/// generated random number stream is consumed; e.g. `try_fill_via_u64`
97112
/// implementation uses `next_u64` thus consuming 8 bytes even when only
98113
/// 1 is required. A different implementation might use `next_u32` and
99114
/// only consume 4 bytes; *however* any change affecting *reproducibility*
100115
/// of output must be considered a breaking change.
101-
fn try_fill(&mut self, dest: &mut [u8]) -> Result<()>;
116+
fn try_fill(&mut self, dest: &mut [u8]) -> Result<(), Error>;
102117
}
103118

104119
impl<'a, R: Rng+?Sized> Rng for &'a mut R {
@@ -115,7 +130,11 @@ impl<'a, R: Rng+?Sized> Rng for &'a mut R {
115130
(**self).next_u128()
116131
}
117132

118-
fn try_fill(&mut self, dest: &mut [u8]) -> Result<()> {
133+
fn fill_bytes(&mut self, dest: &mut [u8]) {
134+
(**self).fill_bytes(dest)
135+
}
136+
137+
fn try_fill(&mut self, dest: &mut [u8]) -> Result<(), Error> {
119138
(**self).try_fill(dest)
120139
}
121140
}
@@ -135,7 +154,11 @@ impl<R: Rng+?Sized> Rng for Box<R> {
135154
(**self).next_u128()
136155
}
137156

138-
fn try_fill(&mut self, dest: &mut [u8]) -> Result<()> {
157+
fn fill_bytes(&mut self, dest: &mut [u8]) {
158+
(**self).fill_bytes(dest)
159+
}
160+
161+
fn try_fill(&mut self, dest: &mut [u8]) -> Result<(), Error> {
139162
(**self).try_fill(dest)
140163
}
141164
}
@@ -158,10 +181,9 @@ pub trait SeedFromRng: Sized {
158181
/// hand, seeding a simple numerical generator from another of the same
159182
/// type sometimes has serious side effects such as effectively cloning the
160183
/// generator.
161-
fn from_rng<R: Rng+?Sized>(rng: &mut R) -> Result<Self>;
184+
fn from_rng<R: Rng+?Sized>(rng: &mut R) -> Result<Self, Error>;
162185
}
163186

164-
165187
/// A random number generator that can be explicitly seeded to produce
166188
/// the same stream of randomness multiple times.
167189
///
@@ -180,21 +202,71 @@ pub trait SeedableRng<Seed>: Rng {
180202
}
181203

182204

183-
/// Error type for cryptographic generators. Technically external generators
184-
/// such as the operating system or hardware generators could fail. A PRNG
185-
/// (algorithm) could also fail if it detects cycles, though most PRNGs have
186-
/// sufficiently long cycles that looping is not usually feasible.
187-
///
188-
/// TODO: how should error details be reported?
189-
#[derive(Debug)]
190-
pub struct Error;
205+
/// Error kind which can be matched over.
206+
#[derive(PartialEq, Eq, Debug, Copy, Clone)]
207+
pub enum ErrorKind {
208+
/// Permanent failure: likely not recoverable without user action.
209+
Unavailable,
210+
/// Temporary failure: recommended to retry a few times, but may also be
211+
/// irrecoverable.
212+
Transient,
213+
/// Not ready yet: recommended to try again a little later.
214+
NotReady,
215+
/// Uncategorised error
216+
Other,
217+
#[doc(hidden)]
218+
__Nonexhaustive,
219+
}
191220

192221
#[cfg(feature="std")]
193-
impl From<::std::io::Error> for Error {
194-
fn from(_: ::std::io::Error) -> Error {
195-
Error
222+
#[derive(Debug)]
223+
pub struct Error {
224+
pub kind: ErrorKind,
225+
pub cause: Option<Box<std::error::Error>>,
226+
}
227+
228+
#[cfg(not(feature="std"))]
229+
#[derive(Debug, Clone, PartialEq, Eq)]
230+
pub struct Error {
231+
pub kind: ErrorKind,
232+
pub cause: Option<&'static str>,
233+
}
234+
235+
impl Error {
236+
#[cfg(feature="std")]
237+
pub fn new(kind: ErrorKind, cause: Option<Box<std::error::Error>>) -> Error {
238+
Error {
239+
kind: kind,
240+
cause: cause,
241+
}
196242
}
197243
}
198244

199-
/// Result type (convenience type-def)
200-
pub type Result<T> = ::std::result::Result<T, Error>;
245+
impl fmt::Display for Error {
246+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
247+
match self.kind {
248+
ErrorKind::Unavailable => write!(f, "RNG not available."),
249+
ErrorKind::Transient => write!(f, "RNG has failed, probably temporary."),
250+
ErrorKind::NotReady => write!(f, "RNG not ready yet."),
251+
ErrorKind::Other => write!(f, "An unspecified RNG error occurred."),
252+
ErrorKind::__Nonexhaustive => unreachable!(),
253+
}
254+
}
255+
}
256+
257+
#[cfg(feature="std")]
258+
impl ::std::error::Error for Error {
259+
fn description(&self) -> &str {
260+
match self.kind {
261+
ErrorKind::Unavailable => "not available",
262+
ErrorKind::Transient => "temporary failure",
263+
ErrorKind::NotReady => "not ready yet",
264+
ErrorKind::Other => "Uncategorised rng error",
265+
ErrorKind::__Nonexhaustive => unreachable!(),
266+
}
267+
}
268+
269+
fn cause(&self) -> Option<&::std::error::Error> {
270+
self.cause.as_ref().map(|e| &**e)
271+
}
272+
}

rand_core/src/mock.rs

+13-5
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
//! Instead maybe this should be yet another crate? Or just leave it here?
1717
1818
use core::num::Wrapping as w;
19-
use {Rng, SeedableRng, impls, Result};
19+
use {Rng, SeedableRng, Error, impls};
2020

2121
/// A simple implementation of `Rng`, purely for testing.
2222
/// Returns an arithmetic sequence (i.e. adds a constant each step).
@@ -57,8 +57,12 @@ impl Rng for MockAddRng<u32> {
5757
impls::next_u128_via_u64(self)
5858
}
5959

60-
fn try_fill(&mut self, dest: &mut [u8]) -> Result<()> {
61-
impls::try_fill_via_u32(self, dest)
60+
fn fill_bytes(&mut self, dest: &mut [u8]) {
61+
impls::fill_bytes_via_u32(self, dest);
62+
}
63+
64+
fn try_fill(&mut self, dest: &mut [u8]) -> Result<(), Error> {
65+
Ok(self.fill_bytes(dest))
6266
}
6367
}
6468

@@ -76,8 +80,12 @@ impl Rng for MockAddRng<u64> {
7680
impls::next_u128_via_u64(self)
7781
}
7882

79-
fn try_fill(&mut self, dest: &mut [u8]) -> Result<()> {
80-
impls::try_fill_via_u32(self, dest)
83+
fn fill_bytes(&mut self, dest: &mut [u8]) {
84+
impls::fill_bytes_via_u64(self, dest);
85+
}
86+
87+
fn try_fill(&mut self, dest: &mut [u8]) -> Result<(), Error> {
88+
Ok(self.fill_bytes(dest))
8189
}
8290
}
8391

src/distributions/range.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ range_int_impl! { i16, i16, u16, i32, u32 }
210210
range_int_impl! { i32, i32, u32, i32, u32 }
211211
range_int_impl! { i64, i64, u64, i64, u64 }
212212
#[cfg(feature = "i128_support")]
213-
range_int_impl! { i128, i128, u128, u128 }
213+
range_int_impl! { i128, i128, u128, u128, u128 }
214214
range_int_impl! { isize, isize, usize, isize, usize }
215215
range_int_impl! { u8, i8, u8, i32, u32 }
216216
range_int_impl! { u16, i16, u16, i32, u32 }

0 commit comments

Comments
 (0)