let full_value = if value { !0 } else { 0 };
// Correct the old tail word, setting or clearing formerly unused bits
- let old_last_word = blocks_for_bits(self.nbits) - 1;
+ let num_cur_blocks = blocks_for_bits(self.nbits);
if self.nbits % u32::BITS as usize > 0 {
let mask = mask_for_bits(self.nbits);
if value {
- self.storage[old_last_word] |= !mask;
+ self.storage[num_cur_blocks - 1] |= !mask;
} else {
// Extra bits are already zero by invariant.
}
// Fill in words after the old tail word
let stop_idx = cmp::min(self.storage.len(), new_nblocks);
- for idx in old_last_word + 1..stop_idx {
+ for idx in num_cur_blocks..stop_idx {
self.storage[idx] = full_value;
}
use prelude::*;
use default::Default;
-
+use num::wrapping::WrappingOps;
use super::Hasher;
/// An implementation of SipHash 2-4.
macro_rules! rotl {
($x:expr, $b:expr) =>
- (($x << $b) | ($x >> (64 - $b)))
+ (($x << $b) | ($x >> (64.wrapping_sub($b))))
}
macro_rules! compress {
($v0:expr, $v1:expr, $v2:expr, $v3:expr) =>
({
- $v0 += $v1; $v1 = rotl!($v1, 13); $v1 ^= $v0;
+ $v0 = $v0.wrapping_add($v1); $v1 = rotl!($v1, 13); $v1 ^= $v0;
$v0 = rotl!($v0, 32);
- $v2 += $v3; $v3 = rotl!($v3, 16); $v3 ^= $v2;
- $v0 += $v3; $v3 = rotl!($v3, 21); $v3 ^= $v0;
- $v2 += $v1; $v1 = rotl!($v1, 17); $v1 ^= $v2;
+ $v2 = $v2.wrapping_add($v3); $v3 = rotl!($v3, 16); $v3 ^= $v2;
+ $v0 = $v0.wrapping_add($v3); $v3 = rotl!($v3, 21); $v3 ^= $v0;
+ $v2 = $v2.wrapping_add($v1); $v1 = rotl!($v1, 17); $v1 ^= $v2;
$v2 = rotl!($v2, 32);
})
}
use result::Result::{self, Ok, Err};
use str::{FromStr, StrExt};
+#[unstable(feature = "core", reason = "may be removed or relocated")]
+pub mod wrapping;
+
/// A built-in signed or unsigned integer.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Int
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+#![allow(missing_docs)]
+
+use ops::*;
+
+#[cfg(not(stage0))]
+use intrinsics::{overflowing_add, overflowing_sub, overflowing_mul};
+
+pub trait WrappingOps {
+ fn wrapping_add(self, rhs: Self) -> Self;
+ fn wrapping_sub(self, rhs: Self) -> Self;
+ fn wrapping_mul(self, rhs: Self) -> Self;
+}
+
+#[cfg(not(stage0))]
+macro_rules! wrapping_impl {
+ ($($t:ty)*) => ($(
+ impl WrappingOps for $t {
+ #[inline(always)]
+ fn wrapping_add(self, rhs: $t) -> $t {
+ unsafe {
+ overflowing_add(self, rhs)
+ }
+ }
+ #[inline(always)]
+ fn wrapping_sub(self, rhs: $t) -> $t {
+ unsafe {
+ overflowing_sub(self, rhs)
+ }
+ }
+ #[inline(always)]
+ fn wrapping_mul(self, rhs: $t) -> $t {
+ unsafe {
+ overflowing_mul(self, rhs)
+ }
+ }
+ }
+ )*)
+}
+
+#[cfg(stage0)]
+macro_rules! wrapping_impl {
+ ($($t:ty)*) => ($(
+ impl WrappingOps for $t {
+ #[inline(always)]
+ fn wrapping_add(self, rhs: $t) -> $t {
+ self + rhs
+ }
+ #[inline(always)]
+ fn wrapping_sub(self, rhs: $t) -> $t {
+ self - rhs
+ }
+ #[inline(always)]
+ fn wrapping_mul(self, rhs: $t) -> $t {
+ self * rhs
+ }
+ }
+ )*)
+}
+
+wrapping_impl! { uint u8 u16 u32 u64 int i8 i16 i32 i64 }
+
+#[unstable(feature = "core", reason = "may be removed, renamed, or relocated")]
+#[derive(PartialEq,Eq,PartialOrd,Ord,Clone,Copy)]
+pub struct Wrapping<T>(pub T);
+
+impl<T:WrappingOps> Add for Wrapping<T> {
+ type Output = Wrapping<T>;
+
+ #[inline(always)]
+ fn add(self, other: Wrapping<T>) -> Wrapping<T> {
+ Wrapping(self.0.wrapping_add(other.0))
+ }
+}
+
+impl<T:WrappingOps> Sub for Wrapping<T> {
+ type Output = Wrapping<T>;
+
+ #[inline(always)]
+ fn sub(self, other: Wrapping<T>) -> Wrapping<T> {
+ Wrapping(self.0.wrapping_sub(other.0))
+ }
+}
+
+impl<T:WrappingOps> Mul for Wrapping<T> {
+ type Output = Wrapping<T>;
+
+ #[inline(always)]
+ fn mul(self, other: Wrapping<T>) -> Wrapping<T> {
+ Wrapping(self.0.wrapping_mul(other.0))
+ }
+}
+
+impl<T:WrappingOps+Not<Output=T>> Not for Wrapping<T> {
+ type Output = Wrapping<T>;
+
+ fn not(self) -> Wrapping<T> {
+ Wrapping(!self.0)
+ }
+}
+
+impl<T:WrappingOps+BitXor<Output=T>> BitXor for Wrapping<T> {
+ type Output = Wrapping<T>;
+
+ #[inline(always)]
+ fn bitxor(self, other: Wrapping<T>) -> Wrapping<T> {
+ Wrapping(self.0 ^ other.0)
+ }
+}
+
+impl<T:WrappingOps+BitOr<Output=T>> BitOr for Wrapping<T> {
+ type Output = Wrapping<T>;
+
+ #[inline(always)]
+ fn bitor(self, other: Wrapping<T>) -> Wrapping<T> {
+ Wrapping(self.0 | other.0)
+ }
+}
+
+impl<T:WrappingOps+BitAnd<Output=T>> BitAnd for Wrapping<T> {
+ type Output = Wrapping<T>;
+
+ #[inline(always)]
+ fn bitand(self, other: Wrapping<T>) -> Wrapping<T> {
+ Wrapping(self.0 & other.0)
+ }
+}
+
+impl<T:WrappingOps+Shl<uint,Output=T>> Shl<uint> for Wrapping<T> {
+ type Output = Wrapping<T>;
+
+ #[inline(always)]
+ fn shl(self, other: uint) -> Wrapping<T> {
+ Wrapping(self.0 << other)
+ }
+}
+
+impl<T:WrappingOps+Shr<uint,Output=T>> Shr<uint> for Wrapping<T> {
+ type Output = Wrapping<T>;
+
+ #[inline(always)]
+ fn shr(self, other: uint) -> Wrapping<T> {
+ Wrapping(self.0 >> other)
+ }
+}
#[inline]
#[allow(dead_code)]
fn maximal_suffix(arr: &[u8], reversed: bool) -> (usize, usize) {
+ use num::wrapping::WrappingOps;
let mut left = -1; // Corresponds to i in the paper
let mut right = 0; // Corresponds to j in the paper
let mut offset = 1; // Corresponds to k in the paper
let a;
let b;
if reversed {
- a = arr[left + offset];
+ a = arr[left.wrapping_add(offset)];
b = arr[right + offset];
} else {
a = arr[right + offset];
- b = arr[left + offset];
+ b = arr[left.wrapping_add(offset)];
}
if a < b {
// Suffix is smaller, period is entire prefix so far.
right += offset;
offset = 1;
- period = right - left;
+ period = right.wrapping_sub(left);
} else if a == b {
// Advance through repetition of the current period.
if offset == period {
period = 1;
}
}
- (left + 1, period)
+ (left.wrapping_add(1), period)
}
}
use core::prelude::{PartialOrd};
use core::num::Int;
+use core::num::wrapping::WrappingOps;
use Rng;
use distributions::{Sample, IndependentSample};
// bijection.
fn construct_range(low: $ty, high: $ty) -> Range<$ty> {
- let range = high as $unsigned - low as $unsigned;
+ let range = (high as $unsigned).wrapping_sub(low as $unsigned);
let unsigned_max: $unsigned = Int::max_value();
// this is the largest number that fits into $unsigned
fn init(&mut self, use_rsl: bool) {
macro_rules! init {
($var:ident) => (
- let mut $var = 0x9e3779b97f4a7c13;
+ let mut $var = Wrapping(0x9e3779b97f4a7c13);
)
}
init!(a); init!(b); init!(c); init!(d);
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;
}}
}
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+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;
}
}}
}
} else {
for i in (0..RAND_SIZE_64 / 8).map(|i| i * 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;
}
}
fn isaac64(&mut self) {
self.c += 1;
// abbreviations
- let mut a = self.a;
- let mut b = self.b + self.c;
+ let mut a = Wrapping(self.a);
+ let mut b = Wrapping(self.b) + Wrapping(self.c);
const MIDPOINT: uint = RAND_SIZE_64 / 2;
const MP_VEC: [(uint, uint); 2] = [(0,MIDPOINT), (MIDPOINT, 0)];
macro_rules! ind {
let mix = if $j == 0 {!mix} else {mix};
unsafe {
- let x = *self.mem.get_unchecked(base + mr_offset);
- a = mix + *self.mem.get_unchecked(base + m2_offset);
- let y = ind!(x) + a + b;
- *self.mem.get_unchecked_mut(base + mr_offset) = y;
+ let x = Wrapping(*self.mem.get_unchecked(base + mr_offset));
+ a = mix + Wrapping(*self.mem.get_unchecked(base + m2_offset));
+ let y = Wrapping(ind!(x.0)) + a + b;
+ *self.mem.get_unchecked_mut(base + mr_offset) = y.0;
- b = ind!(y >> RAND_SIZE_64_LEN) + x;
- *self.rsl.get_unchecked_mut(base + mr_offset) = b;
+ b = Wrapping(ind!(y.0 >> RAND_SIZE_64_LEN)) + x;
+ *self.rsl.get_unchecked_mut(base + mr_offset) = b.0;
}
}}
}
let mix = if $j == 0 {!mix} else {mix};
unsafe {
- let x = *self.mem.get_unchecked(base + mr_offset);
- a = mix + *self.mem.get_unchecked(base + m2_offset);
- let y = ind!(x) + a + b;
- *self.mem.get_unchecked_mut(base + mr_offset) = y;
+ let x = Wrapping(*self.mem.get_unchecked(base + mr_offset));
+ a = mix + Wrapping(*self.mem.get_unchecked(base + m2_offset));
+ let y = Wrapping(ind!(x.0)) + a + b;
+ *self.mem.get_unchecked_mut(base + mr_offset) = y.0;
- b = ind!(y >> RAND_SIZE_64_LEN) + x;
- *self.rsl.get_unchecked_mut(base + mr_offset) = b;
+ b = Wrapping(ind!(y.0 >> RAND_SIZE_64_LEN)) + x;
+ *self.rsl.get_unchecked_mut(base + mr_offset) = b.0;
}
}}
}
}
}
- self.a = a;
- self.b = b;
+ self.a = a.0;
+ self.b = b.0;
self.cnt = RAND_SIZE_64;
}
}
_ => { /* empty */ }
}
let old_disr_val = disr_val;
- disr_val += 1;
+ disr_val = disr_val.wrapping_add(1);
Rc::new(ty::VariantInfo {
args: arg_tys,
arg_names: arg_names,
ecx.tcx.map.with_path(variant.node.id, |path| encode_path(rbml_w, path));
rbml_w.end_tag();
- disr_val += 1;
+ disr_val = disr_val.wrapping_add(1);
i += 1;
}
}
pub fn tr_id(&self, id: ast::NodeId) -> ast::NodeId {
// from_id_range should be non-empty
assert!(!self.from_id_range.empty());
- (id - self.from_id_range.min + self.to_id_range.min)
+ // Use wrapping arithmetic because otherwise it introduces control flow.
+ // Maybe we should just have the control flow? -- aatch
+ (id.wrapping_sub(self.from_id_range.min).wrapping_add(self.to_id_range.min))
}
/// Translates an EXTERNAL def-id, converting the crate number from the one used in the encoded
pub fn enum_variants<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
-> Rc<Vec<Rc<VariantInfo<'tcx>>>> {
+ use std::num::Int; // For checked_add
memoized(&cx.enum_var_cache, id, |id: ast::DefId| {
if ast::LOCAL_CRATE != id.krate {
Rc::new(csearch::get_enum_variants(cx, id))
let mut last_discriminant: Option<Disr> = None;
Rc::new(enum_definition.variants.iter().map(|variant| {
- let mut discriminant = match last_discriminant {
- Some(val) => val + 1,
- None => INITIAL_DISCRIMINANT_VALUE
- };
-
+ let mut discriminant = INITIAL_DISCRIMINANT_VALUE;
if let Some(ref e) = variant.node.disr_expr {
// Preserve all values, and prefer signed.
let ty = Some(cx.types.i64);
"expected constant: {}", err);
}
}
- };
+ } else {
+ if let Some(val) = last_discriminant {
+ if let Some(v) = val.checked_add(1) {
+ discriminant = v
+ } else {
+ cx.sess.span_err(
+ variant.span,
+ &format!("Discriminant overflowed!"));
+ }
+ } else {
+ discriminant = INITIAL_DISCRIMINANT_VALUE;
+ }
+ }
last_discriminant = Some(discriminant);
Rc::new(VariantInfo::from_ast_variant(cx, &**variant,
let FnvHasher(mut hash) = *self;
for byte in bytes {
hash = hash ^ (*byte as u64);
- hash = hash * 0x100000001b3;
+ hash = hash.wrapping_mul(0x100000001b3);
}
*self = FnvHasher(hash);
}
// Sha-512 and Sha-256 use basically the same calculations which are implemented
// by these macros. Inlining the calculations seems to result in better generated code.
macro_rules! schedule_round { ($t:expr) => (
- w[$t] = sigma1(w[$t - 2]) + w[$t - 7] + sigma0(w[$t - 15]) + w[$t - 16];
- )
+ w[$t] = sigma1(w[$t - 2]).wrapping_add(w[$t - 7])
+ .wrapping_add(sigma0(w[$t - 15])).wrapping_add(w[$t - 16]);
+ )
}
macro_rules! sha2_round {
($A:ident, $B:ident, $C:ident, $D:ident,
$E:ident, $F:ident, $G:ident, $H:ident, $K:ident, $t:expr) => (
{
- $H += sum1($E) + ch($E, $F, $G) + $K[$t] + w[$t];
- $D += $H;
- $H += sum0($A) + maj($A, $B, $C);
+ $H = $H.wrapping_add(sum1($E)).wrapping_add(ch($E, $F, $G))
+ .wrapping_add($K[$t]).wrapping_add(w[$t]);
+ $D = $D.wrapping_add($H);
+ $H = $H.wrapping_add(sum0($A)).wrapping_add(maj($A, $B, $C));
}
)
}
sha2_round!(b, c, d, e, f, g, h, a, K32, t + 7);
}
- self.h0 += a;
- self.h1 += b;
- self.h2 += c;
- self.h3 += d;
- self.h4 += e;
- self.h5 += f;
- self.h6 += g;
- self.h7 += h;
+ self.h0 = self.h0.wrapping_add(a);
+ self.h1 = self.h1.wrapping_add(b);
+ self.h2 = self.h2.wrapping_add(c);
+ self.h3 = self.h3.wrapping_add(d);
+ self.h4 = self.h4.wrapping_add(e);
+ self.h5 = self.h5.wrapping_add(f);
+ self.h6 = self.h6.wrapping_add(g);
+ self.h7 = self.h7.wrapping_add(h);
}
}
id: ast::NodeId,
hint: attr::ReprAttr)
-> Vec<Rc<ty::VariantInfo<'tcx>>> {
+ use std::num::Int;
let rty = ty::node_id_to_type(ccx.tcx, id);
let mut variants: Vec<Rc<ty::VariantInfo>> = Vec::new();
// If the discriminant value is specified explicitly in the enum check whether the
// initialization expression is valid, otherwise use the last value plus one.
let mut current_disr_val = match prev_disr_val {
- Some(prev_disr_val) => prev_disr_val + 1,
+ Some(prev_disr_val) => {
+ if let Some(v) = prev_disr_val.checked_add(1) {
+ v
+ } else {
+ ty::INITIAL_DISCRIMINANT_VALUE
+ }
+ }
None => ty::INITIAL_DISCRIMINANT_VALUE
};
M: Deref<Target=RawTable<K, V>>,
F: FnMut(&K) -> bool,
{
+ // This is the only function where capacity can be zero. To avoid
+ // undefined behaviour when Bucket::new gets the raw bucket in this
+ // case, immediately return the appropriate search result.
+ if table.capacity() == 0 {
+ return TableRef(table);
+ }
+
let size = table.size();
let mut probe = Bucket::new(table, hash);
let ib = probe.index();
}
pub fn at_index(table: M, ib_index: usize) -> Bucket<K, V, M> {
+ // if capacity is 0, then the RawBucket will be populated with bogus pointers.
+ // This is an uncommon case though, so avoid it in release builds.
+ debug_assert!(table.capacity() > 0, "Table should have capacity at this point");
let ib_index = ib_index & (table.capacity() - 1);
Bucket {
raw: unsafe {
/// In the cited blog posts above, this is called the "distance to
/// initial bucket", or DIB. Also known as "probe count".
pub fn distance(&self) -> usize {
+ use core::num::wrapping::WrappingOps;
// Calculates the distance one has to travel when going from
// `hash mod capacity` onwards to `idx mod capacity`, wrapping around
// if the destination is not reached before the end of the table.
- (self.idx - self.hash().inspect() as usize) & (self.table.capacity() - 1)
+ (self.idx.wrapping_sub(self.hash().inspect() as usize)) & (self.table.capacity() - 1)
}
#[inline]
pub use core::num::{from_f32, from_f64};
pub use core::num::{FromStrRadix, from_str_radix};
pub use core::num::{FpCategory, ParseIntError, ParseFloatError};
+pub use core::num::wrapping;
use option::Option;
#[doc(no_inline)] pub use old_io::{Buffer, Writer, Reader, Seek, BufferPrelude};
// NB: remove when range syntax lands
#[doc(no_inline)] pub use iter::range;
+
+#[doc(no_inline)] pub use num::wrapping::{Wrapping, WrappingOps};
let encoder = cx.expr_ident(trait_span, blkarg);
let emit_variant_arg = cx.ident_of("emit_enum_variant_arg");
let mut stmts = Vec::new();
- let last = fields.len() - 1;
- for (i, &FieldInfo { ref self_, span, .. }) in fields.iter().enumerate() {
- let enc = cx.expr_method_call(span, self_.clone(),
- encode, vec!(blkencoder.clone()));
- let lambda = cx.lambda_expr_1(span, enc, blkarg);
- let call = cx.expr_method_call(span, blkencoder.clone(),
- emit_variant_arg,
- vec!(cx.expr_usize(span, i),
- lambda));
- let call = if i != last {
- cx.expr_try(span, call)
- } else {
- cx.expr(span, ExprRet(Some(call)))
- };
- stmts.push(cx.stmt_expr(call));
- }
-
- // enums with no fields need to return Ok()
- if stmts.len() == 0 {
+ if fields.len() > 0 {
+ let last = fields.len() - 1;
+ for (i, &FieldInfo { ref self_, span, .. }) in fields.iter().enumerate() {
+ let enc = cx.expr_method_call(span, self_.clone(),
+ encode, vec!(blkencoder.clone()));
+ let lambda = cx.lambda_expr_1(span, enc, blkarg);
+ let call = cx.expr_method_call(span, blkencoder.clone(),
+ emit_variant_arg,
+ vec!(cx.expr_usize(span, i),
+ lambda));
+ let call = if i != last {
+ cx.expr_try(span, call)
+ } else {
+ cx.expr(span, ExprRet(Some(call)))
+ };
+ stmts.push(cx.stmt_expr(call));
+ }
+ } else {
let ret_ok = cx.expr(trait_span,
ExprRet(Some(cx.expr_ok(trait_span,
cx.expr_tuple(trait_span, vec![])))));