Skip to main content

num_primitive/
signed.rs

1use core::convert::Infallible;
2use core::num::NonZero;
3
4use crate::{
5    NonZeroPrimitiveInteger, NonZeroPrimitiveUnsigned, PrimitiveInteger, PrimitiveIntegerRef,
6    PrimitiveUnsigned,
7};
8
9/// Trait for all primitive [signed integer types], including the supertraits [`PrimitiveInteger`]
10/// and [`PrimitiveNumber`][crate::PrimitiveNumber].
11///
12/// This encapsulates trait implementations and inherent methods that are common among all of the
13/// primitive signed integer types: [`i8`], [`i16`], [`i32`], [`i64`], [`i128`], and [`isize`].
14///
15/// See the corresponding items on the individual types for more documentation and examples.
16///
17/// This trait is sealed with a private trait to prevent downstream implementations, so we may
18/// continue to expand along with the standard library without worrying about breaking changes for
19/// implementors.
20///
21/// [signed integer types]: https://doc.rust-lang.org/reference/types/numeric.html#r-type.numeric.int.signed
22///
23/// # Examples
24///
25/// ```
26/// use num_primitive::PrimitiveSigned;
27///
28/// // GCD with Bézout coefficients (extended Euclidean algorithm)
29/// fn extended_gcd<T: PrimitiveSigned>(a: T, b: T) -> (T, T, T) {
30///     let zero = T::from(0i8);
31///     let one = T::from(1i8);
32///
33///     let (mut old_r, mut r) = (a, b);
34///     let (mut old_s, mut s) = (one, zero);
35///     let (mut old_t, mut t) = (zero, one);
36///
37///     while r != zero {
38///         let quotient = old_r.div_euclid(r);
39///         (old_r, r) = (r, old_r - quotient * r);
40///         (old_s, s) = (s, old_s - quotient * s);
41///         (old_t, t) = (t, old_t - quotient * t);
42///     }
43///
44///     let (gcd, x, y) = if old_r.is_negative() {
45///         (-old_r, -old_s, -old_t)
46///     } else {
47///         (old_r, old_s, old_t)
48///     };
49///     assert_eq!(gcd, a * x + b * y);
50///     (gcd, x, y)
51/// }
52///
53/// assert_eq!(extended_gcd::<i8>(0, -42), (42, 0, -1));
54/// assert_eq!(extended_gcd::<i8>(48, 18), (6, -1, 3));
55/// assert_eq!(extended_gcd::<i16>(1071, -462), (21, -3, -7));
56/// assert_eq!(extended_gcd::<i64>(6_700_417, 2_147_483_647), (1, 715_828_096, -2_233_473));
57/// ```
58pub trait PrimitiveSigned:
59    PrimitiveInteger
60    + core::convert::From<i8>
61    + core::convert::TryFrom<i8, Error = Infallible>
62    + core::ops::Neg<Output = Self>
63{
64    /// The unsigned integer type used by methods like [`abs_diff`][Self::abs_diff] and
65    /// [`checked_add_unsigned`][Self::checked_add_unsigned].
66    type Unsigned: PrimitiveUnsigned;
67
68    /// Computes the absolute value of `self`.
69    fn abs(self) -> Self;
70
71    /// Computes the absolute difference between `self` and `other`.
72    fn abs_diff(self, other: Self) -> Self::Unsigned;
73
74    /// Returns the bit pattern of `self` reinterpreted as an unsigned integer of the same size.
75    fn cast_unsigned(self) -> Self::Unsigned;
76
77    /// Checked absolute value. Computes `self.abs()`, returning `None` if `self == MIN`.
78    fn checked_abs(self) -> Option<Self>;
79
80    /// Checked addition with an unsigned integer. Computes `self + rhs`, returning `None` if
81    /// overflow occurred.
82    fn checked_add_unsigned(self, rhs: Self::Unsigned) -> Option<Self>;
83
84    /// Returns the square root of the number, rounded down. Returns `None` if `self` is negative.
85    fn checked_isqrt(self) -> Option<Self>;
86
87    /// Checked subtraction with an unsigned integer. Computes `self - rhs`, returning `None` if
88    /// overflow occurred.
89    fn checked_sub_unsigned(self, rhs: Self::Unsigned) -> Option<Self>;
90
91    /// Returns true if `self` is negative and false if the number is zero or positive.
92    fn is_negative(self) -> bool;
93
94    /// Returns true if `self` is positive and false if the number is zero or negative.
95    fn is_positive(self) -> bool;
96
97    /// Computes the absolute value of `self`. Returns a tuple of the absolute version of `self`
98    /// along with a boolean indicating whether an overflow happened.
99    fn overflowing_abs(self) -> (Self, bool);
100
101    /// Calculates `self + rhs` with an unsigned `rhs`. Returns a tuple of the addition along with
102    /// a boolean indicating whether an arithmetic overflow would occur.
103    fn overflowing_add_unsigned(self, rhs: Self::Unsigned) -> (Self, bool);
104
105    /// Calculates `self - rhs` with an unsigned `rhs`. Returns a tuple of the subtraction along
106    /// with a boolean indicating whether an arithmetic overflow would occur.
107    fn overflowing_sub_unsigned(self, rhs: Self::Unsigned) -> (Self, bool);
108
109    /// Saturating absolute value. Computes `self.abs()`, returning `MAX` if `self == MIN` instead
110    /// of overflowing.
111    fn saturating_abs(self) -> Self;
112
113    /// Saturating addition with an unsigned integer. Computes `self + rhs`, saturating at the
114    /// numeric bounds instead of overflowing.
115    fn saturating_add_unsigned(self, rhs: Self::Unsigned) -> Self;
116
117    /// Saturating integer negation. Computes `-self`, returning `MAX` if `self == MIN` instead of
118    /// overflowing.
119    fn saturating_neg(self) -> Self;
120
121    /// Saturating subtraction with an unsigned integer. Computes `self - rhs`, saturating at the
122    /// numeric bounds instead of overflowing.
123    fn saturating_sub_unsigned(self, rhs: Self::Unsigned) -> Self;
124
125    /// Returns a number representing sign of `self`.
126    fn signum(self) -> Self;
127
128    /// Strict absolute value. Computes `self.abs()`, panicking if `self == MIN`.
129    fn strict_abs(self) -> Self;
130
131    /// Strict addition with an unsigned integer. Computes `self + rhs`,
132    /// panicking if overflow occurred.
133    fn strict_add_unsigned(self, rhs: Self::Unsigned) -> Self;
134
135    /// Strict subtraction with an unsigned integer. Computes `self - rhs`,
136    /// panicking if overflow occurred.
137    fn strict_sub_unsigned(self, rhs: Self::Unsigned) -> Self;
138
139    /// Computes the absolute value of `self` without any wrapping or panicking.
140    fn unsigned_abs(self) -> Self::Unsigned;
141
142    /// Wrapping (modular) absolute value. Computes `self.abs()`, wrapping around at the boundary
143    /// of the type.
144    fn wrapping_abs(self) -> Self;
145
146    /// Wrapping (modular) addition with an unsigned integer. Computes `self + rhs`, wrapping
147    /// around at the boundary of the type.
148    fn wrapping_add_unsigned(self, rhs: Self::Unsigned) -> Self;
149
150    /// Wrapping (modular) subtraction with an unsigned integer. Computes `self - rhs`, wrapping
151    /// around at the boundary of the type.
152    fn wrapping_sub_unsigned(self, rhs: Self::Unsigned) -> Self;
153
154    /// Unchecked negation. Computes `-self`, assuming overflow cannot occur.
155    ///
156    /// # Safety
157    ///
158    /// This results in undefined behavior when `self == Self::MIN`, i.e. when
159    /// [`checked_neg`][PrimitiveInteger::checked_neg] would return `None`.
160    unsafe fn unchecked_neg(self) -> Self;
161}
162
163/// Trait for references to primitive signed integer types ([`PrimitiveSigned`]).
164///
165/// This enables traits like the standard operators in generic code,
166/// e.g. `where &T: PrimitiveSignedRef<T>`.
167pub trait PrimitiveSignedRef<T>: PrimitiveIntegerRef<T> + core::ops::Neg<Output = T> {}
168
169/// Trait for [`NonZero`] primitive signed integers, including the supertrait
170/// [`NonZeroPrimitiveInteger`].
171///
172/// This encapsulates trait implementations and inherent methods that are common among all of the
173/// implementations of `NonZero<T>`, where `T` is a [`PrimitiveSigned`].
174///
175/// See the corresponding items on the individual types for more documentation and examples.
176///
177/// This trait is sealed with a private trait to prevent downstream implementations, so we may
178/// continue to expand along with the standard library without worrying about breaking changes for
179/// implementors.
180///
181/// # Examples
182///
183/// ```
184/// use num_primitive::NonZeroPrimitiveSigned;
185/// use core::num::NonZero;
186///
187/// fn sign_and_magnitude<T: NonZeroPrimitiveSigned>(n: T) -> (bool, T::NonZeroUnsigned) {
188///     (n.is_negative(), n.unsigned_abs())
189/// }
190///
191/// let n = NonZero::new(-42i16).unwrap();
192/// assert_eq!(sign_and_magnitude(n), (true, NonZero::new(42u16).unwrap()));
193/// ```
194pub trait NonZeroPrimitiveSigned:
195    NonZeroPrimitiveInteger<Integer: PrimitiveSigned>
196    + core::convert::From<NonZero<i8>>
197    + core::ops::Neg<Output = Self>
198{
199    /// The unsigned non-zero integer type used by methods like
200    /// [`cast_unsigned`][Self::cast_unsigned].
201    ///
202    /// For `core::num::NonZero<T>`, this is `NonZero<T::Unsigned>`.
203    type NonZeroUnsigned: NonZeroPrimitiveUnsigned;
204
205    /// Computes the absolute value of self.
206    fn abs(self) -> Self;
207
208    /// Returns the bit pattern of `self` reinterpreted as an unsigned integer of the same size.
209    fn cast_unsigned(self) -> Self::NonZeroUnsigned;
210
211    /// Checked absolute value. Checks for overflow and returns [`None`] if `self == Self::MIN`.
212    fn checked_abs(self) -> Option<Self>;
213
214    /// Checked negation. Computes `-self`, returning `None` if `self == Self::MIN`.
215    fn checked_neg(self) -> Option<Self>;
216
217    /// Returns `true` if `self` is positive and `false` if the number is negative.
218    fn is_positive(self) -> bool;
219
220    /// Returns `true` if `self` is negative and `false` if the number is positive.
221    fn is_negative(self) -> bool;
222
223    /// Computes the absolute value of self, with overflow information.
224    fn overflowing_abs(self) -> (Self, bool);
225
226    /// Negates self, overflowing if this is equal to the minimum value.
227    fn overflowing_neg(self) -> (Self, bool);
228
229    /// Saturating absolute value.
230    fn saturating_abs(self) -> Self;
231
232    /// Saturating negation. Computes `-self`, returning `Self::MAX`
233    /// if `self == Self::MIN` instead of overflowing.
234    fn saturating_neg(self) -> Self;
235
236    /// Computes the absolute value of self without any wrapping or panicking.
237    fn unsigned_abs(self) -> Self::NonZeroUnsigned;
238
239    /// Wrapping absolute value.
240    fn wrapping_abs(self) -> Self;
241
242    /// Wrapping (modular) negation. Computes `-self`, wrapping around at the boundary
243    /// of the type.
244    fn wrapping_neg(self) -> Self;
245}
246
247// TODO: consider a NonZero*Ref hierarchy, including Neg here.
248// pub trait NonZeroPrimitiveSignedRef<NZ>: core::ops::Neg<Output = NZ> {}
249
250macro_rules! impl_signed {
251    ($Signed:ident, $Unsigned:ty) => {
252        impl PrimitiveSigned for $Signed {
253            type Unsigned = $Unsigned;
254
255            forward! {
256                fn abs(self) -> Self;
257                fn abs_diff(self, other: Self) -> Self::Unsigned;
258                fn cast_unsigned(self) -> Self::Unsigned;
259                fn checked_abs(self) -> Option<Self>;
260                fn checked_add_unsigned(self, rhs: Self::Unsigned) -> Option<Self>;
261                fn checked_isqrt(self) -> Option<Self>;
262                fn checked_sub_unsigned(self, rhs: Self::Unsigned) -> Option<Self>;
263                fn is_negative(self) -> bool;
264                fn is_positive(self) -> bool;
265                fn overflowing_abs(self) -> (Self, bool);
266                fn overflowing_add_unsigned(self, rhs: Self::Unsigned) -> (Self, bool);
267                fn overflowing_sub_unsigned(self, rhs: Self::Unsigned) -> (Self, bool);
268                fn saturating_abs(self) -> Self;
269                fn saturating_add_unsigned(self, rhs: Self::Unsigned) -> Self;
270                fn saturating_neg(self) -> Self;
271                fn saturating_sub_unsigned(self, rhs: Self::Unsigned) -> Self;
272                fn signum(self) -> Self;
273                fn strict_abs(self) -> Self;
274                fn strict_add_unsigned(self, rhs: Self::Unsigned) -> Self;
275                fn strict_sub_unsigned(self, rhs: Self::Unsigned) -> Self;
276                fn unsigned_abs(self) -> Self::Unsigned;
277                fn wrapping_abs(self) -> Self;
278                fn wrapping_add_unsigned(self, rhs: Self::Unsigned) -> Self;
279                fn wrapping_sub_unsigned(self, rhs: Self::Unsigned) -> Self;
280            }
281            forward! {
282                unsafe fn unchecked_neg(self) -> Self;
283            }
284        }
285
286        impl PrimitiveSignedRef<$Signed> for &$Signed {}
287
288        impl NonZeroPrimitiveSigned for NonZero<$Signed> {
289            type NonZeroUnsigned = NonZero<$Unsigned>;
290
291            forward! {
292                fn abs(self) -> Self;
293                fn cast_unsigned(self) -> Self::NonZeroUnsigned;
294                fn checked_abs(self) -> Option<Self>;
295                fn checked_neg(self) -> Option<Self>;
296                fn is_negative(self) -> bool;
297                fn is_positive(self) -> bool;
298                fn overflowing_abs(self) -> (Self, bool);
299                fn overflowing_neg(self) -> (Self, bool);
300                fn saturating_abs(self) -> Self;
301                fn saturating_neg(self) -> Self;
302                fn unsigned_abs(self) -> Self::NonZeroUnsigned;
303                fn wrapping_abs(self) -> Self;
304                fn wrapping_neg(self) -> Self;
305            }
306        }
307    };
308}
309
310impl_signed!(i8, u8);
311impl_signed!(i16, u16);
312impl_signed!(i32, u32);
313impl_signed!(i64, u64);
314impl_signed!(i128, u128);
315impl_signed!(isize, usize);