diff --git a/src/libarena/lib.rs b/src/libarena/lib.rs index d08c9b3257a..029d9d03835 100644 --- a/src/libarena/lib.rs +++ b/src/libarena/lib.rs @@ -46,6 +46,7 @@ use std::intrinsics; use std::marker; use std::mem; +#[cfg(stage0)] use std::num::{Int, UnsignedInt}; use std::ptr; use std::rc::Rc; diff --git a/src/libcollections/btree/node.rs b/src/libcollections/btree/node.rs index 1a8a4cb7e21..006d6bb040e 100644 --- a/src/libcollections/btree/node.rs +++ b/src/libcollections/btree/node.rs @@ -23,7 +23,7 @@ use core::marker::PhantomData; use core::ops::{Deref, DerefMut, Index, IndexMut}; use core::ptr::Unique; -use core::{slice, mem, ptr, cmp, num, raw}; +use core::{slice, mem, ptr, cmp, raw}; use alloc::heap::{self, EMPTY}; use borrow::Borrow; @@ -105,7 +105,10 @@ struct MutNodeSlice<'a, K: 'a, V: 'a> { /// Fails if `target_alignment` is not a power of two. #[inline] fn round_up_to_next(unrounded: usize, target_alignment: usize) -> usize { - assert!(num::UnsignedInt::is_power_of_two(target_alignment)); + #[cfg(stage0)] + use core::num::UnsignedInt; + + assert!(target_alignment.is_power_of_two()); (unrounded + target_alignment - 1) & !(target_alignment - 1) } diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index 937df5494df..82d68caeb36 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -59,6 +59,7 @@ use core::iter::{repeat, FromIterator, IntoIterator}; use core::marker::PhantomData; use core::mem; +#[cfg(stage0)] use core::num::{Int, UnsignedInt}; use core::ops::{Index, IndexMut, Deref, Add}; use core::ops; diff --git a/src/libcollections/vec_deque.rs b/src/libcollections/vec_deque.rs index 43c9edcaa2b..65e44703df1 100644 --- a/src/libcollections/vec_deque.rs +++ b/src/libcollections/vec_deque.rs @@ -25,6 +25,7 @@ use core::fmt; use core::iter::{self, repeat, FromIterator, IntoIterator, RandomAccessIterator}; use core::mem; +#[cfg(stage0)] use core::num::{Int, UnsignedInt}; use core::num::wrapping::WrappingOps; use core::ops::{Index, IndexMut}; diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 6170092c8d1..4381b1fb3c9 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -708,6 +708,7 @@ fn is_negative(self) -> bool { self < 0 } signed_int_impl! { i64 } signed_int_impl! { int } +#[cfg(stage0)] /// A built-in unsigned integer. #[stable(feature = "rust1", since = "1.0.0")] pub trait UnsignedInt: Int + WrappingOps { @@ -742,21 +743,1010 @@ fn checked_next_power_of_two(self) -> Option { } } +#[cfg(stage0)] #[stable(feature = "rust1", since = "1.0.0")] impl UnsignedInt for uint {} +#[cfg(stage0)] #[stable(feature = "rust1", since = "1.0.0")] impl UnsignedInt for u8 {} +#[cfg(stage0)] #[stable(feature = "rust1", since = "1.0.0")] impl UnsignedInt for u16 {} +#[cfg(stage0)] #[stable(feature = "rust1", since = "1.0.0")] impl UnsignedInt for u32 {} +#[cfg(stage0)] #[stable(feature = "rust1", since = "1.0.0")] impl UnsignedInt for u64 {} +// NB(japaric) I added this module to avoid adding several `cfg(not(stage0))`, and avoid name +// clashes between macros. We should move all the items inside this module into the outer scope +// once the `Int` trait is removed +#[cfg(not(stage0))] +mod inherent { + use intrinsics; + use mem::size_of; + use option::Option::{self, Some, None}; + + use super::wrapping::{OverflowingOps, WrappingOps}; + + // `Int` + `SignedInt` implemented for signed integers + macro_rules! int_impl { + ($T:ty = $ActualT:ty, $UnsignedT:ty, $BITS:expr, + $add_with_overflow:path, + $sub_with_overflow:path, + $mul_with_overflow:path) => { + /// Returns the `0` value of this integer type. + // FIXME (#5527): Should be an associated constant + #[unstable(feature = "core", + reason = "unsure about its place in the world")] + #[inline] + pub fn zero() -> $T { 0 } + + /// Returns the `1` value of this integer type. + // FIXME (#5527): Should be an associated constant + #[unstable(feature = "core", + reason = "unsure about its place in the world")] + #[inline] + pub fn one() -> $T { 1 } + + /// Returns the smallest value that can be represented by this integer type. + // FIXME (#5527): Should be and associated constant + #[unstable(feature = "core", + reason = "unsure about its place in the world")] + #[inline] + pub fn min_value() -> $T { (-1 as $T) << ($BITS - 1) } + + /// Returns the largest value that can be represented by this integer type. + // FIXME (#5527): Should be and associated constant + #[unstable(feature = "core", + reason = "unsure about its place in the world")] + #[inline] + pub fn max_value() -> $T { let min: $T = <$T>::min_value(); !min } + + /// Returns the number of ones in the binary representation of `self`. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0b01001100u8; + /// + /// assert_eq!(n.count_ones(), 3); + /// ``` + #[unstable(feature = "core", + reason = "pending integer conventions")] + #[inline] + pub fn count_ones(self) -> u32 { (self as $UnsignedT).count_ones() } + + /// Returns the number of zeros in the binary representation of `self`. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0b01001100u8; + /// + /// assert_eq!(n.count_zeros(), 5); + /// ``` + #[unstable(feature = "core", + reason = "pending integer conventions")] + #[inline] + pub fn count_zeros(self) -> u32 { + (!self).count_ones() + } + + /// Returns the number of leading zeros in the binary representation + /// of `self`. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0b0101000u16; + /// + /// assert_eq!(n.leading_zeros(), 10); + /// ``` + #[unstable(feature = "core", + reason = "pending integer conventions")] + #[inline] + pub fn leading_zeros(self) -> u32 { (self as $UnsignedT).leading_zeros() } + + /// Returns the number of trailing zeros in the binary representation + /// of `self`. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0b0101000u16; + /// + /// assert_eq!(n.trailing_zeros(), 3); + /// ``` + #[unstable(feature = "core", + reason = "pending integer conventions")] + #[inline] + pub fn trailing_zeros(self) -> u32 { (self as $UnsignedT).trailing_zeros() } + + /// Shifts the bits to the left by a specified amount amount, `n`, wrapping + /// the truncated bits to the end of the resulting integer. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0x0123456789ABCDEFu64; + /// let m = 0x3456789ABCDEF012u64; + /// + /// assert_eq!(n.rotate_left(12), m); + /// ``` + #[unstable(feature = "core", + reason = "pending integer conventions")] + #[inline] + pub fn rotate_left(self, n: u32) -> $T { (self as $UnsignedT).rotate_left(n) as $T } + + /// Shifts the bits to the right by a specified amount amount, `n`, wrapping + /// the truncated bits to the beginning of the resulting integer. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0x0123456789ABCDEFu64; + /// let m = 0xDEF0123456789ABCu64; + /// + /// assert_eq!(n.rotate_right(12), m); + /// ``` + #[unstable(feature = "core", + reason = "pending integer conventions")] + #[inline] + pub fn rotate_right(self, n: u32) -> $T { (self as $UnsignedT).rotate_right(n) as $T } + + /// Reverses the byte order of the integer. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0x0123456789ABCDEFu64; + /// let m = 0xEFCDAB8967452301u64; + /// + /// assert_eq!(n.swap_bytes(), m); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn swap_bytes(self) -> $T { (self as $UnsignedT).swap_bytes() as $T } + + /// Convert an integer from big endian to the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0x0123456789ABCDEFu64; + /// + /// if cfg!(target_endian = "big") { + /// assert_eq!(Int::from_be(n), n) + /// } else { + /// assert_eq!(Int::from_be(n), n.swap_bytes()) + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn from_be(x: $T) -> $T { + if cfg!(target_endian = "big") { x } else { x.swap_bytes() } + } + + /// Convert an integer from little endian to the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0x0123456789ABCDEFu64; + /// + /// if cfg!(target_endian = "little") { + /// assert_eq!(Int::from_le(n), n) + /// } else { + /// assert_eq!(Int::from_le(n), n.swap_bytes()) + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn from_le(x: $T) -> $T { + if cfg!(target_endian = "little") { x } else { x.swap_bytes() } + } + + /// Convert `self` to big endian from the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0x0123456789ABCDEFu64; + /// + /// if cfg!(target_endian = "big") { + /// assert_eq!(n.to_be(), n) + /// } else { + /// assert_eq!(n.to_be(), n.swap_bytes()) + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn to_be(self) -> $T { // or not to be? + if cfg!(target_endian = "big") { self } else { self.swap_bytes() } + } + + /// Convert `self` to little endian from the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0x0123456789ABCDEFu64; + /// + /// if cfg!(target_endian = "little") { + /// assert_eq!(n.to_le(), n) + /// } else { + /// assert_eq!(n.to_le(), n.swap_bytes()) + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn to_le(self) -> $T { + if cfg!(target_endian = "little") { self } else { self.swap_bytes() } + } + + /// Checked integer addition. Computes `self + other`, returning `None` if + /// overflow occurred. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// assert_eq!(5u16.checked_add(65530), Some(65535)); + /// assert_eq!(6u16.checked_add(65530), None); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn checked_add(self, other: $T) -> Option<$T> { + checked_op!($T, $ActualT, $add_with_overflow, self, other) + } + + /// Checked integer subtraction. Computes `self - other`, returning `None` + /// if underflow occurred. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// assert_eq!((-127i8).checked_sub(1), Some(-128)); + /// assert_eq!((-128i8).checked_sub(1), None); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn checked_sub(self, other: $T) -> Option<$T> { + checked_op!($T, $ActualT, $sub_with_overflow, self, other) + } + + /// Checked integer multiplication. Computes `self * other`, returning + /// `None` if underflow or overflow occurred. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// assert_eq!(5u8.checked_mul(51), Some(255)); + /// assert_eq!(5u8.checked_mul(52), None); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn checked_mul(self, other: $T) -> Option<$T> { + checked_op!($T, $ActualT, $mul_with_overflow, self, other) + } + + /// Checked integer division. Computes `self / other`, returning `None` if + /// `other == 0` or the operation results in underflow or overflow. + /// + /// # Examples + /// + /// ```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); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn checked_div(self, v: $T) -> Option<$T> { + match v { + 0 => None, + -1 if self == <$T>::min_value() + => None, + v => Some(self / v), + } + } + + /// Saturating integer addition. Computes `self + other`, saturating at + /// the numeric bounds instead of overflowing. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn saturating_add(self, other: $T) -> $T { + match self.checked_add(other) { + Some(x) => x, + None if other >= <$T>::zero() => <$T>::max_value(), + None => <$T>::min_value(), + } + } + + /// Saturating integer subtraction. Computes `self - other`, saturating at + /// the numeric bounds instead of overflowing. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn saturating_sub(self, other: $T) -> $T { + match self.checked_sub(other) { + Some(x) => x, + None if other >= <$T>::zero() => <$T>::min_value(), + None => <$T>::max_value(), + } + } + + /// Raises self to the power of `exp`, using exponentiation by squaring. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// assert_eq!(2.pow(4), 16); + /// ``` + #[unstable(feature = "core", + reason = "pending integer conventions")] + #[inline] + pub fn pow(self, mut exp: u32) -> $T { + let mut base = self; + let mut acc = <$T>::one(); + + let mut prev_base = self; + let mut base_oflo = false; + while exp > 0 { + if (exp & 1) == 1 { + if base_oflo { + // ensure overflow occurs in the same manner it + // would have otherwise (i.e. signal any exception + // it would have otherwise). + acc = acc * (prev_base * prev_base); + } else { + acc = acc * base; + } + } + prev_base = base; + let (new_base, new_base_oflo) = base.overflowing_mul(base); + base = new_base; + base_oflo = new_base_oflo; + exp /= 2; + } + acc + } + + /// Computes the absolute value of `self`. `Int::min_value()` will be + /// returned if the number is `Int::min_value()`. + #[unstable(feature = "core", reason = "overflow in debug builds?")] + #[inline] + pub fn abs(self) -> $T { + if self.is_negative() { -self } else { self } + } + + /// Returns a number representing sign of `self`. + /// + /// - `0` if the number is zero + /// - `1` if the number is positive + /// - `-1` if the number is negative + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn signum(self) -> $T { + match self { + n if n > 0 => 1, + 0 => 0, + _ => -1, + } + } + + /// Returns `true` if `self` is positive and `false` if the number + /// is zero or negative. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn is_positive(self) -> bool { self > 0 } + + /// Returns `true` if `self` is negative and `false` if the number + /// is zero or positive. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn is_negative(self) -> bool { self < 0 } + } + } + + #[lang = "i8"] + impl i8 { + int_impl! { i8 = i8, u8, 8, + intrinsics::i8_add_with_overflow, + intrinsics::i8_sub_with_overflow, + intrinsics::i8_mul_with_overflow } + } + + #[lang = "i16"] + impl i16 { + int_impl! { i16 = i16, u16, 16, + intrinsics::i16_add_with_overflow, + intrinsics::i16_sub_with_overflow, + intrinsics::i16_mul_with_overflow } + } + + #[lang = "i32"] + impl i32 { + int_impl! { i32 = i32, u32, 32, + intrinsics::i32_add_with_overflow, + intrinsics::i32_sub_with_overflow, + intrinsics::i32_mul_with_overflow } + } + + #[lang = "i64"] + impl i64 { + int_impl! { i64 = i64, u64, 64, + intrinsics::i64_add_with_overflow, + intrinsics::i64_sub_with_overflow, + intrinsics::i64_mul_with_overflow } + } + + #[cfg(target_pointer_width = "32")] + #[lang = "isize"] + impl isize { + int_impl! { int = i32, u32, 32, + intrinsics::i32_add_with_overflow, + intrinsics::i32_sub_with_overflow, + intrinsics::i32_mul_with_overflow } + } + + #[cfg(target_pointer_width = "64")] + #[lang = "isize"] + impl isize { + int_impl! { int = i64, u64, 64, + intrinsics::i64_add_with_overflow, + intrinsics::i64_sub_with_overflow, + intrinsics::i64_mul_with_overflow } + } + + // `Int` + `UnsignedInt` implemented for signed integers + macro_rules! uint_impl { + ($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) => { + /// Returns the `0` value of this integer type. + // FIXME (#5527): Should be an associated constant + #[unstable(feature = "core", + reason = "unsure about its place in the world")] + #[inline] + pub fn zero() -> $T { 0 } + + /// Returns the `1` value of this integer type. + // FIXME (#5527): Should be an associated constant + #[unstable(feature = "core", + reason = "unsure about its place in the world")] + #[inline] + pub fn one() -> $T { 1 } + + /// Returns the smallest value that can be represented by this integer type. + // FIXME (#5527): Should be and associated constant + #[unstable(feature = "core", + reason = "unsure about its place in the world")] + #[inline] + pub fn min_value() -> $T { 0 } + + /// Returns the largest value that can be represented by this integer type. + // FIXME (#5527): Should be and associated constant + #[unstable(feature = "core", + reason = "unsure about its place in the world")] + #[inline] + pub fn max_value() -> $T { -1 } + + /// Returns the number of ones in the binary representation of `self`. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0b01001100u8; + /// + /// assert_eq!(n.count_ones(), 3); + /// ``` + #[unstable(feature = "core", + reason = "pending integer conventions")] + #[inline] + pub fn count_ones(self) -> u32 { unsafe { $ctpop(self as $ActualT) as u32 } } + + /// Returns the number of zeros in the binary representation of `self`. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0b01001100u8; + /// + /// assert_eq!(n.count_zeros(), 5); + /// ``` + #[unstable(feature = "core", + reason = "pending integer conventions")] + #[inline] + pub fn count_zeros(self) -> u32 { + (!self).count_ones() + } + + /// Returns the number of leading zeros in the binary representation + /// of `self`. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0b0101000u16; + /// + /// assert_eq!(n.leading_zeros(), 10); + /// ``` + #[unstable(feature = "core", + reason = "pending integer conventions")] + #[inline] + pub fn leading_zeros(self) -> u32 { unsafe { $ctlz(self as $ActualT) as u32 } } + + /// Returns the number of trailing zeros in the binary representation + /// of `self`. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0b0101000u16; + /// + /// assert_eq!(n.trailing_zeros(), 3); + /// ``` + #[unstable(feature = "core", + reason = "pending integer conventions")] + #[inline] + pub fn trailing_zeros(self) -> u32 { unsafe { $cttz(self as $ActualT) as u32 } } + + /// Shifts the bits to the left by a specified amount amount, `n`, wrapping + /// the truncated bits to the end of the resulting integer. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0x0123456789ABCDEFu64; + /// let m = 0x3456789ABCDEF012u64; + /// + /// assert_eq!(n.rotate_left(12), m); + /// ``` + #[unstable(feature = "core", + reason = "pending integer conventions")] + #[inline] + pub fn rotate_left(self, n: u32) -> $T { + // Protect against undefined behaviour for over-long bit shifts + let n = n % $BITS; + (self << n) | (self >> (($BITS - n) % $BITS)) + } + + /// Shifts the bits to the right by a specified amount amount, `n`, wrapping + /// the truncated bits to the beginning of the resulting integer. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0x0123456789ABCDEFu64; + /// let m = 0xDEF0123456789ABCu64; + /// + /// assert_eq!(n.rotate_right(12), m); + /// ``` + #[unstable(feature = "core", + reason = "pending integer conventions")] + #[inline] + pub fn rotate_right(self, n: u32) -> $T { + // Protect against undefined behaviour for over-long bit shifts + let n = n % $BITS; + (self >> n) | (self << (($BITS - n) % $BITS)) + } + + /// Reverses the byte order of the integer. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0x0123456789ABCDEFu64; + /// let m = 0xEFCDAB8967452301u64; + /// + /// assert_eq!(n.swap_bytes(), m); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn swap_bytes(self) -> $T { unsafe { $bswap(self as $ActualT) as $T } } + + /// Convert an integer from big endian to the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0x0123456789ABCDEFu64; + /// + /// if cfg!(target_endian = "big") { + /// assert_eq!(Int::from_be(n), n) + /// } else { + /// assert_eq!(Int::from_be(n), n.swap_bytes()) + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn from_be(x: $T) -> $T { + if cfg!(target_endian = "big") { x } else { x.swap_bytes() } + } + + /// Convert an integer from little endian to the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0x0123456789ABCDEFu64; + /// + /// if cfg!(target_endian = "little") { + /// assert_eq!(Int::from_le(n), n) + /// } else { + /// assert_eq!(Int::from_le(n), n.swap_bytes()) + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn from_le(x: $T) -> $T { + if cfg!(target_endian = "little") { x } else { x.swap_bytes() } + } + + /// Convert `self` to big endian from the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0x0123456789ABCDEFu64; + /// + /// if cfg!(target_endian = "big") { + /// assert_eq!(n.to_be(), n) + /// } else { + /// assert_eq!(n.to_be(), n.swap_bytes()) + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn to_be(self) -> $T { // or not to be? + if cfg!(target_endian = "big") { self } else { self.swap_bytes() } + } + + /// Convert `self` to little endian from the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0x0123456789ABCDEFu64; + /// + /// if cfg!(target_endian = "little") { + /// assert_eq!(n.to_le(), n) + /// } else { + /// assert_eq!(n.to_le(), n.swap_bytes()) + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn to_le(self) -> $T { + if cfg!(target_endian = "little") { self } else { self.swap_bytes() } + } + + /// Checked integer addition. Computes `self + other`, returning `None` if + /// overflow occurred. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// assert_eq!(5u16.checked_add(65530), Some(65535)); + /// assert_eq!(6u16.checked_add(65530), None); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn checked_add(self, other: $T) -> Option<$T> { + checked_op!($T, $ActualT, $add_with_overflow, self, other) + } + + /// Checked integer subtraction. Computes `self - other`, returning `None` + /// if underflow occurred. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// assert_eq!((-127i8).checked_sub(1), Some(-128)); + /// assert_eq!((-128i8).checked_sub(1), None); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn checked_sub(self, other: $T) -> Option<$T> { + checked_op!($T, $ActualT, $sub_with_overflow, self, other) + } + + /// Checked integer multiplication. Computes `self * other`, returning + /// `None` if underflow or overflow occurred. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// assert_eq!(5u8.checked_mul(51), Some(255)); + /// assert_eq!(5u8.checked_mul(52), None); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn checked_mul(self, other: $T) -> Option<$T> { + checked_op!($T, $ActualT, $mul_with_overflow, self, other) + } + + /// Checked integer division. Computes `self / other`, returning `None` if + /// `other == 0` or the operation results in underflow or overflow. + /// + /// # Examples + /// + /// ```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); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn checked_div(self, v: $T) -> Option<$T> { + match v { + 0 => None, + v => Some(self / v), + } + } + + /// Saturating integer addition. Computes `self + other`, saturating at + /// the numeric bounds instead of overflowing. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn saturating_add(self, other: $T) -> $T { + match self.checked_add(other) { + Some(x) => x, + None if other >= <$T>::zero() => <$T>::max_value(), + None => <$T>::min_value(), + } + } + + /// Saturating integer subtraction. Computes `self - other`, saturating at + /// the numeric bounds instead of overflowing. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn saturating_sub(self, other: $T) -> $T { + match self.checked_sub(other) { + Some(x) => x, + None if other >= <$T>::zero() => <$T>::min_value(), + None => <$T>::max_value(), + } + } + + /// Raises self to the power of `exp`, using exponentiation by squaring. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// assert_eq!(2.pow(4), 16); + /// ``` + #[unstable(feature = "core", + reason = "pending integer conventions")] + #[inline] + pub fn pow(self, mut exp: u32) -> $T { + let mut base = self; + let mut acc = <$T>::one(); + + let mut prev_base = self; + let mut base_oflo = false; + while exp > 0 { + if (exp & 1) == 1 { + if base_oflo { + // ensure overflow occurs in the same manner it + // would have otherwise (i.e. signal any exception + // it would have otherwise). + acc = acc * (prev_base * prev_base); + } else { + acc = acc * base; + } + } + prev_base = base; + let (new_base, new_base_oflo) = base.overflowing_mul(base); + base = new_base; + base_oflo = new_base_oflo; + exp /= 2; + } + acc + } + + /// Returns `true` iff `self == 2^k` for some `k`. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn is_power_of_two(self) -> bool { + (self.wrapping_sub(<$T>::one())) & self == <$T>::zero() && !(self == <$T>::zero()) + } + + /// Returns the smallest power of two greater than or equal to `self`. + /// Unspecified behavior on overflow. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn next_power_of_two(self) -> $T { + let bits = size_of::<$T>() * 8; + let one: $T = <$T>::one(); + one << ((bits - self.wrapping_sub(one).leading_zeros() as usize) % bits) + } + + /// Returns the smallest power of two greater than or equal to `n`. If the + /// next power of two is greater than the type's maximum value, `None` is + /// returned, otherwise the power of two is wrapped in `Some`. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn checked_next_power_of_two(self) -> Option<$T> { + let npot = self.next_power_of_two(); + if npot >= self { + Some(npot) + } else { + None + } + } + } + } + + /// Swapping a single byte is a no-op. This is marked as `unsafe` for + /// consistency with the other `bswap` intrinsics. + unsafe fn bswap8(x: u8) -> u8 { x } + + #[lang = "u8"] + impl u8 { + uint_impl! { u8 = u8, 8, + intrinsics::ctpop8, + intrinsics::ctlz8, + intrinsics::cttz8, + bswap8, + intrinsics::u8_add_with_overflow, + intrinsics::u8_sub_with_overflow, + intrinsics::u8_mul_with_overflow } + } + + #[lang = "u16"] + impl u16 { + uint_impl! { u16 = u16, 16, + intrinsics::ctpop16, + intrinsics::ctlz16, + intrinsics::cttz16, + intrinsics::bswap16, + intrinsics::u16_add_with_overflow, + intrinsics::u16_sub_with_overflow, + intrinsics::u16_mul_with_overflow } + } + + #[lang = "u32"] + impl u32 { + uint_impl! { u32 = u32, 32, + intrinsics::ctpop32, + intrinsics::ctlz32, + intrinsics::cttz32, + intrinsics::bswap32, + intrinsics::u32_add_with_overflow, + intrinsics::u32_sub_with_overflow, + intrinsics::u32_mul_with_overflow } + } + + + #[lang = "u64"] + impl u64 { + uint_impl! { u64 = u64, 64, + intrinsics::ctpop64, + intrinsics::ctlz64, + intrinsics::cttz64, + intrinsics::bswap64, + intrinsics::u64_add_with_overflow, + intrinsics::u64_sub_with_overflow, + intrinsics::u64_mul_with_overflow } + } + + #[cfg(target_pointer_width = "32")] + #[lang = "usize"] + impl usize { + uint_impl! { uint = u32, 32, + intrinsics::ctpop32, + intrinsics::ctlz32, + intrinsics::cttz32, + intrinsics::bswap32, + intrinsics::u32_add_with_overflow, + intrinsics::u32_sub_with_overflow, + intrinsics::u32_mul_with_overflow } + } + + #[cfg(target_pointer_width = "64")] + #[lang = "usize"] + impl usize { + uint_impl! { uint = u64, 64, + intrinsics::ctpop64, + intrinsics::ctlz64, + intrinsics::cttz64, + intrinsics::bswap64, + intrinsics::u64_add_with_overflow, + intrinsics::u64_sub_with_overflow, + intrinsics::u64_mul_with_overflow } + } +} + /// A generic trait for converting a value to a number. #[unstable(feature = "core", reason = "trait is likely to be removed")] pub trait ToPrimitive { diff --git a/src/librand/distributions/mod.rs b/src/librand/distributions/mod.rs index 79b176a4ffd..47bc2f5a113 100644 --- a/src/librand/distributions/mod.rs +++ b/src/librand/distributions/mod.rs @@ -123,7 +123,7 @@ pub fn new(items: &'a mut [Weighted]) -> WeightedChoice<'a, T> { // strictly speaking, this is subsumed by the total weight == 0 case assert!(!items.is_empty(), "WeightedChoice::new called with no items"); - let mut running_total = 0; + let mut running_total = 0_usize; // we convert the list from individual weights to cumulative // weights so we can binary search. This *could* drop elements diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index 0892365d9d5..6f8151c2b9f 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -23,6 +23,7 @@ use iter::{self, Iterator, ExactSizeIterator, IntoIterator, IteratorExt, FromIterator, Extend, Map}; use marker::Sized; use mem::{self, replace}; +#[cfg(stage0)] use num::{Int, UnsignedInt}; use ops::{Deref, FnMut, Index, IndexMut}; use option::Option::{self, Some, None}; diff --git a/src/libstd/collections/hash/table.rs b/src/libstd/collections/hash/table.rs index 7812363d55e..cba46859f34 100644 --- a/src/libstd/collections/hash/table.rs +++ b/src/libstd/collections/hash/table.rs @@ -19,6 +19,7 @@ use marker::{Copy, Send, Sync, Sized, self}; use mem::{min_align_of, size_of}; use mem; +#[cfg(stage0)] use num::{Int, UnsignedInt}; use num::wrapping::{OverflowingOps, WrappingOps}; use ops::{Deref, DerefMut, Drop}; diff --git a/src/libstd/num/mod.rs b/src/libstd/num/mod.rs index 35d973d2d4e..599f3f02a8b 100644 --- a/src/libstd/num/mod.rs +++ b/src/libstd/num/mod.rs @@ -23,7 +23,10 @@ use clone::Clone; use cmp::{PartialOrd, PartialEq}; +#[cfg(stage0)] pub use core::num::{Int, SignedInt, UnsignedInt}; +#[cfg(not(stage0))] +pub use core::num::{Int, SignedInt}; pub use core::num::{cast, FromPrimitive, NumCast, ToPrimitive}; pub use core::num::{from_int, from_i8, from_i16, from_i32, from_i64}; pub use core::num::{from_uint, from_u8, from_u16, from_u32, from_u64};