Update with wrapping ops
Closes #21
diff --git a/Cargo.toml b/Cargo.toml
index 7bc04b6..c27e052 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,7 +1,7 @@
[package]
name = "rand"
-version = "0.1.3"
+version = "0.1.4"
authors = ["The Rust Project Developers"]
license = "MIT/Apache-2.0"
readme = "README.md"
diff --git a/src/chacha.rs b/src/chacha.rs
index 526e895..36543e8 100644
--- a/src/chacha.rs
+++ b/src/chacha.rs
@@ -11,8 +11,10 @@
//! The ChaCha random number generator.
use core::prelude::*;
+
use core::num::Int;
-use {Rng, SeedableRng, Rand};
+use core::num::wrapping::Wrapping as w;
+use {Rng, SeedableRng, Rand, w32};
const KEY_WORDS : usize = 8; // 8 words for the 256-bit key
const STATE_WORDS : usize = 16;
@@ -29,24 +31,24 @@
/// Salsa20*](http://cr.yp.to/chacha.html)
#[derive(Copy, Clone)]
pub struct ChaChaRng {
- buffer: [u32; STATE_WORDS], // Internal buffer of output
- state: [u32; STATE_WORDS], // Initial state
+ buffer: [w32; STATE_WORDS], // Internal buffer of output
+ state: [w32; STATE_WORDS], // Initial state
index: usize, // Index into state
}
static EMPTY: ChaChaRng = ChaChaRng {
- buffer: [0; STATE_WORDS],
- state: [0; STATE_WORDS],
+ buffer: [w(0); STATE_WORDS],
+ state: [w(0); STATE_WORDS],
index: STATE_WORDS
};
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 + $b; $d = $d ^ $a; $d = w($d.0.rotate_left(16));
+ $c = $c + $d; $b = $b ^ $c; $b = w($b.0.rotate_left(12));
+ $a = $a + $b; $d = $d ^ $a; $d = w($d.0.rotate_left( 8));
+ $c = $c + $d; $b = $b ^ $c; $b = w($b.0.rotate_left( 7));
}}
}
@@ -66,7 +68,7 @@
}
#[inline]
-fn core(output: &mut [u32; STATE_WORDS], input: &[u32; STATE_WORDS]) {
+fn core(output: &mut [w32; STATE_WORDS], input: &[w32; STATE_WORDS]) {
*output = *input;
for _ in 0..CHACHA_ROUNDS / 2 {
@@ -74,7 +76,7 @@
}
for i in 0..STATE_WORDS {
- output[i] += input[i];
+ output[i] = output[i] + input[i];
}
}
@@ -97,10 +99,10 @@
/// associated with a particular nonce can call this function with
/// arguments `0, desired_nonce`.
pub fn set_counter(&mut self, counter_low: u64, counter_high: u64) {
- self.state[12] = (counter_low >> 0) as u32;
- self.state[13] = (counter_low >> 32) as u32;
- self.state[14] = (counter_high >> 0) as u32;
- self.state[15] = (counter_high >> 32) as u32;
+ self.state[12] = w((counter_low >> 0) as u32);
+ self.state[13] = w((counter_low >> 32) as u32);
+ self.state[14] = w((counter_high >> 0) as u32);
+ self.state[15] = w((counter_high >> 32) as u32);
self.index = STATE_WORDS; // force recomputation
}
@@ -123,19 +125,19 @@
/// [1]: Daniel J. Bernstein. [*Extending the Salsa20
/// nonce.*](http://cr.yp.to/papers.html#xsalsa)
fn init(&mut self, key: &[u32; KEY_WORDS]) {
- self.state[0] = 0x61707865;
- self.state[1] = 0x3320646E;
- self.state[2] = 0x79622D32;
- self.state[3] = 0x6B206574;
+ self.state[0] = w(0x61707865);
+ self.state[1] = w(0x3320646E);
+ self.state[2] = w(0x79622D32);
+ self.state[3] = w(0x6B206574);
for i in 0..KEY_WORDS {
- self.state[4+i] = key[i];
+ self.state[4+i] = w(key[i]);
}
- self.state[12] = 0;
- self.state[13] = 0;
- self.state[14] = 0;
- self.state[15] = 0;
+ self.state[12] = w(0);
+ self.state[13] = w(0);
+ self.state[14] = w(0);
+ self.state[15] = w(0);
self.index = STATE_WORDS;
}
@@ -145,13 +147,13 @@
core(&mut self.buffer, &self.state);
self.index = 0;
// update 128-bit counter
- self.state[12] += 1;
- if self.state[12] != 0 { return };
- self.state[13] += 1;
- if self.state[13] != 0 { return };
- self.state[14] += 1;
- if self.state[14] != 0 { return };
- self.state[15] += 1;
+ self.state[12] = self.state[12] + w(1);
+ if self.state[12] != w(0) { return };
+ self.state[13] = self.state[13] + w(1);
+ if self.state[13] != w(0) { return };
+ self.state[14] = self.state[14] + w(1);
+ if self.state[14] != w(0) { return };
+ self.state[15] = self.state[15] + w(1);
}
}
@@ -164,7 +166,7 @@
let value = self.buffer[self.index % STATE_WORDS];
self.index += 1;
- value
+ value.0
}
}
@@ -176,7 +178,7 @@
// set key in place
let key = &mut self.state[4 .. 4+KEY_WORDS];
for (k, s) in key.iter_mut().zip(seed.iter()) {
- *k = *s;
+ *k = w(*s);
}
}
diff --git a/src/distributions/range.rs b/src/distributions/range.rs
index 29d8fe6..e74ace1 100644
--- a/src/distributions/range.rs
+++ b/src/distributions/range.rs
@@ -14,6 +14,7 @@
use core::prelude::{PartialOrd};
use core::num::Int;
+use core::num::wrapping::Wrapping as w;
use Rng;
use distributions::{Sample, IndependentSample};
@@ -97,7 +98,7 @@
// bijection.
fn construct_range(low: $ty, high: $ty) -> Range<$ty> {
- let range = high as $unsigned - low as $unsigned;
+ let range = (w(high as $unsigned) - w(low as $unsigned)).0;
let unsigned_max: $unsigned = Int::max_value();
// this is the largest number that fits into $unsigned
@@ -122,7 +123,7 @@
// 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 (w(r.low) + w((v % r.range as $unsigned) as $ty)).0;
}
}
}
diff --git a/src/isaac.rs b/src/isaac.rs
index f07428d..9c77c8b 100644
--- a/src/isaac.rs
+++ b/src/isaac.rs
@@ -10,13 +10,16 @@
//! The ISAAC random number generator.
+#![allow(non_camel_case_types)]
+
use core::prelude::*;
use core::slice;
use core::iter::{range_step, repeat};
+use core::num::wrapping::Wrapping as w;
-use {Rng, SeedableRng, Rand};
+use {Rng, SeedableRng, Rand, w32, w64};
-const RAND_SIZE_LEN: u32 = 8;
+const RAND_SIZE_LEN: usize = 8;
const RAND_SIZE: u32 = 1 << RAND_SIZE_LEN;
const RAND_SIZE_USIZE: usize = 1 << RAND_SIZE_LEN;
@@ -32,18 +35,18 @@
#[derive(Copy)]
pub struct IsaacRng {
cnt: u32,
- rsl: [u32; RAND_SIZE_USIZE],
- mem: [u32; RAND_SIZE_USIZE],
- a: u32,
- b: u32,
- c: u32
+ rsl: [w32; RAND_SIZE_USIZE],
+ mem: [w32; RAND_SIZE_USIZE],
+ a: w32,
+ b: w32,
+ c: w32,
}
static EMPTY: IsaacRng = IsaacRng {
cnt: 0,
- rsl: [0; RAND_SIZE_USIZE],
- mem: [0; RAND_SIZE_USIZE],
- a: 0, b: 0, c: 0
+ rsl: [w(0); RAND_SIZE_USIZE],
+ mem: [w(0); RAND_SIZE_USIZE],
+ a: w(0), b: w(0), c: w(0),
};
impl IsaacRng {
@@ -60,7 +63,7 @@
/// 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 = w(0x9e3779b9);
let mut b = a;
let mut c = a;
let mut d = a;
@@ -71,14 +74,14 @@
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,10 +93,10 @@
macro_rules! memloop {
($arr:expr) => {{
for i in range_step(0, RAND_SIZE_USIZE, 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+$arr[i ]; b=b+$arr[i+1];
+ c=c+$arr[i+2]; d=d+$arr[i+3];
+ e=e+$arr[i+4]; f=f+$arr[i+5];
+ g=g+$arr[i+6]; h=h+$arr[i+7];
mix!();
self.mem[i ]=a; self.mem[i+1]=b;
self.mem[i+2]=c; self.mem[i+3]=d;
@@ -122,15 +125,15 @@
#[inline]
#[allow(unsigned_negation)]
fn isaac(&mut self) {
- self.c += 1;
+ self.c = self.c + w(1);
// abbreviations
let mut a = self.a;
let mut b = self.b + self.c;
- static MIDPOINT: usize = RAND_SIZE_USIZE / 2;
+ const MIDPOINT: usize = RAND_SIZE_USIZE / 2;
macro_rules! ind {
- ($x:expr) => ( self.mem[($x >> 2) as usize & (RAND_SIZE_USIZE - 1)] )
+ ($x:expr) => ( self.mem[($x >> 2).0 as usize & (RAND_SIZE_USIZE - 1)] )
}
let r = [(0, MIDPOINT), (MIDPOINT, 0)];
@@ -207,7 +210,7 @@
// (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 usize]
+ self.rsl[(self.cnt % RAND_SIZE) as usize].0
}
}
@@ -218,12 +221,12 @@
let seed_iter = seed.iter().map(|&x| x).chain(repeat(0u32));
for (rsl_elem, seed_elem) in self.rsl.iter_mut().zip(seed_iter) {
- *rsl_elem = seed_elem;
+ *rsl_elem = w(seed_elem);
}
self.cnt = 0;
- self.a = 0;
- self.b = 0;
- self.c = 0;
+ self.a = w(0);
+ self.b = w(0);
+ self.c = w(0);
self.init(true);
}
@@ -250,9 +253,9 @@
other.fill_bytes(slice);
}
ret.cnt = 0;
- ret.a = 0;
- ret.b = 0;
- ret.c = 0;
+ ret.a = w(0);
+ ret.b = w(0);
+ ret.c = w(0);
ret.init(true);
return ret;
@@ -275,18 +278,18 @@
#[derive(Copy)]
pub struct Isaac64Rng {
cnt: usize,
- rsl: [u64; RAND_SIZE_64],
- mem: [u64; RAND_SIZE_64],
- a: u64,
- b: u64,
- c: u64,
+ rsl: [w64; RAND_SIZE_64],
+ mem: [w64; RAND_SIZE_64],
+ a: w64,
+ b: w64,
+ c: w64,
}
static EMPTY_64: Isaac64Rng = Isaac64Rng {
cnt: 0,
- rsl: [0; RAND_SIZE_64],
- mem: [0; RAND_SIZE_64],
- a: 0, b: 0, c: 0,
+ rsl: [w(0); RAND_SIZE_64],
+ mem: [w(0); RAND_SIZE_64],
+ a: w(0), b: w(0), c: w(0),
};
impl Isaac64Rng {
@@ -304,7 +307,7 @@
fn init(&mut self, use_rsl: bool) {
macro_rules! init {
($var:ident) => (
- let mut $var = 0x9e3779b97f4a7c13;
+ let mut $var = w(0x9e3779b97f4a7c13);
)
}
init!(a); init!(b); init!(c); init!(d);
@@ -312,14 +315,14 @@
macro_rules! mix {
() => {{
- a-=e; f^=h>>9; h+=a;
- b-=f; g^=a<<9; a+=b;
- c-=g; h^=b>>23; b+=c;
- d-=h; a^=c<<15; c+=d;
- e-=a; b^=d>>14; d+=e;
- f-=b; c^=e<<20; e+=f;
- g-=c; d^=f>>17; f+=g;
- h-=d; e^=g<<14; g+=h;
+ a=a-e; f=f^(h>>9); h=h+a;
+ b=b-f; g=g^(a<<9); a=a+b;
+ c=c-g; h=h^(b>>23); b=b+c;
+ d=d-h; a=a^(c<<15); c=c+d;
+ e=e-a; b=b^(d>>14); d=d+e;
+ f=f-b; c=c^(e<<20); e=e+f;
+ g=g-c; d=d^(f>>17); f=f+g;
+ h=h-d; e=e^(g<<14); g=g+h;
}}
}
@@ -331,10 +334,10 @@
macro_rules! memloop {
($arr:expr) => {{
for i in (0..RAND_SIZE_64 / 8).map(|i| i * 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+$arr[i ]; b=b+$arr[i+1];
+ c=c+$arr[i+2]; d=d+$arr[i+3];
+ e=e+$arr[i+4]; f=f+$arr[i+5];
+ g=g+$arr[i+6]; h=h+$arr[i+7];
mix!();
self.mem[i ]=a; self.mem[i+1]=b;
self.mem[i+2]=c; self.mem[i+3]=d;
@@ -361,7 +364,7 @@
/// Refills the output buffer (`self.rsl`)
fn isaac64(&mut self) {
- self.c += 1;
+ self.c = self.c + w(1);
// abbreviations
let mut a = self.a;
let mut b = self.b + self.c;
@@ -369,7 +372,7 @@
const MP_VEC: [(usize, usize); 2] = [(0,MIDPOINT), (MIDPOINT, 0)];
macro_rules! ind {
($x:expr) => {
- *self.mem.get_unchecked(($x as usize >> 3) & (RAND_SIZE_64 - 1))
+ *self.mem.get_unchecked((($x >> 3).0 as usize) & (RAND_SIZE_64 - 1))
}
}
@@ -450,7 +453,7 @@
// See corresponding location in IsaacRng.next_u32 for
// explanation.
debug_assert!(self.cnt < RAND_SIZE_64);
- self.rsl[(self.cnt % RAND_SIZE_64) as usize]
+ self.rsl[(self.cnt % RAND_SIZE_64) as usize].0
}
}
@@ -461,12 +464,12 @@
let seed_iter = seed.iter().map(|&x| x).chain(repeat(0u64));
for (rsl_elem, seed_elem) in self.rsl.iter_mut().zip(seed_iter) {
- *rsl_elem = seed_elem;
+ *rsl_elem = w(seed_elem);
}
self.cnt = 0;
- self.a = 0;
- self.b = 0;
- self.c = 0;
+ self.a = w(0);
+ self.b = w(0);
+ self.c = w(0);
self.init(true);
}
@@ -493,9 +496,9 @@
other.fill_bytes(slice);
}
ret.cnt = 0;
- ret.a = 0;
- ret.b = 0;
- ret.c = 0;
+ ret.a = w(0);
+ ret.b = w(0);
+ ret.c = w(0);
ret.init(true);
return ret;
diff --git a/src/lib.rs b/src/lib.rs
index cac7a6b..50984dc 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -233,6 +233,7 @@
use std::mem;
use std::old_io::IoResult;
use std::rc::Rc;
+use std::num::wrapping::Wrapping as w;
pub use os::OsRng;
@@ -255,6 +256,11 @@
pub mod os;
pub mod reader;
+#[allow(bad_style)]
+type w64 = w<u64>;
+#[allow(bad_style)]
+type w32 = w<u32>;
+
/// A type that can be randomly generated using an `Rng`.
pub trait Rand : Sized {
/// Generates a random instance of this type using the specified source of
@@ -590,10 +596,10 @@
#[allow(missing_copy_implementations)]
#[derive(Clone)]
pub struct XorShiftRng {
- x: u32,
- y: u32,
- z: u32,
- w: u32,
+ x: w32,
+ y: w32,
+ z: w32,
+ w: w32,
}
impl XorShiftRng {
@@ -605,10 +611,10 @@
/// this function
pub fn new_unseeded() -> XorShiftRng {
XorShiftRng {
- x: 0x193a6754,
- y: 0xa8a7d469,
- z: 0x97830e05,
- w: 0x113ba7bb,
+ x: w(0x193a6754),
+ y: w(0xa8a7d469),
+ z: w(0x97830e05),
+ w: w(0x113ba7bb),
}
}
}
@@ -621,9 +627,9 @@
self.x = self.y;
self.y = self.z;
self.z = self.w;
- let w = self.w;
- self.w = w ^ (w >> 19) ^ (t ^ (t >> 8));
- self.w
+ let w_ = self.w;
+ self.w = w_ ^ (w_ >> 19) ^ (t ^ (t >> 8));
+ self.w.0
}
}
@@ -633,10 +639,10 @@
assert!(!seed.iter().all(|&x| x == 0),
"XorShiftRng.reseed called with an all zero seed.");
- self.x = seed[0];
- self.y = seed[1];
- self.z = seed[2];
- self.w = seed[3];
+ self.x = w(seed[0]);
+ self.y = w(seed[1]);
+ self.z = w(seed[2]);
+ self.w = w(seed[3]);
}
/// Create a new XorShiftRng. This will panic if `seed` is entirely 0.
@@ -645,10 +651,10 @@
"XorShiftRng::from_seed called with an all zero seed.");
XorShiftRng {
- x: seed[0],
- y: seed[1],
- z: seed[2],
- w: seed[3]
+ x: w(seed[0]),
+ y: w(seed[1]),
+ z: w(seed[2]),
+ w: w(seed[3]),
}
}
}
@@ -659,8 +665,8 @@
while tuple == (0, 0, 0, 0) {
tuple = rng.gen();
}
- let (x, y, z, w) = tuple;
- XorShiftRng { x: x, y: y, z: z, w: w }
+ let (x, y, z, w_) = tuple;
+ XorShiftRng { x: w(x), y: w(y), z: w(z), w: w(w_) }
}
}