@@ -352,27 +352,21 @@ where
352
352
{
353
353
#[ inline]
354
354
fn next_u32 ( & mut self ) -> u32 {
355
- let mut index = self . index * 2 - self . half_used as usize ;
356
- if index >= self . results . as_ref ( ) . len ( ) * 2 {
355
+ let mut index = self . index - self . half_used as usize ;
356
+ if index >= self . results . as_ref ( ) . len ( ) {
357
357
self . core . generate ( & mut self . results ) ;
358
358
self . index = 0 ;
359
+ index = 0 ;
359
360
// `self.half_used` is by definition `false`
360
361
self . half_used = false ;
361
- index = 0 ;
362
362
}
363
363
364
+ let shift = 32 * ( self . half_used as usize ) ;
365
+
364
366
self . half_used = !self . half_used ;
365
367
self . index += self . half_used as usize ;
366
368
367
- // Index as if this is a u32 slice.
368
- unsafe {
369
- let results = & * ( self . results . as_ref ( ) as * const [ u64 ] as * const [ u32 ] ) ;
370
- if cfg ! ( target_endian = "little" ) {
371
- * results. get_unchecked ( index)
372
- } else {
373
- * results. get_unchecked ( index ^ 1 )
374
- }
375
- }
369
+ ( self . results . as_ref ( ) [ index] >> shift) as u32
376
370
}
377
371
378
372
#[ inline]
@@ -435,3 +429,111 @@ impl<R: BlockRngCore + SeedableRng> SeedableRng for BlockRng64<R> {
435
429
}
436
430
437
431
impl < R : BlockRngCore + CryptoRng > CryptoRng for BlockRng < R > { }
432
+
433
+ #[ cfg( test) ]
434
+ mod test {
435
+ use crate :: { SeedableRng , RngCore } ;
436
+ use crate :: block:: { BlockRng , BlockRng64 , BlockRngCore } ;
437
+
438
+ #[ derive( Debug , Clone ) ]
439
+ struct DummyRng {
440
+ counter : u32 ,
441
+ }
442
+
443
+ impl BlockRngCore for DummyRng {
444
+ type Item = u32 ;
445
+
446
+ type Results = [ u32 ; 16 ] ;
447
+
448
+ fn generate ( & mut self , results : & mut Self :: Results ) {
449
+ for r in results {
450
+ * r = self . counter ;
451
+ self . counter = self . counter . wrapping_add ( 3511615421 ) ;
452
+ }
453
+ }
454
+ }
455
+
456
+ impl SeedableRng for DummyRng {
457
+ type Seed = [ u8 ; 4 ] ;
458
+
459
+ fn from_seed ( seed : Self :: Seed ) -> Self {
460
+ DummyRng { counter : u32:: from_le_bytes ( seed) }
461
+ }
462
+ }
463
+
464
+ #[ test]
465
+ fn blockrng_next_u32_vs_next_u64 ( ) {
466
+ let mut rng1 = BlockRng :: < DummyRng > :: from_seed ( [ 1 , 2 , 3 , 4 ] ) ;
467
+ let mut rng2 = rng1. clone ( ) ;
468
+ let mut rng3 = rng1. clone ( ) ;
469
+
470
+ let mut a = [ 0 ; 16 ] ;
471
+ ( & mut a[ ..4 ] ) . copy_from_slice ( & rng1. next_u32 ( ) . to_le_bytes ( ) ) ;
472
+ ( & mut a[ 4 ..12 ] ) . copy_from_slice ( & rng1. next_u64 ( ) . to_le_bytes ( ) ) ;
473
+ ( & mut a[ 12 ..] ) . copy_from_slice ( & rng1. next_u32 ( ) . to_le_bytes ( ) ) ;
474
+
475
+ let mut b = [ 0 ; 16 ] ;
476
+ ( & mut b[ ..4 ] ) . copy_from_slice ( & rng2. next_u32 ( ) . to_le_bytes ( ) ) ;
477
+ ( & mut b[ 4 ..8 ] ) . copy_from_slice ( & rng2. next_u32 ( ) . to_le_bytes ( ) ) ;
478
+ ( & mut b[ 8 ..] ) . copy_from_slice ( & rng2. next_u64 ( ) . to_le_bytes ( ) ) ;
479
+ assert_eq ! ( a, b) ;
480
+
481
+ let mut c = [ 0 ; 16 ] ;
482
+ ( & mut c[ ..8 ] ) . copy_from_slice ( & rng3. next_u64 ( ) . to_le_bytes ( ) ) ;
483
+ ( & mut c[ 8 ..12 ] ) . copy_from_slice ( & rng3. next_u32 ( ) . to_le_bytes ( ) ) ;
484
+ ( & mut c[ 12 ..] ) . copy_from_slice ( & rng3. next_u32 ( ) . to_le_bytes ( ) ) ;
485
+ assert_eq ! ( a, c) ;
486
+ }
487
+
488
+ #[ derive( Debug , Clone ) ]
489
+ struct DummyRng64 {
490
+ counter : u64 ,
491
+ }
492
+
493
+ impl BlockRngCore for DummyRng64 {
494
+ type Item = u64 ;
495
+
496
+ type Results = [ u64 ; 8 ] ;
497
+
498
+ fn generate ( & mut self , results : & mut Self :: Results ) {
499
+ for r in results {
500
+ * r = self . counter ;
501
+ self . counter = self . counter . wrapping_add ( 2781463553396133981 ) ;
502
+ }
503
+ }
504
+ }
505
+
506
+ impl SeedableRng for DummyRng64 {
507
+ type Seed = [ u8 ; 8 ] ;
508
+
509
+ fn from_seed ( seed : Self :: Seed ) -> Self {
510
+ DummyRng64 { counter : u64:: from_le_bytes ( seed) }
511
+ }
512
+ }
513
+
514
+ #[ test]
515
+ fn blockrng64_next_u32_vs_next_u64 ( ) {
516
+ let mut rng1 = BlockRng64 :: < DummyRng64 > :: from_seed ( [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 ] ) ;
517
+ let mut rng2 = rng1. clone ( ) ;
518
+ let mut rng3 = rng1. clone ( ) ;
519
+
520
+ let mut a = [ 0 ; 16 ] ;
521
+ ( & mut a[ ..4 ] ) . copy_from_slice ( & rng1. next_u32 ( ) . to_le_bytes ( ) ) ;
522
+ ( & mut a[ 4 ..12 ] ) . copy_from_slice ( & rng1. next_u64 ( ) . to_le_bytes ( ) ) ;
523
+ ( & mut a[ 12 ..] ) . copy_from_slice ( & rng1. next_u32 ( ) . to_le_bytes ( ) ) ;
524
+
525
+ let mut b = [ 0 ; 16 ] ;
526
+ ( & mut b[ ..4 ] ) . copy_from_slice ( & rng2. next_u32 ( ) . to_le_bytes ( ) ) ;
527
+ ( & mut b[ 4 ..8 ] ) . copy_from_slice ( & rng2. next_u32 ( ) . to_le_bytes ( ) ) ;
528
+ ( & mut b[ 8 ..] ) . copy_from_slice ( & rng2. next_u64 ( ) . to_le_bytes ( ) ) ;
529
+ assert_ne ! ( a, b) ;
530
+ assert_eq ! ( & a[ ..4 ] , & b[ ..4 ] ) ;
531
+ assert_eq ! ( & a[ 4 ..12 ] , & b[ 8 ..] ) ;
532
+
533
+ let mut c = [ 0 ; 16 ] ;
534
+ ( & mut c[ ..8 ] ) . copy_from_slice ( & rng3. next_u64 ( ) . to_le_bytes ( ) ) ;
535
+ ( & mut c[ 8 ..12 ] ) . copy_from_slice ( & rng3. next_u32 ( ) . to_le_bytes ( ) ) ;
536
+ ( & mut c[ 12 ..] ) . copy_from_slice ( & rng3. next_u32 ( ) . to_le_bytes ( ) ) ;
537
+ assert_eq ! ( b, c) ;
538
+ }
539
+ }
0 commit comments