From 916e6a351e34f95ba0366f1891a0268b8adf85ab Mon Sep 17 00:00:00 2001 From: Apersoma <95072312+Apersoma@users.noreply.github.com> Date: Sun, 15 Feb 2026 19:49:06 -0500 Subject: [PATCH 1/7] Added --- src/integer.rs | 63 +++++++++++++++++++++++++++++++++++++++++++++++-- src/signed.rs | 5 +++- src/unsigned.rs | 10 +++++++- 3 files changed, 74 insertions(+), 4 deletions(-) diff --git a/src/integer.rs b/src/integer.rs index 4ce0f0e..79b30a7 100644 --- a/src/integer.rs +++ b/src/integer.rs @@ -1,5 +1,10 @@ -use core::num::ParseIntError; - +use core::num::{NonZero, ParseIntError, TryFromIntError}; +use core::error::Error; +use core::convert::Infallible; +use core::cmp::Eq; +use core::fmt::{Display, Debug}; +use core::marker::{Send, Sync, Unpin}; +use core::panic::{RefUnwindSafe, UnwindSafe}; use crate::{PrimitiveError, PrimitiveNumber, PrimitiveNumberRef}; /// Trait for all primitive [integer types], including the supertrait [`PrimitiveNumber`]. @@ -517,6 +522,58 @@ 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::cmp::Eq + + core::cmp::Ord + + core::convert::TryFrom + + core::fmt::Binary + + core::fmt::Debug + + core::fmt::LowerHex + + core::fmt::Octal + + core::fmt::UpperHex + + core::fmt::UpperExp + + core::fmt::LowerExp + + core::hash::Hash + + core::ops::BitOr + + core::ops::BitOr + + core::ops::BitOrAssign + + core::ops::BitOrAssign + + core::str::FromStr + + Into + + Copy + + Sized + + core::marker::Send + + core::marker::Sync + + core::marker::Unpin + + core::panic::RefUnwindSafe + + core::panic::UnwindSafe + // the error is always either TryFromIntError or Infallible and these are their shared traits + + core::convert::TryFrom, Error: Debug+Display+Eq+Copy+From+Error+RefUnwindSafe+Send+Sync+Unpin+UnwindSafe> + + core::convert::TryFrom, Error: Debug+Display+Eq+Copy+From+Error+RefUnwindSafe+Send+Sync+Unpin+UnwindSafe> + + core::convert::TryFrom, Error: Debug+Display+Eq+Copy+From+Error+RefUnwindSafe+Send+Sync+Unpin+UnwindSafe> + + core::convert::TryFrom, Error: Debug+Display+Eq+Copy+From+Error+RefUnwindSafe+Send+Sync+Unpin+UnwindSafe> + + core::convert::TryFrom, Error: Debug+Display+Eq+Copy+From+Error+RefUnwindSafe+Send+Sync+Unpin+UnwindSafe> + + core::convert::TryFrom, Error: Debug+Display+Eq+Copy+From+Error+RefUnwindSafe+Send+Sync+Unpin+UnwindSafe> + + core::convert::TryFrom, Error: Debug+Display+Eq+Copy+From+Error+RefUnwindSafe+Send+Sync+Unpin+UnwindSafe> + + core::convert::TryFrom, Error: Debug+Display+Eq+Copy+From+Error+RefUnwindSafe+Send+Sync+Unpin+UnwindSafe> + + core::convert::TryFrom, Error: Debug+Display+Eq+Copy+From+Error+RefUnwindSafe+Send+Sync+Unpin+UnwindSafe> + + core::convert::TryFrom, Error: Debug+Display+Eq+Copy+From+Error+RefUnwindSafe+Send+Sync+Unpin+UnwindSafe> + + core::convert::TryFrom, Error: Debug+Display+Eq+Copy+From+Error+RefUnwindSafe+Send+Sync+Unpin+UnwindSafe> + + core::convert::TryFrom, Error: Debug+Display+Eq+Copy+From+Error+RefUnwindSafe+Send+Sync+Unpin+UnwindSafe> + + core::convert::TryInto, Error: Debug+Display+Eq+Copy+From+Error+RefUnwindSafe+Send+Sync+Unpin+UnwindSafe> + + core::convert::TryInto, Error: Debug+Display+Eq+Copy+From+Error+RefUnwindSafe+Send+Sync+Unpin+UnwindSafe> + + core::convert::TryInto, Error: Debug+Display+Eq+Copy+From+Error+RefUnwindSafe+Send+Sync+Unpin+UnwindSafe> + + core::convert::TryInto, Error: Debug+Display+Eq+Copy+From+Error+RefUnwindSafe+Send+Sync+Unpin+UnwindSafe> + + core::convert::TryInto, Error: Debug+Display+Eq+Copy+From+Error+RefUnwindSafe+Send+Sync+Unpin+UnwindSafe> + + core::convert::TryInto, Error: Debug+Display+Eq+Copy+From+Error+RefUnwindSafe+Send+Sync+Unpin+UnwindSafe> + + core::convert::TryInto, Error: Debug+Display+Eq+Copy+From+Error+RefUnwindSafe+Send+Sync+Unpin+UnwindSafe> + + core::convert::TryInto, Error: Debug+Display+Eq+Copy+From+Error+RefUnwindSafe+Send+Sync+Unpin+UnwindSafe> + + core::convert::TryInto, Error: Debug+Display+Eq+Copy+From+Error+RefUnwindSafe+Send+Sync+Unpin+UnwindSafe> + + core::convert::TryInto, Error: Debug+Display+Eq+Copy+From+Error+RefUnwindSafe+Send+Sync+Unpin+UnwindSafe> + + core::convert::TryInto, Error: Debug+Display+Eq+Copy+From+Error+RefUnwindSafe+Send+Sync+Unpin+UnwindSafe> + + core::convert::TryInto, Error: Debug+Display+Eq+Copy+From+Error+RefUnwindSafe+Send+Sync+Unpin+UnwindSafe>; } /// Trait for references to primitive integer types ([`PrimitiveInteger`]). @@ -690,6 +747,8 @@ macro_rules! impl_integer { unsafe fn unchecked_shr(self, rhs: u32) -> Self; unsafe fn unchecked_sub(self, rhs: Self) -> Self; } + + type NonZero = core::num::NonZero; } impl PrimitiveIntegerRef<$Integer> for &$Integer {} diff --git a/src/signed.rs b/src/signed.rs index 01af8ca..766a299 100644 --- a/src/signed.rs +++ b/src/signed.rs @@ -51,11 +51,14 @@ use crate::{PrimitiveInteger, PrimitiveIntegerRef, PrimitiveUnsigned}; /// assert_eq!(extended_gcd::(1071, -462), (21, -3, -7)); /// assert_eq!(extended_gcd::(6_700_417, 2_147_483_647), (1, 715_828_096, -2_233_473)); /// ``` +// FIXME: add the following statement to the restrictions but get it to compile +// where for<'a> &'a Self::NonZero: core::ops::Neg pub trait PrimitiveSigned: - PrimitiveInteger + PrimitiveInteger> + core::convert::From + core::convert::TryFrom + core::ops::Neg + { /// The unsigned integer type used by methods like [`abs_diff`][Self::abs_diff] and /// [`checked_add_unsigned`][Self::checked_add_unsigned]. diff --git a/src/unsigned.rs b/src/unsigned.rs index 6bb21b9..356a9bb 100644 --- a/src/unsigned.rs +++ b/src/unsigned.rs @@ -34,7 +34,15 @@ use crate::{PrimitiveInteger, PrimitiveIntegerRef, PrimitiveSigned}; /// assert_eq!(gcd::(1071, 462), 21); /// assert_eq!(gcd::(6_700_417, 2_147_483_647), 1); /// ``` -pub trait PrimitiveUnsigned: PrimitiveInteger + From + TryFrom { +pub trait PrimitiveUnsigned: + PrimitiveInteger + + From + + TryFrom + + core::ops::Div + + core::ops::DivAssign + + core::ops::Rem + + core::ops::RemAssign +{ /// The signed integer type used by methods like /// [`checked_add_signed`][Self::checked_add_signed]. type Signed: PrimitiveSigned; From dcff0f52144685c45af3ec05a72784893d107717 Mon Sep 17 00:00:00 2001 From: Apersoma <95072312+Apersoma@users.noreply.github.com> Date: Sun, 15 Feb 2026 19:56:22 -0500 Subject: [PATCH 2/7] swapped NonZero try restrictions to using PrimitiveError --- src/integer.rs | 50 +++++++++++++++++++++++++------------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/src/integer.rs b/src/integer.rs index 79b30a7..ef2714a 100644 --- a/src/integer.rs +++ b/src/integer.rs @@ -3,7 +3,7 @@ use core::error::Error; use core::convert::Infallible; use core::cmp::Eq; use core::fmt::{Display, Debug}; -use core::marker::{Send, Sync, Unpin}; +use core::marker::Unpin; use core::panic::{RefUnwindSafe, UnwindSafe}; use crate::{PrimitiveError, PrimitiveNumber, PrimitiveNumberRef}; @@ -550,30 +550,30 @@ pub trait PrimitiveInteger: + core::panic::RefUnwindSafe + core::panic::UnwindSafe // the error is always either TryFromIntError or Infallible and these are their shared traits - + core::convert::TryFrom, Error: Debug+Display+Eq+Copy+From+Error+RefUnwindSafe+Send+Sync+Unpin+UnwindSafe> - + core::convert::TryFrom, Error: Debug+Display+Eq+Copy+From+Error+RefUnwindSafe+Send+Sync+Unpin+UnwindSafe> - + core::convert::TryFrom, Error: Debug+Display+Eq+Copy+From+Error+RefUnwindSafe+Send+Sync+Unpin+UnwindSafe> - + core::convert::TryFrom, Error: Debug+Display+Eq+Copy+From+Error+RefUnwindSafe+Send+Sync+Unpin+UnwindSafe> - + core::convert::TryFrom, Error: Debug+Display+Eq+Copy+From+Error+RefUnwindSafe+Send+Sync+Unpin+UnwindSafe> - + core::convert::TryFrom, Error: Debug+Display+Eq+Copy+From+Error+RefUnwindSafe+Send+Sync+Unpin+UnwindSafe> - + core::convert::TryFrom, Error: Debug+Display+Eq+Copy+From+Error+RefUnwindSafe+Send+Sync+Unpin+UnwindSafe> - + core::convert::TryFrom, Error: Debug+Display+Eq+Copy+From+Error+RefUnwindSafe+Send+Sync+Unpin+UnwindSafe> - + core::convert::TryFrom, Error: Debug+Display+Eq+Copy+From+Error+RefUnwindSafe+Send+Sync+Unpin+UnwindSafe> - + core::convert::TryFrom, Error: Debug+Display+Eq+Copy+From+Error+RefUnwindSafe+Send+Sync+Unpin+UnwindSafe> - + core::convert::TryFrom, Error: Debug+Display+Eq+Copy+From+Error+RefUnwindSafe+Send+Sync+Unpin+UnwindSafe> - + core::convert::TryFrom, Error: Debug+Display+Eq+Copy+From+Error+RefUnwindSafe+Send+Sync+Unpin+UnwindSafe> - + core::convert::TryInto, Error: Debug+Display+Eq+Copy+From+Error+RefUnwindSafe+Send+Sync+Unpin+UnwindSafe> - + core::convert::TryInto, Error: Debug+Display+Eq+Copy+From+Error+RefUnwindSafe+Send+Sync+Unpin+UnwindSafe> - + core::convert::TryInto, Error: Debug+Display+Eq+Copy+From+Error+RefUnwindSafe+Send+Sync+Unpin+UnwindSafe> - + core::convert::TryInto, Error: Debug+Display+Eq+Copy+From+Error+RefUnwindSafe+Send+Sync+Unpin+UnwindSafe> - + core::convert::TryInto, Error: Debug+Display+Eq+Copy+From+Error+RefUnwindSafe+Send+Sync+Unpin+UnwindSafe> - + core::convert::TryInto, Error: Debug+Display+Eq+Copy+From+Error+RefUnwindSafe+Send+Sync+Unpin+UnwindSafe> - + core::convert::TryInto, Error: Debug+Display+Eq+Copy+From+Error+RefUnwindSafe+Send+Sync+Unpin+UnwindSafe> - + core::convert::TryInto, Error: Debug+Display+Eq+Copy+From+Error+RefUnwindSafe+Send+Sync+Unpin+UnwindSafe> - + core::convert::TryInto, Error: Debug+Display+Eq+Copy+From+Error+RefUnwindSafe+Send+Sync+Unpin+UnwindSafe> - + core::convert::TryInto, Error: Debug+Display+Eq+Copy+From+Error+RefUnwindSafe+Send+Sync+Unpin+UnwindSafe> - + core::convert::TryInto, Error: Debug+Display+Eq+Copy+From+Error+RefUnwindSafe+Send+Sync+Unpin+UnwindSafe> - + core::convert::TryInto, Error: Debug+Display+Eq+Copy+From+Error+RefUnwindSafe+Send+Sync+Unpin+UnwindSafe>; + + 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>; } /// Trait for references to primitive integer types ([`PrimitiveInteger`]). From 24e8e6cbcb0fe6bfd824ab79b45c159ff644c858 Mon Sep 17 00:00:00 2001 From: Apersoma <95072312+Apersoma@users.noreply.github.com> Date: Sun, 15 Feb 2026 20:00:14 -0500 Subject: [PATCH 3/7] removed extra imports --- src/integer.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/integer.rs b/src/integer.rs index ef2714a..d106e48 100644 --- a/src/integer.rs +++ b/src/integer.rs @@ -1,10 +1,4 @@ use core::num::{NonZero, ParseIntError, TryFromIntError}; -use core::error::Error; -use core::convert::Infallible; -use core::cmp::Eq; -use core::fmt::{Display, Debug}; -use core::marker::Unpin; -use core::panic::{RefUnwindSafe, UnwindSafe}; use crate::{PrimitiveError, PrimitiveNumber, PrimitiveNumberRef}; /// Trait for all primitive [integer types], including the supertrait [`PrimitiveNumber`]. From 118ffafb19a1296a0941bb59113a061750ac0d32 Mon Sep 17 00:00:00 2001 From: Apersoma <95072312+Apersoma@users.noreply.github.com> Date: Mon, 13 Apr 2026 15:48:27 -0400 Subject: [PATCH 4/7] nonzero nearly complete, encountering weird error --- src/integer.rs | 49 +------ src/lib.rs | 2 + src/macros.rs | 8 ++ src/nonzero/mod.rs | 237 ++++++++++++++++++++++++++++++++ src/nonzero/signed_nonzero.rs | 67 +++++++++ src/nonzero/unsigned_nonzero.rs | 84 +++++++++++ 6 files changed, 401 insertions(+), 46 deletions(-) create mode 100644 src/nonzero/mod.rs create mode 100644 src/nonzero/signed_nonzero.rs create mode 100644 src/nonzero/unsigned_nonzero.rs diff --git a/src/integer.rs b/src/integer.rs index d106e48..f157bc7 100644 --- a/src/integer.rs +++ b/src/integer.rs @@ -519,55 +519,12 @@ pub trait PrimitiveInteger: /// The NonZero struct for this integer type NonZero: - core::cmp::Eq - + core::cmp::Ord - + core::convert::TryFrom - + core::fmt::Binary - + core::fmt::Debug - + core::fmt::LowerHex - + core::fmt::Octal - + core::fmt::UpperHex - + core::fmt::UpperExp - + core::fmt::LowerExp - + core::hash::Hash + core::convert::TryFrom + core::ops::BitOr + core::ops::BitOr + core::ops::BitOrAssign + core::ops::BitOrAssign - + core::str::FromStr - + Into - + Copy - + Sized - + core::marker::Send - + core::marker::Sync - + core::marker::Unpin - + core::panic::RefUnwindSafe - + core::panic::UnwindSafe - // the error is always either TryFromIntError or Infallible and these are their shared traits - + 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>; + + Into; } /// Trait for references to primitive integer types ([`PrimitiveInteger`]). @@ -742,7 +699,7 @@ macro_rules! impl_integer { unsafe fn unchecked_sub(self, rhs: Self) -> Self; } - type NonZero = core::num::NonZero; + 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/mod.rs b/src/nonzero/mod.rs new file mode 100644 index 0000000..773085d --- /dev/null +++ b/src/nonzero/mod.rs @@ -0,0 +1,237 @@ +mod signed_nonzero; +mod unsigned_nonzero; + +pub use self::unsigned_nonzero::NonZeroPrimitiveUnsigned; +pub use self::signed_nonzero::NonZeroPrimitiveSigned; + +use crate::{PrimitiveInteger, PrimitiveError, PrimitiveUnsigned}; +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. +/// +/// # Examples +/// +/// ``` +/// use core::ops::NonZero; +/// use num_primitive::NonZeroPrimitiveInteger; +/// +/// fn ceil_log2(x: ) -> u32 { +/// +/// } +/// +/// assert_eq!(gcd::>(48, 18), (2, 12)); +/// ``` +pub trait NonZeroPrimitiveInteger: + 'static + + core::cmp::PartialEq + + core::cmp::PartialOrd + + core::fmt::Debug + + core::fmt::Display + + core::fmt::LowerExp + + core::fmt::UpperExp + + core::marker::Copy + + core::marker::Send + + core::marker::Sync + + core::marker::Unpin + + core::panic::RefUnwindSafe + + core::panic::UnwindSafe + + core::str::FromStr + + core::cmp::Eq + + core::cmp::Ord + + core::hash::Hash + + core::fmt::Binary + + core::fmt::LowerHex + + core::fmt::Octal + + core::fmt::UpperHex + + 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::cmp::Ord + + core::fmt::Binary + + 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; +} + +/* +/// A trait +pub trait NonZeroPrimitiveSigned: NonZeroPrimitiveInteger { + /// 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) -> Self; + + /// 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; + + /// 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; +} +*/ + +macro_rules! impl_nonzero { + (@uint $($t:ty),+) => { + impl_nonzero!($($t, <$t as PrimitiveUnsigned>::Signed),+); + }; + ($($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/signed_nonzero.rs b/src/nonzero/signed_nonzero.rs new file mode 100644 index 0000000..068196d --- /dev/null +++ b/src/nonzero/signed_nonzero.rs @@ -0,0 +1,67 @@ +use crate::{NonZeroPrimitiveInteger, NonZeroPrimitiveUnsigned, PrimitiveSigned}; +use core::num::NonZero; + +/// temp +/// +pub trait NonZeroPrimitiveSigned: + NonZeroPrimitiveInteger + + core::ops::Neg + + Into + + Into> +{ + /// 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) -> Self; + + /// 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; + + /// 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..3979324 --- /dev/null +++ b/src/nonzero/unsigned_nonzero.rs @@ -0,0 +1,84 @@ +use core::num::NonZero; + +use crate::{NonZeroPrimitiveInteger, NonZeroPrimitiveSigned}; + +/// # 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(); +/// let nz_6 = NonZero::new(6).unwrap(); +/// assert_eq!(gcd::>(nz_48, nz_18).get(), 6); +/// ``` +pub trait NonZeroPrimitiveUnsigned: NonZeroPrimitiveInteger + + Into + + Into> +where Self::Zeroable: + core::ops::BitOr + + core::ops::BitOr + + core::ops::BitOrAssign + + core::ops::Div + + core::ops::DivAssign + + core::ops::Rem + + core::ops::RemAssign + // causes an error when uncommented + // + 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) -> 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) -> Self; + /// 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) -> Self::Signed; + /// Integer log base 2. Computes `ilog₁₀(self)`. + #[must_use = "this returns the result of the operation, without modifying the original"] + fn ilog10(self) -> Self::Signed; + + /// 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) -> Self; + + /// 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) -> Self; +} + +// impl NonZeroPrimitiveUnsigned for NonZero { +// type Signed = NonZero; +// } From 40a3bbf42c75c71991bde50b4cac12a8544062fa Mon Sep 17 00:00:00 2001 From: Apersoma <95072312+Apersoma@users.noreply.github.com> Date: Mon, 13 Apr 2026 16:28:25 -0400 Subject: [PATCH 5/7] FIxed error, added docs --- src/nonzero/implement.rs | 69 ++++++++++++++++++++ src/nonzero/mod.rs | 112 +------------------------------- src/nonzero/signed_nonzero.rs | 22 +++++-- src/nonzero/unsigned_nonzero.rs | 49 +++++++------- 4 files changed, 114 insertions(+), 138 deletions(-) create mode 100644 src/nonzero/implement.rs 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 index 773085d..493570f 100644 --- a/src/nonzero/mod.rs +++ b/src/nonzero/mod.rs @@ -1,10 +1,11 @@ mod signed_nonzero; mod unsigned_nonzero; +mod implement; pub use self::unsigned_nonzero::NonZeroPrimitiveUnsigned; pub use self::signed_nonzero::NonZeroPrimitiveSigned; -use crate::{PrimitiveInteger, PrimitiveError, PrimitiveUnsigned}; +use crate::{PrimitiveInteger, PrimitiveError}; use core::num::NonZero; @@ -18,19 +19,6 @@ use core::num::NonZero; /// 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::NonZeroPrimitiveInteger; -/// -/// fn ceil_log2(x: ) -> u32 { -/// -/// } -/// -/// assert_eq!(gcd::>(48, 18), (2, 12)); -/// ``` pub trait NonZeroPrimitiveInteger: 'static + core::cmp::PartialEq @@ -140,98 +128,4 @@ pub trait NonZeroPrimitiveInteger: /// 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; -} - -/* -/// A trait -pub trait NonZeroPrimitiveSigned: NonZeroPrimitiveInteger { - /// 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) -> Self; - - /// 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; - - /// 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; -} -*/ - -macro_rules! impl_nonzero { - (@uint $($t:ty),+) => { - impl_nonzero!($($t, <$t as PrimitiveUnsigned>::Signed),+); - }; - ($($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 +} \ No newline at end of file diff --git a/src/nonzero/signed_nonzero.rs b/src/nonzero/signed_nonzero.rs index 068196d..574d48b 100644 --- a/src/nonzero/signed_nonzero.rs +++ b/src/nonzero/signed_nonzero.rs @@ -1,13 +1,23 @@ +use core::{convert::Infallible, num::NonZero}; + use crate::{NonZeroPrimitiveInteger, NonZeroPrimitiveUnsigned, PrimitiveSigned}; -use core::num::NonZero; -/// temp +/// 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 + core::ops::Neg - + Into - + Into> + + TryFrom, Error=Infallible> { /// The unsigned nonzero type with the same size as this. type Unsigned: NonZeroPrimitiveUnsigned; @@ -50,12 +60,12 @@ pub trait NonZeroPrimitiveSigned: /// 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) -> Self; + 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; + 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"] diff --git a/src/nonzero/unsigned_nonzero.rs b/src/nonzero/unsigned_nonzero.rs index 3979324..2d7103d 100644 --- a/src/nonzero/unsigned_nonzero.rs +++ b/src/nonzero/unsigned_nonzero.rs @@ -1,7 +1,18 @@ -use core::num::NonZero; +use core::{convert::Infallible, num::NonZero}; use crate::{NonZeroPrimitiveInteger, NonZeroPrimitiveSigned}; +/// 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 /// /// ``` @@ -25,21 +36,17 @@ use crate::{NonZeroPrimitiveInteger, NonZeroPrimitiveSigned}; /// /// let nz_48 = NonZero::new(48u16).unwrap(); /// let nz_18 = NonZero::new(18).unwrap(); -/// let nz_6 = NonZero::new(6).unwrap(); /// assert_eq!(gcd::>(nz_48, nz_18).get(), 6); /// ``` pub trait NonZeroPrimitiveUnsigned: NonZeroPrimitiveInteger - + Into - + Into> + + TryFrom, Error=Infallible> where Self::Zeroable: - core::ops::BitOr - + core::ops::BitOr - + core::ops::BitOrAssign - + core::ops::Div - + core::ops::DivAssign - + core::ops::Rem - + core::ops::RemAssign - // causes an error when uncommented + // for some reason causes an error in `signed_nonzero` when uncommented + // don't ask why, I don't know the answer + // core::ops::Div + // + core::ops::DivAssign + // + core::ops::Rem + // + core::ops::RemAssign // + PrimitiveUnsigned { /// The unsigned nonzero type with the same size as this. @@ -47,20 +54,20 @@ where Self::Zeroable: /// 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) -> Self; + 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) -> Self; + 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) -> Self::Signed; + 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) -> Self::Signed; + 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"] @@ -72,13 +79,9 @@ where Self::Zeroable: /// 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) -> Self; + 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) -> Self; -} - -// impl NonZeroPrimitiveUnsigned for NonZero { -// type Signed = NonZero; -// } + fn is_power_of_two(self) -> bool; +} \ No newline at end of file From 8f00d3a8b1aa1806b8ce66d8c5732f76c5aa1601 Mon Sep 17 00:00:00 2001 From: Apersoma <95072312+Apersoma@users.noreply.github.com> Date: Mon, 13 Apr 2026 17:13:45 -0400 Subject: [PATCH 6/7] cleanup + more trait impl --- src/nonzero/mod.rs | 16 +++++++--------- src/nonzero/signed_nonzero.rs | 15 ++++++++++++--- src/nonzero/unsigned_nonzero.rs | 17 ++++++++--------- src/signed.rs | 3 --- 4 files changed, 27 insertions(+), 24 deletions(-) diff --git a/src/nonzero/mod.rs b/src/nonzero/mod.rs index 493570f..5a7dda4 100644 --- a/src/nonzero/mod.rs +++ b/src/nonzero/mod.rs @@ -21,12 +21,19 @@ use core::num::NonZero; /// 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 @@ -34,13 +41,6 @@ pub trait NonZeroPrimitiveInteger: + core::panic::RefUnwindSafe + core::panic::UnwindSafe + core::str::FromStr - + core::cmp::Eq - + core::cmp::Ord - + core::hash::Hash - + core::fmt::Binary - + core::fmt::LowerHex - + core::fmt::Octal - + core::fmt::UpperHex + core::convert::TryFrom, Error: PrimitiveError> + core::convert::TryFrom, Error: PrimitiveError> + core::convert::TryFrom, Error: PrimitiveError> @@ -65,8 +65,6 @@ pub trait NonZeroPrimitiveInteger: + core::convert::TryInto, Error: PrimitiveError> + core::convert::TryInto, Error: PrimitiveError> + core::convert::TryInto, Error: PrimitiveError> - + core::cmp::Ord - + core::fmt::Binary + core::ops::BitOr + core::ops::BitOr + core::ops::BitOrAssign diff --git a/src/nonzero/signed_nonzero.rs b/src/nonzero/signed_nonzero.rs index 574d48b..47f1a03 100644 --- a/src/nonzero/signed_nonzero.rs +++ b/src/nonzero/signed_nonzero.rs @@ -1,6 +1,8 @@ -use core::{convert::Infallible, num::NonZero}; +use core::convert::Infallible; +use core::num::NonZero; +use core::ops::{Neg, Div, DivAssign, Rem, RemAssign}; -use crate::{NonZeroPrimitiveInteger, NonZeroPrimitiveUnsigned, PrimitiveSigned}; +use crate::{NonZeroPrimitiveInteger, NonZeroPrimitiveUnsigned, PrimitiveSigned, PrimitiveUnsigned}; /// A trait for [`NonZero`] of a signed integer. /// @@ -16,8 +18,15 @@ use crate::{NonZeroPrimitiveInteger, NonZeroPrimitiveUnsigned, PrimitiveSigned}; /// pub trait NonZeroPrimitiveSigned: NonZeroPrimitiveInteger - + core::ops::Neg + 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; diff --git a/src/nonzero/unsigned_nonzero.rs b/src/nonzero/unsigned_nonzero.rs index 2d7103d..9b2cd5b 100644 --- a/src/nonzero/unsigned_nonzero.rs +++ b/src/nonzero/unsigned_nonzero.rs @@ -1,6 +1,6 @@ use core::{convert::Infallible, num::NonZero}; -use crate::{NonZeroPrimitiveInteger, NonZeroPrimitiveSigned}; +use crate::{NonZeroPrimitiveInteger, NonZeroPrimitiveSigned, PrimitiveUnsigned, PrimitiveSigned}; /// A trait for [`NonZero`] of a unsigned integer. /// @@ -40,14 +40,13 @@ use crate::{NonZeroPrimitiveInteger, NonZeroPrimitiveSigned}; /// ``` pub trait NonZeroPrimitiveUnsigned: NonZeroPrimitiveInteger + TryFrom, Error=Infallible> -where Self::Zeroable: - // for some reason causes an error in `signed_nonzero` when uncommented - // don't ask why, I don't know the answer - // core::ops::Div - // + core::ops::DivAssign - // + core::ops::Rem - // + core::ops::RemAssign - // + PrimitiveUnsigned +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; diff --git a/src/signed.rs b/src/signed.rs index 766a299..fcf00f7 100644 --- a/src/signed.rs +++ b/src/signed.rs @@ -51,14 +51,11 @@ use crate::{PrimitiveInteger, PrimitiveIntegerRef, PrimitiveUnsigned}; /// assert_eq!(extended_gcd::(1071, -462), (21, -3, -7)); /// assert_eq!(extended_gcd::(6_700_417, 2_147_483_647), (1, 715_828_096, -2_233_473)); /// ``` -// FIXME: add the following statement to the restrictions but get it to compile -// where for<'a> &'a Self::NonZero: core::ops::Neg pub trait PrimitiveSigned: PrimitiveInteger> + core::convert::From + core::convert::TryFrom + core::ops::Neg - { /// The unsigned integer type used by methods like [`abs_diff`][Self::abs_diff] and /// [`checked_add_unsigned`][Self::checked_add_unsigned]. From 90a5cf5dc747e74fbb089d916a083c6130b16af4 Mon Sep 17 00:00:00 2001 From: Apersoma <95072312+Apersoma@users.noreply.github.com> Date: Mon, 13 Apr 2026 17:15:52 -0400 Subject: [PATCH 7/7] more cleanup --- src/unsigned.rs | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/unsigned.rs b/src/unsigned.rs index 356a9bb..6bb21b9 100644 --- a/src/unsigned.rs +++ b/src/unsigned.rs @@ -34,15 +34,7 @@ use crate::{PrimitiveInteger, PrimitiveIntegerRef, PrimitiveSigned}; /// assert_eq!(gcd::(1071, 462), 21); /// assert_eq!(gcd::(6_700_417, 2_147_483_647), 1); /// ``` -pub trait PrimitiveUnsigned: - PrimitiveInteger - + From - + TryFrom - + core::ops::Div - + core::ops::DivAssign - + core::ops::Rem - + core::ops::RemAssign -{ +pub trait PrimitiveUnsigned: PrimitiveInteger + From + TryFrom { /// The signed integer type used by methods like /// [`checked_add_signed`][Self::checked_add_signed]. type Signed: PrimitiveSigned;