Skip to content

Commit

Permalink
Auto merge of rust-lang#68165 - thomcc:lt_ones, r=sfackler
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
bors committed Jan 27, 2020
2 parents 320ada6 + 783a7dc commit 1d5f6d4
Show file tree
Hide file tree
Showing 4 changed files with 138 additions and 0 deletions.
83 changes: 83 additions & 0 deletions src/libcore/num/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand Down
1 change: 1 addition & 0 deletions src/libcore/tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
#![feature(const_raw_ptr_deref)]
#![feature(never_type)]
#![feature(unwrap_infallible)]
#![feature(leading_trailing_ones)]

extern crate test;

Expand Down
27 changes: 27 additions & 0 deletions src/libcore/tests/num/int_macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
27 changes: 27 additions & 0 deletions src/libcore/tests/num/uint_macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit 1d5f6d4

Please sign in to comment.