2020-09-04 13:07:03 +00:00
//! Definitions of integer that is known not to equal zero.
use crate ::fmt ;
2020-11-18 07:48:03 +02:00
use crate ::ops ::{ BitOr , BitOrAssign , Div , Rem } ;
2020-09-04 13:07:03 +00:00
use crate ::str ::FromStr ;
use super ::from_str_radix ;
use super ::{ IntErrorKind , ParseIntError } ;
2020-11-17 19:29:15 +01:00
use crate ::intrinsics ;
2020-09-04 13:07:03 +00:00
macro_rules ! impl_nonzero_fmt {
( #[ $stability: meta ] ( $( $Trait : ident ) , + ) for $Ty : ident ) = > {
$(
#[ $stability ]
impl fmt ::$Trait for $Ty {
#[ inline ]
fn fmt ( & self , f : & mut fmt ::Formatter < '_ > ) -> fmt ::Result {
self . get ( ) . fmt ( f )
}
}
) +
}
}
macro_rules ! nonzero_integers {
( $( #[ $stability: meta ] $Ty : ident ( $Int : ty ) ; ) + ) = > {
$(
2020-11-17 23:57:29 +01:00
/// An integer that is known not to equal zero.
///
/// This enables some memory layout optimization.
#[ doc = concat!( " For example, `Option< " , stringify!($Ty), " >` is the same size as ` " , stringify!($Int), " `: " ) ]
///
/// ```rust
/// use std::mem::size_of;
#[ doc = concat!( " assert_eq!(size_of::<Option<core::num:: " , stringify!($Ty), " >>(), size_of::< " , stringify!($Int), " >()); " ) ]
/// ```
#[ $stability ]
#[ derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash) ]
#[ repr(transparent) ]
#[ rustc_layout_scalar_valid_range_start(1) ]
#[ rustc_nonnull_optimization_guaranteed ]
pub struct $Ty ( $Int ) ;
2020-09-04 13:07:03 +00:00
impl $Ty {
/// Creates a non-zero without checking the value.
///
/// # Safety
///
/// The value must not be zero.
#[ $stability ]
#[ rustc_const_stable(feature = " nonzero " , since = " 1.34.0 " ) ]
#[ inline ]
pub const unsafe fn new_unchecked ( n : $Int ) -> Self {
// SAFETY: this is guaranteed to be safe by the caller.
unsafe { Self ( n ) }
}
/// Creates a non-zero if the given value is not zero.
#[ $stability ]
#[ rustc_const_stable(feature = " const_nonzero_int_methods " , since = " 1.47.0 " ) ]
#[ inline ]
pub const fn new ( n : $Int ) -> Option < Self > {
if n ! = 0 {
// SAFETY: we just checked that there's no `0`
Some ( unsafe { Self ( n ) } )
} else {
None
}
}
/// Returns the value as a primitive type.
#[ $stability ]
#[ inline ]
#[ rustc_const_stable(feature = " nonzero " , since = " 1.34.0 " ) ]
pub const fn get ( self ) -> $Int {
self . 0
}
}
#[ stable(feature = " from_nonzero " , since = " 1.31.0 " ) ]
impl From < $Ty > for $Int {
2020-11-17 23:57:29 +01:00
#[ doc = concat!( " Converts a ` " , stringify!($Ty), " ` into an ` " , stringify!($Int), " ` " ) ]
#[ inline ]
fn from ( nonzero : $Ty ) -> Self {
nonzero . 0
2020-09-04 13:07:03 +00:00
}
}
#[ stable(feature = " nonzero_bitor " , since = " 1.45.0 " ) ]
impl BitOr for $Ty {
type Output = Self ;
#[ inline ]
fn bitor ( self , rhs : Self ) -> Self ::Output {
// SAFETY: since `self` and `rhs` are both nonzero, the
// result of the bitwise-or will be nonzero.
unsafe { $Ty ::new_unchecked ( self . get ( ) | rhs . get ( ) ) }
}
}
#[ stable(feature = " nonzero_bitor " , since = " 1.45.0 " ) ]
impl BitOr < $Int > for $Ty {
type Output = Self ;
#[ inline ]
fn bitor ( self , rhs : $Int ) -> Self ::Output {
// SAFETY: since `self` is nonzero, the result of the
// bitwise-or will be nonzero regardless of the value of
// `rhs`.
unsafe { $Ty ::new_unchecked ( self . get ( ) | rhs ) }
}
}
#[ stable(feature = " nonzero_bitor " , since = " 1.45.0 " ) ]
impl BitOr < $Ty > for $Int {
type Output = $Ty ;
#[ inline ]
fn bitor ( self , rhs : $Ty ) -> Self ::Output {
// SAFETY: since `rhs` is nonzero, the result of the
// bitwise-or will be nonzero regardless of the value of
// `self`.
unsafe { $Ty ::new_unchecked ( self | rhs . get ( ) ) }
}
}
#[ stable(feature = " nonzero_bitor " , since = " 1.45.0 " ) ]
impl BitOrAssign for $Ty {
#[ inline ]
fn bitor_assign ( & mut self , rhs : Self ) {
* self = * self | rhs ;
}
}
#[ stable(feature = " nonzero_bitor " , since = " 1.45.0 " ) ]
impl BitOrAssign < $Int > for $Ty {
#[ inline ]
fn bitor_assign ( & mut self , rhs : $Int ) {
* self = * self | rhs ;
}
}
impl_nonzero_fmt! {
#[ $stability ] ( Debug , Display , Binary , Octal , LowerHex , UpperHex ) for $Ty
}
) +
}
}
nonzero_integers! {
#[ stable(feature = " nonzero " , since = " 1.28.0 " ) ] NonZeroU8 ( u8 ) ;
#[ stable(feature = " nonzero " , since = " 1.28.0 " ) ] NonZeroU16 ( u16 ) ;
#[ stable(feature = " nonzero " , since = " 1.28.0 " ) ] NonZeroU32 ( u32 ) ;
#[ stable(feature = " nonzero " , since = " 1.28.0 " ) ] NonZeroU64 ( u64 ) ;
#[ stable(feature = " nonzero " , since = " 1.28.0 " ) ] NonZeroU128 ( u128 ) ;
#[ stable(feature = " nonzero " , since = " 1.28.0 " ) ] NonZeroUsize ( usize ) ;
#[ stable(feature = " signed_nonzero " , since = " 1.34.0 " ) ] NonZeroI8 ( i8 ) ;
#[ stable(feature = " signed_nonzero " , since = " 1.34.0 " ) ] NonZeroI16 ( i16 ) ;
#[ stable(feature = " signed_nonzero " , since = " 1.34.0 " ) ] NonZeroI32 ( i32 ) ;
#[ stable(feature = " signed_nonzero " , since = " 1.34.0 " ) ] NonZeroI64 ( i64 ) ;
#[ stable(feature = " signed_nonzero " , since = " 1.34.0 " ) ] NonZeroI128 ( i128 ) ;
#[ stable(feature = " signed_nonzero " , since = " 1.34.0 " ) ] NonZeroIsize ( isize ) ;
}
macro_rules ! from_str_radix_nzint_impl {
( $( $t :ty ) * ) = > { $(
#[ stable(feature = " nonzero_parse " , since = " 1.35.0 " ) ]
impl FromStr for $t {
type Err = ParseIntError ;
fn from_str ( src : & str ) -> Result < Self , Self ::Err > {
Self ::new ( from_str_radix ( src , 10 ) ? )
. ok_or ( ParseIntError {
kind : IntErrorKind ::Zero
} )
}
}
) * }
}
from_str_radix_nzint_impl! { NonZeroU8 NonZeroU16 NonZeroU32 NonZeroU64 NonZeroU128 NonZeroUsize
NonZeroI8 NonZeroI16 NonZeroI32 NonZeroI64 NonZeroI128 NonZeroIsize }
2020-11-17 19:29:15 +01:00
macro_rules ! nonzero_leading_trailing_zeros {
( $( $Ty : ident ( $Uint : ty ) , $LeadingTestExpr :expr ; ) + ) = > {
$(
impl $Ty {
2020-12-30 22:36:17 +01:00
/// 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:
///
/// ```
#[ doc = concat!( " let n = std::num:: " , stringify!($Ty), " ::new( " , stringify!($LeadingTestExpr), " ).unwrap(); " ) ]
///
/// assert_eq!(n.leading_zeros(), 0);
/// ```
2021-04-11 19:15:55 +02:00
#[ stable(feature = " nonzero_leading_trailing_zeros " , since = " 1.53.0 " ) ]
#[ rustc_const_stable(feature = " nonzero_leading_trailing_zeros " , since = " 1.53.0 " ) ]
2020-12-30 22:36:17 +01:00
#[ 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 }
2020-11-17 19:29:15 +01:00
}
2020-12-30 22:36:17 +01:00
/// 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:
///
/// ```
#[ doc = concat!( " let n = std::num:: " , stringify!($Ty), " ::new(0b0101000).unwrap(); " ) ]
///
/// assert_eq!(n.trailing_zeros(), 3);
/// ```
2021-04-11 19:15:55 +02:00
#[ stable(feature = " nonzero_leading_trailing_zeros " , since = " 1.53.0 " ) ]
#[ rustc_const_stable(feature = " nonzero_leading_trailing_zeros " , since = " 1.53.0 " ) ]
2020-12-30 22:36:17 +01:00
#[ 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 }
2020-11-17 19:29:15 +01:00
}
}
) +
}
}
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 ) , - 1 i8 ;
NonZeroI16 ( u16 ) , - 1 i16 ;
NonZeroI32 ( u32 ) , - 1 i32 ;
NonZeroI64 ( u64 ) , - 1 i64 ;
NonZeroI128 ( u128 ) , - 1 i128 ;
NonZeroIsize ( usize ) , - 1 isize ;
}
2020-11-16 15:38:22 +02:00
macro_rules ! nonzero_integers_div {
( $( $Ty : ident ( $Int : ty ) ; ) + ) = > {
$(
2020-12-27 03:17:30 -08:00
#[ stable(feature = " nonzero_div " , since = " 1.51.0 " ) ]
2020-11-16 15:38:22 +02:00
impl Div < $Ty > for $Int {
type Output = $Int ;
/// This operation rounds towards zero,
/// truncating any fractional part of the exact result, and cannot panic.
#[ inline ]
fn div ( self , other : $Ty ) -> $Int {
// SAFETY: div by zero is checked because `other` is a nonzero,
// and MIN/-1 is checked because `self` is an unsigned int.
unsafe { crate ::intrinsics ::unchecked_div ( self , other . get ( ) ) }
}
}
2020-11-18 07:48:03 +02:00
2020-12-27 03:17:30 -08:00
#[ stable(feature = " nonzero_div " , since = " 1.51.0 " ) ]
2020-11-18 07:48:03 +02:00
impl Rem < $Ty > for $Int {
type Output = $Int ;
/// This operation satisfies `n % d == n - (n / d) * d`, and cannot panic.
#[ inline ]
fn rem ( self , other : $Ty ) -> $Int {
// SAFETY: rem by zero is checked because `other` is a nonzero,
// and MIN/-1 is checked because `self` is an unsigned int.
unsafe { crate ::intrinsics ::unchecked_rem ( self , other . get ( ) ) }
}
}
2020-11-16 15:38:22 +02:00
) +
}
}
nonzero_integers_div! {
NonZeroU8 ( u8 ) ;
NonZeroU16 ( u16 ) ;
NonZeroU32 ( u32 ) ;
NonZeroU64 ( u64 ) ;
NonZeroU128 ( u128 ) ;
NonZeroUsize ( usize ) ;
}
2021-01-16 19:27:51 -08:00
macro_rules ! nonzero_unsigned_is_power_of_two {
( $( $Ty : ident ) + ) = > {
$(
impl $Ty {
/// Returns `true` if and only if `self == (1 << k)` for some `k`.
///
/// On many architectures, this function can perform better than `is_power_of_two()`
/// on the underlying integer type, as special handling of zero can be avoided.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// #![feature(nonzero_is_power_of_two)]
///
#[ doc = concat!( " let eight = std::num:: " , stringify!($Ty), " ::new(8).unwrap(); " ) ]
/// assert!(eight.is_power_of_two());
#[ doc = concat!( " let ten = std::num:: " , stringify!($Ty), " ::new(10).unwrap(); " ) ]
/// assert!(!ten.is_power_of_two());
/// ```
#[ unstable(feature = " nonzero_is_power_of_two " , issue = " 81106 " ) ]
#[ inline ]
pub const fn is_power_of_two ( self ) -> bool {
// LLVM 11 normalizes `unchecked_sub(x, 1) & x == 0` to the implementation seen here.
// On the basic x86-64 target, this saves 3 instructions for the zero check.
// On x86_64 with BMI1, being nonzero lets it codegen to `BLSR`, which saves an instruction
// compared to the `POPCNT` implementation on the underlying integer type.
intrinsics ::ctpop ( self . get ( ) ) < 2
}
}
) +
}
}
nonzero_unsigned_is_power_of_two! { NonZeroU8 NonZeroU16 NonZeroU32 NonZeroU64 NonZeroU128 NonZeroUsize }