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