diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index a062fbda5bad0..97fcd8ebb50d7 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -188,8 +188,6 @@ impl fmt::UpperHex for Wrapping { } } -mod wrapping; - // All these modules are technically private and only exposed for coretests: pub mod flt2dec; pub mod dec2flt; @@ -203,6 +201,8 @@ macro_rules! doc_comment { }; } +mod wrapping; + // `Int` + `SignedInt` implemented for signed integers macro_rules! int_impl { ($SelfT:ty, $ActualT:ident, $UnsignedT:ty, $BITS:expr, $Min:expr, $Max:expr, $Feature:expr, @@ -3423,6 +3423,30 @@ $EndFeature, " } } + doc_comment! { + concat!("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, +the return value is wrapped to `0`. + +# Examples + +Basic usage: + +``` +#![feature(wrapping_next_power_of_two)] +", $Feature, " +assert_eq!(2", stringify!($SelfT), ".wrapping_next_power_of_two(), 2); +assert_eq!(3", stringify!($SelfT), ".wrapping_next_power_of_two(), 4); +assert_eq!(", stringify!($SelfT), "::max_value().wrapping_next_power_of_two(), 0);", +$EndFeature, " +```"), + #[unstable(feature = "wrapping_next_power_of_two", issue = "32463", + reason = "needs decision on wrapping behaviour")] + pub fn wrapping_next_power_of_two(self) -> Self { + self.one_less_than_next_power_of_two().wrapping_add(1) + } + } + /// Return the memory representation of this integer as a byte array. /// /// The target platform’s native endianness is used. diff --git a/src/libcore/num/wrapping.rs b/src/libcore/num/wrapping.rs index 826883fdc3f01..d7f87d37f5b33 100644 --- a/src/libcore/num/wrapping.rs +++ b/src/libcore/num/wrapping.rs @@ -112,17 +112,19 @@ macro_rules! sh_impl_all { //sh_impl_unsigned! { $t, u16 } //sh_impl_unsigned! { $t, u32 } //sh_impl_unsigned! { $t, u64 } + //sh_impl_unsigned! { $t, u128 } sh_impl_unsigned! { $t, usize } //sh_impl_signed! { $t, i8 } //sh_impl_signed! { $t, i16 } //sh_impl_signed! { $t, i32 } //sh_impl_signed! { $t, i64 } + //sh_impl_signed! { $t, i128 } //sh_impl_signed! { $t, isize } )*) } -sh_impl_all! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize } +sh_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize } // FIXME(30524): impl Op for Wrapping, impl OpAssign for Wrapping macro_rules! wrapping_impl { @@ -326,88 +328,111 @@ wrapping_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } macro_rules! wrapping_int_impl { ($($t:ty)*) => ($( impl Wrapping<$t> { - /// Returns the number of ones in the binary representation of - /// `self`. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// #![feature(wrapping_int_impl)] - /// use std::num::Wrapping; - /// - /// let n: Wrapping = Wrapping(-0b1000_0000); - /// - /// assert_eq!(n.count_ones(), 1); - /// ``` - #[inline] - #[unstable(feature = "wrapping_int_impl", issue = "32463")] - pub fn count_ones(self) -> u32 { - self.0.count_ones() + doc_comment! { + concat!("Returns the smallest value that can be represented by this integer type. + +# Examples + +Basic usage: + +``` +#![feature(wrapping_int_impl)] +use std::num::Wrapping; + +assert_eq!(>::min_value(), ", +"Wrapping(", stringify!($t), "::min_value())); +```"), + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + #[inline] + pub const fn min_value() -> Self { + Wrapping(<$t>::min_value()) + } } - /// Returns the number of zeros in the binary representation of - /// `self`. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// #![feature(wrapping_int_impl)] - /// use std::num::Wrapping; - /// - /// let n: Wrapping = Wrapping(-0b1000_0000); - /// - /// assert_eq!(n.count_zeros(), 7); - /// ``` - #[inline] - #[unstable(feature = "wrapping_int_impl", issue = "32463")] - pub fn count_zeros(self) -> u32 { - self.0.count_zeros() + doc_comment! { + concat!("Returns the largest value that can be represented by this integer type. + +# Examples + +Basic usage: + +``` +#![feature(wrapping_int_impl)] +use std::num::Wrapping; + +assert_eq!(>::max_value(), ", +"Wrapping(", stringify!($t), "::max_value())); +```"), + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + #[inline] + pub const fn max_value() -> Self { + Wrapping(<$t>::max_value()) + } } - /// Returns the number of leading zeros in the binary representation - /// of `self`. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// #![feature(wrapping_int_impl)] - /// use std::num::Wrapping; - /// - /// let n: Wrapping = Wrapping(-1); - /// - /// assert_eq!(n.leading_zeros(), 0); - /// ``` - #[inline] - #[unstable(feature = "wrapping_int_impl", issue = "32463")] - pub fn leading_zeros(self) -> u32 { - self.0.leading_zeros() + doc_comment! { + concat!("Returns the number of ones in the binary representation of `self`. + +# Examples + +Basic usage: + +``` +#![feature(wrapping_int_impl)] +use std::num::Wrapping; + +let n = Wrapping(0b01001100", stringify!($t), "); + +assert_eq!(n.count_ones(), 3); +```"), + #[inline] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub fn count_ones(self) -> u32 { + self.0.count_ones() + } } - /// Returns the number of trailing zeros in the binary representation - /// of `self`. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// #![feature(wrapping_int_impl)] - /// use std::num::Wrapping; - /// - /// let n: Wrapping = Wrapping(-4); - /// - /// assert_eq!(n.trailing_zeros(), 2); - /// ``` - #[inline] - #[unstable(feature = "wrapping_int_impl", issue = "32463")] - pub fn trailing_zeros(self) -> u32 { - self.0.trailing_zeros() + doc_comment! { + concat!("Returns the number of zeros in the binary representation of `self`. + +# Examples + +Basic usage: + +``` +#![feature(wrapping_int_impl)] +use std::num::Wrapping; + +assert_eq!(Wrapping(!0", stringify!($t), ").count_zeros(), 0); +```"), + #[inline] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub fn count_zeros(self) -> u32 { + self.0.count_zeros() + } + } + + doc_comment! { + concat!("Returns the number of trailing zeros in the binary representation +of `self`. + +# Examples + +Basic usage: + +``` +#![feature(wrapping_int_impl)] +use std::num::Wrapping; + +let n = Wrapping(0b0101000", stringify!($t), "); + +assert_eq!(n.trailing_zeros(), 3); +```"), + #[inline] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub fn trailing_zeros(self) -> u32 { + self.0.trailing_zeros() + } } /// Shifts the bits to the left by a specified amount, `n`, @@ -484,145 +509,178 @@ macro_rules! wrapping_int_impl { Wrapping(self.0.swap_bytes()) } - /// Converts 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. + /// Reverses the bit pattern of the integer. /// /// # Examples /// + /// Please note that this example is shared between integer types. + /// Which explains why `i16` is used here. + /// /// Basic usage: /// /// ``` - /// #![feature(wrapping_int_impl)] + /// #![feature(reverse_bits)] /// use std::num::Wrapping; /// - /// let n: Wrapping = Wrapping(0x0123456789ABCDEF); + /// let n = Wrapping(0b0000000_01010101i16); + /// assert_eq!(n, Wrapping(85)); + /// + /// let m = n.reverse_bits(); /// - /// if cfg!(target_endian = "big") { - /// assert_eq!(Wrapping::::from_be(n), n); - /// } else { - /// assert_eq!(Wrapping::::from_be(n), n.swap_bytes()); - /// } + /// assert_eq!(m.0 as u16, 0b10101010_00000000); + /// assert_eq!(m, Wrapping(-22016)); /// ``` + #[unstable(feature = "reverse_bits", issue = "48763")] + #[cfg(not(stage0))] #[inline] - #[unstable(feature = "wrapping_int_impl", issue = "32463")] - pub fn from_be(x: Self) -> Self { - Wrapping(<$t>::from_be(x.0)) + pub fn reverse_bits(self) -> Self { + Wrapping(self.0.reverse_bits()) } - /// Converts 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 - /// - /// Basic usage: - /// - /// ``` - /// #![feature(wrapping_int_impl)] - /// use std::num::Wrapping; - /// - /// let n: Wrapping = Wrapping(0x0123456789ABCDEF); - /// - /// if cfg!(target_endian = "little") { - /// assert_eq!(Wrapping::::from_le(n), n); - /// } else { - /// assert_eq!(Wrapping::::from_le(n), n.swap_bytes()); - /// } - /// ``` - #[inline] - #[unstable(feature = "wrapping_int_impl", issue = "32463")] - pub fn from_le(x: Self) -> Self { - Wrapping(<$t>::from_le(x.0)) + doc_comment! { + concat!("Converts 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 + +Basic usage: + +``` +#![feature(wrapping_int_impl)] +use std::num::Wrapping; + +let n = Wrapping(0x1A", stringify!($t), "); + +if cfg!(target_endian = \"big\") { + assert_eq!(>::from_be(n), n) +} else { + assert_eq!(>::from_be(n), n.swap_bytes()) +} +```"), + #[inline] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub fn from_be(x: Self) -> Self { + Wrapping(<$t>::from_be(x.0)) + } } - /// Converts `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 - /// - /// Basic usage: - /// - /// ``` - /// #![feature(wrapping_int_impl)] - /// use std::num::Wrapping; - /// - /// let n: Wrapping = Wrapping(0x0123456789ABCDEF); - /// - /// if cfg!(target_endian = "big") { - /// assert_eq!(n.to_be(), n); - /// } else { - /// assert_eq!(n.to_be(), n.swap_bytes()); - /// } - /// ``` - #[inline] - #[unstable(feature = "wrapping_int_impl", issue = "32463")] - pub fn to_be(self) -> Self { - Wrapping(self.0.to_be()) + doc_comment! { + concat!("Converts 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 + +Basic usage: + +``` +#![feature(wrapping_int_impl)] +use std::num::Wrapping; + +let n = Wrapping(0x1A", stringify!($t), "); + +if cfg!(target_endian = \"little\") { + assert_eq!(>::from_le(n), n) +} else { + assert_eq!(>::from_le(n), n.swap_bytes()) +} +```"), + #[inline] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub fn from_le(x: Self) -> Self { + Wrapping(<$t>::from_le(x.0)) + } } - /// Converts `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 - /// - /// Basic usage: - /// - /// ``` - /// #![feature(wrapping_int_impl)] - /// use std::num::Wrapping; - /// - /// let n: Wrapping = Wrapping(0x0123456789ABCDEF); - /// - /// if cfg!(target_endian = "little") { - /// assert_eq!(n.to_le(), n); - /// } else { - /// assert_eq!(n.to_le(), n.swap_bytes()); - /// } - /// ``` - #[inline] - #[unstable(feature = "wrapping_int_impl", issue = "32463")] - pub fn to_le(self) -> Self { - Wrapping(self.0.to_le()) + doc_comment! { + concat!("Converts `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 + +Basic usage: + +``` +#![feature(wrapping_int_impl)] +use std::num::Wrapping; + +let n = Wrapping(0x1A", stringify!($t), "); + +if cfg!(target_endian = \"big\") { + assert_eq!(n.to_be(), n) +} else { + assert_eq!(n.to_be(), n.swap_bytes()) +} +```"), + #[inline] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub fn to_be(self) -> Self { + Wrapping(self.0.to_be()) + } } - /// Raises self to the power of `exp`, using exponentiation by - /// squaring. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// #![feature(wrapping_int_impl)] - /// use std::num::Wrapping; - /// - /// let x: Wrapping = Wrapping(2); // or any other integer type - /// - /// assert_eq!(x.pow(4), Wrapping(16)); - /// ``` - /// - /// Results that are too large are wrapped: - /// - /// ``` - /// #![feature(wrapping_int_impl)] - /// use std::num::Wrapping; - /// - /// // 5 ^ 4 = 625, which is too big for a u8 - /// let x: Wrapping = Wrapping(5); - /// - /// assert_eq!(x.pow(4).0, 113); - /// ``` - #[inline] - #[unstable(feature = "wrapping_int_impl", issue = "32463")] - pub fn pow(self, exp: u32) -> Self { - Wrapping(self.0.wrapping_pow(exp)) + doc_comment! { + concat!("Converts `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 + +Basic usage: + +``` +#![feature(wrapping_int_impl)] +use std::num::Wrapping; + +let n = Wrapping(0x1A", stringify!($t), "); + +if cfg!(target_endian = \"little\") { + assert_eq!(n.to_le(), n) +} else { + assert_eq!(n.to_le(), n.swap_bytes()) +} +```"), + #[inline] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub fn to_le(self) -> Self { + Wrapping(self.0.to_le()) + } + } + + doc_comment! { + concat!("Raises self to the power of `exp`, using exponentiation by squaring. + +# Examples + +Basic usage: + +``` +#![feature(wrapping_int_impl)] +use std::num::Wrapping; + +assert_eq!(Wrapping(3", stringify!($t), ").pow(4), Wrapping(81)); +``` + +Results that are too large are wrapped: + +``` +#![feature(wrapping_int_impl)] +use std::num::Wrapping; + +assert_eq!(Wrapping(3i8).pow(5), Wrapping(-13)); +assert_eq!(Wrapping(3i8).pow(6), Wrapping(-39)); +```"), + #[inline] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub fn pow(self, exp: u32) -> Self { + Wrapping(self.0.wrapping_pow(exp)) + } } } )*) @@ -630,6 +688,211 @@ macro_rules! wrapping_int_impl { wrapping_int_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } +macro_rules! wrapping_int_impl_signed { + ($($t:ty)*) => ($( + impl Wrapping<$t> { + doc_comment! { + concat!("Returns the number of leading zeros in the binary representation of `self`. + +# Examples + +Basic usage: + +``` +#![feature(wrapping_int_impl)] +use std::num::Wrapping; + +let n = Wrapping(", stringify!($t), "::max_value()) >> 2; + +assert_eq!(n.leading_zeros(), 3); +```"), + #[inline] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub fn leading_zeros(self) -> u32 { + self.0.leading_zeros() + } + } + + doc_comment! { + concat!("Computes the absolute value of `self`, wrapping around at +the boundary of the type. + +The only case where such wrapping can occur is when one takes the absolute value of the negative +minimal value for the type this is a positive value that is too large to represent in the type. In +such a case, this function returns `MIN` itself. + +# Examples + +Basic usage: + +``` +#![feature(wrapping_int_impl)] +use std::num::Wrapping; + +assert_eq!(Wrapping(100", stringify!($t), ").abs(), Wrapping(100)); +assert_eq!(Wrapping(-100", stringify!($t), ").abs(), Wrapping(100)); +assert_eq!(Wrapping(", stringify!($t), "::min_value()).abs(), Wrapping(", stringify!($t), +"::min_value())); +assert_eq!(Wrapping(-128i8).abs().0 as u8, 128u8); +```"), + #[inline] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub fn abs(self) -> Wrapping<$t> { + Wrapping(self.0.wrapping_abs()) + } + } + + doc_comment! { + concat!("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 + +# Examples + +Basic usage: + +``` +#![feature(wrapping_int_impl)] +use std::num::Wrapping; + +assert_eq!(Wrapping(10", stringify!($t), ").signum(), Wrapping(1)); +assert_eq!(Wrapping(0", stringify!($t), ").signum(), Wrapping(0)); +assert_eq!(Wrapping(-10", stringify!($t), ").signum(), Wrapping(-1)); +```"), + #[inline] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub fn signum(self) -> Wrapping<$t> { + Wrapping(self.0.signum()) + } + } + + doc_comment! { + concat!("Returns `true` if `self` is positive and `false` if the number is zero or +negative. + +# Examples + +Basic usage: + +``` +#![feature(wrapping_int_impl)] +use std::num::Wrapping; + +assert!(Wrapping(10", stringify!($t), ").is_positive()); +assert!(!Wrapping(-10", stringify!($t), ").is_positive()); +```"), + #[inline] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub fn is_positive(self) -> bool { + self.0.is_positive() + } + } + + doc_comment! { + concat!("Returns `true` if `self` is negative and `false` if the number is zero or +positive. + +# Examples + +Basic usage: + +``` +#![feature(wrapping_int_impl)] +use std::num::Wrapping; + +assert!(Wrapping(-10", stringify!($t), ").is_negative()); +assert!(!Wrapping(10", stringify!($t), ").is_negative()); +```"), + #[inline] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub fn is_negative(self) -> bool { + self.0.is_negative() + } + } + } + )*) +} + +wrapping_int_impl_signed! { isize i8 i16 i32 i64 i128 } + +macro_rules! wrapping_int_impl_unsigned { + ($($t:ty)*) => ($( + impl Wrapping<$t> { + doc_comment! { + concat!("Returns the number of leading zeros in the binary representation of `self`. + +# Examples + +Basic usage: + +``` +#![feature(wrapping_int_impl)] +use std::num::Wrapping; + +let n = Wrapping(", stringify!($t), "::max_value()) >> 2; + +assert_eq!(n.leading_zeros(), 2); +```"), + #[inline] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub fn leading_zeros(self) -> u32 { + self.0.leading_zeros() + } + } + + doc_comment! { + concat!("Returns `true` if and only if `self == 2^k` for some `k`. + +# Examples + +Basic usage: + +``` +#![feature(wrapping_int_impl)] +use std::num::Wrapping; + +assert!(Wrapping(16", stringify!($t), ").is_power_of_two()); +assert!(!Wrapping(10", stringify!($t), ").is_power_of_two()); +```"), + #[inline] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub fn is_power_of_two(self) -> bool { + self.0.is_power_of_two() + } + } + + doc_comment! { + concat!("Returns the smallest power of two greater than or equal to `self`. + +When return value overflows (i.e. `self > (1 << (N-1))` for type +`uN`), overflows to `2^N = 0`. + +# Examples + +Basic usage: + +``` +#![feature(wrapping_next_power_of_two)] +use std::num::Wrapping; + +assert_eq!(Wrapping(2", stringify!($t), ").next_power_of_two(), Wrapping(2)); +assert_eq!(Wrapping(3", stringify!($t), ").next_power_of_two(), Wrapping(4)); +assert_eq!(Wrapping(200_u8).next_power_of_two(), Wrapping(0)); +```"), + #[inline] + #[unstable(feature = "wrapping_next_power_of_two", issue = "32463", + reason = "needs decision on wrapping behaviour")] + pub fn next_power_of_two(self) -> Self { + Wrapping(self.0.wrapping_next_power_of_two()) + } + } + } + )*) +} + +wrapping_int_impl_unsigned! { usize u8 u16 u32 u64 u128 } mod shift_max { #![allow(non_upper_case_globals)] @@ -656,11 +919,13 @@ mod shift_max { pub const i16: u32 = (1 << 4) - 1; pub const i32: u32 = (1 << 5) - 1; pub const i64: u32 = (1 << 6) - 1; + pub const i128: u32 = (1 << 7) - 1; pub use self::platform::isize; pub const u8: u32 = i8; pub const u16: u32 = i16; pub const u32: u32 = i32; pub const u64: u32 = i64; + pub const u128: u32 = i128; pub use self::platform::usize; }