about summary refs log tree commit diff
diff options
context:
space:
mode:
authorFelix S. Klock II <pnkfelix@pnkfx.org>2015-02-20 00:10:08 +0100
committerFelix S. Klock II <pnkfelix@pnkfx.org>2015-03-03 12:10:57 +0100
commit6189e99c8605578aae841be6fba9e27bfbad97fc (patch)
tree3c4019f4987c0825d751474029637a9b670f9dbf
parent7c8edabac8030889f4a885b944c86190772953fd (diff)
downloadrust-6189e99c8605578aae841be6fba9e27bfbad97fc.tar.gz
rust-6189e99c8605578aae841be6fba9e27bfbad97fc.zip
Accommodate arith-overflow in `rand` and `std::rand`.
Regarding the `rand` changes: It is unfortunate that Wrapping(T) does
not support the `+=` operator.  We may want to try to fix that before
1.0 to make porting code like this palatable.

Regarding `std::rand`, just arith-overflow in first example from
`std::rand::random()` doc.
-rw-r--r--src/librand/chacha.rs11
-rw-r--r--src/librand/distributions/range.rs2
-rw-r--r--src/librand/isaac.rs62
-rw-r--r--src/libstd/rand/mod.rs4
4 files changed, 41 insertions, 38 deletions
diff --git a/src/librand/chacha.rs b/src/librand/chacha.rs
index 2673649f344..71ace016d6b 100644
--- a/src/librand/chacha.rs
+++ b/src/librand/chacha.rs
@@ -12,6 +12,7 @@
 
 use core::prelude::*;
 use core::num::Int;
+use core::num::wrapping::WrappingOps;
 use {Rng, SeedableRng, Rand};
 
 const KEY_WORDS    : uint =  8; // 8 words for the 256-bit key
@@ -43,10 +44,10 @@ static EMPTY: ChaChaRng = ChaChaRng {
 
 macro_rules! quarter_round{
     ($a: expr, $b: expr, $c: expr, $d: expr) => {{
-        $a += $b; $d ^= $a; $d = $d.rotate_left(16);
-        $c += $d; $b ^= $c; $b = $b.rotate_left(12);
-        $a += $b; $d ^= $a; $d = $d.rotate_left( 8);
-        $c += $d; $b ^= $c; $b = $b.rotate_left( 7);
+        $a = $a.wrapping_add($b); $d = $d ^ $a; $d = $d.rotate_left(16);
+        $c = $c.wrapping_add($d); $b = $b ^ $c; $b = $b.rotate_left(12);
+        $a = $a.wrapping_add($b); $d = $d ^ $a; $d = $d.rotate_left( 8);
+        $c = $c.wrapping_add($d); $b = $b ^ $c; $b = $b.rotate_left( 7);
     }}
 }
 
@@ -74,7 +75,7 @@ fn core(output: &mut [u32; STATE_WORDS], input: &[u32; STATE_WORDS]) {
     }
 
     for i in 0..STATE_WORDS {
-        output[i] += input[i];
+        output[i] = output[i].wrapping_add(input[i]);
     }
 }
 
diff --git a/src/librand/distributions/range.rs b/src/librand/distributions/range.rs
index 04c67b16a7c..fb73a44c2b9 100644
--- a/src/librand/distributions/range.rs
+++ b/src/librand/distributions/range.rs
@@ -123,7 +123,7 @@ macro_rules! integer_impl {
                     // be uniformly distributed)
                     if v < r.accept_zone as $unsigned {
                         // and return it, with some adjustments
-                        return r.low + (v % r.range as $unsigned) as $ty;
+                        return r.low.wrapping_add((v % r.range as $unsigned) as $ty);
                     }
                 }
             }
diff --git a/src/librand/isaac.rs b/src/librand/isaac.rs
index 63eb8417655..6bc00abd85f 100644
--- a/src/librand/isaac.rs
+++ b/src/librand/isaac.rs
@@ -13,6 +13,7 @@
 use core::prelude::*;
 use core::slice;
 use core::iter::{range_step, repeat};
+use core::num::wrapping::Wrapping;
 
 use {Rng, SeedableRng, Rand};
 
