1use core::cmp::Ordering;
2use core::fmt;
3use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
4
5use crate::{Decimal, UnderlyingInt, bits_to_digits};
6
7impl<I: UnderlyingInt> Decimal<I> {
8 #[must_use]
10 pub fn abs(self) -> Self {
11 Self(self.0 << 1 >> 1)
12 }
13
14 #[must_use]
32 pub fn checked_add(self, right: Self) -> Option<Self> {
33 let (b_sign, b_scale, b_man) = right.unpack();
34 self.do_add(b_sign, b_scale, b_man)
35 }
36
37 #[must_use]
55 pub fn checked_sub(self, right: Self) -> Option<Self> {
56 let (b_sign, b_scale, b_man) = right.unpack();
57 self.do_add(b_sign ^ 1, b_scale, b_man)
58 }
59
60 #[inline]
61 fn do_add(self, b_sign: u8, b_scale: u32, b_man: I) -> Option<Self> {
62 let (a_sign, a_scale, a_man) = self.unpack();
63
64 let (a_man, b_man, scale) = if a_scale == b_scale {
65 (a_man, b_man, a_scale)
66 } else {
67 align_scale(a_man, a_scale, b_man, b_scale)
68 };
69
70 let (sign, sum) = if a_sign == b_sign {
72 (a_sign, a_man + b_man)
73 } else if a_man > b_man {
74 (a_sign, a_man - b_man)
75 } else {
76 (b_sign, b_man - a_man)
77 };
78
79 if sum <= I::MAX_MATISSA {
81 Some(Self::pack(sign, scale, sum))
82 } else if scale > 0 {
83 let man = (sum + (I::TEN >> 1)) / I::TEN; Some(Self::pack(sign, scale - 1, man))
85 } else {
86 None
87 }
88 }
89
90 #[must_use]
110 pub fn checked_mul(self, right: impl Into<Self>) -> Option<Self> {
111 let (a_sign, a_scale, a_man) = self.unpack();
112 let (b_sign, b_scale, b_man) = right.into().unpack();
113
114 let (p_man, p_scale) = a_man.mul_with_sum_scale(b_man, a_scale + b_scale)?;
115
116 Some(Self::pack(a_sign ^ b_sign, p_scale, p_man))
117 }
118
119 #[must_use]
139 pub fn checked_div(self, right: impl Into<Self>) -> Option<Self> {
140 let (a_sign, a_scale, a_man) = self.unpack();
141 let (b_sign, b_scale, b_man) = right.into().unpack();
142 if b_man == I::ZERO {
143 return None;
144 }
145
146 let (q_man, q_scale) = a_man.div_with_scales(b_man, a_scale, b_scale)?;
147
148 Some(Self::pack(a_sign ^ b_sign, q_scale, q_man))
149 }
150
151 #[must_use]
164 pub fn round_to(self, dst_scale: u32) -> Self {
165 let (a_sign, a_scale, a_man) = self.unpack();
166 if dst_scale >= a_scale {
167 return self;
168 }
169 let new_man = a_man.div_exp(a_scale - dst_scale);
170 Self::pack(a_sign, dst_scale, new_man)
171 }
172}
173
174impl<I: UnderlyingInt> Decimal<I> {
175 #[must_use]
177 pub fn is_zero(self) -> bool {
178 let (_, _, man) = self.unpack();
179 man == I::ZERO
180 }
181
182 #[must_use]
184 pub fn is_positive(self) -> bool {
185 let (sign, _, man) = self.unpack();
186 sign == 0 && man != I::ZERO
187 }
188
189 #[must_use]
191 pub fn is_negative(self) -> bool {
192 let (sign, _, man) = self.unpack();
193 sign != 0 && man != I::ZERO
194 }
195}
196
197impl<I: UnderlyingInt> Eq for Decimal<I> {}
198
199impl<I: UnderlyingInt> PartialEq for Decimal<I> {
200 fn eq(&self, other: &Self) -> bool {
201 let (a_sign, a_scale, a_man) = self.unpack();
202 let (b_sign, b_scale, b_man) = other.unpack();
203
204 if a_man == I::ZERO {
205 return b_man == I::ZERO;
206 }
207 if b_man == I::ZERO {
208 return a_man == I::ZERO;
209 }
210 if a_sign != b_sign {
211 return false;
212 }
213 if a_scale == b_scale {
214 return a_man == b_man;
215 }
216 if a_scale < b_scale {
217 match a_man.checked_mul_exp(b_scale - a_scale) {
218 Some(a_man) => a_man == b_man,
219 None => false,
220 }
221 } else {
222 match b_man.checked_mul_exp(a_scale - b_scale) {
223 Some(b_man) => b_man == a_man,
224 None => false,
225 }
226 }
227 }
228}
229
230impl<I: UnderlyingInt> Ord for Decimal<I> {
231 fn cmp(&self, other: &Self) -> Ordering {
232 let (a_sign, a_scale, a_man) = self.unpack();
233 let (b_sign, b_scale, b_man) = other.unpack();
234
235 if a_sign != b_sign {
236 if a_man == I::ZERO && b_man == I::ZERO {
237 Ordering::Equal
238 } else if a_sign == 0 {
239 Ordering::Greater
240 } else {
241 Ordering::Less
242 }
243 } else {
244 let ret = if a_scale == b_scale {
245 a_man.cmp(&b_man)
246 } else if a_scale < b_scale {
247 match a_man.checked_mul_exp(b_scale - a_scale) {
248 Some(a_man) => a_man.cmp(&b_man),
249 None => Ordering::Greater,
250 }
251 } else {
252 match b_man.checked_mul_exp(a_scale - b_scale) {
253 Some(b_man) => a_man.cmp(&b_man),
254 None => Ordering::Less,
255 }
256 };
257
258 if a_sign == 0 {
259 ret
260 } else {
261 match ret {
262 Ordering::Less => Ordering::Greater,
263 Ordering::Greater => Ordering::Less,
264 Ordering::Equal => Ordering::Equal,
265 }
266 }
267 }
268 }
269}
270
271impl<I: UnderlyingInt> PartialOrd for Decimal<I> {
272 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
273 Some(self.cmp(other))
274 }
275}
276
277impl<I: UnderlyingInt> Neg for Decimal<I> {
278 type Output = Self;
279 fn neg(self) -> Self::Output {
280 let sign = I::ONE << (I::BITS - 1);
281 Self(self.0 ^ sign)
282 }
283}
284
285impl<I: UnderlyingInt> Add for Decimal<I> {
286 type Output = Self;
287 fn add(self, rhs: Self) -> Self::Output {
288 self.checked_add(rhs).expect("addition overflow")
289 }
290}
291
292impl<I: UnderlyingInt> AddAssign for Decimal<I> {
293 fn add_assign(&mut self, rhs: Self) {
294 *self = *self + rhs;
295 }
296}
297
298impl<I: UnderlyingInt> Sub for Decimal<I> {
299 type Output = Self;
300 fn sub(self, rhs: Self) -> Self::Output {
301 self.checked_sub(rhs).expect("substraction overflow")
302 }
303}
304
305impl<I: UnderlyingInt> SubAssign for Decimal<I> {
306 fn sub_assign(&mut self, rhs: Self) {
307 *self = *self - rhs;
308 }
309}
310
311impl<I: UnderlyingInt, R: Into<Self>> Mul<R> for Decimal<I> {
312 type Output = Self;
313 fn mul(self, rhs: R) -> Self::Output {
314 self.checked_mul(rhs).expect("multiplication overflow")
315 }
316}
317
318impl<I: UnderlyingInt, R: Into<Self>> MulAssign<R> for Decimal<I> {
319 fn mul_assign(&mut self, rhs: R) {
320 *self = *self * rhs;
321 }
322}
323
324impl<I: UnderlyingInt, R: Into<Self>> Div<R> for Decimal<I> {
325 type Output = Self;
326 fn div(self, rhs: R) -> Self::Output {
327 self.checked_div(rhs).expect("division overflow or by zero")
328 }
329}
330
331impl<I: UnderlyingInt, R: Into<Self>> DivAssign<R> for Decimal<I> {
332 fn div_assign(&mut self, rhs: R) {
333 *self = *self / rhs;
334 }
335}
336
337impl<I: UnderlyingInt> core::iter::Sum for Decimal<I> {
338 fn sum<Iter: Iterator<Item = Self>>(iter: Iter) -> Self {
339 iter.fold(Self::ZERO, |acc, d| acc + d)
340 }
341}
342
343impl<'a, I: UnderlyingInt> core::iter::Sum<&'a Self> for Decimal<I> {
344 fn sum<Iter: Iterator<Item = &'a Self>>(iter: Iter) -> Self {
345 iter.fold(Self::ZERO, |acc, d| acc + *d)
346 }
347}
348
349impl<I: UnderlyingInt> fmt::Debug for Decimal<I> {
350 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
351 let (iman, scale) = self.parts();
352 write!(f, "Decimal[{iman} {scale}]")
353 }
354}
355
356#[inline(never)]
360fn align_scale<I>(mut a_man: I, a_scale: u32, mut b_man: I, b_scale: u32) -> (I, I, u32)
361where
362 I: UnderlyingInt,
363{
364 let (big_man, mut big_scale, small_man, small_scale) = if a_scale > b_scale {
367 (&mut a_man, a_scale, &mut b_man, b_scale)
368 } else {
369 (&mut b_man, b_scale, &mut a_man, a_scale)
370 };
371
372 let small_avail = bits_to_digits(small_man.leading_zeros() - I::META_BITS);
373 let diff = big_scale - small_scale;
374
375 if diff <= small_avail {
376 *small_man = small_man.mul_exp(diff);
378 } else {
379 *small_man = small_man.mul_exp(small_avail);
381 *big_man = big_man.div_exp(diff - small_avail);
382 big_scale = small_scale + small_avail;
383 }
384
385 (a_man, b_man, big_scale)
386}