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, Default)]
12pub enum SignedOne {
13 #[default]
15 PlusOne,
16 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}