10
10
11
11
//! The ISAAC random number generator.
12
12
13
- use rand:: { seed, Rng } ;
14
- use iter:: { Iterator , range, range_step} ;
13
+ use rand:: { seed, Rng , SeedableRng } ;
14
+ use iter:: { Iterator , range, range_step, Repeat } ;
15
15
use option:: { None , Some } ;
16
16
17
- use cast;
18
- use cmp;
19
- use sys;
20
- use vec;
21
-
22
17
static RAND_SIZE_LEN : u32 = 8 ;
23
18
static RAND_SIZE : u32 = 1 << RAND_SIZE_LEN ;
24
19
@@ -38,30 +33,8 @@ pub struct IsaacRng {
38
33
impl IsaacRng {
39
34
/// Create an ISAAC random number generator with a random seed.
40
35
pub fn new ( ) -> IsaacRng {
41
- IsaacRng :: new_seeded ( seed ( RAND_SIZE as uint * 4 ) )
42
- }
43
-
44
- /// Create an ISAAC random number generator with a seed. This can be any
45
- /// length, although the maximum number of bytes used is 1024 and any more
46
- /// will be silently ignored. A generator constructed with a given seed
47
- /// will generate the same sequence of values as all other generators
48
- /// constructed with the same seed.
49
- pub fn new_seeded ( seed : & [ u8 ] ) -> IsaacRng {
50
- let mut rng = IsaacRng {
51
- cnt : 0 ,
52
- rsl : [ 0 , .. RAND_SIZE ] ,
53
- mem : [ 0 , .. RAND_SIZE ] ,
54
- a : 0 , b : 0 , c : 0
55
- } ;
56
-
57
- let array_size = sys:: size_of_val ( & rng. rsl ) ;
58
- let copy_length = cmp:: min ( array_size, seed. len ( ) ) ;
59
-
60
- // manually create a &mut [u8] slice of randrsl to copy into.
61
- let dest = unsafe { cast:: transmute ( ( & mut rng. rsl , array_size) ) } ;
62
- vec:: bytes:: copy_memory ( dest, seed, copy_length) ;
63
- rng. init ( true ) ;
64
- rng
36
+ let s = unsafe { seed :: < u32 > ( RAND_SIZE as uint ) } ;
37
+ SeedableRng :: from_seed ( s. as_slice ( ) )
65
38
}
66
39
67
40
/// Create an ISAAC random number generator using the default
@@ -197,6 +170,43 @@ impl Rng for IsaacRng {
197
170
}
198
171
}
199
172
173
+ impl < ' self > SeedableRng < & ' self [ u32 ] > for IsaacRng {
174
+ fn reseed ( & mut self , seed : & ' self [ u32 ] ) {
175
+ // make the seed into [seed[0], seed[1], ..., seed[seed.len()
176
+ // - 1], 0, 0, ...], to fill rng.rsl.
177
+ let seed_iter = seed. iter ( ) . map ( |& x| x) . chain ( Repeat :: new ( 0u32 ) ) ;
178
+
179
+ for ( rsl_elem, seed_elem) in self . rsl . mut_iter ( ) . zip ( seed_iter) {
180
+ * rsl_elem = seed_elem;
181
+ }
182
+ self . cnt = 0 ;
183
+ self . a = 0 ;
184
+ self . b = 0 ;
185
+ self . c = 0 ;
186
+
187
+ self . init ( true ) ;
188
+ }
189
+
190
+ /// Create an ISAAC random number generator with a seed. This can
191
+ /// be any length, although the maximum number of elements used is
192
+ /// 256 and any more will be silently ignored. A generator
193
+ /// constructed with a given seed will generate the same sequence
194
+ /// of values as all other generators constructed with that seed.
195
+ fn from_seed ( seed : & ' self [ u32 ] ) -> IsaacRng {
196
+ let mut rng = IsaacRng {
197
+ cnt : 0 ,
198
+ rsl : [ 0 , .. RAND_SIZE ] ,
199
+ mem : [ 0 , .. RAND_SIZE ] ,
200
+ a : 0 , b : 0 , c : 0
201
+ } ;
202
+
203
+ rng. reseed ( seed) ;
204
+
205
+ rng
206
+ }
207
+ }
208
+
209
+
200
210
static RAND_SIZE_64_LEN : uint = 8 ;
201
211
static RAND_SIZE_64 : uint = 1 << RAND_SIZE_64_LEN ;
202
212
@@ -218,31 +228,8 @@ impl Isaac64Rng {
218
228
/// Create a 64-bit ISAAC random number generator with a random
219
229
/// seed.
220
230
pub fn new ( ) -> Isaac64Rng {
221
- Isaac64Rng :: new_seeded ( seed ( RAND_SIZE_64 as uint * 8 ) )
222
- }
223
-
224
- /// Create a 64-bit ISAAC random number generator with a
225
- /// seed. This can be any length, although the maximum number of
226
- /// bytes used is 2048 and any more will be silently ignored. A
227
- /// generator constructed with a given seed will generate the same
228
- /// sequence of values as all other generators constructed with
229
- /// the same seed.
230
- pub fn new_seeded ( seed : & [ u8 ] ) -> Isaac64Rng {
231
- let mut rng = Isaac64Rng {
232
- cnt : 0 ,
233
- rsl : [ 0 , .. RAND_SIZE_64 ] ,
234
- mem : [ 0 , .. RAND_SIZE_64 ] ,
235
- a : 0 , b : 0 , c : 0 ,
236
- } ;
237
-
238
- let array_size = sys:: size_of_val ( & rng. rsl ) ;
239
- let copy_length = cmp:: min ( array_size, seed. len ( ) ) ;
240
-
241
- // manually create a &mut [u8] slice of randrsl to copy into.
242
- let dest = unsafe { cast:: transmute ( ( & mut rng. rsl , array_size) ) } ;
243
- vec:: bytes:: copy_memory ( dest, seed, copy_length) ;
244
- rng. init ( true ) ;
245
- rng
231
+ let s = unsafe { seed :: < u64 > ( RAND_SIZE_64 ) } ;
232
+ SeedableRng :: from_seed ( s. as_slice ( ) )
246
233
}
247
234
248
235
/// Create a 64-bit ISAAC random number generator using the
@@ -378,52 +365,118 @@ impl Rng for Isaac64Rng {
378
365
}
379
366
}
380
367
368
+ impl < ' self > SeedableRng < & ' self [ u64 ] > for Isaac64Rng {
369
+ fn reseed ( & mut self , seed : & ' self [ u64 ] ) {
370
+ // make the seed into [seed[0], seed[1], ..., seed[seed.len()
371
+ // - 1], 0, 0, ...], to fill rng.rsl.
372
+ let seed_iter = seed. iter ( ) . map ( |& x| x) . chain ( Repeat :: new ( 0u64 ) ) ;
373
+
374
+ for ( rsl_elem, seed_elem) in self . rsl . mut_iter ( ) . zip ( seed_iter) {
375
+ * rsl_elem = seed_elem;
376
+ }
377
+ self . cnt = 0 ;
378
+ self . a = 0 ;
379
+ self . b = 0 ;
380
+ self . c = 0 ;
381
+
382
+ self . init ( true ) ;
383
+ }
384
+
385
+ /// Create an ISAAC random number generator with a seed. This can
386
+ /// be any length, although the maximum number of elements used is
387
+ /// 256 and any more will be silently ignored. A generator
388
+ /// constructed with a given seed will generate the same sequence
389
+ /// of values as all other generators constructed with that seed.
390
+ fn from_seed ( seed : & ' self [ u64 ] ) -> Isaac64Rng {
391
+ let mut rng = Isaac64Rng {
392
+ cnt : 0 ,
393
+ rsl : [ 0 , .. RAND_SIZE_64 ] ,
394
+ mem : [ 0 , .. RAND_SIZE_64 ] ,
395
+ a : 0 , b : 0 , c : 0 ,
396
+ } ;
397
+ rng. reseed ( seed) ;
398
+ rng
399
+ }
400
+ }
401
+
381
402
#[ cfg( test) ]
382
403
mod test {
383
404
use super :: * ;
384
- use rand:: { Rng , seed} ;
385
- use option:: { Option , Some } ;
405
+ use rand:: { Rng , SeedableRng , seed} ;
406
+ use option:: Some ;
407
+ use iter:: range;
408
+ use vec;
386
409
387
410
#[ test]
388
411
fn test_rng_seeded ( ) {
389
- let seed = seed ( 1024 ) ;
390
- let mut ra = IsaacRng :: new_seeded ( seed ) ;
391
- let mut rb = IsaacRng :: new_seeded ( seed ) ;
412
+ let s = unsafe { seed :: < u32 > ( 256 ) } ;
413
+ let mut ra: IsaacRng = SeedableRng :: from_seed ( s . as_slice ( ) ) ;
414
+ let mut rb: IsaacRng = SeedableRng :: from_seed ( s . as_slice ( ) ) ;
392
415
assert_eq ! ( ra. gen_ascii_str( 100 u) , rb. gen_ascii_str( 100 u) ) ;
393
416
394
- let seed = seed ( 2048 ) ;
395
- let mut ra = Isaac64Rng :: new_seeded ( seed ) ;
396
- let mut rb = Isaac64Rng :: new_seeded ( seed ) ;
417
+ let s = unsafe { seed :: < u64 > ( 256 ) } ;
418
+ let mut ra: Isaac64Rng = SeedableRng :: from_seed ( s . as_slice ( ) ) ;
419
+ let mut rb: Isaac64Rng = SeedableRng :: from_seed ( s . as_slice ( ) ) ;
397
420
assert_eq ! ( ra. gen_ascii_str( 100 u) , rb. gen_ascii_str( 100 u) ) ;
398
421
}
399
422
400
423
#[ test]
401
424
fn test_rng_seeded_custom_seed ( ) {
402
425
// much shorter than generated seeds which are 1024 & 2048
403
426
// bytes resp.
404
- let seed = [ 2u8 , 32u8 , 4u8 , 32u8 , 51u8 ] ;
405
- let mut ra = IsaacRng :: new_seeded ( seed) ;
406
- let mut rb = IsaacRng :: new_seeded ( seed) ;
427
+ let seed = & [ 2 , 32 , 4 , 32 , 51 ] ;
428
+ let mut ra: IsaacRng = SeedableRng :: from_seed ( seed) ;
429
+ let mut rb: IsaacRng = SeedableRng :: from_seed ( seed) ;
407
430
assert_eq ! ( ra. gen_ascii_str( 100 u) , rb. gen_ascii_str( 100 u) ) ;
408
431
409
- let mut ra = Isaac64Rng :: new_seeded ( seed) ;
410
- let mut rb = Isaac64Rng :: new_seeded ( seed) ;
432
+ let seed = & [ 2 , 32 , 4 , 32 , 51 ] ;
433
+ let mut ra: Isaac64Rng = SeedableRng :: from_seed ( seed) ;
434
+ let mut rb: Isaac64Rng = SeedableRng :: from_seed ( seed) ;
411
435
assert_eq ! ( ra. gen_ascii_str( 100 u) , rb. gen_ascii_str( 100 u) ) ;
412
436
}
413
437
414
438
#[ test]
415
- fn test_rng_seeded_custom_seed2 ( ) {
416
- let seed = [ 2u8 , 32u8 , 4u8 , 32u8 , 51u8 ] ;
417
- let mut ra = IsaacRng :: new_seeded ( seed) ;
439
+ fn test_rng_32_true_values ( ) {
440
+ let seed = & [ 2 , 32 , 4 , 32 , 51 ] ;
441
+ let mut ra: IsaacRng = SeedableRng :: from_seed ( seed) ;
418
442
// Regression test that isaac is actually using the above vector
419
- let r = ra. next_u32 ( ) ;
420
- error2 ! ( "{:?}" , r) ;
421
- assert_eq ! ( r, 2935188040u32 ) ;
422
-
423
- let mut ra = Isaac64Rng :: new_seeded ( seed) ;
443
+ let v = vec:: from_fn ( 10 , |_| ra. next_u32 ( ) ) ;
444
+ assert_eq ! ( v,
445
+ ~[ 447462228 , 2081944040 , 3163797308 , 2379916134 , 2377489184 ,
446
+ 1132373754 , 536342443 , 2995223415 , 1265094839 , 345325140 ] ) ;
447
+
448
+ let seed = & [ 500 , -4000 , 123456 , 9876543 , 1 , 1 , 1 , 1 , 1 ] ;
449
+ let mut rb: IsaacRng = SeedableRng :: from_seed ( seed) ;
450
+ // skip forward to the 10000th number
451
+ for _ in range ( 0 , 10000 ) { rb. next_u32 ( ) ; }
452
+
453
+ let v = vec:: from_fn ( 10 , |_| rb. next_u32 ( ) ) ;
454
+ assert_eq ! ( v,
455
+ ~[ 612373032 , 292987903 , 1819311337 , 3141271980 , 422447569 ,
456
+ 310096395 , 1083172510 , 867909094 , 2478664230 , 2073577855 ] ) ;
457
+ }
458
+ #[ test]
459
+ fn test_rng_64_true_values ( ) {
460
+ let seed = & [ 2 , 32 , 4 , 32 , 51 ] ;
461
+ let mut ra: Isaac64Rng = SeedableRng :: from_seed ( seed) ;
424
462
// Regression test that isaac is actually using the above vector
425
- let r = ra. next_u64 ( ) ;
426
- error2 ! ( "{:?}" , r) ;
427
- assert ! ( r == 0 && r == 1 ) ; // FIXME: find true value
463
+ let v = vec:: from_fn ( 10 , |_| ra. next_u64 ( ) ) ;
464
+ assert_eq ! ( v,
465
+ ~[ 15015576812873463115 , 12461067598045625862 , 14818626436142668771 ,
466
+ 5562406406765984441 , 11813289907965514161 , 13443797187798420053 ,
467
+ 6935026941854944442 , 7750800609318664042 , 14428747036317928637 ,
468
+ 14028894460301215947 ] ) ;
469
+
470
+ let seed = & [ 500 , -4000 , 123456 , 9876543 , 1 , 1 , 1 , 1 , 1 ] ;
471
+ let mut rb: Isaac64Rng = SeedableRng :: from_seed ( seed) ;
472
+ // skip forward to the 10000th number
473
+ for _ in range ( 0 , 10000 ) { rb. next_u64 ( ) ; }
474
+
475
+ let v = vec:: from_fn ( 10 , |_| rb. next_u64 ( ) ) ;
476
+ assert_eq ! ( v,
477
+ ~[ 13557216323596688637 , 17060829581390442094 , 4927582063811333743 ,
478
+ 2699639759356482270 , 4819341314392384881 , 6047100822963614452 ,
479
+ 11086255989965979163 , 11901890363215659856 , 5370800226050011580 ,
480
+ 16496463556025356451 ] ) ;
428
481
}
429
482
}
0 commit comments