1use super::consts::*;
2use super::signed::SignedNumeric;
3use super::InnerUint;
4use core::convert::*;
5use core::ops::{Add, Sub, Mul, Div};
6
7#[cfg(not(feature = "std"))]
8use alloc::{format, string::String};
9
10#[derive(Clone, Debug, PartialEq)]
72pub struct UnsignedNumeric {
73 pub value: InnerUint,
75}
76
77impl UnsignedNumeric {
78 pub fn zero() -> Self {
80 Self { value: zero() }
81 }
82
83 pub fn one() -> Self {
85 Self { value: one() }
86 }
87
88 pub fn new(value: u128) -> Self {
91 let value = InnerUint::from(value).checked_mul(one()).unwrap();
93 Self { value }
94 }
95
96 pub fn from_scaled_u128(value: u128) -> Self {
99 Self {
100 value: InnerUint::from(value),
101 }
102 }
103
104 pub fn from_values(lo: u64, mid: u64, hi: u64) -> Self {
108 Self {
109 value: InnerUint([lo, mid, hi]),
110 }
111 }
112
113 pub fn to_bytes(&self) -> [u8; 24] {
115 let InnerUint([lo, mid, hi]) = self.value;
116
117 let mut bytes = [0u8; 24];
118 bytes[0..8].copy_from_slice(&lo.to_le_bytes());
119 bytes[8..16].copy_from_slice(&mid.to_le_bytes());
120 bytes[16..24].copy_from_slice(&hi.to_le_bytes());
121
122 bytes
123 }
124
125 pub fn from_bytes(bytes: &[u8; 24]) -> Self {
127 let lo = u64::from_le_bytes(bytes[0..8].try_into().unwrap());
128 let mid = u64::from_le_bytes(bytes[8..16].try_into().unwrap());
129 let hi = u64::from_le_bytes(bytes[16..24].try_into().unwrap());
130
131 Self {
132 value: InnerUint([lo, mid, hi]),
133 }
134 }
135
136 pub fn to_imprecise(&self) -> Option<u128> {
140 self.value
141 .checked_add(Self::rounding_correction())?
142 .checked_div(one())
143 .map(|v| v.as_u128())
144 }
145
146 pub fn signed(&self) -> SignedNumeric {
150 SignedNumeric {
151 value: self.clone(),
152 is_negative: false,
153 }
154 }
155
156 fn rounding_correction() -> InnerUint {
160 InnerUint::from(ONE / 2)
161 }
162
163 pub fn almost_eq(&self, rhs: &Self, precision: InnerUint) -> bool {
166 let (difference, _) = self.unsigned_sub(rhs);
167 difference.value < precision
168 }
169
170 pub fn less_than(&self, rhs: &Self) -> bool {
172 self.value < rhs.value
173 }
174
175 pub fn greater_than(&self, rhs: &Self) -> bool {
177 self.value > rhs.value
178 }
179
180 pub fn less_than_or_equal(&self, rhs: &Self) -> bool {
182 self.value <= rhs.value
183 }
184
185 pub fn greater_than_or_equal(&self, rhs: &Self) -> bool {
187 self.value >= rhs.value
188 }
189
190 pub fn floor(&self) -> Option<Self> {
192 let value = self.value.checked_div(one())?.checked_mul(one())?;
193 Some(Self { value })
194 }
195
196 pub fn ceiling(&self) -> Option<Self> {
198 let value = self
199 .value
200 .checked_add(one().checked_sub(InnerUint::from(1))?)?
201 .checked_div(one())?
202 .checked_mul(one())?;
203 Some(Self { value })
204 }
205
206 pub fn checked_div(&self, rhs: &Self) -> Option<Self> {
210 if *rhs == Self::zero() {
211 return None;
212 }
213 match self.value.checked_mul(one()) {
214 Some(v) => {
215 let value = v
216 .checked_add(Self::rounding_correction())?
217 .checked_div(rhs.value)?;
218 Some(Self { value })
219 }
220 None => {
221 let value = self
222 .value
223 .checked_add(Self::rounding_correction())?
224 .checked_div(rhs.value)?
225 .checked_mul(one())?;
226 Some(Self { value })
227 }
228 }
229 }
230
231 pub fn checked_mul(&self, rhs: &Self) -> Option<Self> {
235 match self.value.checked_mul(rhs.value) {
236 Some(v) => {
237 let value = v
238 .checked_add(Self::rounding_correction())?
239 .checked_div(one())?;
240 Some(Self { value })
241 }
242 None => {
243 let value = if self.value >= rhs.value {
244 self.value.checked_div(one())?.checked_mul(rhs.value)?
245 } else {
246 rhs.value.checked_div(one())?.checked_mul(self.value)?
247 };
248 Some(Self { value })
249 }
250 }
251 }
252
253 pub fn checked_add(&self, rhs: &Self) -> Option<Self> {
255 let value = self.value.checked_add(rhs.value)?;
256 Some(Self { value })
257 }
258
259 pub fn checked_sub(&self, rhs: &Self) -> Option<Self> {
261 let value = self.value.checked_sub(rhs.value)?;
262 Some(Self { value })
263 }
264
265 pub fn unsigned_sub(&self, rhs: &Self) -> (Self, bool) {
268 match self.value.checked_sub(rhs.value) {
269 None => {
270 let value = rhs.value.checked_sub(self.value).unwrap();
271 (Self { value }, true)
272 }
273 Some(value) => (Self { value }, false),
274 }
275 }
276
277 pub fn to_string(&self) -> String {
282 let whole = self.floor().unwrap().to_imprecise().unwrap();
283 let decimals = self
284 .checked_sub(&UnsignedNumeric::new(whole))
285 .unwrap()
286 .checked_mul(&UnsignedNumeric::new(ONE))
287 .unwrap()
288 .to_imprecise()
289 .unwrap();
290 format!("{}.{:0>width$}", whole, decimals, width = 18)
291 }
292}
293
294impl Add for UnsignedNumeric {
296 type Output = Self;
297
298 fn add(self, rhs: Self) -> Self::Output {
299 self.checked_add(&rhs).unwrap()
300 }
301}
302
303impl Add<&UnsignedNumeric> for UnsignedNumeric {
304 type Output = Self;
305
306 fn add(self, rhs: &Self) -> Self::Output {
307 self.checked_add(rhs).unwrap()
308 }
309}
310
311impl Add<UnsignedNumeric> for &UnsignedNumeric {
312 type Output = UnsignedNumeric;
313
314 fn add(self, rhs: UnsignedNumeric) -> Self::Output {
315 self.checked_add(&rhs).unwrap()
316 }
317}
318
319impl Add<&UnsignedNumeric> for &UnsignedNumeric {
320 type Output = UnsignedNumeric;
321
322 fn add(self, rhs: &UnsignedNumeric) -> Self::Output {
323 self.checked_add(rhs).unwrap()
324 }
325}
326
327impl Sub for UnsignedNumeric {
328 type Output = Self;
329
330 fn sub(self, rhs: Self) -> Self::Output {
331 self.checked_sub(&rhs).unwrap()
332 }
333}
334
335impl Sub<&UnsignedNumeric> for UnsignedNumeric {
336 type Output = Self;
337
338 fn sub(self, rhs: &Self) -> Self::Output {
339 self.checked_sub(rhs).unwrap()
340 }
341}
342
343impl Sub<UnsignedNumeric> for &UnsignedNumeric {
344 type Output = UnsignedNumeric;
345
346 fn sub(self, rhs: UnsignedNumeric) -> Self::Output {
347 self.checked_sub(&rhs).unwrap()
348 }
349}
350
351impl Sub<&UnsignedNumeric> for &UnsignedNumeric {
352 type Output = UnsignedNumeric;
353
354 fn sub(self, rhs: &UnsignedNumeric) -> Self::Output {
355 self.checked_sub(rhs).unwrap()
356 }
357}
358
359impl Mul for UnsignedNumeric {
360 type Output = Self;
361
362 fn mul(self, rhs: Self) -> Self::Output {
363 self.checked_mul(&rhs).unwrap()
364 }
365}
366
367impl Mul<&UnsignedNumeric> for UnsignedNumeric {
368 type Output = Self;
369
370 fn mul(self, rhs: &Self) -> Self::Output {
371 self.checked_mul(rhs).unwrap()
372 }
373}
374
375impl Mul<UnsignedNumeric> for &UnsignedNumeric {
376 type Output = UnsignedNumeric;
377
378 fn mul(self, rhs: UnsignedNumeric) -> Self::Output {
379 self.checked_mul(&rhs).unwrap()
380 }
381}
382
383impl Mul<&UnsignedNumeric> for &UnsignedNumeric {
384 type Output = UnsignedNumeric;
385
386 fn mul(self, rhs: &UnsignedNumeric) -> Self::Output {
387 self.checked_mul(rhs).unwrap()
388 }
389}
390
391impl Div for UnsignedNumeric {
392 type Output = Self;
393
394 fn div(self, rhs: Self) -> Self::Output {
395 self.checked_div(&rhs).unwrap()
396 }
397}
398
399impl Div<&UnsignedNumeric> for UnsignedNumeric {
400 type Output = Self;
401
402 fn div(self, rhs: &Self) -> Self::Output {
403 self.checked_div(rhs).unwrap()
404 }
405}
406
407impl Div<UnsignedNumeric> for &UnsignedNumeric {
408 type Output = UnsignedNumeric;
409
410 fn div(self, rhs: UnsignedNumeric) -> Self::Output {
411 self.checked_div(&rhs).unwrap()
412 }
413}
414
415impl Div<&UnsignedNumeric> for &UnsignedNumeric {
416 type Output = UnsignedNumeric;
417
418 fn div(self, rhs: &UnsignedNumeric) -> Self::Output {
419 self.checked_div(rhs).unwrap()
420 }
421}
422
423#[cfg(test)]
424mod tests {
425 use super::*;
426
427 fn max_numeric() -> UnsignedNumeric {
428 UnsignedNumeric {
429 value: InnerUint::MAX,
430 }
431 }
432
433 #[test]
434 fn test_zero_and_one() {
435 assert_eq!(UnsignedNumeric::zero().value, InnerUint::from(0));
436 assert_eq!(UnsignedNumeric::one().value, InnerUint::from(ONE));
437 }
438
439 #[test]
440 fn test_from_scaled_u128() {
441 let n = UnsignedNumeric::from_scaled_u128(42 * ONE);
442 assert_eq!(n.to_imprecise().unwrap(), 42);
443 }
444
445 #[test]
446 fn test_to_string_exact() {
447 let n = UnsignedNumeric::new(3);
448 assert_eq!(n.to_string(), "3.000000000000000000");
449 }
450
451 #[test]
452 fn test_to_string_fractional() {
453 let mut n = UnsignedNumeric::new(3);
454 n.value += InnerUint::from(250_000_000_000_000_000u128); assert_eq!(n.to_string(), "3.250000000000000000");
456 }
457
458 #[test]
459 fn test_checked_add() {
460 let a = UnsignedNumeric::new(1);
461 let b = UnsignedNumeric::new(2);
462 let sum = a.checked_add(&b).unwrap();
463 assert_eq!(sum.to_imprecise().unwrap(), 3);
464 }
465
466 #[test]
467 fn test_checked_sub_underflow() {
468 let a = UnsignedNumeric::new(1);
469 let b = UnsignedNumeric::new(2);
470 assert!(a.checked_sub(&b).is_none());
471 }
472
473 #[test]
474 fn test_checked_sub_valid() {
475 let a = UnsignedNumeric::new(3);
476 let b = UnsignedNumeric::new(1);
477 let result = a.checked_sub(&b).unwrap();
478 assert_eq!(result.to_imprecise().unwrap(), 2);
479 }
480
481 #[test]
482 fn test_checked_mul_simple() {
483 let a = UnsignedNumeric::new(2);
484 let b = UnsignedNumeric::new(3);
485 let product = a.checked_mul(&b).unwrap();
486 assert_eq!(product.to_imprecise().unwrap(), 6);
487 }
488
489 #[test]
490 fn test_checked_div_exact() {
491 let a = UnsignedNumeric::new(6);
492 let b = UnsignedNumeric::new(2);
493 let result = a.checked_div(&b).unwrap();
494 assert_eq!(result.to_imprecise().unwrap(), 3);
495 }
496
497 #[test]
498 fn test_checked_div_rounded() {
499 let a = UnsignedNumeric::new(1);
500 let b = UnsignedNumeric::new(3); let result = a.checked_div(&b).unwrap();
503 let expected = UnsignedNumeric::from_scaled_u128(333_333_333_333_333_333); assert!(result.almost_eq(&expected, InnerUint::from(1_000_000)));
506 }
507
508 #[test]
509 fn test_unsigned_sub_positive() {
510 let a = UnsignedNumeric::new(7);
511 let b = UnsignedNumeric::new(3);
512 let (result, is_negative) = a.unsigned_sub(&b);
513 assert_eq!(result.to_imprecise().unwrap(), 4);
514 assert!(!is_negative);
515 }
516
517 #[test]
518 fn test_unsigned_sub_negative() {
519 let a = UnsignedNumeric::new(3);
520 let b = UnsignedNumeric::new(7);
521 let (result, is_negative) = a.unsigned_sub(&b);
522 assert_eq!(result.to_imprecise().unwrap(), 4);
523 assert!(is_negative);
524 }
525
526 #[test]
527 fn test_almost_eq_within_precision() {
528 let a = UnsignedNumeric::new(5);
529 let mut b = a.clone();
530 b.value += InnerUint::from(10); assert!(a.almost_eq(&b, InnerUint::from(20)));
533 assert!(!a.almost_eq(&b, InnerUint::from(5)));
534 }
535
536 #[test]
537 fn test_comparisons() {
538 let a = UnsignedNumeric::new(1);
539 let b = UnsignedNumeric::new(2);
540 assert!(a.less_than(&b));
541 assert!(b.greater_than(&a));
542 assert!(a.less_than_or_equal(&b));
543 assert!(b.greater_than_or_equal(&a));
544 assert!(a.less_than_or_equal(&a));
545 assert!(a.greater_than_or_equal(&a));
546 }
547
548 #[test]
549 fn test_signed_conversion() {
550 let u = UnsignedNumeric::new(42);
551 let s = u.signed();
552 assert_eq!(s.value, u);
553 assert!(!s.is_negative);
554 }
555
556 #[test]
557 fn test_serialization() {
558 let original = UnsignedNumeric::from_values(123, 456, 789);
559 let bytes = original.to_bytes();
560 let recovered = UnsignedNumeric::from_bytes(&bytes);
561
562 assert_eq!(original, recovered);
563 }
564
565 #[test]
566 fn test_floor() {
567 let whole_number = UnsignedNumeric::new(2);
568 let mut decimal_number = UnsignedNumeric::new(2);
569 decimal_number.value += InnerUint::from(1);
570 let floor = decimal_number.floor().unwrap();
571 let floor_again = floor.floor().unwrap();
572 assert_eq!(whole_number.value, floor.value);
573 assert_eq!(whole_number.value, floor_again.value);
574 }
575
576 #[test]
577 fn test_ceiling() {
578 let whole_number = UnsignedNumeric::new(2);
579 let mut decimal_number = UnsignedNumeric::new(2);
580 decimal_number.value -= InnerUint::from(1);
581 let ceiling = decimal_number.ceiling().unwrap();
582 let ceiling_again = ceiling.ceiling().unwrap();
583 assert_eq!(whole_number.value, ceiling.value);
584 assert_eq!(whole_number.value, ceiling_again.value);
585 }
586
587 #[test]
588 fn test_add_overflow() {
589 let a = max_numeric();
590 let b = UnsignedNumeric::one();
591 assert!(a.checked_add(&b).is_none(), "Expected overflow on add");
592 }
593
594 #[test]
595 fn test_mul_overflow() {
596 let a = max_numeric();
597 let b = UnsignedNumeric::new(2); let result = a.checked_mul(&b);
600 assert!(result.is_none(), "Expected overflow on multiply");
601 }
602
603 #[test]
604 fn test_mul_fallback_path() {
605 let a = UnsignedNumeric::new(1_000_000_000_000u128); let b = UnsignedNumeric::new(2);
607
608 let result = a.checked_mul(&b).unwrap();
609 assert_eq!(result.to_imprecise().unwrap(), 2_000_000_000_000);
610 }
611
612 #[test]
613 fn test_mul_large_by_large_overflow() {
614 let a = UnsignedNumeric {
615 value: InnerUint([0, 0, 1]), };
617 let b = a.clone(); let result = a.checked_mul(&b);
620 assert!(result.is_none(), "Expected overflow on large * large");
621 }
622
623 #[test]
624 fn test_div_by_zero() {
625 let a = UnsignedNumeric::new(42);
626 let zero = UnsignedNumeric::zero();
627
628 assert!(a.checked_div(&zero).is_none(), "Expected div by zero to fail");
629 }
630
631 #[test]
632 fn test_floor_overflow_fallback() {
633 let a = max_numeric();
636 let result = a.floor();
637 assert!(result.is_some(), "Should handle overflow in floor safely");
638 }
639
640 #[test]
641 fn test_ceiling_overflow() {
642 let a = max_numeric();
645 let result = a.ceiling();
646 assert!(result.is_none(), "Expected overflow in ceiling()");
647 }
648
649 #[test]
650 fn test_rounding_correction_addition_overflow() {
651 let a = max_numeric();
652 let corrected = a.value.checked_add(UnsignedNumeric::rounding_correction());
654 assert!(corrected.is_none(), "Expected overflow in rounding correction");
655 }
656
657 #[test]
658 fn test_arithmetic_operators() {
659 let a = UnsignedNumeric::new(5);
660 let b = UnsignedNumeric::new(3);
661
662 let sum = a.clone() + b.clone();
664 assert_eq!(sum.to_imprecise().unwrap(), 8);
665
666 let diff = a.clone() - b.clone();
668 assert_eq!(diff.to_imprecise().unwrap(), 2);
669
670 let product = a.clone() * b.clone();
672 assert_eq!(product.to_imprecise().unwrap(), 15);
673
674 let quotient = a / b;
676 assert!(quotient.almost_eq(&UnsignedNumeric::from_scaled_u128(1_666_666_666_666_666_666), InnerUint::from(1_000_000)));
677 }
678
679 #[test]
680 fn test_arithmetic_operators_with_references() {
681 let a = UnsignedNumeric::new(10);
682 let b = UnsignedNumeric::new(4);
683
684 let sum = &a + &b;
686 assert_eq!(sum.to_imprecise().unwrap(), 14);
687
688 let diff = &a - &b;
689 assert_eq!(diff.to_imprecise().unwrap(), 6);
690
691 let product = &a * &b;
692 assert_eq!(product.to_imprecise().unwrap(), 40);
693
694 let quotient = &a / &b;
695 assert_eq!(quotient.to_imprecise().unwrap(), 3);
696 }
697
698 #[test]
699 fn test_arithmetic_operators_mixed_references() {
700 let a = UnsignedNumeric::new(6);
701 let b = UnsignedNumeric::new(2);
702
703 let sum1 = a.clone() + &b;
705 let sum2 = &a + b.clone();
706 assert_eq!(sum1.to_imprecise().unwrap(), 8);
707 assert_eq!(sum2.to_imprecise().unwrap(), 8);
708
709 let product1 = a.clone() * &b;
710 let product2 = &a * b.clone();
711 assert_eq!(product1.to_imprecise().unwrap(), 12);
712 assert_eq!(product2.to_imprecise().unwrap(), 12);
713 }
714}