relp_num/integer/
sign.rs

1//! # NonZero signs of integers
2use std::cmp::Ordering;
3use std::num::{NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize};
4use std::num::{NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize};
5
6use crate::Negateable;
7use crate::Sign;
8use crate::Signed;
9
10macro_rules! unsigned {
11    ($ty:ty) => {
12        impl Signed for $ty {
13            #[must_use]
14            #[inline]
15            fn signum(&self) -> Sign {
16                if *self == 0 {
17                    Sign::Zero
18                } else {
19                    Sign::Positive
20                }
21            }
22        }
23    }
24}
25
26unsigned!(u8);
27unsigned!(u16);
28unsigned!(u32);
29unsigned!(u64);
30unsigned!(u128);
31unsigned!(usize);
32
33macro_rules! signed {
34    ($ty:ty) => {
35        impl Signed for $ty {
36            #[must_use]
37            #[inline]
38            fn signum(&self) -> Sign {
39                match self.cmp(&0) {
40                    Ordering::Less => Sign::Negative,
41                    Ordering::Equal => Sign::Zero,
42                    Ordering::Greater => Sign::Positive,
43                }
44            }
45        }
46
47        impl Negateable for $ty {
48            #[inline]
49            fn negate(&mut self) {
50                *self = -*self;
51            }
52        }
53    }
54}
55
56signed!(i8);
57signed!(i16);
58signed!(i32);
59signed!(i64);
60signed!(i128);
61signed!(isize);
62
63macro_rules! non_zero_unsigned {
64    ($ty:ty) => {
65        impl Signed for $ty {
66            #[must_use]
67            #[inline]
68            fn signum(&self) -> Sign {
69                Sign::Positive
70            }
71        }
72    }
73}
74
75non_zero_unsigned!(NonZeroU8);
76non_zero_unsigned!(NonZeroU16);
77non_zero_unsigned!(NonZeroU32);
78non_zero_unsigned!(NonZeroU64);
79non_zero_unsigned!(NonZeroU128);
80non_zero_unsigned!(NonZeroUsize);
81
82macro_rules! non_zero_signed {
83    ($ty:ty) => {
84        impl Signed for $ty {
85            #[must_use]
86            #[inline]
87            fn signum(&self) -> Sign {
88                if self.get() > 0 {
89                    Sign::Positive
90                } else {
91                    Sign::Negative
92                }
93            }
94        }
95
96        impl Negateable for $ty {
97            #[inline]
98            fn negate(&mut self) {
99                *self = unsafe {
100                    // SAFETY: Was non zero before, only sign gets flipped.
101                    <$ty>::new_unchecked(-self.get())
102                };
103            }
104        }
105    }
106}
107
108non_zero_signed!(NonZeroI8);
109non_zero_signed!(NonZeroI16);
110non_zero_signed!(NonZeroI32);
111non_zero_signed!(NonZeroI64);
112non_zero_signed!(NonZeroI128);
113non_zero_signed!(NonZeroIsize);
114
115#[cfg(test)]
116mod test {
117    use std::num::{NonZeroI8, NonZeroU8};
118
119    use crate::{NonZeroSign, NonZeroSigned};
120
121    #[test]
122    fn test_zero_sign() {
123        assert_eq!(1_u32.non_zero_signum(), NonZeroSign::Positive);
124        assert_eq!(-1_u32.non_zero_signum(), NonZeroSign::Negative);
125
126        assert_eq!(NonZeroU8::new(1).unwrap().non_zero_signum(), NonZeroSign::Positive);
127        assert_eq!(NonZeroI8::new(1).unwrap().non_zero_signum(), NonZeroSign::Positive);
128        assert_eq!(NonZeroI8::new(-1).unwrap().non_zero_signum(), NonZeroSign::Negative);
129    }
130
131    #[test]
132    #[should_panic]
133    fn test_non_zero_on_zero() {
134        0_u32.non_zero_signum();
135    }
136
137    #[test]
138    #[should_panic]
139    fn test_non_zero_on_zero_signed() {
140        0_i8.non_zero_signum();
141    }
142}