mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-22 20:53:37 +00:00
add trailing_zeros and leading_zeros to non zero types
This commit is contained in:
parent
5fab31e5dd
commit
9bbc4c16d3
@ -80,6 +80,7 @@
|
||||
#![feature(const_mut_refs)]
|
||||
#![feature(const_int_pow)]
|
||||
#![feature(constctlz)]
|
||||
#![feature(const_cttz)]
|
||||
#![feature(const_panic)]
|
||||
#![feature(const_pin)]
|
||||
#![feature(const_fn)]
|
||||
|
@ -6,6 +6,7 @@ use crate::str::FromStr;
|
||||
|
||||
use super::from_str_radix;
|
||||
use super::{IntErrorKind, ParseIntError};
|
||||
use crate::intrinsics;
|
||||
|
||||
macro_rules! doc_comment {
|
||||
($x:expr, $($tt:tt)*) => {
|
||||
@ -189,3 +190,76 @@ macro_rules! from_str_radix_nzint_impl {
|
||||
|
||||
from_str_radix_nzint_impl! { NonZeroU8 NonZeroU16 NonZeroU32 NonZeroU64 NonZeroU128 NonZeroUsize
|
||||
NonZeroI8 NonZeroI16 NonZeroI32 NonZeroI64 NonZeroI128 NonZeroIsize }
|
||||
|
||||
macro_rules! nonzero_leading_trailing_zeros {
|
||||
( $( $Ty: ident($Uint: ty) , $LeadingTestExpr:expr ;)+ ) => {
|
||||
$(
|
||||
impl $Ty {
|
||||
doc_comment! {
|
||||
concat!("Returns the number of leading zeros in the binary representation of `self`.
|
||||
|
||||
On many architectures, this function can perform better than `leading_zeros()` on the underlying integer type, as special handling of zero can be avoided.
|
||||
|
||||
# Examples
|
||||
|
||||
Basic usage:
|
||||
|
||||
```
|
||||
#![feature(nonzero_leading_trailing_zeros)]
|
||||
let n = std::num::", stringify!($Ty), "::new(", stringify!($LeadingTestExpr), ").unwrap();
|
||||
|
||||
assert_eq!(n.leading_zeros(), 0);
|
||||
```"),
|
||||
#[unstable(feature = "nonzero_leading_trailing_zeros", issue = "79143")]
|
||||
#[rustc_const_unstable(feature = "nonzero_leading_trailing_zeros", issue = "79143")]
|
||||
#[inline]
|
||||
pub const fn leading_zeros(self) -> u32 {
|
||||
// SAFETY: since `self` can not be zero it is safe to call ctlz_nonzero
|
||||
unsafe { intrinsics::ctlz_nonzero(self.0 as $Uint) as u32 }
|
||||
}
|
||||
}
|
||||
|
||||
doc_comment! {
|
||||
concat!("Returns the number of trailing zeros in the binary representation
|
||||
of `self`.
|
||||
|
||||
On many architectures, this function can perform better than `trailing_zeros()` on the underlying integer type, as special handling of zero can be avoided.
|
||||
|
||||
# Examples
|
||||
|
||||
Basic usage:
|
||||
|
||||
```
|
||||
#![feature(nonzero_leading_trailing_zeros)]
|
||||
let n = std::num::", stringify!($Ty), "::new(0b0101000).unwrap();
|
||||
|
||||
assert_eq!(n.trailing_zeros(), 3);
|
||||
```"),
|
||||
#[unstable(feature = "nonzero_leading_trailing_zeros", issue = "79143")]
|
||||
#[rustc_const_unstable(feature = "nonzero_leading_trailing_zeros", issue = "79143")]
|
||||
#[inline]
|
||||
pub const fn trailing_zeros(self) -> u32 {
|
||||
// SAFETY: since `self` can not be zero it is safe to call cttz_nonzero
|
||||
unsafe { intrinsics::cttz_nonzero(self.0 as $Uint) as u32 }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
)+
|
||||
}
|
||||
}
|
||||
|
||||
nonzero_leading_trailing_zeros! {
|
||||
NonZeroU8(u8), u8::MAX;
|
||||
NonZeroU16(u16), u16::MAX;
|
||||
NonZeroU32(u32), u32::MAX;
|
||||
NonZeroU64(u64), u64::MAX;
|
||||
NonZeroU128(u128), u128::MAX;
|
||||
NonZeroUsize(usize), usize::MAX;
|
||||
NonZeroI8(u8), -1i8;
|
||||
NonZeroI16(u16), -1i16;
|
||||
NonZeroI32(u32), -1i32;
|
||||
NonZeroI64(u64), -1i64;
|
||||
NonZeroI128(u128), -1i128;
|
||||
NonZeroIsize(usize), -1isize;
|
||||
}
|
||||
|
@ -60,6 +60,8 @@
|
||||
#![feature(once_cell)]
|
||||
#![feature(unsafe_block_in_unsafe_fn)]
|
||||
#![feature(int_bits_const)]
|
||||
#![feature(nonzero_leading_trailing_zeros)]
|
||||
#![feature(const_option)]
|
||||
#![deny(unsafe_op_in_unsafe_fn)]
|
||||
|
||||
extern crate test;
|
||||
|
@ -1,5 +1,8 @@
|
||||
use core::convert::TryFrom;
|
||||
use core::num::{IntErrorKind, NonZeroI32, NonZeroI8, NonZeroU32, NonZeroU8};
|
||||
use core::num::{
|
||||
IntErrorKind, NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize,
|
||||
NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize,
|
||||
};
|
||||
use core::option::Option::{self, None, Some};
|
||||
use std::mem::size_of;
|
||||
|
||||
@ -212,3 +215,100 @@ fn nonzero_const() {
|
||||
const ONE: Option<NonZeroU8> = NonZeroU8::new(1);
|
||||
assert!(ONE.is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn nonzero_leading_zeros() {
|
||||
assert_eq!(NonZeroU8::new(1).unwrap().leading_zeros(), 7);
|
||||
assert_eq!(NonZeroI8::new(1).unwrap().leading_zeros(), 7);
|
||||
assert_eq!(NonZeroU16::new(1).unwrap().leading_zeros(), 15);
|
||||
assert_eq!(NonZeroI16::new(1).unwrap().leading_zeros(), 15);
|
||||
assert_eq!(NonZeroU32::new(1).unwrap().leading_zeros(), 31);
|
||||
assert_eq!(NonZeroI32::new(1).unwrap().leading_zeros(), 31);
|
||||
assert_eq!(NonZeroU64::new(1).unwrap().leading_zeros(), 63);
|
||||
assert_eq!(NonZeroI64::new(1).unwrap().leading_zeros(), 63);
|
||||
assert_eq!(NonZeroU128::new(1).unwrap().leading_zeros(), 127);
|
||||
assert_eq!(NonZeroI128::new(1).unwrap().leading_zeros(), 127);
|
||||
assert_eq!(NonZeroUsize::new(1).unwrap().leading_zeros(), usize::BITS - 1);
|
||||
assert_eq!(NonZeroIsize::new(1).unwrap().leading_zeros(), usize::BITS - 1);
|
||||
|
||||
assert_eq!(NonZeroU8::new(u8::MAX >> 2).unwrap().leading_zeros(), 2);
|
||||
assert_eq!(NonZeroI8::new((u8::MAX >> 2) as i8).unwrap().leading_zeros(), 2);
|
||||
assert_eq!(NonZeroU16::new(u16::MAX >> 2).unwrap().leading_zeros(), 2);
|
||||
assert_eq!(NonZeroI16::new((u16::MAX >> 2) as i16).unwrap().leading_zeros(), 2);
|
||||
assert_eq!(NonZeroU32::new(u32::MAX >> 2).unwrap().leading_zeros(), 2);
|
||||
assert_eq!(NonZeroI32::new((u32::MAX >> 2) as i32).unwrap().leading_zeros(), 2);
|
||||
assert_eq!(NonZeroU64::new(u64::MAX >> 2).unwrap().leading_zeros(), 2);
|
||||
assert_eq!(NonZeroI64::new((u64::MAX >> 2) as i64).unwrap().leading_zeros(), 2);
|
||||
assert_eq!(NonZeroU128::new(u128::MAX >> 2).unwrap().leading_zeros(), 2);
|
||||
assert_eq!(NonZeroI128::new((u128::MAX >> 2) as i128).unwrap().leading_zeros(), 2);
|
||||
assert_eq!(NonZeroUsize::new(usize::MAX >> 2).unwrap().leading_zeros(), 2);
|
||||
assert_eq!(NonZeroIsize::new((usize::MAX >> 2) as isize).unwrap().leading_zeros(), 2);
|
||||
|
||||
assert_eq!(NonZeroU8::new(u8::MAX).unwrap().leading_zeros(), 0);
|
||||
assert_eq!(NonZeroI8::new(-1i8).unwrap().leading_zeros(), 0);
|
||||
assert_eq!(NonZeroU16::new(u16::MAX).unwrap().leading_zeros(), 0);
|
||||
assert_eq!(NonZeroI16::new(-1i16).unwrap().leading_zeros(), 0);
|
||||
assert_eq!(NonZeroU32::new(u32::MAX).unwrap().leading_zeros(), 0);
|
||||
assert_eq!(NonZeroI32::new(-1i32).unwrap().leading_zeros(), 0);
|
||||
assert_eq!(NonZeroU64::new(u64::MAX).unwrap().leading_zeros(), 0);
|
||||
assert_eq!(NonZeroI64::new(-1i64).unwrap().leading_zeros(), 0);
|
||||
assert_eq!(NonZeroU128::new(u128::MAX).unwrap().leading_zeros(), 0);
|
||||
assert_eq!(NonZeroI128::new(-1i128).unwrap().leading_zeros(), 0);
|
||||
assert_eq!(NonZeroUsize::new(usize::MAX).unwrap().leading_zeros(), 0);
|
||||
assert_eq!(NonZeroIsize::new(-1isize).unwrap().leading_zeros(), 0);
|
||||
|
||||
const LEADING_ZEROS: u32 = NonZeroU16::new(1).unwrap().leading_zeros();
|
||||
assert_eq!(LEADING_ZEROS, 15);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn nonzero_trailing_zeros() {
|
||||
assert_eq!(NonZeroU8::new(1).unwrap().trailing_zeros(), 0);
|
||||
assert_eq!(NonZeroI8::new(1).unwrap().trailing_zeros(), 0);
|
||||
assert_eq!(NonZeroU16::new(1).unwrap().trailing_zeros(), 0);
|
||||
assert_eq!(NonZeroI16::new(1).unwrap().trailing_zeros(), 0);
|
||||
assert_eq!(NonZeroU32::new(1).unwrap().trailing_zeros(), 0);
|
||||
assert_eq!(NonZeroI32::new(1).unwrap().trailing_zeros(), 0);
|
||||
assert_eq!(NonZeroU64::new(1).unwrap().trailing_zeros(), 0);
|
||||
assert_eq!(NonZeroI64::new(1).unwrap().trailing_zeros(), 0);
|
||||
assert_eq!(NonZeroU128::new(1).unwrap().trailing_zeros(), 0);
|
||||
assert_eq!(NonZeroI128::new(1).unwrap().trailing_zeros(), 0);
|
||||
assert_eq!(NonZeroUsize::new(1).unwrap().trailing_zeros(), 0);
|
||||
assert_eq!(NonZeroIsize::new(1).unwrap().trailing_zeros(), 0);
|
||||
|
||||
assert_eq!(NonZeroU8::new(1 << 2).unwrap().trailing_zeros(), 2);
|
||||
assert_eq!(NonZeroI8::new(1 << 2).unwrap().trailing_zeros(), 2);
|
||||
assert_eq!(NonZeroU16::new(1 << 2).unwrap().trailing_zeros(), 2);
|
||||
assert_eq!(NonZeroI16::new(1 << 2).unwrap().trailing_zeros(), 2);
|
||||
assert_eq!(NonZeroU32::new(1 << 2).unwrap().trailing_zeros(), 2);
|
||||
assert_eq!(NonZeroI32::new(1 << 2).unwrap().trailing_zeros(), 2);
|
||||
assert_eq!(NonZeroU64::new(1 << 2).unwrap().trailing_zeros(), 2);
|
||||
assert_eq!(NonZeroI64::new(1 << 2).unwrap().trailing_zeros(), 2);
|
||||
assert_eq!(NonZeroU128::new(1 << 2).unwrap().trailing_zeros(), 2);
|
||||
assert_eq!(NonZeroI128::new(1 << 2).unwrap().trailing_zeros(), 2);
|
||||
assert_eq!(NonZeroUsize::new(1 << 2).unwrap().trailing_zeros(), 2);
|
||||
assert_eq!(NonZeroIsize::new(1 << 2).unwrap().trailing_zeros(), 2);
|
||||
|
||||
assert_eq!(NonZeroU8::new(1 << 7).unwrap().trailing_zeros(), 7);
|
||||
assert_eq!(NonZeroI8::new(1 << 7).unwrap().trailing_zeros(), 7);
|
||||
assert_eq!(NonZeroU16::new(1 << 15).unwrap().trailing_zeros(), 15);
|
||||
assert_eq!(NonZeroI16::new(1 << 15).unwrap().trailing_zeros(), 15);
|
||||
assert_eq!(NonZeroU32::new(1 << 31).unwrap().trailing_zeros(), 31);
|
||||
assert_eq!(NonZeroI32::new(1 << 31).unwrap().trailing_zeros(), 31);
|
||||
assert_eq!(NonZeroU64::new(1 << 63).unwrap().trailing_zeros(), 63);
|
||||
assert_eq!(NonZeroI64::new(1 << 63).unwrap().trailing_zeros(), 63);
|
||||
assert_eq!(NonZeroU128::new(1 << 127).unwrap().trailing_zeros(), 127);
|
||||
assert_eq!(NonZeroI128::new(1 << 127).unwrap().trailing_zeros(), 127);
|
||||
|
||||
assert_eq!(
|
||||
NonZeroUsize::new(1 << (usize::BITS - 1)).unwrap().trailing_zeros(),
|
||||
usize::BITS - 1
|
||||
);
|
||||
assert_eq!(
|
||||
NonZeroIsize::new(1 << (usize::BITS - 1)).unwrap().trailing_zeros(),
|
||||
usize::BITS - 1
|
||||
);
|
||||
|
||||
const TRAILING_ZEROS: u32 = NonZeroU16::new(1 << 2).unwrap().trailing_zeros();
|
||||
assert_eq!(TRAILING_ZEROS, 2);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user