diff --git a/src/integer.rs b/src/integer.rs index 4ce0f0e..f157bc7 100644 --- a/src/integer.rs +++ b/src/integer.rs @@ -1,5 +1,4 @@ -use core::num::ParseIntError; - +use core::num::{NonZero, ParseIntError, TryFromIntError}; use crate::{PrimitiveError, PrimitiveNumber, PrimitiveNumberRef}; /// Trait for all primitive [integer types], including the supertrait [`PrimitiveNumber`]. @@ -517,6 +516,15 @@ pub trait PrimitiveInteger: /// This results in undefined behavior when `self - rhs > Self::MAX` or `self - rhs < /// Self::MIN`, i.e. when [`checked_sub`][Self::checked_sub] would return `None`. unsafe fn unchecked_sub(self, rhs: Self) -> Self; + + /// The NonZero struct for this integer + type NonZero: + core::convert::TryFrom + + core::ops::BitOr + + core::ops::BitOr + + core::ops::BitOrAssign + + core::ops::BitOrAssign + + Into; } /// Trait for references to primitive integer types ([`PrimitiveInteger`]). @@ -690,6 +698,8 @@ macro_rules! impl_integer { unsafe fn unchecked_shr(self, rhs: u32) -> Self; unsafe fn unchecked_sub(self, rhs: Self) -> Self; } + + type NonZero = NonZero; } impl PrimitiveIntegerRef<$Integer> for &$Integer {} diff --git a/src/lib.rs b/src/lib.rs index 2901999..76564d3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -66,6 +66,7 @@ mod integer; mod number; mod signed; mod unsigned; +mod nonzero; #[cfg(test)] mod tests; @@ -77,3 +78,4 @@ pub use self::integer::{PrimitiveInteger, PrimitiveIntegerRef}; pub use self::number::{PrimitiveNumber, PrimitiveNumberAs, PrimitiveNumberRef}; pub use self::signed::{PrimitiveSigned, PrimitiveSignedRef}; pub use self::unsigned::{PrimitiveUnsigned, PrimitiveUnsignedRef}; +pub use self::nonzero::{NonZeroPrimitiveInteger, NonZeroPrimitiveSigned, NonZeroPrimitiveUnsigned}; \ No newline at end of file diff --git a/src/macros.rs b/src/macros.rs index 07e8187..da5b152 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -21,6 +21,14 @@ macro_rules! forward { Self::$method($( $arg ),* ) } )*}; + ($(unsafe fn $method:ident ( $( $arg:ident : $ty:ty )* ) -> $ret:ty ; )*) => {$( + #[doc = forward_doc!($method)] + #[inline] + unsafe fn $method( $( $arg : $ty )* ) -> $ret { + // SAFETY: we're just passing through here! + unsafe { Self::$method( $( $arg ),* ) } + } + )*}; ($(unsafe fn $method:ident ( self $( , $arg:ident : $ty:ty )* ) -> $ret:ty ; )*) => {$( #[doc = forward_doc!($method)] #[inline] diff --git a/src/nonzero/implement.rs b/src/nonzero/implement.rs new file mode 100644 index 0000000..c0556a0 --- /dev/null +++ b/src/nonzero/implement.rs @@ -0,0 +1,69 @@ +use super::{NonZeroPrimitiveInteger, NonZeroPrimitiveUnsigned, NonZeroPrimitiveSigned}; +use crate::PrimitiveUnsigned; +use core::num::NonZero; + +macro_rules! impl_nonzero { + (@uint $($t:ty),+) => { + impl_nonzero!($($t, <$t as PrimitiveUnsigned>::Signed),+); + $( + impl NonZeroPrimitiveUnsigned for NonZero<$t> { + type Signed = NonZero<<$t as PrimitiveUnsigned>::Signed>; + forward!( + fn saturating_add(self, rhs: $t) -> Self; + fn checked_add(self, rhs: $t) -> Option; + fn cast_signed(self) -> Self::Signed; + fn ilog2(self) -> u32; + fn ilog10(self) -> u32; + fn isqrt(self) -> Self; + fn midpoint(self, rhs: Self) -> Self; + fn checked_next_power_of_two(self) -> Option; + fn is_power_of_two(self) -> bool; + ); + } + impl NonZeroPrimitiveSigned for NonZero<<$t as PrimitiveUnsigned>::Signed> { + type Unsigned = NonZero<$t>; + forward!( + fn abs(self) -> Self; + fn checked_abs(self) -> Option; + fn saturating_abs(self) -> Self; + fn overflowing_abs(self) -> (Self, bool); + fn wrapping_abs(self) -> Self; + fn unsigned_abs(self) -> Self::Unsigned; + fn is_positive(self) -> bool; + fn is_negative(self) -> bool; + fn checked_neg(self) -> Option; + fn overflowing_neg(self) -> (Self, bool); + fn saturating_neg(self) -> Self; + fn cast_unsigned(self) -> Self::Unsigned; + ); + } + )+ + }; + ($($t:ty),+) => {$( + impl NonZeroPrimitiveInteger for NonZero<$t> { + type Zeroable = $t; + forward! { + fn new(n: Self::Zeroable) -> Option; + } + forward! { + fn get(self) -> Self::Zeroable; + fn leading_zeros(self) -> u32; + fn trailing_zeros(self) -> u32; + fn checked_mul(self, rhs: Self) -> Option; + fn checked_pow(self, exponent: u32) -> Option; + fn saturating_pow(self, exponent: u32) -> Self; + fn count_ones(self) -> NonZero; + } + forward! { + unsafe fn new_unchecked(n: Self::Zeroable) -> Self; + } + // not forwarding because core's docs are inaccurate + // It specifies that it can only saturate to `Self::MAX` + // even on signed types. + fn saturating_mul(self, rhs: Self) -> Self { + self.saturating_mul(rhs) + } + } + )+}; +} +impl_nonzero!(@uint u8, u16, u32, u64, u128, usize); \ No newline at end of file diff --git a/src/nonzero/mod.rs b/src/nonzero/mod.rs new file mode 100644 index 0000000..5a7dda4 --- /dev/null +++ b/src/nonzero/mod.rs @@ -0,0 +1,129 @@ +mod signed_nonzero; +mod unsigned_nonzero; +mod implement; + +pub use self::unsigned_nonzero::NonZeroPrimitiveUnsigned; +pub use self::signed_nonzero::NonZeroPrimitiveSigned; + +use crate::{PrimitiveInteger, PrimitiveError}; +use core::num::NonZero; + + +/// Trait for [`NonZero`]. +/// +/// This encapsulates trait implementations, constants, and inherent methods that are common among +/// all of the implementations of `NonZero`. +/// +/// See the corresponding items on the individual types for more documentation and examples. +/// +/// This trait is sealed with a private trait to prevent downstream implementations, so we may +/// continue to expand along with the standard library without worrying about breaking changes for +/// implementors. +pub trait NonZeroPrimitiveInteger: + 'static + + core::cmp::Eq + + core::cmp::PartialEq + + core::cmp::Ord + + core::cmp::PartialOrd + + core::fmt::Debug + + core::fmt::Display + + core::fmt::LowerExp + + core::fmt::UpperExp + + core::fmt::Binary + + core::fmt::LowerHex + + core::fmt::Octal + + core::fmt::UpperHex + + core::hash::Hash + + core::marker::Copy + + core::marker::Send + + core::marker::Sync + + core::marker::Unpin + + core::panic::RefUnwindSafe + + core::panic::UnwindSafe + + core::str::FromStr + + core::convert::TryFrom, Error: PrimitiveError> + + core::convert::TryFrom, Error: PrimitiveError> + + core::convert::TryFrom, Error: PrimitiveError> + + core::convert::TryFrom, Error: PrimitiveError> + + core::convert::TryFrom, Error: PrimitiveError> + + core::convert::TryFrom, Error: PrimitiveError> + + core::convert::TryFrom, Error: PrimitiveError> + + core::convert::TryFrom, Error: PrimitiveError> + + core::convert::TryFrom, Error: PrimitiveError> + + core::convert::TryFrom, Error: PrimitiveError> + + core::convert::TryFrom, Error: PrimitiveError> + + core::convert::TryFrom, Error: PrimitiveError> + + core::convert::TryInto, Error: PrimitiveError> + + core::convert::TryInto, Error: PrimitiveError> + + core::convert::TryInto, Error: PrimitiveError> + + core::convert::TryInto, Error: PrimitiveError> + + core::convert::TryInto, Error: PrimitiveError> + + core::convert::TryInto, Error: PrimitiveError> + + core::convert::TryInto, Error: PrimitiveError> + + core::convert::TryInto, Error: PrimitiveError> + + core::convert::TryInto, Error: PrimitiveError> + + core::convert::TryInto, Error: PrimitiveError> + + core::convert::TryInto, Error: PrimitiveError> + + core::convert::TryInto, Error: PrimitiveError> + + core::ops::BitOr + + core::ops::BitOr + + core::ops::BitOrAssign +{ + /// The integer type that this represents, + /// For a `NonZero` this is `T`. + type Zeroable: + PrimitiveInteger + + core::ops::BitOr + + From + + TryInto; + + /// The size of this non-zero integer type in bits, equal to `Self::Zeroable::BITS` + const BITS: u32 = Self::Zeroable::BITS; + + /// The largest value that can be represented by this non-zero integer type, equal to `Self::Zeroable::MAX`. + const MAX: Self = unsafe { core::mem::transmute_copy::(&Self::Zeroable::MAX) }; + + /// Creates a non-zero if the given value is not zero. + fn new(n: Self::Zeroable) -> Option; + + /// Creates a non-zero without checking whether the value is non-zero. + /// This results in undefined behavior if the value is zero. + /// + /// # Safety + /// The value must not be zero. + unsafe fn new_unchecked(n: Self::Zeroable) -> Self; + + /// Returns the contained value as a primitive type. + fn get(self) -> Self::Zeroable; + + /// Returns the number of leading zeros in the binary representation of `self`. + /// + /// On many architectures, this function can perform better than `leading_zeros()` + /// on `Self::Zeroable`, as special handling of zero can be avoided. + fn leading_zeros(self) -> u32; + + /// Returns the number of leading zeros in the binary representation of `self`. + /// + /// On many architectures, this function can perform better than `trailing_zeros()` + /// on the `Self::Zeroable`, as special handling of zero can be avoided. + fn trailing_zeros(self) -> u32; + + /// Returns the number of ones in the binary representation of `self`. + fn count_ones(self) -> NonZero; + + /// Multiplies two non-zero integers together. Checks for overflow and returns `None` + /// if it occurs. As a consequence, the result cannot wrap to zero. + fn checked_mul(self, rhs: Self) -> Option; + + /// Multiplies two non-zero integers together, saturating at the numeric upper and lower + /// bounds instead of overflowing. As a consequence, the result cannot wrap to zero. + fn saturating_mul(self, rhs: Self) -> Self; + + /// Raise non-zero value to an integer power. Checks for overflow and returns `None` on + /// overflow. As a consequence, the result cannot wrap to zero. + fn checked_pow(self, exponent: u32) -> Option; + + /// Raise non-zero value to an integer power. Return NonZero::::MIN or NonZero::::MAX + /// on overflow based on the sign of the exact result. + fn saturating_pow(self, exponent: u32) -> Self; +} \ No newline at end of file diff --git a/src/nonzero/signed_nonzero.rs b/src/nonzero/signed_nonzero.rs new file mode 100644 index 0000000..47f1a03 --- /dev/null +++ b/src/nonzero/signed_nonzero.rs @@ -0,0 +1,86 @@ +use core::convert::Infallible; +use core::num::NonZero; +use core::ops::{Neg, Div, DivAssign, Rem, RemAssign}; + +use crate::{NonZeroPrimitiveInteger, NonZeroPrimitiveUnsigned, PrimitiveSigned, PrimitiveUnsigned}; + +/// A trait for [`NonZero`] of a signed integer. +/// +/// This encapsulates trait implementations, constants, and inherent methods that are common among +/// all of the implementations of `NonZero where T: PrimitiveSigned`. +/// +/// See the corresponding items on the individual types for more documentation and examples. +/// +/// This trait is sealed with a private trait to prevent downstream implementations, so we may +/// continue to expand along with the standard library without worrying about breaking changes for +/// implementors. +/// +/// +pub trait NonZeroPrimitiveSigned: + NonZeroPrimitiveInteger + + TryFrom, Error=Infallible> + + Neg +where Self::Zeroable: PrimitiveSigned, + ::Zeroable: + Div::Zeroable> + + DivAssign + + Rem::Zeroable> + + RemAssign + + PrimitiveUnsigned +{ + /// The unsigned nonzero type with the same size as this. + type Unsigned: NonZeroPrimitiveUnsigned; + + /// Computes the absolute value of `self`. + #[must_use = "this returns the result of the operation, without modifying the original"] + fn abs(self) -> Self; + + /// Checked absolute value. Computes the absolute value of `self`, returning `None` + /// if it overflows. + #[must_use = "this returns the result of the operation, without modifying the original"] + fn checked_abs(self) -> Option; + + /// Saturating absolute value. Computes the absolute value of `self`, saturating to + /// `Self::MAX` when it would overflow. + #[must_use = "this returns the result of the operation, without modifying the original"] + fn saturating_abs(self) -> Self; + + /// Overflowing absolute value. Computes the absolute value of `self`, returning a + /// tuple of the result and a bool indicating if the operation overflowed. + #[must_use = "this returns the result of the operation, without modifying the original"] + fn overflowing_abs(self) -> (Self, bool); + + /// Overflowing absolute value. Computes the absolute value of `self`, wrapping when + /// `self == Self::MIN`. + #[must_use = "this returns the result of the operation, without modifying the original"] + fn wrapping_abs(self) -> Self; + + /// Computes the absolute value of `Self` without any wrapping or panicking. + #[must_use = "this returns the result of the operation, without modifying the original"] + fn unsigned_abs(self) -> Self::Unsigned; + + /// Returns true if `self` is positive and `false` if it is negative. + #[must_use = "this returns the result of the operation, without modifying the original"] + fn is_positive(self) -> bool; + + /// Returns true if `self` is positive and `false` if it is negative. + #[must_use = "this returns the result of the operation, without modifying the original"] + fn is_negative(self) -> bool; + + /// Checked negation. Compute `-self`, returning `None` if it overflows. + #[must_use = "this returns the result of the operation, without modifying the original"] + fn checked_neg(self) -> Option; + + /// Checked negation. Compute `-self`, returning a tuple of the result and a bool + /// indicating if the operation overflowed. + #[must_use = "this returns the result of the operation, without modifying the original"] + fn overflowing_neg(self) -> (Self, bool); + + /// Checked negation. Compute `-self`, saturating to `Self::MAX` when it would overflow. + #[must_use = "this returns the result of the operation, without modifying the original"] + fn saturating_neg(self) -> Self; + + /// Returns the bit pattern of `self` reinterpreted as an unsigned integer of the same size. + #[must_use = "this returns the result of the operation, without modifying the original"] + fn cast_unsigned(self) -> Self::Unsigned; +} \ No newline at end of file diff --git a/src/nonzero/unsigned_nonzero.rs b/src/nonzero/unsigned_nonzero.rs new file mode 100644 index 0000000..9b2cd5b --- /dev/null +++ b/src/nonzero/unsigned_nonzero.rs @@ -0,0 +1,86 @@ +use core::{convert::Infallible, num::NonZero}; + +use crate::{NonZeroPrimitiveInteger, NonZeroPrimitiveSigned, PrimitiveUnsigned, PrimitiveSigned}; + +/// A trait for [`NonZero`] of a unsigned integer. +/// +/// This encapsulates trait implementations, constants, and inherent methods that are common among +/// all of the implementations of `NonZero where T: PrimitiveUnsigned`. +/// +/// See the corresponding items on the individual types for more documentation and examples. +/// +/// This trait is sealed with a private trait to prevent downstream implementations, so we may +/// continue to expand along with the standard library without worrying about breaking changes for +/// implementors. +/// +/// # Examples +/// +/// ``` +/// use core::ops::NonZero; +/// use num_primitive::NonZeroPrimitiveUnsigned; +/// +/// fn gcd(mut u: T, mut v: T) -> u32 { +/// loop { +/// if let Some(u0) = T::new(v.get() % u) { +/// v = u; +/// u = u0; +/// } else { +/// return v; +/// }; +/// } +/// } +/// +/// let nz_3 = NonZero::::new(3u64).unwrap(); +/// let nz_22 = NonZero::new(22).unwrap(); +/// assert_eq!(gcd(nz_3, nz_2).get(), 1); +/// +/// let nz_48 = NonZero::new(48u16).unwrap(); +/// let nz_18 = NonZero::new(18).unwrap(); +/// assert_eq!(gcd::>(nz_48, nz_18).get(), 6); +/// ``` +pub trait NonZeroPrimitiveUnsigned: NonZeroPrimitiveInteger + + TryFrom, Error=Infallible> +where ::Zeroable: PrimitiveSigned, + Self::Zeroable: + core::ops::Div + + core::ops::DivAssign + + core::ops::Rem + + core::ops::RemAssign + + PrimitiveUnsigned +{ + /// The unsigned nonzero type with the same size as this. + type Signed: NonZeroPrimitiveSigned; + + /// Saturating integer addition. Computes `self + rhs` saturating to `Self::MAX` on overflow. + #[must_use = "this returns the result of the operation, without modifying the original"] + fn saturating_add(self, rhs: Self::Zeroable) -> Self; + /// Checked integer addition. Computes `self + rhs`, returning `None` on overflow. + #[must_use = "this returns the result of the operation, without modifying the original"] + fn checked_add(self, rhs: Self::Zeroable) -> Option; + /// Returns the bit pattern of `self` reinterpreted as an signed integer of the same size. + #[must_use = "this returns the result of the operation, without modifying the original"] + fn cast_signed(self) -> Self::Signed; + + /// Integer log base 2. Computes `ilog₂(self)`. + #[must_use = "this returns the result of the operation, without modifying the original"] + fn ilog2(self) -> u32; + /// Integer log base 2. Computes `ilog₁₀(self)`. + #[must_use = "this returns the result of the operation, without modifying the original"] + fn ilog10(self) -> u32; + + /// Integer square root. Computes the square root of `self`, rounding down to an integer. + #[must_use = "this returns the result of the operation, without modifying the original"] + fn isqrt(self) -> Self; + + /// Computes the average of `self` and `rhs`, rounding down to an integer. + #[must_use = "this returns the result of the operation, without modifying the original"] + fn midpoint(self, rhs: Self) -> Self; + + /// Computes the next power of 2 greater than `self`. Returns `None` if it overflows. + #[must_use = "this returns the result of the operation, without modifying the original"] + fn checked_next_power_of_two(self) -> Option; + + /// Checks if `self` is a power of 2. + #[must_use = "this returns the result of the operation, without modifying the original"] + fn is_power_of_two(self) -> bool; +} \ No newline at end of file diff --git a/src/signed.rs b/src/signed.rs index 01af8ca..fcf00f7 100644 --- a/src/signed.rs +++ b/src/signed.rs @@ -52,7 +52,7 @@ use crate::{PrimitiveInteger, PrimitiveIntegerRef, PrimitiveUnsigned}; /// assert_eq!(extended_gcd::(6_700_417, 2_147_483_647), (1, 715_828_096, -2_233_473)); /// ``` pub trait PrimitiveSigned: - PrimitiveInteger + PrimitiveInteger> + core::convert::From + core::convert::TryFrom + core::ops::Neg