1use std::fmt;
3use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign};
4
5use crate::NonZero;
6
7#[derive(Eq, PartialEq, Copy, Clone)]
12pub enum SignedOne {
13 PlusOne,
15 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}