about summary refs log tree commit diff
path: root/src/libcore
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-01-27 08:42:56 +0000
committerbors <bors@rust-lang.org>2020-01-27 08:42:56 +0000
commit1d5f6d41e140a3d6a9c6584d555bc09f10222d24 (patch)
treea8563b9552a092e5660b1a3cde97de357dbd6a80 /src/libcore
parent320ada6479b3e29c7d9a66bc56ac44c2d2b57566 (diff)
parent783a7dc8ed03a38910b9ea5ded11139616dfa67b (diff)
downloadrust-1d5f6d41e140a3d6a9c6584d555bc09f10222d24.tar.gz
rust-1d5f6d41e140a3d6a9c6584d555bc09f10222d24.zip
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.
Diffstat (limited to 'src/libcore')
-rw-r--r--src/libcore/num/mod.rs83
-rw-r--r--src/libcore/tests/lib.rs1
-rw-r--r--src/libcore/tests/num/int_macros.rs27
-rw-r--r--src/libcore/tests/num/uint_macros.rs27
4 files changed, 138 insertions, 0 deletions
diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs
index 072966abf2c..91848abd68d 100644
--- a/src/libcore/num/mod.rs
+++ b/src/libcore/num/mod.rs
@@ -394,6 +394,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.
 
@@ -2486,6 +2528,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.
 
diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs
index f0420247acf..21e279066e7 100644
--- a/src/libcore/tests/lib.rs
+++ b/src/libcore/tests/lib.rs
@@ -42,6 +42,7 @@
 #![feature(const_raw_ptr_deref)]
 #![feature(never_type)]
 #![feature(unwrap_infallible)]
+#![feature(leading_trailing_ones)]
 
 extern crate test;
 
diff --git a/src/libcore/tests/num/int_macros.rs b/src/libcore/tests/num/int_macros.rs
index 4a44b5f24b9..48a49073b2c 100644
--- a/src/libcore/tests/num/int_macros.rs
+++ b/src/libcore/tests/num/int_macros.rs
@@ -90,6 +90,33 @@ macro_rules! int_module {
             }
 
             #[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);
                 assert_eq!(B.rotate_left(3).rotate_left(2).rotate_right(5), B);
diff --git a/src/libcore/tests/num/uint_macros.rs b/src/libcore/tests/num/uint_macros.rs
index f94b2f56bbb..8f1ca8e6fac 100644
--- a/src/libcore/tests/num/uint_macros.rs
+++ b/src/libcore/tests/num/uint_macros.rs
@@ -54,6 +54,33 @@ macro_rules! uint_module {
             }
 
             #[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);
                 assert_eq!(B.rotate_left(3).rotate_left(2).rotate_right(5), B);