Move checked arithmetic operators into Int trait
This commit is contained in:
parent
7e57cd843c
commit
e51cc089da
@ -97,7 +97,7 @@ syn keyword rustTrait FromIterator IntoIterator Extend ExactSize
|
||||
syn keyword rustTrait Iterator DoubleEndedIterator
|
||||
syn keyword rustTrait RandomAccessIterator CloneableIterator
|
||||
syn keyword rustTrait OrdIterator MutableDoubleEndedIterator
|
||||
syn keyword rustTrait Num NumCast CheckedAdd CheckedSub CheckedMul CheckedDiv
|
||||
syn keyword rustTrait Num NumCast
|
||||
syn keyword rustTrait Signed Unsigned Primitive Int Float
|
||||
syn keyword rustTrait FloatMath ToPrimitive FromPrimitive
|
||||
syn keyword rustTrait Box
|
||||
|
@ -132,7 +132,7 @@ impl Drop for Arena {
|
||||
|
||||
#[inline]
|
||||
fn round_up(base: uint, align: uint) -> uint {
|
||||
(base.checked_add(&(align - 1))).unwrap() & !(align - 1)
|
||||
(base.checked_add(align - 1)).unwrap() & !(align - 1)
|
||||
}
|
||||
|
||||
// Walk down a chunk, running the destructors for any objects stored
|
||||
@ -376,8 +376,8 @@ fn calculate_size<T>(capacity: uint) -> uint {
|
||||
let mut size = mem::size_of::<TypedArenaChunk<T>>();
|
||||
size = round_up(size, mem::min_align_of::<T>());
|
||||
let elem_size = mem::size_of::<T>();
|
||||
let elems_size = elem_size.checked_mul(&capacity).unwrap();
|
||||
size = size.checked_add(&elems_size).unwrap();
|
||||
let elems_size = elem_size.checked_mul(capacity).unwrap();
|
||||
size = size.checked_add(elems_size).unwrap();
|
||||
size
|
||||
}
|
||||
|
||||
@ -432,7 +432,7 @@ impl<T> TypedArenaChunk<T> {
|
||||
#[inline]
|
||||
fn end(&self) -> *const u8 {
|
||||
unsafe {
|
||||
let size = mem::size_of::<T>().checked_mul(&self.capacity).unwrap();
|
||||
let size = mem::size_of::<T>().checked_mul(self.capacity).unwrap();
|
||||
self.start().offset(size as int)
|
||||
}
|
||||
}
|
||||
@ -481,7 +481,7 @@ impl<T> TypedArena<T> {
|
||||
fn grow(&self) {
|
||||
unsafe {
|
||||
let chunk = *self.first.borrow_mut();
|
||||
let new_capacity = (*chunk).capacity.checked_mul(&2).unwrap();
|
||||
let new_capacity = (*chunk).capacity.checked_mul(2).unwrap();
|
||||
let chunk = TypedArenaChunk::<T>::new(chunk, new_capacity);
|
||||
self.ptr.set((*chunk).start() as *const T);
|
||||
self.end.set((*chunk).end() as *const T);
|
||||
|
@ -161,7 +161,7 @@ impl<T> Vec<T> {
|
||||
} else if capacity == 0 {
|
||||
Vec::new()
|
||||
} else {
|
||||
let size = capacity.checked_mul(&mem::size_of::<T>())
|
||||
let size = capacity.checked_mul(mem::size_of::<T>())
|
||||
.expect("capacity overflow");
|
||||
let ptr = unsafe { allocate(size, mem::min_align_of::<T>()) };
|
||||
Vec { ptr: ptr as *mut T, len: 0, cap: capacity }
|
||||
@ -601,7 +601,7 @@ impl<T> Vec<T> {
|
||||
#[unstable = "matches collection reform specification, waiting for dust to settle"]
|
||||
pub fn reserve(&mut self, additional: uint) {
|
||||
if self.cap - self.len < additional {
|
||||
match self.len.checked_add(&additional) {
|
||||
match self.len.checked_add(additional) {
|
||||
None => panic!("Vec::reserve: `uint` overflow"),
|
||||
// if the checked_add
|
||||
Some(new_cap) => {
|
||||
@ -638,7 +638,7 @@ impl<T> Vec<T> {
|
||||
#[unstable = "matches collection reform specification, waiting for dust to settle"]
|
||||
pub fn reserve_exact(&mut self, additional: uint) {
|
||||
if self.cap - self.len < additional {
|
||||
match self.len.checked_add(&additional) {
|
||||
match self.len.checked_add(additional) {
|
||||
None => panic!("Vec::reserve: `uint` overflow"),
|
||||
Some(new_cap) => self.grow_capacity(new_cap)
|
||||
}
|
||||
@ -971,7 +971,7 @@ impl<T> Vec<T> {
|
||||
pub fn push(&mut self, value: T) {
|
||||
if mem::size_of::<T>() == 0 {
|
||||
// zero-size types consume no memory, so we can't rely on the address space running out
|
||||
self.len = self.len.checked_add(&1).expect("length overflow");
|
||||
self.len = self.len.checked_add(1).expect("length overflow");
|
||||
unsafe { mem::forget(value); }
|
||||
return
|
||||
}
|
||||
@ -1064,7 +1064,7 @@ impl<T> Vec<T> {
|
||||
if mem::size_of::<T>() == 0 { return }
|
||||
|
||||
if capacity > self.cap {
|
||||
let size = capacity.checked_mul(&mem::size_of::<T>())
|
||||
let size = capacity.checked_mul(mem::size_of::<T>())
|
||||
.expect("capacity overflow");
|
||||
unsafe {
|
||||
self.ptr = alloc_or_realloc(self.ptr, self.cap * mem::size_of::<T>(), size);
|
||||
|
@ -60,9 +60,9 @@ This `for` loop syntax can be applied to any iterator over any type.
|
||||
|
||||
use clone::Clone;
|
||||
use cmp;
|
||||
use cmp::{PartialEq, PartialOrd, Ord};
|
||||
use cmp::{PartialOrd, Ord};
|
||||
use mem;
|
||||
use num::{Zero, One, CheckedAdd, CheckedSub, ToPrimitive, Int};
|
||||
use num::{Zero, One, ToPrimitive, Int};
|
||||
use ops::{Add, Mul, Sub};
|
||||
use option::{Option, Some, None};
|
||||
use uint;
|
||||
@ -1093,7 +1093,7 @@ impl<A, T: Iterator<A>, U: Iterator<A>> Iterator<A> for Chain<T, U> {
|
||||
let lower = a_lower.saturating_add(b_lower);
|
||||
|
||||
let upper = match (a_upper, b_upper) {
|
||||
(Some(x), Some(y)) => x.checked_add(&y),
|
||||
(Some(x), Some(y)) => x.checked_add(y),
|
||||
_ => None
|
||||
};
|
||||
|
||||
@ -1415,7 +1415,7 @@ impl<A, T: Iterator<A>> Iterator<A> for Peekable<A, T> {
|
||||
if self.peeked.is_some() {
|
||||
let lo = lo.saturating_add(1);
|
||||
let hi = match hi {
|
||||
Some(x) => x.checked_add(&1),
|
||||
Some(x) => x.checked_add(1),
|
||||
None => None
|
||||
};
|
||||
(lo, hi)
|
||||
@ -1680,7 +1680,7 @@ impl<'a, A, T: Iterator<A>, B, U: Iterator<B>> Iterator<B> for FlatMap<'a, A, T,
|
||||
let (blo, bhi) = self.backiter.as_ref().map_or((0, Some(0)), |it| it.size_hint());
|
||||
let lo = flo.saturating_add(blo);
|
||||
match (self.iter.size_hint(), fhi, bhi) {
|
||||
((0, Some(0)), Some(a), Some(b)) => (lo, a.checked_add(&b)),
|
||||
((0, Some(0)), Some(a), Some(b)) => (lo, a.checked_add(b)),
|
||||
_ => (lo, None)
|
||||
}
|
||||
}
|
||||
@ -1946,7 +1946,7 @@ impl<A: Add<A, A> + PartialOrd + Clone + ToPrimitive> Iterator<A> for Range<A> {
|
||||
// the i64/u64 might lie within their range.
|
||||
let bound = match self.state.to_i64() {
|
||||
Some(a) => {
|
||||
let sz = self.stop.to_i64().map(|b| b.checked_sub(&a));
|
||||
let sz = self.stop.to_i64().map(|b| b.checked_sub(a));
|
||||
match sz {
|
||||
Some(Some(bound)) => bound.to_uint(),
|
||||
_ => None,
|
||||
@ -1954,7 +1954,7 @@ impl<A: Add<A, A> + PartialOrd + Clone + ToPrimitive> Iterator<A> for Range<A> {
|
||||
},
|
||||
None => match self.state.to_u64() {
|
||||
Some(a) => {
|
||||
let sz = self.stop.to_u64().map(|b| b.checked_sub(&a));
|
||||
let sz = self.stop.to_u64().map(|b| b.checked_sub(a));
|
||||
match sz {
|
||||
Some(Some(bound)) => bound.to_uint(),
|
||||
_ => None
|
||||
@ -2024,7 +2024,7 @@ impl<A: Add<A, A> + PartialOrd + Clone + ToPrimitive> Iterator<A> for RangeInclu
|
||||
} else {
|
||||
let lo = lo.saturating_add(1);
|
||||
let hi = match hi {
|
||||
Some(x) => x.checked_add(&1),
|
||||
Some(x) => x.checked_add(1),
|
||||
None => None
|
||||
};
|
||||
(lo, hi)
|
||||
@ -2060,18 +2060,17 @@ pub struct RangeStep<A> {
|
||||
|
||||
/// Return an iterator over the range [start, stop) by `step`. It handles overflow by stopping.
|
||||
#[inline]
|
||||
pub fn range_step<A: CheckedAdd + PartialOrd +
|
||||
Clone + Zero>(start: A, stop: A, step: A) -> RangeStep<A> {
|
||||
pub fn range_step<A: Int>(start: A, stop: A, step: A) -> RangeStep<A> {
|
||||
let rev = step < Zero::zero();
|
||||
RangeStep{state: start, stop: stop, step: step, rev: rev}
|
||||
}
|
||||
|
||||
impl<A: CheckedAdd + PartialOrd + Clone> Iterator<A> for RangeStep<A> {
|
||||
impl<A: Int> Iterator<A> for RangeStep<A> {
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<A> {
|
||||
if (self.rev && self.state > self.stop) || (!self.rev && self.state < self.stop) {
|
||||
let result = self.state.clone();
|
||||
match self.state.checked_add(&self.step) {
|
||||
let result = self.state;
|
||||
match self.state.checked_add(self.step) {
|
||||
Some(x) => self.state = x,
|
||||
None => self.state = self.stop.clone()
|
||||
}
|
||||
@ -2094,19 +2093,18 @@ pub struct RangeStepInclusive<A> {
|
||||
|
||||
/// Return an iterator over the range [start, stop] by `step`. It handles overflow by stopping.
|
||||
#[inline]
|
||||
pub fn range_step_inclusive<A: CheckedAdd + PartialOrd + Clone + Zero>(start: A, stop: A,
|
||||
step: A) -> RangeStepInclusive<A> {
|
||||
pub fn range_step_inclusive<A: Int>(start: A, stop: A, step: A) -> RangeStepInclusive<A> {
|
||||
let rev = step < Zero::zero();
|
||||
RangeStepInclusive{state: start, stop: stop, step: step, rev: rev, done: false}
|
||||
}
|
||||
|
||||
impl<A: CheckedAdd + PartialOrd + Clone + PartialEq> Iterator<A> for RangeStepInclusive<A> {
|
||||
impl<A: Int> Iterator<A> for RangeStepInclusive<A> {
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<A> {
|
||||
if !self.done && ((self.rev && self.state >= self.stop) ||
|
||||
(!self.rev && self.state <= self.stop)) {
|
||||
let result = self.state.clone();
|
||||
match self.state.checked_add(&self.step) {
|
||||
let result = self.state;
|
||||
match self.state.checked_add(self.step) {
|
||||
Some(x) => self.state = x,
|
||||
None => self.done = true
|
||||
}
|
||||
|
@ -348,10 +348,6 @@ trait_impl!(Primitive for uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64)
|
||||
/// operators, bit counting methods, and endian conversion functions.
|
||||
pub trait Int: Primitive
|
||||
+ Ord
|
||||
+ CheckedAdd
|
||||
+ CheckedSub
|
||||
+ CheckedMul
|
||||
+ CheckedDiv
|
||||
+ Bounded
|
||||
+ Not<Self>
|
||||
+ BitAnd<Self,Self>
|
||||
@ -526,11 +522,65 @@ pub trait Int: Primitive
|
||||
if cfg!(target_endian = "little") { self } else { self.swap_bytes() }
|
||||
}
|
||||
|
||||
/// Adds two numbers, checking for overflow. If overflow occurs, `None` is
|
||||
/// returned.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::num::Int;
|
||||
///
|
||||
/// assert_eq!(5u16.checked_add(65530), Some(65535));
|
||||
/// assert_eq!(6u16.checked_add(65530), None);
|
||||
/// ```
|
||||
fn checked_add(self, other: Self) -> Option<Self>;
|
||||
|
||||
/// Subtracts two numbers, checking for underflow. If underflow occurs,
|
||||
/// `None` is returned.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::num::Int;
|
||||
///
|
||||
/// assert_eq!((-127i8).checked_sub(1), Some(-128));
|
||||
/// assert_eq!((-128i8).checked_sub(1), None);
|
||||
/// ```
|
||||
fn checked_sub(self, other: Self) -> Option<Self>;
|
||||
|
||||
/// Multiplies two numbers, checking for underflow or overflow. If underflow
|
||||
/// or overflow occurs, `None` is returned.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::num::Int;
|
||||
///
|
||||
/// assert_eq!(5u8.checked_mul(51), Some(255));
|
||||
/// assert_eq!(5u8.checked_mul(52), None);
|
||||
/// ```
|
||||
fn checked_mul(self, other: Self) -> Option<Self>;
|
||||
|
||||
/// Divides two numbers, checking for underflow, overflow and division by
|
||||
/// zero. If underflow occurs, `None` is returned.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::num::Int;
|
||||
///
|
||||
/// assert_eq!((-127i8).checked_div(-1), Some(127));
|
||||
/// assert_eq!((-128i8).checked_div(-1), None);
|
||||
/// assert_eq!((1i8).checked_div(0), None);
|
||||
/// ```
|
||||
#[inline]
|
||||
fn checked_div(self, other: Self) -> Option<Self>;
|
||||
|
||||
/// Saturating addition. Returns `self + other`, saturating at the
|
||||
/// numeric bounds instead of overflowing.
|
||||
#[inline]
|
||||
fn saturating_add(self, other: Self) -> Self {
|
||||
match self.checked_add(&other) {
|
||||
match self.checked_add(other) {
|
||||
Some(x) => x,
|
||||
None if other >= Zero::zero() => Bounded::max_value(),
|
||||
None => Bounded::min_value(),
|
||||
@ -541,7 +591,7 @@ pub trait Int: Primitive
|
||||
/// numeric bounds instead of overflowing.
|
||||
#[inline]
|
||||
fn saturating_sub(self, other: Self) -> Self {
|
||||
match self.checked_sub(&other) {
|
||||
match self.checked_sub(other) {
|
||||
Some(x) => x,
|
||||
None if other >= Zero::zero() => Bounded::min_value(),
|
||||
None => Bounded::max_value(),
|
||||
@ -549,9 +599,22 @@ pub trait Int: Primitive
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! checked_op {
|
||||
($T:ty, $U:ty, $op:path, $x:expr, $y:expr) => {{
|
||||
let (result, overflowed) = unsafe { $op($x as $U, $y as $U) };
|
||||
if overflowed { None } else { Some(result as $T) }
|
||||
}}
|
||||
}
|
||||
|
||||
macro_rules! uint_impl {
|
||||
($T:ty, $ActualT:ty, $BITS:expr,
|
||||
$ctpop:path, $ctlz:path, $cttz:path, $bswap:path) => {
|
||||
($T:ty = $ActualT:ty, $BITS:expr,
|
||||
$ctpop:path,
|
||||
$ctlz:path,
|
||||
$cttz:path,
|
||||
$bswap:path,
|
||||
$add_with_overflow:path,
|
||||
$sub_with_overflow:path,
|
||||
$mul_with_overflow:path) => {
|
||||
impl Int for $T {
|
||||
#[inline]
|
||||
fn count_ones(self) -> uint { unsafe { $ctpop(self as $ActualT) as uint } }
|
||||
@ -578,6 +641,29 @@ macro_rules! uint_impl {
|
||||
|
||||
#[inline]
|
||||
fn swap_bytes(self) -> $T { unsafe { $bswap(self as $ActualT) as $T } }
|
||||
|
||||
#[inline]
|
||||
fn checked_add(self, other: $T) -> Option<$T> {
|
||||
checked_op!($T, $ActualT, $add_with_overflow, self, other)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn checked_sub(self, other: $T) -> Option<$T> {
|
||||
checked_op!($T, $ActualT, $sub_with_overflow, self, other)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn checked_mul(self, other: $T) -> Option<$T> {
|
||||
checked_op!($T, $ActualT, $mul_with_overflow, self, other)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn checked_div(self, v: $T) -> Option<$T> {
|
||||
match v {
|
||||
0 => None,
|
||||
v => Some(self / v),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -586,74 +672,145 @@ macro_rules! uint_impl {
|
||||
/// consistency with the other `bswap` intrinsics.
|
||||
unsafe fn bswap8(x: u8) -> u8 { x }
|
||||
|
||||
uint_impl!(u8, u8, 8,
|
||||
uint_impl!(u8 = u8, 8,
|
||||
intrinsics::ctpop8,
|
||||
intrinsics::ctlz8,
|
||||
intrinsics::cttz8,
|
||||
bswap8)
|
||||
bswap8,
|
||||
intrinsics::u8_add_with_overflow,
|
||||
intrinsics::u8_sub_with_overflow,
|
||||
intrinsics::u8_mul_with_overflow)
|
||||
|
||||
uint_impl!(u16, u16, 16,
|
||||
uint_impl!(u16 = u16, 16,
|
||||
intrinsics::ctpop16,
|
||||
intrinsics::ctlz16,
|
||||
intrinsics::cttz16,
|
||||
intrinsics::bswap16)
|
||||
intrinsics::bswap16,
|
||||
intrinsics::u16_add_with_overflow,
|
||||
intrinsics::u16_sub_with_overflow,
|
||||
intrinsics::u16_mul_with_overflow)
|
||||
|
||||
uint_impl!(u32, u32, 32,
|
||||
uint_impl!(u32 = u32, 32,
|
||||
intrinsics::ctpop32,
|
||||
intrinsics::ctlz32,
|
||||
intrinsics::cttz32,
|
||||
intrinsics::bswap32)
|
||||
intrinsics::bswap32,
|
||||
intrinsics::u32_add_with_overflow,
|
||||
intrinsics::u32_sub_with_overflow,
|
||||
intrinsics::u32_mul_with_overflow)
|
||||
|
||||
uint_impl!(u64, u64, 64,
|
||||
uint_impl!(u64 = u64, 64,
|
||||
intrinsics::ctpop64,
|
||||
intrinsics::ctlz64,
|
||||
intrinsics::cttz64,
|
||||
intrinsics::bswap64)
|
||||
intrinsics::bswap64,
|
||||
intrinsics::u64_add_with_overflow,
|
||||
intrinsics::u64_sub_with_overflow,
|
||||
intrinsics::u64_mul_with_overflow)
|
||||
|
||||
#[cfg(target_word_size = "32")]
|
||||
uint_impl!(uint, u32, 32,
|
||||
uint_impl!(uint = u32, 32,
|
||||
intrinsics::ctpop32,
|
||||
intrinsics::ctlz32,
|
||||
intrinsics::cttz32,
|
||||
intrinsics::bswap32)
|
||||
intrinsics::bswap32,
|
||||
intrinsics::u32_add_with_overflow,
|
||||
intrinsics::u32_sub_with_overflow,
|
||||
intrinsics::u32_mul_with_overflow)
|
||||
|
||||
#[cfg(target_word_size = "64")]
|
||||
uint_impl!(uint, u64, 64,
|
||||
uint_impl!(uint = u64, 64,
|
||||
intrinsics::ctpop64,
|
||||
intrinsics::ctlz64,
|
||||
intrinsics::cttz64,
|
||||
intrinsics::bswap64)
|
||||
intrinsics::bswap64,
|
||||
intrinsics::u64_add_with_overflow,
|
||||
intrinsics::u64_sub_with_overflow,
|
||||
intrinsics::u64_mul_with_overflow)
|
||||
|
||||
macro_rules! int_impl {
|
||||
($T:ty, $U:ty) => {
|
||||
($T:ty = $ActualT:ty, $UnsignedT:ty,
|
||||
$add_with_overflow:path,
|
||||
$sub_with_overflow:path,
|
||||
$mul_with_overflow:path) => {
|
||||
impl Int for $T {
|
||||
#[inline]
|
||||
fn count_ones(self) -> uint { (self as $U).count_ones() }
|
||||
fn count_ones(self) -> uint { (self as $UnsignedT).count_ones() }
|
||||
|
||||
#[inline]
|
||||
fn leading_zeros(self) -> uint { (self as $U).leading_zeros() }
|
||||
fn leading_zeros(self) -> uint { (self as $UnsignedT).leading_zeros() }
|
||||
|
||||
#[inline]
|
||||
fn trailing_zeros(self) -> uint { (self as $U).trailing_zeros() }
|
||||
fn trailing_zeros(self) -> uint { (self as $UnsignedT).trailing_zeros() }
|
||||
|
||||
#[inline]
|
||||
fn rotate_left(self, n: uint) -> $T { (self as $U).rotate_left(n) as $T }
|
||||
fn rotate_left(self, n: uint) -> $T { (self as $UnsignedT).rotate_left(n) as $T }
|
||||
|
||||
#[inline]
|
||||
fn rotate_right(self, n: uint) -> $T { (self as $U).rotate_right(n) as $T }
|
||||
fn rotate_right(self, n: uint) -> $T { (self as $UnsignedT).rotate_right(n) as $T }
|
||||
|
||||
#[inline]
|
||||
fn swap_bytes(self) -> $T { (self as $U).swap_bytes() as $T }
|
||||
fn swap_bytes(self) -> $T { (self as $UnsignedT).swap_bytes() as $T }
|
||||
|
||||
#[inline]
|
||||
fn checked_add(self, other: $T) -> Option<$T> {
|
||||
checked_op!($T, $ActualT, $add_with_overflow, self, other)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn checked_sub(self, other: $T) -> Option<$T> {
|
||||
checked_op!($T, $ActualT, $sub_with_overflow, self, other)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn checked_mul(self, other: $T) -> Option<$T> {
|
||||
checked_op!($T, $ActualT, $mul_with_overflow, self, other)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn checked_div(self, v: $T) -> Option<$T> {
|
||||
match v {
|
||||
0 => None,
|
||||
-1 if self == Bounded::min_value()
|
||||
=> None,
|
||||
v => Some(self / v),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int_impl!(i8, u8)
|
||||
int_impl!(i16, u16)
|
||||
int_impl!(i32, u32)
|
||||
int_impl!(i64, u64)
|
||||
#[cfg(target_word_size = "32")] int_impl!(int, u32)
|
||||
#[cfg(target_word_size = "64")] int_impl!(int, u64)
|
||||
int_impl!(i8 = i8, u8,
|
||||
intrinsics::i8_add_with_overflow,
|
||||
intrinsics::i8_sub_with_overflow,
|
||||
intrinsics::i8_mul_with_overflow)
|
||||
|
||||
int_impl!(i16 = i16, u16,
|
||||
intrinsics::i16_add_with_overflow,
|
||||
intrinsics::i16_sub_with_overflow,
|
||||
intrinsics::i16_mul_with_overflow)
|
||||
|
||||
int_impl!(i32 = i32, u32,
|
||||
intrinsics::i32_add_with_overflow,
|
||||
intrinsics::i32_sub_with_overflow,
|
||||
intrinsics::i32_mul_with_overflow)
|
||||
|
||||
int_impl!(i64 = i64, u64,
|
||||
intrinsics::i64_add_with_overflow,
|
||||
intrinsics::i64_sub_with_overflow,
|
||||
intrinsics::i64_mul_with_overflow)
|
||||
|
||||
#[cfg(target_word_size = "32")]
|
||||
int_impl!(int = i32, u32,
|
||||
intrinsics::i32_add_with_overflow,
|
||||
intrinsics::i32_sub_with_overflow,
|
||||
intrinsics::i32_mul_with_overflow)
|
||||
|
||||
#[cfg(target_word_size = "64")]
|
||||
int_impl!(int = i64, u64,
|
||||
intrinsics::i64_add_with_overflow,
|
||||
intrinsics::i64_sub_with_overflow,
|
||||
intrinsics::i64_mul_with_overflow)
|
||||
|
||||
/// Unsigned integers
|
||||
pub trait UnsignedInt: Int {
|
||||
@ -686,7 +843,7 @@ pub trait UnsignedInt: Int {
|
||||
tmp = tmp | (tmp >> shift);
|
||||
shift = shift << 1u;
|
||||
}
|
||||
tmp.checked_add(&one())
|
||||
tmp.checked_add(one())
|
||||
}
|
||||
}
|
||||
|
||||
@ -1184,192 +1341,6 @@ impl_num_cast!(int, to_int)
|
||||
impl_num_cast!(f32, to_f32)
|
||||
impl_num_cast!(f64, to_f64)
|
||||
|
||||
/// Performs addition that returns `None` instead of wrapping around on overflow.
|
||||
pub trait CheckedAdd: Add<Self, Self> {
|
||||
/// Adds two numbers, checking for overflow. If overflow happens, `None` is returned.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::num::CheckedAdd;
|
||||
/// assert_eq!(5u16.checked_add(&65530), Some(65535));
|
||||
/// assert_eq!(6u16.checked_add(&65530), None);
|
||||
/// ```
|
||||
fn checked_add(&self, v: &Self) -> Option<Self>;
|
||||
}
|
||||
|
||||
macro_rules! checked_impl(
|
||||
($trait_name:ident, $method:ident, $t:ty, $op:path) => {
|
||||
impl $trait_name for $t {
|
||||
#[inline]
|
||||
fn $method(&self, v: &$t) -> Option<$t> {
|
||||
unsafe {
|
||||
let (x, y) = $op(*self, *v);
|
||||
if y { None } else { Some(x) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
macro_rules! checked_cast_impl(
|
||||
($trait_name:ident, $method:ident, $t:ty, $cast:ty, $op:path) => {
|
||||
impl $trait_name for $t {
|
||||
#[inline]
|
||||
fn $method(&self, v: &$t) -> Option<$t> {
|
||||
unsafe {
|
||||
let (x, y) = $op(*self as $cast, *v as $cast);
|
||||
if y { None } else { Some(x as $t) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
#[cfg(target_word_size = "32")]
|
||||
checked_cast_impl!(CheckedAdd, checked_add, uint, u32, intrinsics::u32_add_with_overflow)
|
||||
#[cfg(target_word_size = "64")]
|
||||
checked_cast_impl!(CheckedAdd, checked_add, uint, u64, intrinsics::u64_add_with_overflow)
|
||||
|
||||
checked_impl!(CheckedAdd, checked_add, u8, intrinsics::u8_add_with_overflow)
|
||||
checked_impl!(CheckedAdd, checked_add, u16, intrinsics::u16_add_with_overflow)
|
||||
checked_impl!(CheckedAdd, checked_add, u32, intrinsics::u32_add_with_overflow)
|
||||
checked_impl!(CheckedAdd, checked_add, u64, intrinsics::u64_add_with_overflow)
|
||||
|
||||
#[cfg(target_word_size = "32")]
|
||||
checked_cast_impl!(CheckedAdd, checked_add, int, i32, intrinsics::i32_add_with_overflow)
|
||||
#[cfg(target_word_size = "64")]
|
||||
checked_cast_impl!(CheckedAdd, checked_add, int, i64, intrinsics::i64_add_with_overflow)
|
||||
|
||||
checked_impl!(CheckedAdd, checked_add, i8, intrinsics::i8_add_with_overflow)
|
||||
checked_impl!(CheckedAdd, checked_add, i16, intrinsics::i16_add_with_overflow)
|
||||
checked_impl!(CheckedAdd, checked_add, i32, intrinsics::i32_add_with_overflow)
|
||||
checked_impl!(CheckedAdd, checked_add, i64, intrinsics::i64_add_with_overflow)
|
||||
|
||||
/// Performs subtraction that returns `None` instead of wrapping around on underflow.
|
||||
pub trait CheckedSub: Sub<Self, Self> {
|
||||
/// Subtracts two numbers, checking for underflow. If underflow happens, `None` is returned.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::num::CheckedSub;
|
||||
/// assert_eq!((-127i8).checked_sub(&1), Some(-128));
|
||||
/// assert_eq!((-128i8).checked_sub(&1), None);
|
||||
/// ```
|
||||
fn checked_sub(&self, v: &Self) -> Option<Self>;
|
||||
}
|
||||
|
||||
#[cfg(target_word_size = "32")]
|
||||
checked_cast_impl!(CheckedSub, checked_sub, uint, u32, intrinsics::u32_sub_with_overflow)
|
||||
#[cfg(target_word_size = "64")]
|
||||
checked_cast_impl!(CheckedSub, checked_sub, uint, u64, intrinsics::u64_sub_with_overflow)
|
||||
|
||||
checked_impl!(CheckedSub, checked_sub, u8, intrinsics::u8_sub_with_overflow)
|
||||
checked_impl!(CheckedSub, checked_sub, u16, intrinsics::u16_sub_with_overflow)
|
||||
checked_impl!(CheckedSub, checked_sub, u32, intrinsics::u32_sub_with_overflow)
|
||||
checked_impl!(CheckedSub, checked_sub, u64, intrinsics::u64_sub_with_overflow)
|
||||
|
||||
#[cfg(target_word_size = "32")]
|
||||
checked_cast_impl!(CheckedSub, checked_sub, int, i32, intrinsics::i32_sub_with_overflow)
|
||||
#[cfg(target_word_size = "64")]
|
||||
checked_cast_impl!(CheckedSub, checked_sub, int, i64, intrinsics::i64_sub_with_overflow)
|
||||
|
||||
checked_impl!(CheckedSub, checked_sub, i8, intrinsics::i8_sub_with_overflow)
|
||||
checked_impl!(CheckedSub, checked_sub, i16, intrinsics::i16_sub_with_overflow)
|
||||
checked_impl!(CheckedSub, checked_sub, i32, intrinsics::i32_sub_with_overflow)
|
||||
checked_impl!(CheckedSub, checked_sub, i64, intrinsics::i64_sub_with_overflow)
|
||||
|
||||
/// Performs multiplication that returns `None` instead of wrapping around on underflow or
|
||||
/// overflow.
|
||||
pub trait CheckedMul: Mul<Self, Self> {
|
||||
/// Multiplies two numbers, checking for underflow or overflow. If underflow or overflow
|
||||
/// happens, `None` is returned.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::num::CheckedMul;
|
||||
/// assert_eq!(5u8.checked_mul(&51), Some(255));
|
||||
/// assert_eq!(5u8.checked_mul(&52), None);
|
||||
/// ```
|
||||
fn checked_mul(&self, v: &Self) -> Option<Self>;
|
||||
}
|
||||
|
||||
#[cfg(target_word_size = "32")]
|
||||
checked_cast_impl!(CheckedMul, checked_mul, uint, u32, intrinsics::u32_mul_with_overflow)
|
||||
#[cfg(target_word_size = "64")]
|
||||
checked_cast_impl!(CheckedMul, checked_mul, uint, u64, intrinsics::u64_mul_with_overflow)
|
||||
|
||||
checked_impl!(CheckedMul, checked_mul, u8, intrinsics::u8_mul_with_overflow)
|
||||
checked_impl!(CheckedMul, checked_mul, u16, intrinsics::u16_mul_with_overflow)
|
||||
checked_impl!(CheckedMul, checked_mul, u32, intrinsics::u32_mul_with_overflow)
|
||||
checked_impl!(CheckedMul, checked_mul, u64, intrinsics::u64_mul_with_overflow)
|
||||
|
||||
#[cfg(target_word_size = "32")]
|
||||
checked_cast_impl!(CheckedMul, checked_mul, int, i32, intrinsics::i32_mul_with_overflow)
|
||||
#[cfg(target_word_size = "64")]
|
||||
checked_cast_impl!(CheckedMul, checked_mul, int, i64, intrinsics::i64_mul_with_overflow)
|
||||
|
||||
checked_impl!(CheckedMul, checked_mul, i8, intrinsics::i8_mul_with_overflow)
|
||||
checked_impl!(CheckedMul, checked_mul, i16, intrinsics::i16_mul_with_overflow)
|
||||
checked_impl!(CheckedMul, checked_mul, i32, intrinsics::i32_mul_with_overflow)
|
||||
checked_impl!(CheckedMul, checked_mul, i64, intrinsics::i64_mul_with_overflow)
|
||||
|
||||
/// Performs division that returns `None` instead of panicking on division by zero and instead of
|
||||
/// wrapping around on underflow and overflow.
|
||||
pub trait CheckedDiv: Div<Self, Self> {
|
||||
/// Divides two numbers, checking for underflow, overflow and division by zero. If any of that
|
||||
/// happens, `None` is returned.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::num::CheckedDiv;
|
||||
/// assert_eq!((-127i8).checked_div(&-1), Some(127));
|
||||
/// assert_eq!((-128i8).checked_div(&-1), None);
|
||||
/// assert_eq!((1i8).checked_div(&0), None);
|
||||
/// ```
|
||||
fn checked_div(&self, v: &Self) -> Option<Self>;
|
||||
}
|
||||
|
||||
macro_rules! checkeddiv_int_impl(
|
||||
($t:ty, $min:expr) => {
|
||||
impl CheckedDiv for $t {
|
||||
#[inline]
|
||||
fn checked_div(&self, v: &$t) -> Option<$t> {
|
||||
if *v == 0 || (*self == $min && *v == -1) {
|
||||
None
|
||||
} else {
|
||||
Some(*self / *v)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
checkeddiv_int_impl!(int, int::MIN)
|
||||
checkeddiv_int_impl!(i8, i8::MIN)
|
||||
checkeddiv_int_impl!(i16, i16::MIN)
|
||||
checkeddiv_int_impl!(i32, i32::MIN)
|
||||
checkeddiv_int_impl!(i64, i64::MIN)
|
||||
|
||||
macro_rules! checkeddiv_uint_impl(
|
||||
($($t:ty)*) => ($(
|
||||
impl CheckedDiv for $t {
|
||||
#[inline]
|
||||
fn checked_div(&self, v: &$t) -> Option<$t> {
|
||||
if *v == 0 {
|
||||
None
|
||||
} else {
|
||||
Some(*self / *v)
|
||||
}
|
||||
}
|
||||
}
|
||||
)*)
|
||||
)
|
||||
|
||||
checkeddiv_uint_impl!(uint u8 u16 u32 u64)
|
||||
|
||||
/// Used for representing the classification of floating point numbers
|
||||
#[deriving(PartialEq, Show)]
|
||||
pub enum FPCategory {
|
||||
|
@ -51,7 +51,7 @@ pub use cmp::{Ordering, Less, Equal, Greater, Equiv};
|
||||
pub use iter::{FromIterator, Extend};
|
||||
pub use iter::{Iterator, DoubleEndedIterator, RandomAccessIterator, CloneableIterator};
|
||||
pub use iter::{OrdIterator, MutableDoubleEndedIterator, ExactSize};
|
||||
pub use num::{Num, NumCast, CheckedAdd, CheckedSub, CheckedMul};
|
||||
pub use num::{Num, NumCast};
|
||||
pub use num::{Signed, Unsigned, Float};
|
||||
pub use num::{Primitive, Int, ToPrimitive, FromPrimitive};
|
||||
pub use option::{Option, Some, None};
|
||||
|
@ -40,7 +40,7 @@ use cmp::{PartialEq, PartialOrd, Eq, Ord, Ordering, Less, Equal, Greater, Equiv}
|
||||
use cmp;
|
||||
use default::Default;
|
||||
use iter::*;
|
||||
use num::{CheckedAdd, Int, div_rem};
|
||||
use num::{Int, div_rem};
|
||||
use ops;
|
||||
use option::{None, Option, Some};
|
||||
use ptr;
|
||||
@ -1346,7 +1346,7 @@ impl<'a, T> Iterator<&'a [T]> for Windows<'a, T> {
|
||||
(0, Some(0))
|
||||
} else {
|
||||
let x = self.v.len() - self.size;
|
||||
(x.saturating_add(1), x.checked_add(&1u))
|
||||
(x.saturating_add(1), x.checked_add(1u))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ use iter::{Map, Iterator};
|
||||
use iter::{DoubleEndedIterator, ExactSize};
|
||||
use iter::range;
|
||||
use kinds::Sized;
|
||||
use num::{CheckedMul, Int};
|
||||
use num::Int;
|
||||
use option::{Option, None, Some};
|
||||
use raw::Repr;
|
||||
use slice::{mod, SlicePrelude};
|
||||
@ -750,7 +750,7 @@ impl<'a> Iterator<u16> for Utf16CodeUnits<'a> {
|
||||
// every char gets either one u16 or two u16,
|
||||
// so this iterator is between 1 or 2 times as
|
||||
// long as the underlying iterator.
|
||||
(low, high.and_then(|n| n.checked_mul(&2)))
|
||||
(low, high.and_then(|n| n.checked_mul(2)))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,6 @@ mod tests {
|
||||
use core::$T_i::*;
|
||||
use core::int;
|
||||
use num;
|
||||
use core::num::CheckedDiv;
|
||||
|
||||
#[test]
|
||||
fn test_overflows() {
|
||||
@ -152,9 +151,9 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_signed_checked_div() {
|
||||
assert!(10i.checked_div(&2) == Some(5));
|
||||
assert!(5i.checked_div(&0) == None);
|
||||
assert!(int::MIN.checked_div(&-1) == None);
|
||||
assert!(10i.checked_div(2) == Some(5));
|
||||
assert!(5i.checked_div(0) == None);
|
||||
assert!(int::MIN.checked_div(-1) == None);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,6 @@ macro_rules! uint_module (($T:ty, $T_i:ident) => (
|
||||
mod tests {
|
||||
use core::$T_i::*;
|
||||
use num;
|
||||
use core::num::CheckedDiv;
|
||||
|
||||
#[test]
|
||||
fn test_overflows() {
|
||||
@ -120,8 +119,8 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_unsigned_checked_div() {
|
||||
assert!(10u.checked_div(&2) == Some(5));
|
||||
assert!(5u.checked_div(&0) == None);
|
||||
assert!(10u.checked_div(2) == Some(5));
|
||||
assert!(5u.checked_div(0) == None);
|
||||
}
|
||||
}
|
||||
))
|
||||
|
@ -126,7 +126,7 @@ impl<'a, T: Clone> WeightedChoice<'a, T> {
|
||||
// weights so we can binary search. This *could* drop elements
|
||||
// with weight == 0 as an optimisation.
|
||||
for item in items.iter_mut() {
|
||||
running_total = match running_total.checked_add(&item.weight) {
|
||||
running_total = match running_total.checked_add(item.weight) {
|
||||
Some(n) => n,
|
||||
None => panic!("WeightedChoice::new called with a total weight \
|
||||
larger than a uint can contain")
|
||||
|
@ -24,15 +24,13 @@ use middle::trans::type_::Type;
|
||||
use syntax::abi;
|
||||
use syntax::ast;
|
||||
|
||||
use std::num::CheckedMul;
|
||||
|
||||
// LLVM doesn't like objects that are too big. Issue #17913
|
||||
fn ensure_array_fits_in_address_space(ccx: &CrateContext,
|
||||
llet: Type,
|
||||
size: machine::llsize,
|
||||
scapegoat: ty::t) {
|
||||
let esz = machine::llsize_of_alloc(ccx, llet);
|
||||
match esz.checked_mul(&size) {
|
||||
match esz.checked_mul(size) {
|
||||
Some(n) if n < ccx.max_obj_size() => {}
|
||||
_ => { ccx.report_overbig_object(scapegoat) }
|
||||
}
|
||||
|
@ -61,14 +61,14 @@ impl ToBits for u64 {
|
||||
|
||||
/// Adds the specified number of bytes to the bit count. panic!() if this would cause numeric
|
||||
/// overflow.
|
||||
fn add_bytes_to_bits<T: Int + CheckedAdd + ToBits>(bits: T, bytes: T) -> T {
|
||||
fn add_bytes_to_bits<T: Int + ToBits>(bits: T, bytes: T) -> T {
|
||||
let (new_high_bits, new_low_bits) = bytes.to_bits();
|
||||
|
||||
if new_high_bits > Zero::zero() {
|
||||
panic!("numeric overflow occurred.")
|
||||
}
|
||||
|
||||
match bits.checked_add(&new_low_bits) {
|
||||
match bits.checked_add(new_low_bits) {
|
||||
Some(x) => return x,
|
||||
None => panic!("numeric overflow occurred.")
|
||||
}
|
||||
|
@ -609,7 +609,7 @@ impl<'a> PrettyEncoder<'a> {
|
||||
/// This is safe to set during encoding.
|
||||
pub fn set_indent<'a>(&mut self, indent: uint) {
|
||||
// self.indent very well could be 0 so we need to use checked division.
|
||||
let level = self.curr_indent.checked_div(&self.indent).unwrap_or(0);
|
||||
let level = self.curr_indent.checked_div(self.indent).unwrap_or(0);
|
||||
self.indent = indent;
|
||||
self.curr_indent = level * self.indent;
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ use iter::{Iterator, count};
|
||||
use kinds::{Sized, marker};
|
||||
use mem::{min_align_of, size_of};
|
||||
use mem;
|
||||
use num::{CheckedAdd, CheckedMul, UnsignedInt};
|
||||
use num::{Int, UnsignedInt};
|
||||
use ops::{Deref, DerefMut, Drop};
|
||||
use option::{Some, None, Option};
|
||||
use ptr::{RawPtr, copy_nonoverlapping_memory, zero_memory};
|
||||
@ -604,9 +604,9 @@ impl<K, V> RawTable<K, V> {
|
||||
vals_size, min_align_of::< V >());
|
||||
|
||||
// One check for overflow that covers calculation and rounding of size.
|
||||
let size_of_bucket = size_of::<u64>().checked_add(&size_of::<K>()).unwrap()
|
||||
.checked_add(&size_of::<V>()).unwrap();
|
||||
assert!(size >= capacity.checked_mul(&size_of_bucket)
|
||||
let size_of_bucket = size_of::<u64>().checked_add(size_of::<K>()).unwrap()
|
||||
.checked_add(size_of::<V>()).unwrap();
|
||||
assert!(size >= capacity.checked_mul(size_of_bucket)
|
||||
.expect("capacity overflow"),
|
||||
"capacity overflow");
|
||||
|
||||
|
@ -24,7 +24,6 @@ pub use core::num::{Num, div_rem, Zero, zero, One, one};
|
||||
pub use core::num::{Signed, abs, signum};
|
||||
pub use core::num::{Unsigned, pow, Bounded};
|
||||
pub use core::num::{Primitive, Int, UnsignedInt};
|
||||
pub use core::num::{CheckedAdd, CheckedSub, CheckedMul, CheckedDiv};
|
||||
pub use core::num::{cast, FromPrimitive, NumCast, ToPrimitive};
|
||||
pub use core::num::{next_power_of_two, is_power_of_two};
|
||||
pub use core::num::{checked_next_power_of_two};
|
||||
@ -636,36 +635,36 @@ mod tests {
|
||||
#[test]
|
||||
fn test_checked_add() {
|
||||
let five_less = uint::MAX - 5;
|
||||
assert_eq!(five_less.checked_add(&0), Some(uint::MAX - 5));
|
||||
assert_eq!(five_less.checked_add(&1), Some(uint::MAX - 4));
|
||||
assert_eq!(five_less.checked_add(&2), Some(uint::MAX - 3));
|
||||
assert_eq!(five_less.checked_add(&3), Some(uint::MAX - 2));
|
||||
assert_eq!(five_less.checked_add(&4), Some(uint::MAX - 1));
|
||||
assert_eq!(five_less.checked_add(&5), Some(uint::MAX));
|
||||
assert_eq!(five_less.checked_add(&6), None);
|
||||
assert_eq!(five_less.checked_add(&7), None);
|
||||
assert_eq!(five_less.checked_add(0), Some(uint::MAX - 5));
|
||||
assert_eq!(five_less.checked_add(1), Some(uint::MAX - 4));
|
||||
assert_eq!(five_less.checked_add(2), Some(uint::MAX - 3));
|
||||
assert_eq!(five_less.checked_add(3), Some(uint::MAX - 2));
|
||||
assert_eq!(five_less.checked_add(4), Some(uint::MAX - 1));
|
||||
assert_eq!(five_less.checked_add(5), Some(uint::MAX));
|
||||
assert_eq!(five_less.checked_add(6), None);
|
||||
assert_eq!(five_less.checked_add(7), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_checked_sub() {
|
||||
assert_eq!(5u.checked_sub(&0), Some(5));
|
||||
assert_eq!(5u.checked_sub(&1), Some(4));
|
||||
assert_eq!(5u.checked_sub(&2), Some(3));
|
||||
assert_eq!(5u.checked_sub(&3), Some(2));
|
||||
assert_eq!(5u.checked_sub(&4), Some(1));
|
||||
assert_eq!(5u.checked_sub(&5), Some(0));
|
||||
assert_eq!(5u.checked_sub(&6), None);
|
||||
assert_eq!(5u.checked_sub(&7), None);
|
||||
assert_eq!(5u.checked_sub(0), Some(5));
|
||||
assert_eq!(5u.checked_sub(1), Some(4));
|
||||
assert_eq!(5u.checked_sub(2), Some(3));
|
||||
assert_eq!(5u.checked_sub(3), Some(2));
|
||||
assert_eq!(5u.checked_sub(4), Some(1));
|
||||
assert_eq!(5u.checked_sub(5), Some(0));
|
||||
assert_eq!(5u.checked_sub(6), None);
|
||||
assert_eq!(5u.checked_sub(7), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_checked_mul() {
|
||||
let third = uint::MAX / 3;
|
||||
assert_eq!(third.checked_mul(&0), Some(0));
|
||||
assert_eq!(third.checked_mul(&1), Some(third));
|
||||
assert_eq!(third.checked_mul(&2), Some(third * 2));
|
||||
assert_eq!(third.checked_mul(&3), Some(third * 3));
|
||||
assert_eq!(third.checked_mul(&4), None);
|
||||
assert_eq!(third.checked_mul(0), Some(0));
|
||||
assert_eq!(third.checked_mul(1), Some(third));
|
||||
assert_eq!(third.checked_mul(2), Some(third * 2));
|
||||
assert_eq!(third.checked_mul(3), Some(third * 3));
|
||||
assert_eq!(third.checked_mul(4), None);
|
||||
}
|
||||
|
||||
macro_rules! test_next_power_of_two(
|
||||
|
@ -601,11 +601,11 @@ pub fn from_str_radix_int<T: Int>(src: &str, radix: uint) -> Option<T> {
|
||||
Some(x) => x,
|
||||
None => return None,
|
||||
};
|
||||
result = match result.checked_mul(&radix) {
|
||||
result = match result.checked_mul(radix) {
|
||||
Some(result) => result,
|
||||
None => return None,
|
||||
};
|
||||
result = match result.checked_add(&x) {
|
||||
result = match result.checked_add(x) {
|
||||
Some(result) => result,
|
||||
None => return None,
|
||||
};
|
||||
@ -616,11 +616,11 @@ pub fn from_str_radix_int<T: Int>(src: &str, radix: uint) -> Option<T> {
|
||||
Some(x) => x,
|
||||
None => return None,
|
||||
};
|
||||
result = match result.checked_mul(&radix) {
|
||||
result = match result.checked_mul(radix) {
|
||||
Some(result) => result,
|
||||
None => return None,
|
||||
};
|
||||
result = match result.checked_sub(&x) {
|
||||
result = match result.checked_sub(x) {
|
||||
Some(result) => result,
|
||||
None => return None,
|
||||
};
|
||||
|
@ -67,7 +67,7 @@
|
||||
#[doc(no_inline)] pub use iter::{Iterator, DoubleEndedIterator};
|
||||
#[doc(no_inline)] pub use iter::{RandomAccessIterator, CloneableIterator};
|
||||
#[doc(no_inline)] pub use iter::{OrdIterator, MutableDoubleEndedIterator};
|
||||
#[doc(no_inline)] pub use num::{Num, NumCast, CheckedAdd, CheckedSub, CheckedMul, CheckedDiv};
|
||||
#[doc(no_inline)] pub use num::{Num, NumCast};
|
||||
#[doc(no_inline)] pub use num::{Signed, Unsigned, Primitive, Int, Float};
|
||||
#[doc(no_inline)] pub use num::{FloatMath, ToPrimitive, FromPrimitive};
|
||||
#[doc(no_inline)] pub use boxed::Box;
|
||||
|
@ -15,8 +15,7 @@
|
||||
use {fmt, i64};
|
||||
use ops::{Add, Sub, Mul, Div, Neg};
|
||||
use option::{Option, Some, None};
|
||||
use num;
|
||||
use num::{CheckedAdd, CheckedMul};
|
||||
use num::Int;
|
||||
use result::{Result, Ok, Err};
|
||||
|
||||
/// The number of nanoseconds in a microsecond.
|
||||
@ -69,7 +68,7 @@ impl Duration {
|
||||
/// Fails when the duration is out of bounds.
|
||||
#[inline]
|
||||
pub fn weeks(weeks: i64) -> Duration {
|
||||
let secs = weeks.checked_mul(&SECS_PER_WEEK).expect("Duration::weeks out of bounds");
|
||||
let secs = weeks.checked_mul(SECS_PER_WEEK).expect("Duration::weeks out of bounds");
|
||||
Duration::seconds(secs)
|
||||
}
|
||||
|
||||
@ -78,7 +77,7 @@ impl Duration {
|
||||
/// Fails when the duration is out of bounds.
|
||||
#[inline]
|
||||
pub fn days(days: i64) -> Duration {
|
||||
let secs = days.checked_mul(&SECS_PER_DAY).expect("Duration::days out of bounds");
|
||||
let secs = days.checked_mul(SECS_PER_DAY).expect("Duration::days out of bounds");
|
||||
Duration::seconds(secs)
|
||||
}
|
||||
|
||||
@ -87,7 +86,7 @@ impl Duration {
|
||||
/// Fails when the duration is out of bounds.
|
||||
#[inline]
|
||||
pub fn hours(hours: i64) -> Duration {
|
||||
let secs = hours.checked_mul(&SECS_PER_HOUR).expect("Duration::hours ouf of bounds");
|
||||
let secs = hours.checked_mul(SECS_PER_HOUR).expect("Duration::hours ouf of bounds");
|
||||
Duration::seconds(secs)
|
||||
}
|
||||
|
||||
@ -96,7 +95,7 @@ impl Duration {
|
||||
/// Fails when the duration is out of bounds.
|
||||
#[inline]
|
||||
pub fn minutes(minutes: i64) -> Duration {
|
||||
let secs = minutes.checked_mul(&SECS_PER_MINUTE).expect("Duration::minutes out of bounds");
|
||||
let secs = minutes.checked_mul(SECS_PER_MINUTE).expect("Duration::minutes out of bounds");
|
||||
Duration::seconds(secs)
|
||||
}
|
||||
|
||||
@ -191,33 +190,64 @@ impl Duration {
|
||||
/// Returns the total number of whole microseconds in the duration,
|
||||
/// or `None` on overflow (exceeding 2^63 microseconds in either direction).
|
||||
pub fn num_microseconds(&self) -> Option<i64> {
|
||||
let secs_part = try_opt!(self.num_seconds().checked_mul(&MICROS_PER_SEC));
|
||||
let secs_part = try_opt!(self.num_seconds().checked_mul(MICROS_PER_SEC));
|
||||
let nanos_part = self.nanos_mod_sec() / NANOS_PER_MICRO;
|
||||
secs_part.checked_add(&(nanos_part as i64))
|
||||
secs_part.checked_add(nanos_part as i64)
|
||||
}
|
||||
|
||||
/// Returns the total number of whole nanoseconds in the duration,
|
||||
/// or `None` on overflow (exceeding 2^63 nanoseconds in either direction).
|
||||
pub fn num_nanoseconds(&self) -> Option<i64> {
|
||||
let secs_part = try_opt!(self.num_seconds().checked_mul(&(NANOS_PER_SEC as i64)));
|
||||
let secs_part = try_opt!(self.num_seconds().checked_mul(NANOS_PER_SEC as i64));
|
||||
let nanos_part = self.nanos_mod_sec();
|
||||
secs_part.checked_add(&(nanos_part as i64))
|
||||
secs_part.checked_add(nanos_part as i64)
|
||||
}
|
||||
}
|
||||
|
||||
impl num::Bounded for Duration {
|
||||
#[inline] fn min_value() -> Duration { MIN }
|
||||
#[inline] fn max_value() -> Duration { MAX }
|
||||
}
|
||||
/// Add two durations, returning `None` if overflow occured.
|
||||
pub fn checked_add(&self, rhs: &Duration) -> Option<Duration> {
|
||||
let mut secs = try_opt!(self.secs.checked_add(rhs.secs));
|
||||
let mut nanos = self.nanos + rhs.nanos;
|
||||
if nanos >= NANOS_PER_SEC {
|
||||
nanos -= NANOS_PER_SEC;
|
||||
secs = try_opt!(secs.checked_add(1));
|
||||
}
|
||||
let d = Duration { secs: secs, nanos: nanos };
|
||||
// Even if d is within the bounds of i64 seconds,
|
||||
// it might still overflow i64 milliseconds.
|
||||
if d < MIN || d > MAX { None } else { Some(d) }
|
||||
}
|
||||
|
||||
impl num::Zero for Duration {
|
||||
/// Subtract two durations, returning `None` if overflow occured.
|
||||
pub fn checked_sub(&self, rhs: &Duration) -> Option<Duration> {
|
||||
let mut secs = try_opt!(self.secs.checked_sub(rhs.secs));
|
||||
let mut nanos = self.nanos - rhs.nanos;
|
||||
if nanos < 0 {
|
||||
nanos += NANOS_PER_SEC;
|
||||
secs = try_opt!(secs.checked_sub(1));
|
||||
}
|
||||
let d = Duration { secs: secs, nanos: nanos };
|
||||
// Even if d is within the bounds of i64 seconds,
|
||||
// it might still overflow i64 milliseconds.
|
||||
if d < MIN || d > MAX { None } else { Some(d) }
|
||||
}
|
||||
|
||||
/// The minimum possible `Duration`: `i64::MIN` milliseconds.
|
||||
#[inline]
|
||||
fn zero() -> Duration {
|
||||
pub fn min_value() -> Duration { MIN }
|
||||
|
||||
/// The maximum possible `Duration`: `i64::MAX` milliseconds.
|
||||
#[inline]
|
||||
pub fn max_value() -> Duration { MAX }
|
||||
|
||||
/// A duration where the stored seconds and nanoseconds are equal to zero.
|
||||
#[inline]
|
||||
pub fn zero() -> Duration {
|
||||
Duration { secs: 0, nanos: 0 }
|
||||
}
|
||||
|
||||
/// Returns `true` if the duration equals `Duration::zero()`.
|
||||
#[inline]
|
||||
fn is_zero(&self) -> bool {
|
||||
pub fn is_zero(&self) -> bool {
|
||||
self.secs == 0 && self.nanos == 0
|
||||
}
|
||||
}
|
||||
@ -245,21 +275,6 @@ impl Add<Duration,Duration> for Duration {
|
||||
}
|
||||
}
|
||||
|
||||
impl num::CheckedAdd for Duration {
|
||||
fn checked_add(&self, rhs: &Duration) -> Option<Duration> {
|
||||
let mut secs = try_opt!(self.secs.checked_add(&rhs.secs));
|
||||
let mut nanos = self.nanos + rhs.nanos;
|
||||
if nanos >= NANOS_PER_SEC {
|
||||
nanos -= NANOS_PER_SEC;
|
||||
secs = try_opt!(secs.checked_add(&1));
|
||||
}
|
||||
let d = Duration { secs: secs, nanos: nanos };
|
||||
// Even if d is within the bounds of i64 seconds,
|
||||
// it might still overflow i64 milliseconds.
|
||||
if d < MIN || d > MAX { None } else { Some(d) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Sub<Duration,Duration> for Duration {
|
||||
fn sub(&self, rhs: &Duration) -> Duration {
|
||||
let mut secs = self.secs - rhs.secs;
|
||||
@ -272,21 +287,6 @@ impl Sub<Duration,Duration> for Duration {
|
||||
}
|
||||
}
|
||||
|
||||
impl num::CheckedSub for Duration {
|
||||
fn checked_sub(&self, rhs: &Duration) -> Option<Duration> {
|
||||
let mut secs = try_opt!(self.secs.checked_sub(&rhs.secs));
|
||||
let mut nanos = self.nanos - rhs.nanos;
|
||||
if nanos < 0 {
|
||||
nanos += NANOS_PER_SEC;
|
||||
secs = try_opt!(secs.checked_sub(&1));
|
||||
}
|
||||
let d = Duration { secs: secs, nanos: nanos };
|
||||
// Even if d is within the bounds of i64 seconds,
|
||||
// it might still overflow i64 milliseconds.
|
||||
if d < MIN || d > MAX { None } else { Some(d) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<i32,Duration> for Duration {
|
||||
fn mul(&self, rhs: &i32) -> Duration {
|
||||
// Multiply nanoseconds as i64, because it cannot overflow that way.
|
||||
@ -379,15 +379,12 @@ fn div_rem_64(this: i64, other: i64) -> (i64, i64) {
|
||||
mod tests {
|
||||
use super::{Duration, MIN, MAX};
|
||||
use {i32, i64};
|
||||
use num::{Zero, CheckedAdd, CheckedSub};
|
||||
use option::{Some, None};
|
||||
use to_string::ToString;
|
||||
|
||||
#[test]
|
||||
fn test_duration() {
|
||||
let d: Duration = Zero::zero();
|
||||
assert_eq!(d, Zero::zero());
|
||||
assert!(Duration::seconds(1) != Zero::zero());
|
||||
assert!(Duration::seconds(1) != Duration::zero());
|
||||
assert_eq!(Duration::seconds(1) + Duration::seconds(2), Duration::seconds(3));
|
||||
assert_eq!(Duration::seconds(86399) + Duration::seconds(4),
|
||||
Duration::days(1) + Duration::seconds(3));
|
||||
@ -403,8 +400,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_duration_num_days() {
|
||||
let d: Duration = Zero::zero();
|
||||
assert_eq!(d.num_days(), 0);
|
||||
assert_eq!(Duration::zero().num_days(), 0);
|
||||
assert_eq!(Duration::days(1).num_days(), 1);
|
||||
assert_eq!(Duration::days(-1).num_days(), -1);
|
||||
assert_eq!(Duration::seconds(86399).num_days(), 0);
|
||||
@ -417,8 +413,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_duration_num_seconds() {
|
||||
let d: Duration = Zero::zero();
|
||||
assert_eq!(d.num_seconds(), 0);
|
||||
assert_eq!(Duration::zero().num_seconds(), 0);
|
||||
assert_eq!(Duration::seconds(1).num_seconds(), 1);
|
||||
assert_eq!(Duration::seconds(-1).num_seconds(), -1);
|
||||
assert_eq!(Duration::milliseconds(999).num_seconds(), 0);
|
||||
@ -429,8 +424,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_duration_num_milliseconds() {
|
||||
let d: Duration = Zero::zero();
|
||||
assert_eq!(d.num_milliseconds(), 0);
|
||||
assert_eq!(Duration::zero().num_milliseconds(), 0);
|
||||
assert_eq!(Duration::milliseconds(1).num_milliseconds(), 1);
|
||||
assert_eq!(Duration::milliseconds(-1).num_milliseconds(), -1);
|
||||
assert_eq!(Duration::microseconds(999).num_milliseconds(), 0);
|
||||
@ -445,8 +439,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_duration_num_microseconds() {
|
||||
let d: Duration = Zero::zero();
|
||||
assert_eq!(d.num_microseconds(), Some(0));
|
||||
assert_eq!(Duration::zero().num_microseconds(), Some(0));
|
||||
assert_eq!(Duration::microseconds(1).num_microseconds(), Some(1));
|
||||
assert_eq!(Duration::microseconds(-1).num_microseconds(), Some(-1));
|
||||
assert_eq!(Duration::nanoseconds(999).num_microseconds(), Some(0));
|
||||
@ -470,8 +463,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_duration_num_nanoseconds() {
|
||||
let d: Duration = Zero::zero();
|
||||
assert_eq!(d.num_nanoseconds(), Some(0));
|
||||
assert_eq!(Duration::zero().num_nanoseconds(), Some(0));
|
||||
assert_eq!(Duration::nanoseconds(1).num_nanoseconds(), Some(1));
|
||||
assert_eq!(Duration::nanoseconds(-1).num_nanoseconds(), Some(-1));
|
||||
assert_eq!(Duration::nanoseconds(i64::MAX).num_nanoseconds(), Some(i64::MAX));
|
||||
@ -504,10 +496,9 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_duration_mul() {
|
||||
let d: Duration = Zero::zero();
|
||||
assert_eq!(d * i32::MAX, d);
|
||||
assert_eq!(d * i32::MIN, d);
|
||||
assert_eq!(Duration::nanoseconds(1) * 0, Zero::zero());
|
||||
assert_eq!(Duration::zero() * i32::MAX, Duration::zero());
|
||||
assert_eq!(Duration::zero() * i32::MIN, Duration::zero());
|
||||
assert_eq!(Duration::nanoseconds(1) * 0, Duration::zero());
|
||||
assert_eq!(Duration::nanoseconds(1) * 1, Duration::nanoseconds(1));
|
||||
assert_eq!(Duration::nanoseconds(1) * 1_000_000_000, Duration::seconds(1));
|
||||
assert_eq!(Duration::nanoseconds(1) * -1_000_000_000, -Duration::seconds(1));
|
||||
@ -522,9 +513,8 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_duration_div() {
|
||||
let d: Duration = Zero::zero();
|
||||
assert_eq!(d / i32::MAX, d);
|
||||
assert_eq!(d / i32::MIN, d);
|
||||
assert_eq!(Duration::zero() / i32::MAX, Duration::zero());
|
||||
assert_eq!(Duration::zero() / i32::MIN, Duration::zero());
|
||||
assert_eq!(Duration::nanoseconds(123_456_789) / 1, Duration::nanoseconds(123_456_789));
|
||||
assert_eq!(Duration::nanoseconds(123_456_789) / -1, -Duration::nanoseconds(123_456_789));
|
||||
assert_eq!(-Duration::nanoseconds(123_456_789) / -1, Duration::nanoseconds(123_456_789));
|
||||
@ -540,8 +530,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_duration_fmt() {
|
||||
let d: Duration = Zero::zero();
|
||||
assert_eq!(d.to_string(), "PT0S".to_string());
|
||||
assert_eq!(Duration::zero().to_string(), "PT0S".to_string());
|
||||
assert_eq!(Duration::days(42).to_string(), "P42D".to_string());
|
||||
assert_eq!(Duration::days(-42).to_string(), "-P42D".to_string());
|
||||
assert_eq!(Duration::seconds(42).to_string(), "PT42S".to_string());
|
||||
|
@ -63,7 +63,7 @@ impl ParseSess {
|
||||
pub fn reserve_node_ids(&self, count: ast::NodeId) -> ast::NodeId {
|
||||
let v = self.node_id.get();
|
||||
|
||||
match v.checked_add(&count) {
|
||||
match v.checked_add(count) {
|
||||
Some(next) => { self.node_id.set(next); }
|
||||
None => panic!("Input too large, ran out of node ids!")
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user