relp_num/non_zero/
sign.rs1use std::cmp::Ordering;
5use std::ops::{Mul, MulAssign, Neg, Not};
6
7use crate::{Negateable, Signed};
8use crate::non_zero::NonZero;
9use crate::sign::Sign;
10
11pub trait NonZeroSigned: NonZero + Signed {
13 fn non_zero_signum(&self) -> NonZeroSign;
15 #[inline]
17 fn non_zero_is_positive(&self) -> bool {
18 self.non_zero_signum() == NonZeroSign::Positive
19 }
20 #[inline]
22 fn non_zero_is_negative(&self) -> bool {
23 self.non_zero_signum() == NonZeroSign::Negative
24 }
25}
26
27#[derive(Eq, PartialEq, Copy, Clone, Debug)]
32pub enum NonZeroSign {
33 Positive = 1,
35 Negative = -1,
37}
38
39impl<T: NonZero + Signed> NonZeroSigned for T {
40 #[inline]
41 fn non_zero_signum(&self) -> NonZeroSign {
42 match self.signum() {
43 Sign::Positive => NonZeroSign::Positive,
44 Sign::Zero => panic!("attempt to convert a zero sign into a non zero sign"),
45 Sign::Negative => NonZeroSign::Negative,
46 }
47 }
48}
49
50impl Signed for NonZeroSign {
51 fn signum(&self) -> Sign {
52 match self {
53 NonZeroSign::Positive => Sign::Positive,
54 NonZeroSign::Negative => Sign::Negative,
55 }
56 }
57}
58
59impl NonZero for NonZeroSign {
60 fn is_not_zero(&self) -> bool {
61 true
62 }
63}
64
65impl Negateable for NonZeroSign {
66 fn negate(&mut self) {
67 *self = match self {
68 NonZeroSign::Positive => NonZeroSign::Negative,
69 NonZeroSign::Negative => NonZeroSign::Positive,
70 }
71 }
72}
73
74impl Not for NonZeroSign {
75 type Output = Self;
76
77 fn not(mut self) -> Self::Output {
78 Negateable::negate(&mut self);
79 self
80 }
81}
82
83impl Neg for NonZeroSign {
84 type Output = Self;
85
86 fn neg(mut self) -> Self::Output {
87 Negateable::negate(&mut self);
88 self
89 }
90}
91
92impl From<Sign> for NonZeroSign {
93 fn from(other: Sign) -> Self {
94 debug_assert!(other.is_not_zero());
95
96 match other {
97 Sign::Positive => NonZeroSign::Positive,
98 Sign::Zero => panic!("attempt to convert a zero sign into a non zero sign"),
99 Sign::Negative => NonZeroSign::Negative,
100 }
101 }
102}
103
104impl PartialOrd for NonZeroSign {
105 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
106 match (self, other) {
107 (NonZeroSign::Positive, NonZeroSign::Positive) => None,
108 (NonZeroSign::Positive, NonZeroSign::Negative) => Some(Ordering::Greater),
109 (NonZeroSign::Negative, NonZeroSign::Positive) => Some(Ordering::Less),
110 (NonZeroSign::Negative, NonZeroSign::Negative) => None,
111 }
112 }
113}
114
115impl Mul for NonZeroSign {
116 type Output = Self;
117
118 fn mul(mut self, rhs: Self) -> Self::Output {
119 MulAssign::mul_assign(&mut self, rhs);
120 self
121 }
122}
123
124impl MulAssign for NonZeroSign {
125 fn mul_assign(&mut self, rhs: Self) {
126 *self = match (*self, rhs) {
127 (NonZeroSign::Positive, NonZeroSign::Positive) => NonZeroSign::Positive,
128 (NonZeroSign::Positive, NonZeroSign::Negative) => NonZeroSign::Negative,
129 (NonZeroSign::Negative, NonZeroSign::Positive) => NonZeroSign::Negative,
130 (NonZeroSign::Negative, NonZeroSign::Negative) => NonZeroSign::Positive,
131 }
132 }
133}
134
135#[cfg(test)]
136mod test {
137 use std::cmp::Ordering;
138
139 use crate::{NonZeroSign, NonZeroSigned, Sign};
140 use crate::{R64, RB};
141
142 #[test]
143 fn test_cmp() {
144 assert!(NonZeroSign::Positive > NonZeroSign::Negative);
145 assert_eq!(NonZeroSign::Positive.partial_cmp(&NonZeroSign::Positive), None);
146 assert_eq!(NonZeroSign::Negative.partial_cmp(&NonZeroSign::Negative), None);
147 assert_eq!(NonZeroSign::Negative.partial_cmp(&NonZeroSign::Positive), Some(Ordering::Less));
148 }
149
150 #[test]
151 fn test_numbers() {
152 use crate::Signed;
153 assert_eq!(Signed::signum(&RB!(1)), Sign::Positive);
154 assert_eq!(Signed::signum(&RB!(-1)), Sign::Negative);
155 assert!(RB!(1).is_positive());
156 assert!(RB!(-1).is_negative());
157 }
158
159 #[test]
160 fn test_numbers_non_zero() {
161 assert_eq!(1.non_zero_signum(), NonZeroSign::Positive);
162 assert_eq!((-1).non_zero_signum(), NonZeroSign::Negative);
163
164 assert_eq!(RB!(-1).non_zero_signum() * RB!(-1).non_zero_signum(), NonZeroSign::Positive);
165 assert_eq!(RB!(1).non_zero_signum() * RB!(1).non_zero_signum(), NonZeroSign::Positive);
166
167 assert_eq!(RB!(-1).non_zero_signum() * RB!(1).non_zero_signum(), NonZeroSign::Negative);
168
169 assert_eq!(R64!(1).non_zero_signum(), NonZeroSign::Positive);
170 assert_eq!(R64!(-1).non_zero_signum(), NonZeroSign::Negative);
171
172 assert_eq!(R64!(-1).non_zero_signum() * R64!(-1).non_zero_signum(), NonZeroSign::Positive);
173 assert_eq!(R64!(1).non_zero_signum() * R64!(1).non_zero_signum(), NonZeroSign::Positive);
174 assert_eq!(R64!(-1).non_zero_signum() * R64!(1).non_zero_signum(), NonZeroSign::Negative);
175 }
176
177 #[test]
178 #[should_panic]
179 fn test_zero() {
180 RB!(0).non_zero_signum();
181 }
182}