Skip to content

Commit d4c73e2

Browse files
committed
Remove complex indexing, use a bool.
[Cherry-picked from 0bdb1c3]
1 parent 53ac84f commit d4c73e2

File tree

1 file changed

+21
-26
lines changed

1 file changed

+21
-26
lines changed

src/prng/isaac64.rs

Lines changed: 21 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ pub struct Isaac64Rng {
7878
b: w64,
7979
c: w64,
8080
index: u32,
81+
half_used: bool, // true if only half of the previous result is used
8182
}
8283

8384
// Cannot be derived because [u64; 256] does not implement Clone
@@ -91,6 +92,7 @@ impl Clone for Isaac64Rng {
9192
b: self.b,
9293
c: self.c,
9394
index: self.index,
95+
half_used: self.half_used,
9496
}
9597
}
9698
}
@@ -136,13 +138,6 @@ impl Isaac64Rng {
136138
/// - We fill `rsl` backwards. The reference implementation reads values
137139
/// from `rsl` in reverse. We read them in the normal direction, to make
138140
/// `fill_bytes` a memcopy. To maintain compatibility we fill in reverse.
139-
/// - We store `index` as if `rsl` contains `u32`'s instead of `u64`'s, plus
140-
/// one. This way we can make more efficient use of the generated results
141-
/// in `next_u32`.
142-
/// For `next_u32` the correct index is `index - 1`.
143-
/// For `next_u64` the correct index is `index >> 1`, which also takes
144-
/// care of any alignment issues that could arise if `next_u64` was called
145-
/// after `next_u32`.
146141
fn isaac64(&mut self) {
147142
self.c += w(1);
148143
// abbreviations
@@ -192,7 +187,8 @@ impl Isaac64Rng {
192187

193188
self.a = a;
194189
self.b = b;
195-
self.index = 1;
190+
self.index = 0;
191+
self.half_used = false;
196192
}
197193
}
198194

@@ -201,54 +197,52 @@ impl Rng for Isaac64Rng {
201197
fn next_u32(&mut self) -> u32 {
202198
// Using a local variable for `index`, and checking the size avoids a
203199
// bounds check later on.
204-
let mut index = self.index as usize - 1;
200+
let mut index = self.index as usize * 2 - self.half_used as usize;
205201
if index >= RAND_SIZE * 2 {
206202
self.isaac64();
207203
index = 0;
208204
}
209205

210-
let value;
206+
self.half_used = !self.half_used;
207+
self.index += self.half_used as u32;
208+
209+
// Index as if this is a u32 slice.
210+
let rsl = unsafe { &*(&mut self.rsl as *mut [u64; RAND_SIZE]
211+
as *mut [u32; RAND_SIZE * 2]) };
212+
211213
if cfg!(target_endian = "little") {
212-
// Index as if this is a u32 slice.
213-
let rsl = unsafe { &*(&mut self.rsl as *mut [u64; RAND_SIZE]
214-
as *mut [u32; RAND_SIZE * 2]) };
215-
value = rsl[index];
214+
rsl[index]
216215
} else {
217-
// Index into the u64 slice, rotate and truncate the result.
218-
// Works always, also on big-endian systems, but is slower.
219-
let tmp = self.rsl[index >> 1];
220-
value = tmp as u32;
221-
self.rsl[index >> 1] = tmp.rotate_right(32);
216+
rsl[index ^ 1]
222217
}
223-
self.index += 1;
224-
value
225218
}
226219

227220
#[inline]
228221
fn next_u64(&mut self) -> u64 {
229-
let mut index = self.index as usize >> 1;
222+
let mut index = self.index as usize;
230223
if index >= RAND_SIZE {
231224
self.isaac64();
232225
index = 0;
233226
}
234227

235228
let value = self.rsl[index];
236-
self.index += 2;
229+
self.index += 1;
230+
self.half_used = false;
237231
value
238232
}
239233

240234
fn fill_bytes(&mut self, dest: &mut [u8]) {
241235
let mut read_len = 0;
242236
while read_len < dest.len() {
243-
if (self.index as usize >> 1) >= RAND_SIZE {
237+
if self.index as usize >= RAND_SIZE {
244238
self.isaac64();
245239
}
246240

247241
let (consumed_u64, filled_u8) =
248-
impls::fill_via_u64_chunks(&mut self.rsl[(self.index as usize >> 1)..],
242+
impls::fill_via_u64_chunks(&mut self.rsl[self.index as usize..],
249243
&mut dest[read_len..]);
250244

251-
self.index += consumed_u64 as u32 * 2;
245+
self.index += consumed_u64 as u32;
252246
read_len += filled_u8;
253247
}
254248
}
@@ -292,6 +286,7 @@ fn init(mut mem: [w64; RAND_SIZE], rounds: u32) -> Isaac64Rng {
292286
b: w(0),
293287
c: w(0),
294288
index: 0,
289+
half_used: false,
295290
};
296291

297292
// Prepare the first set of results

0 commit comments

Comments
 (0)