@@ -72,12 +72,12 @@ const RAND_SIZE: usize = 1 << RAND_SIZE_LEN;
72
72
/// [1]: Bob Jenkins, [*ISAAC and RC4*]
73
73
/// (http://burtleburtle.net/bob/rand/isaac.html)
74
74
pub struct Isaac64Rng {
75
- rsl : [ w64 ; RAND_SIZE ] ,
75
+ rsl : [ u64 ; RAND_SIZE ] ,
76
76
mem : [ w64 ; RAND_SIZE ] ,
77
77
a : w64 ,
78
78
b : w64 ,
79
79
c : w64 ,
80
- cnt : u32 ,
80
+ index : u32 ,
81
81
}
82
82
83
83
// Cannot be derived because [u64; 256] does not implement Clone
@@ -90,7 +90,7 @@ impl Clone for Isaac64Rng {
90
90
a : self . a ,
91
91
b : self . b ,
92
92
c : self . c ,
93
- cnt : self . cnt ,
93
+ index : self . index ,
94
94
}
95
95
}
96
96
}
@@ -133,20 +133,23 @@ impl Isaac64Rng {
133
133
/// - We maintain one index `i` and add `m` or `m2` as base (m2 for the
134
134
/// `s[i+128 mod 256]`), relying on the optimizer to turn it into pointer
135
135
/// arithmetic.
136
+ /// - We fill `rsl` backwards. The reference implementation reads values
137
+ /// from `rsl` in reverse. We read them in the normal direction, to make
138
+ /// `fill_bytes` a memcopy. To maintain compatibility we fill in reverse.
136
139
fn isaac64 ( & mut self ) {
137
140
self . c += w ( 1 ) ;
138
141
// abbreviations
139
142
let mut a = self . a ;
140
143
let mut b = self . b + self . c ;
141
144
const MIDPOINT : usize = RAND_SIZE / 2 ;
142
145
143
- #[ inline( always ) ]
146
+ #[ inline]
144
147
fn ind ( mem : & [ w64 ; RAND_SIZE ] , v : w64 , amount : usize ) -> w64 {
145
148
let index = ( v >> amount) . 0 as usize % RAND_SIZE ;
146
149
mem[ index]
147
150
}
148
151
149
- #[ inline( always ) ]
152
+ #[ inline]
150
153
fn rngstep ( ctx : & mut Isaac64Rng ,
151
154
mix : w64 ,
152
155
a : & mut w64 ,
@@ -159,7 +162,7 @@ impl Isaac64Rng {
159
162
let y = * a + * b + ind ( & ctx. mem , x, 3 ) ;
160
163
ctx. mem [ base + m] = y;
161
164
* b = x + ind ( & ctx. mem , y, 3 + RAND_SIZE_LEN ) ;
162
- ctx. rsl [ base + m] = * b ;
165
+ ctx. rsl [ RAND_SIZE - 1 - base - m] = ( * b ) . 0 ;
163
166
}
164
167
165
168
let mut m = 0 ;
@@ -182,7 +185,7 @@ impl Isaac64Rng {
182
185
183
186
self . a = a;
184
187
self . b = b;
185
- self . cnt = RAND_SIZE as u32 ;
188
+ self . index = 0 ;
186
189
}
187
190
}
188
191
@@ -194,28 +197,31 @@ impl Rng for Isaac64Rng {
194
197
195
198
#[ inline]
196
199
fn next_u64 ( & mut self ) -> u64 {
197
- if self . cnt == 0 {
198
- // make some more numbers
200
+ let mut index = self . index as usize ;
201
+ if index >= RAND_SIZE {
199
202
self . isaac64 ( ) ;
203
+ index = 0 ;
200
204
}
201
- self . cnt -= 1 ;
202
-
203
- // self.cnt is at most RAND_SIZE, but that is before the
204
- // subtraction above. We want to index without bounds
205
- // checking, but this could lead to incorrect code if someone
206
- // misrefactors, so we check, sometimes.
207
- //
208
- // (Changes here should be reflected in IsaacRng.next_u32.)
209
- debug_assert ! ( ( self . cnt as usize ) < RAND_SIZE ) ;
210
-
211
- // (the % is cheaply telling the optimiser that we're always
212
- // in bounds, without unsafe. NB. this is a power of two, so
213
- // it optimises to a bitwise mask).
214
- self . rsl [ self . cnt as usize % RAND_SIZE ] . 0
205
+
206
+ let value = self . rsl [ index] ;
207
+ self . index += 1 ;
208
+ value
215
209
}
216
210
217
211
fn fill_bytes ( & mut self , dest : & mut [ u8 ] ) {
218
- impls:: fill_bytes_via_u64 ( self , dest)
212
+ let mut read_len = 0 ;
213
+ while read_len < dest. len ( ) {
214
+ if self . index as usize >= RAND_SIZE {
215
+ self . isaac64 ( ) ;
216
+ }
217
+
218
+ let ( consumed_u64, filled_u8) =
219
+ impls:: fill_via_u64_chunks ( & mut self . rsl [ ( self . index as usize ) ..] ,
220
+ & mut dest[ read_len..] ) ;
221
+
222
+ self . index += consumed_u64 as u32 ;
223
+ read_len += filled_u8;
224
+ }
219
225
}
220
226
}
221
227
@@ -251,12 +257,12 @@ fn init(mut mem: [w64; RAND_SIZE], rounds: u32) -> Isaac64Rng {
251
257
}
252
258
253
259
let mut rng = Isaac64Rng {
254
- rsl : [ w ( 0 ) ; RAND_SIZE ] ,
260
+ rsl : [ 0 ; RAND_SIZE ] ,
255
261
mem : mem,
256
262
a : w ( 0 ) ,
257
263
b : w ( 0 ) ,
258
264
c : w ( 0 ) ,
259
- cnt : 0 ,
265
+ index : 0 ,
260
266
} ;
261
267
262
268
// Prepare the first set of results
0 commit comments