1use std::cmp::Ordering;
5use std::fmt;
6use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
7
8use crate::{Negateable, NonZero, Sign, Signed};
9
10#[derive(Copy, Clone, PartialEq, Eq, Hash, Default)]
24pub enum SignedOne {
25 #[default]
27 PlusOne = 1,
28 MinusOne = -1,
30}
31
32impl num_traits::One for SignedOne {
33 #[inline]
34 fn one() -> Self {
35 Self::PlusOne
36 }
37}
38
39impl Mul<SignedOne> for SignedOne {
40 type Output = Self;
41
42 #[inline]
43 fn mul(self, rhs: SignedOne) -> Self::Output {
44 match (self, rhs) {
45 (Self::PlusOne, Self::PlusOne) => Self::PlusOne,
46 (Self::PlusOne, Self::MinusOne) => Self::MinusOne,
47 (Self::MinusOne, Self::PlusOne) => Self::MinusOne,
48 (Self::MinusOne, Self::MinusOne) => Self::PlusOne,
49 }
50 }
51}
52
53impl Signed for SignedOne {
55 #[inline]
56 fn signum(&self) -> Sign {
57 match self {
58 SignedOne::PlusOne => Sign::Positive,
59 SignedOne::MinusOne => Sign::Negative,
60 }
61 }
62}
63
64impl Negateable for SignedOne {
66 #[inline]
67 fn negate(&mut self) {
68 *self = match self {
69 SignedOne::PlusOne => SignedOne::MinusOne,
70 SignedOne::MinusOne => SignedOne::PlusOne,
71 };
72 }
73}
74
75impl Neg for SignedOne {
76 type Output = Self;
77
78 #[inline]
79 fn neg(mut self) -> Self::Output {
80 Negateable::negate(&mut self);
81 self
82 }
83}
84
85impl NonZero for SignedOne {
86 #[inline]
87 fn is_not_zero(&self) -> bool {
88 true
89 }
90}
91
92impl Ord for SignedOne {
95 #[inline]
96 fn cmp(&self, other: &Self) -> Ordering {
97 (*self as i8).cmp(&(*other as i8))
98 }
99}
100
101impl PartialOrd for SignedOne {
102 #[inline]
103 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
104 Some(self.cmp(other))
105 }
106}
107
108impl fmt::Debug for SignedOne {
111 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
112 fmt::Display::fmt(&self, f)
113 }
114}
115
116impl fmt::Display for SignedOne {
117 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
118 match self {
119 SignedOne::PlusOne => f.write_str("1"),
120 SignedOne::MinusOne => f.write_str("-1"),
121 }
122 }
123}
124
125macro_rules! define_signed_ops {
126 ($primitive:ident) => {
127 impl From<SignedOne> for $primitive {
128 fn from(rhs: SignedOne) -> Self {
129 match rhs {
130 SignedOne::PlusOne => 1,
131 SignedOne::MinusOne => -1,
132 }
133 }
134 }
135
136 impl From<&SignedOne> for $primitive {
137 fn from(rhs: &SignedOne) -> Self {
138 match rhs {
139 SignedOne::PlusOne => 1,
140 SignedOne::MinusOne => -1,
141 }
142 }
143 }
144
145 impl Mul<SignedOne> for $primitive {
146 type Output = Self;
147
148 fn mul(mut self, rhs: SignedOne) -> Self::Output {
149 MulAssign::mul_assign(&mut self, rhs);
150 self
151 }
152 }
153
154 impl Mul<&SignedOne> for $primitive {
155 type Output = Self;
156
157 fn mul(mut self, rhs: &SignedOne) -> Self::Output {
158 MulAssign::mul_assign(&mut self, rhs);
159 self
160 }
161 }
162
163 impl Mul<&SignedOne> for &$primitive {
164 type Output = $primitive;
165
166 fn mul(self, rhs: &SignedOne) -> Self::Output {
167 match rhs {
168 SignedOne::PlusOne => *self,
169 SignedOne::MinusOne => -self,
170 }
171 }
172 }
173
174 impl MulAssign<&SignedOne> for $primitive {
175 fn mul_assign(&mut self, rhs: &SignedOne) {
176 MulAssign::mul_assign(self, *rhs);
177 }
178 }
179
180 impl MulAssign<SignedOne> for $primitive {
181 fn mul_assign(&mut self, rhs: SignedOne) {
182 match rhs {
183 SignedOne::PlusOne => {},
184 SignedOne::MinusOne => *self = -*self,
185 }
186 }
187 }
188
189 impl Div<SignedOne> for $primitive {
190 type Output = Self;
191
192 fn div(mut self, rhs: SignedOne) -> Self::Output {
193 MulAssign::mul_assign(&mut self, rhs);
194 self
195 }
196 }
197
198 impl Div<&SignedOne> for $primitive {
199 type Output = Self;
200
201 fn div(mut self, rhs: &SignedOne) -> Self::Output {
202 MulAssign::mul_assign(&mut self, rhs);
203 self
204 }
205 }
206
207 impl DivAssign<&SignedOne> for $primitive {
208 fn div_assign(&mut self, rhs: &SignedOne) {
209 DivAssign::div_assign(self, *rhs);
210 }
211 }
212
213 impl DivAssign<SignedOne> for $primitive {
214 fn div_assign(&mut self, rhs: SignedOne) {
215 MulAssign::mul_assign(self, rhs);
216 }
217 }
218 }
219}
220
221macro_rules! define_unsigned_ops {
222 ($primitive:ident) => {
223 impl Add<SignedOne> for $primitive {
224 type Output = Self;
225
226 fn add(mut self, rhs: SignedOne) -> Self::Output {
227 AddAssign::add_assign(&mut self, rhs);
228 self
229 }
230 }
231
232 impl Add<&SignedOne> for $primitive {
233 type Output = Self;
234
235 fn add(mut self, rhs: &SignedOne) -> Self::Output {
236 AddAssign::add_assign(&mut self, rhs);
237 self
238 }
239 }
240
241 impl AddAssign<&SignedOne> for $primitive {
242 fn add_assign(&mut self, rhs: &SignedOne) {
243 AddAssign::add_assign(self, *rhs);
244 }
245 }
246
247 impl AddAssign<SignedOne> for $primitive {
248 fn add_assign(&mut self, rhs: SignedOne) {
249 match rhs {
250 SignedOne::PlusOne => *self += 1,
251 SignedOne::MinusOne => *self -= 1,
252 }
253 }
254 }
255
256 impl Sub<SignedOne> for $primitive {
257 type Output = Self;
258
259 fn sub(mut self, rhs: SignedOne) -> Self::Output {
260 SubAssign::sub_assign(&mut self, rhs);
261 self
262 }
263 }
264
265 impl Sub<&SignedOne> for $primitive {
266 type Output = Self;
267
268 fn sub(mut self, rhs: &SignedOne) -> Self::Output {
269 SubAssign::sub_assign(&mut self, rhs);
270 self
271 }
272 }
273
274 impl SubAssign<&SignedOne> for $primitive {
275 fn sub_assign(&mut self, rhs: &SignedOne) {
276 SubAssign::sub_assign(self, *rhs);
277 }
278 }
279
280 impl SubAssign<SignedOne> for $primitive {
281 fn sub_assign(&mut self, rhs: SignedOne) {
282 match rhs {
283 SignedOne::PlusOne => *self -= 1,
284 SignedOne::MinusOne => *self += 1,
285 }
286 }
287 }
288 }
289}
290
291define_signed_ops!(i8);
292define_signed_ops!(i16);
293define_signed_ops!(i32);
294define_signed_ops!(i64);
295define_signed_ops!(i128);
296define_unsigned_ops!(i8);
297define_unsigned_ops!(i16);
298define_unsigned_ops!(i32);
299define_unsigned_ops!(i64);
300define_unsigned_ops!(i128);
301
302define_unsigned_ops!(u8);
303define_unsigned_ops!(u16);
304define_unsigned_ops!(u32);
305define_unsigned_ops!(u64);
306define_unsigned_ops!(u128);
307
308#[cfg(test)]
309mod test {
310 use std::cmp::Ordering;
311
312 use crate::{Negateable, NonZero, Sign, Signed};
313 use crate::fixed::SignedOne;
314
315 #[test]
316 fn test_signed_one() {
317 assert_eq!(<SignedOne as num_traits::One>::one(), SignedOne::PlusOne);
318 assert_eq!(SignedOne::PlusOne * SignedOne::PlusOne, SignedOne::PlusOne);
319 assert_eq!(SignedOne::PlusOne * SignedOne::MinusOne, SignedOne::MinusOne);
320 assert_eq!(SignedOne::MinusOne * SignedOne::MinusOne, SignedOne::PlusOne);
321 }
322
323 #[test]
324 fn test_default() {
325 assert_eq!(SignedOne::default(), SignedOne::PlusOne);
326 }
327
328 #[test]
329 fn test_signum() {
330 assert_eq!(SignedOne::PlusOne.signum(), Sign::Positive);
331 assert_eq!(SignedOne::MinusOne.signum(), Sign::Negative);
332 assert!(SignedOne::PlusOne.is_positive());
333 assert!(!SignedOne::MinusOne.is_positive());
334 assert!(SignedOne::MinusOne.is_negative());
335 assert!(!SignedOne::PlusOne.is_negative());
336 }
337
338 #[test]
339 fn test_non_zero() {
340 assert!(SignedOne::PlusOne.is_not_zero());
341 assert!(SignedOne::MinusOne.is_not_zero());
342 }
343
344 #[test]
345 fn test_negate() {
346 assert_eq!(-SignedOne::PlusOne, SignedOne::MinusOne);
347 assert_eq!(-SignedOne::MinusOne, SignedOne::PlusOne);
348
349 let mut value = SignedOne::PlusOne;
350 value.negate();
351 assert_eq!(value, SignedOne::MinusOne);
352 value.negate();
353 assert_eq!(value, SignedOne::PlusOne);
354 }
355
356 #[test]
358 fn test_ord() {
359 assert_eq!(SignedOne::MinusOne.cmp(&SignedOne::PlusOne), Ordering::Less);
360 assert_eq!(SignedOne::PlusOne.cmp(&SignedOne::MinusOne), Ordering::Greater);
361 assert!(SignedOne::MinusOne < SignedOne::PlusOne);
362
363 for a in [SignedOne::MinusOne, SignedOne::PlusOne] {
364 assert_eq!(a.cmp(&a), Ordering::Equal);
365 for b in [SignedOne::MinusOne, SignedOne::PlusOne] {
366 assert_eq!(a.partial_cmp(&b), Some(a.cmp(&b)));
367 assert_eq!(a.cmp(&b), b.cmp(&a).reverse());
368 assert_eq!(a == b, a.cmp(&b) == Ordering::Equal);
369 }
370 }
371 }
372
373 #[test]
374 fn test_display() {
375 assert_eq!(SignedOne::PlusOne.to_string(), "1");
376 assert_eq!(SignedOne::MinusOne.to_string(), "-1");
377 assert_eq!(format!("{:?}", SignedOne::PlusOne), "1");
378 assert_eq!(format!("{:?}", SignedOne::MinusOne), "-1");
379 }
380
381 #[test]
382 fn test_integer() {
383 assert_eq!(1 + SignedOne::PlusOne, 2);
384 assert_eq!(-1 + SignedOne::PlusOne, 0);
385 assert_eq!(1 + SignedOne::PlusOne, 2);
386 assert_eq!(-1 + SignedOne::PlusOne, 0);
387 assert_eq!(33 / SignedOne::PlusOne, 33);
388 assert_eq!(-33 / &SignedOne::PlusOne, -33);
389 assert_eq!(894 * SignedOne::PlusOne, 894);
390 assert_eq!(-894 * &SignedOne::PlusOne, -894);
391
392 assert_eq!(1 + SignedOne::MinusOne, 0);
393 assert_eq!(-1 + SignedOne::MinusOne, -2);
394 assert_eq!(1 - SignedOne::MinusOne, 2);
395 assert_eq!(-1 - SignedOne::MinusOne, 0);
396 assert_eq!(33 / SignedOne::MinusOne, -33);
397 assert_eq!(-33 / &SignedOne::MinusOne, 33);
398 assert_eq!(894 * SignedOne::MinusOne, -894);
399 assert_eq!(-894 * &SignedOne::MinusOne, 894);
400 }
401}