Auto merge of #50465 - clarcharr:wrapping, r=KodrAus

Add missing Wrapping methods, use doc_comment!

Re-opened version of #49393 . Finishing touches for #32463.

Note that this adds `Shl` and `Shr` implementations for `Wrapping<i128>` and `Wrapping<u128>`, which were previously missed. This is technically insta-stable, but I don't know why this would be a problem.
This commit is contained in:
bors 2018-05-28 22:28:43 +00:00
commit e9a489be94
2 changed files with 488 additions and 199 deletions

View file

@ -168,8 +168,6 @@ impl<T: fmt::UpperHex> fmt::UpperHex for Wrapping<T> {
}
}
mod wrapping;
// All these modules are technically private and only exposed for coretests:
pub mod flt2dec;
pub mod dec2flt;
@ -183,6 +181,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,
@ -3401,6 +3401,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 platforms native endianness is used.

View file

@ -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<T> for Wrapping<T>, impl OpAssign<T> for Wrapping<T>
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<i8> = 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!(<Wrapping<", stringify!($t), ">>::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<i8> = 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!(<Wrapping<", stringify!($t), ">>::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<i16> = 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<i8> = 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<i64> = Wrapping(0x0123456789ABCDEF);
/// let n = Wrapping(0b0000000_01010101i16);
/// assert_eq!(n, Wrapping(85));
///
/// if cfg!(target_endian = "big") {
/// assert_eq!(Wrapping::<i64>::from_be(n), n);
/// } else {
/// assert_eq!(Wrapping::<i64>::from_be(n), n.swap_bytes());
/// }
/// let m = n.reverse_bits();
///
/// 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<i64> = Wrapping(0x0123456789ABCDEF);
///
/// if cfg!(target_endian = "little") {
/// assert_eq!(Wrapping::<i64>::from_le(n), n);
/// } else {
/// assert_eq!(Wrapping::<i64>::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!(<Wrapping<", stringify!($t), ">>::from_be(n), n)
} else {
assert_eq!(<Wrapping<", stringify!($t), ">>::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<i64> = 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!(<Wrapping<", stringify!($t), ">>::from_le(n), n)
} else {
assert_eq!(<Wrapping<", stringify!($t), ">>::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<i64> = 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<i32> = 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<u8> = 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;
}