Auto merge of #68165 - thomcc:lt_ones, r=sfackler

Add leading_ones and trailing_ones methods to the primitive integer types

I was surprised these were missing (given that `leading_zeros` and `trailing_zeros` exist), and they seem trivial and hopefully not controversial.

Note that there's some precedent in that `count_ones` and `count_zeros` are both supported even though only one of these has an intrinsic.

I'm not sure if these need a `rustc_const_unstable` flag (the tests don't seem to mind that it's missing). I just made them const, since there's not really any reason for these to be non-const when the `_zeros` variants are const.

Note: My understanding is trivial stuff like (hopefully) this can land without an RFC, but I'm not fully sure about the process though. Questions like "when does the tracking issue get filed?", are a total mystery to me. So, any guidance is appreciated, and sorry in advance if I should have gone through some more involved process for this.
This commit is contained in:
bors 2020-01-27 08:42:56 +00:00
commit 1d5f6d41e1
4 changed files with 138 additions and 0 deletions

View file

@ -393,6 +393,48 @@ $EndFeature, "
}
}
doc_comment! {
concat!("Returns the number of leading ones in the binary representation of `self`.
# Examples
Basic usage:
```
", $Feature, "#![feature(leading_trailing_ones)]
let n = -1", stringify!($SelfT), ";
assert_eq!(n.leading_ones(), ", stringify!($BITS), ");",
$EndFeature, "
```"),
#[unstable(feature = "leading_trailing_ones", issue = "57969")]
#[inline]
pub const fn leading_ones(self) -> u32 {
(self as $UnsignedT).leading_ones()
}
}
doc_comment! {
concat!("Returns the number of trailing ones in the binary representation of `self`.
# Examples
Basic usage:
```
", $Feature, "#![feature(leading_trailing_ones)]
let n = 3", stringify!($SelfT), ";
assert_eq!(n.trailing_ones(), 2);",
$EndFeature, "
```"),
#[unstable(feature = "leading_trailing_ones", issue = "57969")]
#[inline]
pub const fn trailing_ones(self) -> u32 {
(self as $UnsignedT).trailing_ones()
}
}
doc_comment! {
concat!("Shifts the bits to the left by a specified amount, `n`,
wrapping the truncated bits to the end of the resulting integer.
@ -2485,6 +2527,47 @@ assert_eq!(n.trailing_zeros(), 3);", $EndFeature, "
}
}
doc_comment! {
concat!("Returns the number of leading ones in the binary representation of `self`.
# Examples
Basic usage:
```
", $Feature, "#![feature(leading_trailing_ones)]
let n = !(", stringify!($SelfT), "::max_value() >> 2);
assert_eq!(n.leading_ones(), 2);", $EndFeature, "
```"),
#[unstable(feature = "leading_trailing_ones", issue = "57969")]
#[inline]
pub const fn leading_ones(self) -> u32 {
(!self).leading_zeros()
}
}
doc_comment! {
concat!("Returns the number of trailing ones in the binary representation
of `self`.
# Examples
Basic usage:
```
", $Feature, "#![feature(leading_trailing_ones)]
let n = 0b1010111", stringify!($SelfT), ";
assert_eq!(n.trailing_ones(), 3);", $EndFeature, "
```"),
#[unstable(feature = "leading_trailing_ones", issue = "57969")]
#[inline]
pub const fn trailing_ones(self) -> u32 {
(!self).trailing_zeros()
}
}
doc_comment! {
concat!("Shifts the bits to the left by a specified amount, `n`,
wrapping the truncated bits to the end of the resulting integer.

View file

@ -42,6 +42,7 @@
#![feature(const_raw_ptr_deref)]
#![feature(never_type)]
#![feature(unwrap_infallible)]
#![feature(leading_trailing_ones)]
extern crate test;

View file

@ -89,6 +89,33 @@ macro_rules! int_module {
assert_eq!(C.count_zeros(), bits as u32 - 5);
}
#[test]
fn test_leading_trailing_ones() {
let bits = (mem::size_of::<$T>() * 8) as u32;
let a: $T = 0b0101_1111;
assert_eq!(a.trailing_ones(), 5);
assert_eq!((!a).leading_ones(), bits - 7);
assert_eq!(a.reverse_bits().leading_ones(), 5);
assert_eq!(_1.leading_ones(), bits);
assert_eq!(_1.trailing_ones(), bits);
assert_eq!((_1 << 1).trailing_ones(), 0);
assert_eq!(MAX.leading_ones(), 0);
assert_eq!((_1 << 1).leading_ones(), bits - 1);
assert_eq!(MAX.trailing_ones(), bits - 1);
assert_eq!(_0.leading_ones(), 0);
assert_eq!(_0.trailing_ones(), 0);
let x: $T = 0b0010_1100;
assert_eq!(x.leading_ones(), 0);
assert_eq!(x.trailing_ones(), 0);
}
#[test]
fn test_rotate() {
assert_eq!(A.rotate_left(6).rotate_right(2).rotate_right(4), A);

View file

@ -53,6 +53,33 @@ macro_rules! uint_module {
assert!(C.count_zeros() == bits as u32 - 5);
}
#[test]
fn test_leading_trailing_ones() {
let bits = (mem::size_of::<$T>() * 8) as u32;
let a: $T = 0b0101_1111;
assert_eq!(a.trailing_ones(), 5);
assert_eq!((!a).leading_ones(), bits - 7);
assert_eq!(a.reverse_bits().leading_ones(), 5);
assert_eq!(_1.leading_ones(), bits);
assert_eq!(_1.trailing_ones(), bits);
assert_eq!((_1 << 1).trailing_ones(), 0);
assert_eq!((_1 >> 1).leading_ones(), 0);
assert_eq!((_1 << 1).leading_ones(), bits - 1);
assert_eq!((_1 >> 1).trailing_ones(), bits - 1);
assert_eq!(_0.leading_ones(), 0);
assert_eq!(_0.trailing_ones(), 0);
let x: $T = 0b0010_1100;
assert_eq!(x.leading_ones(), 0);
assert_eq!(x.trailing_ones(), 0);
}
#[test]
fn test_rotate() {
assert_eq!(A.rotate_left(6).rotate_right(2).rotate_right(4), A);