1use std::ops::{AddAssign, SubAssign};
2
3pub trait Signed: AddAssign + SubAssign
5where
6 Self: Sized + Copy,
7{
8 type Unsigned;
9 const ZERO: Self;
10
11 fn get_absolute(&mut self) -> Absolute<'_, Self>;
12
13 fn abs_diff(self, other: Self) -> Self::Unsigned;
14
15 fn abs(self) -> Self;
16
17 fn is_positive(self) -> bool;
18
19 fn is_negative(self) -> bool;
20
21 fn signum(self) -> Self;
22}
23
24#[derive(Debug)]
67pub struct Absolute<'a, I: Signed> {
68 num: &'a mut I,
69}
70
71impl Signed for i8 {
72 type Unsigned = u8;
73 const ZERO: i8 = 0;
74
75 #[inline]
76 fn get_absolute(&mut self) -> Absolute<'_, Self> {
77 Absolute { num: self }
78 }
79
80 #[inline]
81 fn abs(self) -> Self {
82 self.abs()
83 }
84
85 #[inline]
86 fn abs_diff(self, other: Self) -> Self::Unsigned {
87 self.abs_diff(other)
88 }
89
90 #[inline]
91 fn is_positive(self) -> bool {
92 self.is_positive()
93 }
94
95 #[inline]
96 fn is_negative(self) -> bool {
97 self.is_negative()
98 }
99
100 #[inline]
101 fn signum(self) -> Self {
102 self.signum()
103 }
104}
105
106impl Signed for i16 {
107 type Unsigned = u16;
108 const ZERO: i16 = 0;
109
110 #[inline]
111 fn get_absolute(&mut self) -> Absolute<'_, Self> {
112 Absolute { num: self }
113 }
114
115 #[inline]
116 fn abs_diff(self, other: Self) -> Self::Unsigned {
117 self.abs_diff(other)
118 }
119
120 #[inline]
121 fn abs(self) -> Self {
122 self.abs()
123 }
124
125 #[inline]
126 fn is_positive(self) -> bool {
127 self.is_positive()
128 }
129
130 #[inline]
131 fn is_negative(self) -> bool {
132 self.is_negative()
133 }
134
135 #[inline]
136 fn signum(self) -> Self {
137 self.signum()
138 }
139}
140
141impl Signed for i32 {
142 type Unsigned = u32;
143 const ZERO: i32 = 0;
144
145 #[inline]
146 fn get_absolute(&mut self) -> Absolute<'_, Self> {
147 Absolute { num: self }
148 }
149
150 #[inline]
151 fn abs_diff(self, other: Self) -> Self::Unsigned {
152 self.abs_diff(other)
153 }
154
155 #[inline]
156 fn abs(self) -> Self {
157 self.abs()
158 }
159
160 #[inline]
161 fn is_positive(self) -> bool {
162 self.is_positive()
163 }
164
165 #[inline]
166 fn is_negative(self) -> bool {
167 self.is_negative()
168 }
169
170 #[inline]
171 fn signum(self) -> Self {
172 self.signum()
173 }
174}
175
176impl Signed for i64 {
177 type Unsigned = u64;
178 const ZERO: i64 = 0;
179
180 #[inline]
181 fn get_absolute(&mut self) -> Absolute<'_, Self> {
182 Absolute { num: self }
183 }
184
185 #[inline]
186 fn abs_diff(self, other: Self) -> Self::Unsigned {
187 self.abs_diff(other)
188 }
189
190 #[inline]
191 fn abs(self) -> Self {
192 self.abs()
193 }
194
195 #[inline]
196 fn is_positive(self) -> bool {
197 self.is_positive()
198 }
199
200 #[inline]
201 fn is_negative(self) -> bool {
202 self.is_negative()
203 }
204
205 fn signum(self) -> Self {
206 self.signum()
207 }
208}
209
210impl Signed for i128 {
211 type Unsigned = u128;
212 const ZERO: i128 = 0;
213
214 #[inline]
215 fn get_absolute(&mut self) -> Absolute<'_, Self> {
216 Absolute { num: self }
217 }
218
219 #[inline]
220 fn abs_diff(self, other: Self) -> Self::Unsigned {
221 self.abs_diff(other)
222 }
223
224 #[inline]
225 fn abs(self) -> Self {
226 self.abs()
227 }
228
229 #[inline]
230 fn is_positive(self) -> bool {
231 self.is_positive()
232 }
233
234 #[inline]
235 fn is_negative(self) -> bool {
236 self.is_negative()
237 }
238
239 #[inline]
240 fn signum(self) -> Self {
241 self.signum()
242 }
243}
244
245impl<'a, I: Signed> Absolute<'a, I> {
246 #[inline]
248 pub fn get_value(&self) -> I::Unsigned {
249 self.num.abs_diff(I::ZERO)
250 }
251}
252
253impl<'a, I: Signed> AddAssign<&I> for Absolute<'a, I> {
254 #[inline]
255 fn add_assign(&mut self, rhs: &I) {
256 if self.num.is_negative() {
257 self.num.sub_assign(*rhs)
258 } else {
259 self.num.add_assign(*rhs)
260 };
261 }
262}
263
264impl<'a, I: Signed> SubAssign<&I> for Absolute<'a, I> {
265 #[inline]
266 fn sub_assign(&mut self, rhs: &I) {
267 if self.num.is_negative() {
268 self.num.add_assign(*rhs)
269 } else {
270 self.num.sub_assign(*rhs)
271 }
272 }
273}