@@ -277,6 +277,7 @@ use distributions::range::SampleRange;
277
277
278
278
// public modules
279
279
pub mod distributions;
280
+ mod impls;
280
281
pub mod jitter;
281
282
#[ cfg( feature="std" ) ] pub mod os;
282
283
#[ cfg( feature="std" ) ] pub mod read;
@@ -338,21 +339,28 @@ pub trait Rand : Sized {
338
339
339
340
/// A random number generator.
340
341
pub trait Rng {
341
- /// Return the next random u32.
342
- ///
343
- /// This rarely needs to be called directly, prefer `r.gen()` to
344
- /// `r.next_u32()`.
345
- // FIXME #rust-lang/rfcs#628: Should be implemented in terms of next_u64
342
+ /// Return the next random `u32`.
343
+ ///
344
+ /// Implementations of this trait must implement at least one of
345
+ /// `next_u32`, `next_u64` and `fill_bytes` directly. In the case this
346
+ /// function is not implemented directly, it can be implemented using
347
+ /// `self.next_u64() as u32` or via `fill_bytes` (TODO: expose helper
348
+ /// function).
346
349
fn next_u32 ( & mut self ) -> u32 ;
347
350
348
- /// Return the next random u64.
349
- ///
350
- /// By default this is implemented in terms of `next_u32`. An
351
- /// implementation of this trait must provide at least one of
352
- /// these two methods. Similarly to `next_u32`, this rarely needs
353
- /// to be called directly, prefer `r.gen()` to `r.next_u64()`.
351
+ /// Return the next random `u64`.
352
+ ///
353
+ /// Implementations of this trait must implement at least one of
354
+ /// `next_u32`, `next_u64` and `fill_bytes` directly. In the case this
355
+ /// function is not implemented directly, the default implementation will
356
+ /// generate values via `next_u32` in little-endian fashion, or this
357
+ /// function can be implemented via `fill_bytes` (TODO: expose helper
358
+ /// function).
359
+ ///
360
+ /// Types wrapping an inner RNG must not use the default implementation,
361
+ /// since the inner RNG's implementation may produce different values.
354
362
fn next_u64 ( & mut self ) -> u64 {
355
- ( ( self . next_u32 ( ) as u64 ) << 32 ) | ( self . next_u32 ( ) as u64 )
363
+ impls :: next_u64_via_u32 ( self )
356
364
}
357
365
358
366
/// Return the next random f32 selected from the half-open
@@ -408,18 +416,22 @@ pub trait Rng {
408
416
}
409
417
410
418
/// Fill `dest` with random data.
411
- ///
412
- /// This has a default implementation in terms of `next_u64` and
413
- /// `next_u32`, but should be overridden by implementations that
414
- /// offer a more efficient solution than just calling those
415
- /// methods repeatedly.
416
- ///
417
- /// This method does *not* have a requirement to bear any fixed
418
- /// relationship to the other methods, for example, it does *not*
419
- /// have to result in the same output as progressively filling
420
- /// `dest` with `self.gen::<u8>()`, and any such behaviour should
421
- /// not be relied upon.
422
- ///
419
+ ///
420
+ /// Implementations of this trait must implement at least one of
421
+ /// `next_u32`, `next_u64` and `fill_bytes` directly. In the case this
422
+ /// function is not implemented directly, the default implementation will
423
+ /// generate values via `next_u64` in little-endian fashion.
424
+ /// (TODO: expose helper function to allow implementation via `next_u32`.)
425
+ ///
426
+ /// There is no requirement on how this method generates values relative to
427
+ /// `next_u32` or `next_u64`; e.g. a `u64` cast to bytes is not required to
428
+ /// have the same value as eight bytes filled via this function. There *is*
429
+ /// a requirement of portability for reproducible generators which implies
430
+ /// that any seedable generator must fix endianness when generating bytes.
431
+ ///
432
+ /// Types wrapping an inner RNG must not use the default implementation,
433
+ /// since the inner RNG's implementation may produce different values.
434
+ ///
423
435
/// This method should guarantee that `dest` is entirely filled
424
436
/// with new data, and may panic if this is impossible
425
437
/// (e.g. reading past the end of a file that is being used as the
@@ -435,27 +447,7 @@ pub trait Rng {
435
447
/// println!("{:?}", &v[..]);
436
448
/// ```
437
449
fn fill_bytes ( & mut self , dest : & mut [ u8 ] ) {
438
- // this could, in theory, be done by transmuting dest to a
439
- // [u64], but this is (1) likely to be undefined behaviour for
440
- // LLVM, (2) has to be very careful about alignment concerns,
441
- // (3) adds more `unsafe` that needs to be checked, (4)
442
- // probably doesn't give much performance gain if
443
- // optimisations are on.
444
- let mut count = 0 ;
445
- let mut num = 0 ;
446
- for byte in dest. iter_mut ( ) {
447
- if count == 0 {
448
- // we could micro-optimise here by generating a u32 if
449
- // we only need a few more bytes to fill the vector
450
- // (i.e. at most 4).
451
- num = self . next_u64 ( ) ;
452
- count = 8 ;
453
- }
454
-
455
- * byte = ( num & 0xff ) as u8 ;
456
- num >>= 8 ;
457
- count -= 1 ;
458
- }
450
+ impls:: fill_bytes_via_u64 ( self , dest)
459
451
}
460
452
461
453
/// Return a random value of a `Rand` type.
@@ -768,7 +760,7 @@ pub struct Closed01<F>(pub F);
768
760
769
761
/// The standard RNG. This is designed to be efficient on the current
770
762
/// platform.
771
- #[ derive( Copy , Clone , Debug ) ]
763
+ #[ derive( Clone , Debug ) ]
772
764
pub struct StdRng {
773
765
rng : IsaacWordRng ,
774
766
}
@@ -811,6 +803,11 @@ impl Rng for StdRng {
811
803
fn next_u64 ( & mut self ) -> u64 {
812
804
self . rng . next_u64 ( )
813
805
}
806
+
807
+ #[ inline]
808
+ fn fill_bytes ( & mut self , dest : & mut [ u8 ] ) {
809
+ self . rng . fill_bytes ( dest)
810
+ }
814
811
}
815
812
816
813
impl < ' a > SeedableRng < & ' a [ usize ] > for StdRng {
@@ -985,17 +982,21 @@ pub fn sample<T, I, R>(rng: &mut R, iterable: I, amount: usize) -> Vec<T>
985
982
986
983
#[ cfg( test) ]
987
984
mod test {
985
+ use impls;
988
986
use super :: { Rng , thread_rng, random, SeedableRng , StdRng , weak_rng} ;
989
987
use std:: iter:: repeat;
990
988
991
989
pub struct MyRng < R > { inner : R }
992
990
993
991
impl < R : Rng > Rng for MyRng < R > {
994
992
fn next_u32 ( & mut self ) -> u32 {
995
- fn next < T : Rng > ( t : & mut T ) -> u32 {
996
- t. next_u32 ( )
997
- }
998
- next ( & mut self . inner )
993
+ self . inner . next_u32 ( )
994
+ }
995
+ fn next_u64 ( & mut self ) -> u64 {
996
+ self . inner . next_u64 ( )
997
+ }
998
+ fn fill_bytes ( & mut self , dest : & mut [ u8 ] ) {
999
+ self . inner . fill_bytes ( dest)
999
1000
}
1000
1001
}
1001
1002
@@ -1007,8 +1008,10 @@ mod test {
1007
1008
impl Rng for ConstRng {
1008
1009
fn next_u32 ( & mut self ) -> u32 { self . i as u32 }
1009
1010
fn next_u64 ( & mut self ) -> u64 { self . i }
1010
-
1011
- // no fill_bytes on purpose
1011
+
1012
+ fn fill_bytes ( & mut self , dest : & mut [ u8 ] ) {
1013
+ impls:: fill_bytes_via_u64 ( self , dest)
1014
+ }
1012
1015
}
1013
1016
1014
1017
pub fn iter_eq < I , J > ( i : I , j : J ) -> bool
0 commit comments