]> git.lizzy.rs Git - rust.git/blobdiff - src/librand/isaac.rs
rollup merge of #17355 : gamazeps/issue17210
[rust.git] / src / librand / isaac.rs
index 2fbfa6d6e85a0da393ae2050cb9d7ff963e4ab3f..0a857da92bbe498cee3f6d3032143eae1dc546c1 100644 (file)
@@ -13,7 +13,6 @@
 use core::prelude::*;
 use core::iter::{range_step, Repeat};
 use core::slice::raw;
-use core::mem;
 
 use {Rng, SeedableRng, Rand};
 
@@ -46,6 +45,7 @@ pub struct IsaacRng {
 };
 
 impl IsaacRng {
+
     /// Create an ISAAC random number generator using the default
     /// fixed seed.
     pub fn new_unseeded() -> IsaacRng {
@@ -185,7 +185,19 @@ fn next_u32(&mut self) -> u32 {
             self.isaac();
         }
         self.cnt -= 1;
-        self.rsl[self.cnt as uint]
+
+        // self.cnt is at most RAND_SIZE, but that is before the
+        // subtraction above. We want to index without bounds
+        // checking, but this could lead to incorrect code if someone
+        // misrefactors, so we check, sometimes.
+        //
+        // (Changes here should be reflected in Isaac64Rng.next_u64.)
+        debug_assert!(self.cnt < RAND_SIZE);
+
+        // (the % is cheaply telling the optimiser that we're always
+        // in bounds, without unsafe. NB. this is a power of two, so
+        // it optimises to a bitwise mask).
+        self.rsl[(self.cnt % RAND_SIZE) as uint]
     }
 }
 
@@ -195,7 +207,7 @@ fn reseed(&mut self, seed: &'a [u32]) {
         // - 1], 0, 0, ...], to fill rng.rsl.
         let seed_iter = seed.iter().map(|&x| x).chain(Repeat::new(0u32));
 
-        for (rsl_elem, seed_elem) in self.rsl.mut_iter().zip(seed_iter) {
+        for (rsl_elem, seed_elem) in self.rsl.iter_mut().zip(seed_iter) {
             *rsl_elem = seed_elem;
         }
         self.cnt = 0;
@@ -225,7 +237,7 @@ fn rand<R: Rng>(other: &mut R) -> IsaacRng {
             let ptr = ret.rsl.as_mut_ptr();
 
             raw::mut_buf_as_slice(ptr as *mut u8,
-                                  mem::size_of_val(&ret.rsl), |slice| {
+                                  (RAND_SIZE*4) as uint, |slice| {
                 other.fill_bytes(slice);
             })
         }
@@ -416,7 +428,11 @@ fn next_u64(&mut self) -> u64 {
             self.isaac64();
         }
         self.cnt -= 1;
-        unsafe { *self.rsl.unsafe_get(self.cnt) }
+
+        // See corresponding location in IsaacRng.next_u32 for
+        // explanation.
+        debug_assert!(self.cnt < RAND_SIZE_64)
+        self.rsl[(self.cnt % RAND_SIZE_64) as uint]
     }
 }
 
@@ -426,7 +442,7 @@ fn reseed(&mut self, seed: &'a [u64]) {
         // - 1], 0, 0, ...], to fill rng.rsl.
         let seed_iter = seed.iter().map(|&x| x).chain(Repeat::new(0u64));
 
-        for (rsl_elem, seed_elem) in self.rsl.mut_iter().zip(seed_iter) {
+        for (rsl_elem, seed_elem) in self.rsl.iter_mut().zip(seed_iter) {
             *rsl_elem = seed_elem;
         }
         self.cnt = 0;
@@ -456,7 +472,7 @@ fn rand<R: Rng>(other: &mut R) -> Isaac64Rng {
             let ptr = ret.rsl.as_mut_ptr();
 
             raw::mut_buf_as_slice(ptr as *mut u8,
-                                  mem::size_of_val(&ret.rsl), |slice| {
+                                  (RAND_SIZE_64*8) as uint, |slice| {
                 other.fill_bytes(slice);
             })
         }
@@ -497,7 +513,7 @@ fn test_rng_64_rand_seeded() {
 
     #[test]
     fn test_rng_32_seeded() {
-        let seed = &[1, 23, 456, 7890, 12345];
+        let seed: &[_] = &[1, 23, 456, 7890, 12345];
         let mut ra: IsaacRng = SeedableRng::from_seed(seed);
         let mut rb: IsaacRng = SeedableRng::from_seed(seed);
         assert!(order::equals(ra.gen_ascii_chars().take(100),
@@ -505,7 +521,7 @@ fn test_rng_32_seeded() {
     }
     #[test]
     fn test_rng_64_seeded() {
-        let seed = &[1, 23, 456, 7890, 12345];
+        let seed: &[_] = &[1, 23, 456, 7890, 12345];
         let mut ra: Isaac64Rng = SeedableRng::from_seed(seed);
         let mut rb: Isaac64Rng = SeedableRng::from_seed(seed);
         assert!(order::equals(ra.gen_ascii_chars().take(100),
@@ -537,7 +553,7 @@ fn test_rng_64_reseed() {
 
     #[test]
     fn test_rng_32_true_values() {
-        let seed = &[1, 23, 456, 7890, 12345];
+        let seed: &[_] = &[1, 23, 456, 7890, 12345];
         let mut ra: IsaacRng = SeedableRng::from_seed(seed);
         // Regression test that isaac is actually using the above vector
         let v = Vec::from_fn(10, |_| ra.next_u32());
@@ -545,7 +561,7 @@ fn test_rng_32_true_values() {
                    vec!(2558573138, 873787463, 263499565, 2103644246, 3595684709,
                         4203127393, 264982119, 2765226902, 2737944514, 3900253796));
 
-        let seed = &[12345, 67890, 54321, 9876];
+        let seed: &[_] = &[12345, 67890, 54321, 9876];
         let mut rb: IsaacRng = SeedableRng::from_seed(seed);
         // skip forward to the 10000th number
         for _ in range(0u, 10000) { rb.next_u32(); }
@@ -557,7 +573,7 @@ fn test_rng_32_true_values() {
     }
     #[test]
     fn test_rng_64_true_values() {
-        let seed = &[1, 23, 456, 7890, 12345];
+        let seed: &[_] = &[1, 23, 456, 7890, 12345];
         let mut ra: Isaac64Rng = SeedableRng::from_seed(seed);
         // Regression test that isaac is actually using the above vector
         let v = Vec::from_fn(10, |_| ra.next_u64());
@@ -567,7 +583,7 @@ fn test_rng_64_true_values() {
                         4469761996653280935, 15552757044682284409, 6860251611068737823,
                         13722198873481261842));
 
-        let seed = &[12345, 67890, 54321, 9876];
+        let seed: &[_] = &[12345, 67890, 54321, 9876];
         let mut rb: Isaac64Rng = SeedableRng::from_seed(seed);
         // skip forward to the 10000th number
         for _ in range(0u, 10000) { rb.next_u64(); }