Skip to main content

relp_num/
signed_one.rs

1//! # Signed One
2use std::fmt;
3use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign};
4
5use crate::NonZero;
6
7/// A type representing the value `1` or `-1`.
8///
9/// Can be used when a type from the `MatrixProvider` can only have the value `1` or `-1`, such as
10/// with some network problems, where an arc is either incoming or outgoing.
11#[derive(Eq, PartialEq, Copy, Clone, Default)]
12pub enum SignedOne {
13    /// +1.
14    #[default]
15    PlusOne,
16    /// -1.
17    MinusOne,
18}
19
20impl num_traits::One for SignedOne {
21    #[inline]
22    fn one() -> Self {
23        Self::PlusOne
24    }
25}
26
27impl Mul<SignedOne> for SignedOne {
28    type Output = Self;
29
30    #[inline]
31    fn mul(self, rhs: SignedOne) -> Self::Output {
32        match (self, rhs) {
33            (Self::PlusOne, Self::PlusOne) => Self::PlusOne,
34            (Self::PlusOne, Self::MinusOne) => Self::MinusOne,
35            (Self::MinusOne, Self::PlusOne) => Self::MinusOne,
36            (Self::MinusOne, Self::MinusOne) => Self::PlusOne,
37        }
38    }
39}
40
41impl NonZero for SignedOne {
42    #[inline]
43    fn is_not_zero(&self) -> bool {
44        true
45    }
46}
47
48impl fmt::Debug for SignedOne {
49    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
50        fmt::Display::fmt(&self, f)
51    }
52}
53
54impl fmt::Display for SignedOne {
55    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
56        match self {
57            SignedOne::PlusOne => f.write_str("1"),
58            SignedOne::MinusOne => f.write_str("-1"),
59        }
60    }
61}
62
63macro_rules! define_signed_ops {
64    ($primitive:ident) => {
65        impl From<SignedOne> for $primitive {
66            fn from(rhs: SignedOne) -> Self {
67                match rhs {
68                    SignedOne::PlusOne => 1,
69                    SignedOne::MinusOne => -1,
70                }
71            }
72        }
73
74        impl From<&SignedOne> for $primitive {
75            fn from(rhs: &SignedOne) -> Self {
76                match rhs {
77                    SignedOne::PlusOne => 1,
78                    SignedOne::MinusOne => -1,
79                }
80            }
81        }
82
83        impl Mul<SignedOne> for $primitive {
84            type Output = Self;
85
86            fn mul(mut self, rhs: SignedOne) -> Self::Output {
87                MulAssign::mul_assign(&mut self, rhs);
88                self
89            }
90        }
91
92        impl Mul<&SignedOne> for $primitive {
93            type Output = Self;
94
95            fn mul(mut self, rhs: &SignedOne) -> Self::Output {
96                MulAssign::mul_assign(&mut self, rhs);
97                self
98            }
99        }
100
101        impl Mul<&SignedOne> for &$primitive {
102            type Output = $primitive;
103
104            fn mul(self, rhs: &SignedOne) -> Self::Output {
105                match rhs {
106                    SignedOne::PlusOne => *self,
107                    SignedOne::MinusOne => -self,
108                }
109            }
110        }
111
112        impl MulAssign<&SignedOne> for $primitive {
113            fn mul_assign(&mut self, rhs: &SignedOne) {
114                MulAssign::mul_assign(self, *rhs);
115            }
116        }
117
118        impl MulAssign<SignedOne> for $primitive {
119            fn mul_assign(&mut self, rhs: SignedOne) {
120                match rhs {
121                    SignedOne::PlusOne => {},
122                    SignedOne::MinusOne => *self = -*self,
123                }
124            }
125        }
126
127        impl Div<SignedOne> for $primitive {
128            type Output = Self;
129
130            fn div(mut self, rhs: SignedOne) -> Self::Output {
131                MulAssign::mul_assign(&mut self, rhs);
132                self
133            }
134        }
135
136        impl Div<&SignedOne> for $primitive {
137            type Output = Self;
138
139            fn div(mut self, rhs: &SignedOne) -> Self::Output {
140                MulAssign::mul_assign(&mut self, rhs);
141                self
142            }
143        }
144
145        impl DivAssign<&SignedOne> for $primitive {
146            fn div_assign(&mut self, rhs: &SignedOne) {
147                DivAssign::div_assign(self, *rhs);
148            }
149        }
150
151        impl DivAssign<SignedOne> for $primitive {
152            fn div_assign(&mut self, rhs: SignedOne) {
153                MulAssign::mul_assign(self, rhs);
154            }
155        }
156    }
157}
158
159macro_rules! define_unsigned_ops {
160    ($primitive:ident) => {
161        impl Add<SignedOne> for $primitive {
162            type Output = Self;
163
164            fn add(mut self, rhs: SignedOne) -> Self::Output {
165                AddAssign::add_assign(&mut self, rhs);
166                self
167            }
168        }
169
170        impl Add<&SignedOne> for $primitive {
171            type Output = Self;
172
173            fn add(mut self, rhs: &SignedOne) -> Self::Output {
174                AddAssign::add_assign(&mut self, rhs);
175                self
176            }
177        }
178
179        impl AddAssign<&SignedOne> for $primitive {
180            fn add_assign(&mut self, rhs: &SignedOne) {
181                AddAssign::add_assign(self, *rhs);
182            }
183        }
184
185        impl AddAssign<SignedOne> for $primitive {
186            fn add_assign(&mut self, rhs: SignedOne) {
187                match rhs {
188                    SignedOne::PlusOne => *self += 1,
189                    SignedOne::MinusOne => *self -= 1,
190                }
191            }
192        }
193
194        impl Sub<SignedOne> for $primitive {
195            type Output = Self;
196
197            fn sub(mut self, rhs: SignedOne) -> Self::Output {
198                SubAssign::sub_assign(&mut self, rhs);
199                self
200            }
201        }
202
203        impl Sub<&SignedOne> for $primitive {
204            type Output = Self;
205
206            fn sub(mut self, rhs: &SignedOne) -> Self::Output {
207                SubAssign::sub_assign(&mut self, rhs);
208                self
209            }
210        }
211
212        impl SubAssign<&SignedOne> for $primitive {
213            fn sub_assign(&mut self, rhs: &SignedOne) {
214                SubAssign::sub_assign(self, *rhs);
215            }
216        }
217
218        impl SubAssign<SignedOne> for $primitive {
219            fn sub_assign(&mut self, rhs: SignedOne) {
220                match rhs {
221                    SignedOne::PlusOne => *self -= 1,
222                    SignedOne::MinusOne => *self += 1,
223                }
224            }
225        }
226    }
227}
228
229define_signed_ops!(i8);
230define_signed_ops!(i16);
231define_signed_ops!(i32);
232define_signed_ops!(i64);
233define_signed_ops!(i128);
234define_unsigned_ops!(i8);
235define_unsigned_ops!(i16);
236define_unsigned_ops!(i32);
237define_unsigned_ops!(i64);
238define_unsigned_ops!(i128);
239
240define_unsigned_ops!(u8);
241define_unsigned_ops!(u16);
242define_unsigned_ops!(u32);
243define_unsigned_ops!(u64);
244define_unsigned_ops!(u128);
245
246#[cfg(test)]
247mod test {
248    use crate::SignedOne;
249
250    #[test]
251    fn test_integer() {
252        assert_eq!(1 + SignedOne::PlusOne, 2);
253        assert_eq!(-1 + SignedOne::PlusOne, 0);
254        assert_eq!(1 + SignedOne::PlusOne, 2);
255        assert_eq!(-1 + SignedOne::PlusOne, 0);
256        assert_eq!(33 / SignedOne::PlusOne, 33);
257        assert_eq!(-33 / &SignedOne::PlusOne, -33);
258        assert_eq!(894 * SignedOne::PlusOne, 894);
259        assert_eq!(-894 * &SignedOne::PlusOne, -894);
260
261        assert_eq!(1 + SignedOne::MinusOne, 0);
262        assert_eq!(-1 + SignedOne::MinusOne, -2);
263        assert_eq!(1 - SignedOne::MinusOne, 2);
264        assert_eq!(-1 - SignedOne::MinusOne, 0);
265        assert_eq!(33 / SignedOne::MinusOne, -33);
266        assert_eq!(-33 / &SignedOne::MinusOne, 33);
267        assert_eq!(894 * SignedOne::MinusOne, -894);
268        assert_eq!(-894 * &SignedOne::MinusOne, 894);
269    }
270}