@@ -60,7 +61,7 @@ impl IsaacRng {
     /// of `rsl` as a seed, otherwise construct one algorithmically (not
     /// randomly).
     fn init(&mut self, use_rsl: bool) {
-        let mut a = 0x9e3779b9;
+        let mut a = Wrapping(0x9e3779b9);
         let mut b = a;
         let mut c = a;
         let mut d = a;
@@ -71,14 +72,14 @@ impl IsaacRng {
 
         macro_rules! mix {
             () => {{
-                a^=b<<11; d+=a; b+=c;
-                b^=c>>2;  e+=b; c+=d;
-                c^=d<<8;  f+=c; d+=e;
-                d^=e>>16; g+=d; e+=f;
-                e^=f<<10; h+=e; f+=g;
-                f^=g>>4;  a+=f; g+=h;
-                g^=h<<8;  b+=g; h+=a;
-                h^=a>>9;  c+=h; a+=b;
+                a=a^(b<<11); d=d+a; b=b+c;
+                b=b^(c>>2);  e=e+b; c=c+d;
+                c=c^(d<<8);  f=f+c; d=d+e;
+                d=d^(e>>16); g=g+d; e=e+f;
+                e=e^(f<<10); h=h+e; f=f+g;
+                f=f^(g>>4);  a=a+f; g=g+h;
+                g=g^(h<<8);  b=b+g; h=h+a;
+                h=h^(a>>9);  c=c+h; a=a+b;
             }}
         }
 
@@ -90,15 +91,15 @@ impl IsaacRng {
             macro_rules! memloop {
                 ($arr:expr) => {{
                     for i in range_step(0, RAND_SIZE as uint, 8) {
-                        a+=$arr[i  ]; b+=$arr[i+1];
-                        c+=$arr[i+2]; d+=$arr[i+3];
-                        e+=$arr[i+4]; f+=$arr[i+5];
-                        g+=$arr[i+6]; h+=$arr[i+7];
+                        a=a+Wrapping($arr[i  ]); b=b+Wrapping($arr[i+1]);
+                        c=c+Wrapping($arr[i+2]); d=d+Wrapping($arr[i+3]);
+                        e=e+Wrapping($arr[i+4]); f=f+Wrapping($arr[i+5]);
+                        g=g+Wrapping($arr[i+6]); h=h+Wrapping($arr[i+7]);
                         mix!();
-                        self.mem[i  ]=a; self.mem[i+1]=b;
-                        self.mem[i+2]=c; self.mem[i+3]=d;
-                        self.mem[i+4]=e; self.mem[i+5]=f;
-                        self.mem[i+6]=g; self.mem[i+7]=h;
+                        self.mem[i  ]=a.0; self.mem[i+1]=b.0;
+                        self.mem[i+2]=c.0; self.mem[i+3]=d.0;
+                        self.mem[i+4]=e.0; self.mem[i+5]=f.0;
+                        self.mem[i+6]=g.0; self.mem[i+7]=h.0;
                     }
                 }}
             }
@@ -108,10 +109,10 @@ impl IsaacRng {
         } else {
             for i in range_step(0, RAND_SIZE as uint, 8) {
                 mix!();
-                self.mem[i  ]=a; self.mem[i+1]=b;
-                self.mem[i+2]=c; self.mem[i+3]=d;
-                self.mem[i+4]=e; self.mem[i+5]=f;
-                self.mem[i+6]=g; self.mem[i+7]=h;
+                self.mem[i  ]=a.0; self.mem[i+1]=b.0;
+                self.mem[i+2]=c.0; self.mem[i+3]=d.0;
+                self.mem[i+4]=e.0; self.mem[i+5]=f.0;
+                self.mem[i+6]=g.0; self.mem[i+7]=h.0;
             }
         }
 
@@ -130,7 +131,8 @@ impl IsaacRng {
         static MIDPOINT: uint = (RAND_SIZE / 2) as uint;
 
         macro_rules! ind {
-            ($x:expr) => ( self.mem[(($x >> 2) as uint & ((RAND_SIZE - 1) as uint))] )
+            ($x:expr) => (Wrapping( self.mem[(($x >> 2) as uint &
+                                              ((RAND_SIZE - 1) as uint))] ))
         }
 
         let r = [(0, MIDPOINT), (MIDPOINT, 0)];
@@ -142,11 +144,11 @@ impl IsaacRng {
                     let mix = a << $shift as uint;
 
                     let x = self.mem[base  + mr_offset];
-                    a = (a ^ mix) + self.mem[base + m2_offset];
-                    let y = ind!(x) + a + b;
-                    self.mem[base + mr_offset] = y;
+                    a = (Wrapping(a ^ mix) + Wrapping(self.mem[base + m2_offset])).0;
+                    let y = ind!(x) + Wrapping(a) + Wrapping(b);
+                    self.mem[base + mr_offset] = y.0;
 
-                    b = ind!(y >> RAND_SIZE_LEN as uint) + x;
+                    b = (ind!(y.0 >> RAND_SIZE_LEN as uint) + Wrapping(x)).0;
                     self.rsl[base + mr_offset] = b;
                 }}
             }
@@ -157,11 +159,11 @@ impl IsaacRng {
                     let mix = a >> $shift as uint;
 
                     let x = self.mem[base  + mr_offset];
-                    a = (a ^ mix) + self.mem[base + m2_offset];
-                    let y = ind!(x) + a + b;
-                    self.mem[base + mr_offset] = y;
+                    a = (Wrapping(a ^ mix) + Wrapping(self.mem[base + m2_offset])).0;
+                    let y = ind!(x) + Wrapping(a) + Wrapping(b);
+                    self.mem[base + mr_offset] = y.0;
 
-                    b = ind!(y >> RAND_SIZE_LEN as uint) + x;
+                    b = (ind!(y.0 >> RAND_SIZE_LEN as uint) + Wrapping(x)).0;
                     self.rsl[base + mr_offset] = b;
                 }}
             }
diff --git a/src/libstd/rand/mod.rs b/src/libstd/rand/mod.rs
index 5c891441198..ac7622fc7f7 100644
--- a/src/libstd/rand/mod.rs
+++ b/src/libstd/rand/mod.rs
@@ -386,8 +386,8 @@ impl Rng for ThreadRng {
 /// ```
 /// use std::rand;
 ///
-/// let x = rand::random();
-/// println!("{}", 2u8 * x);
+/// let x: u8 = rand::random();
+/// println!("{}", 2 * x as u16);
 ///
 /// let y = rand::random::<f64>();
 /// println!("{}", y);