1use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
2
3use bytemuck::{Pod, Zeroable};
4
5const PRECISION: i32 = 10;
6const ONE: i128 = 10_000_000_000;
7
8const POWERS_OF_TEN: &[i128] = &[
9 1,
10 10,
11 100,
12 1_000,
13 10_000,
14 100_000,
15 1_000_000,
16 10_000_000,
17 100_000_000,
18 1_000_000_000,
19 10_000_000_000,
20 100_000_000_000,
21 1_000_000_000_000,
22];
23
24#[derive(Pod, Zeroable, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
26#[repr(C)]
27pub struct Number128(i128);
28
29impl Number128 {
30 pub const ONE: Self = Self(ONE);
31 pub const ZERO: Self = Self(0i128);
32 pub const MAX: Self = Self(i128::MAX);
33 pub const MIN: Self = Self(i128::MIN);
34 pub const BITS: u32 = i128::BITS;
35
36 pub fn as_u64(&self, exponent: impl Into<i32>) -> u64 {
41 let extra_precision = PRECISION + exponent.into();
42 let prec_value = POWERS_OF_TEN[extra_precision.unsigned_abs() as usize];
43
44 let target_value = if extra_precision < 0 {
45 self.0 * prec_value
46 } else {
47 self.0 / prec_value
48 };
49
50 if target_value > std::u64::MAX as i128 {
51 panic!("cannot convert to u64 due to overflow");
52 }
53
54 if target_value < 0 {
55 panic!("cannot convert to u64 because value < 0");
56 }
57
58 target_value as u64
59 }
60
61 pub fn as_f64(&self) -> f64 {
63 self.to_i128() as f64 / 10_000_000_000.0
65 }
66
67 pub fn from_decimal(value: impl Into<i128>, exponent: impl Into<i32>) -> Self {
69 let extra_precision = PRECISION + exponent.into();
70 let prec_value = POWERS_OF_TEN[extra_precision.unsigned_abs() as usize];
71
72 if extra_precision < 0 {
73 Self(value.into() / prec_value)
74 } else {
75 Self(value.into() * prec_value)
76 }
77 }
78
79 pub fn from_bps(basis_points: u16) -> Self {
81 Self::from_decimal(basis_points, crate::BPS_EXPONENT)
82 }
83
84 pub fn into_bits(self) -> [u8; 16] {
87 self.0.to_ne_bytes()
88 }
89
90 pub fn from_bits(bits: [u8; 16]) -> Self {
94 Self(i128::from_ne_bytes(bits))
95 }
96
97 pub fn to_i128(self) -> i128 {
99 self.0
100 }
101
102 pub fn from_i128(value: i128) -> Self {
104 Self(value)
105 }
106}
107
108impl std::fmt::Debug for Number128 {
109 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
110 <Self as std::fmt::Display>::fmt(self, f)
111 }
112}
113
114impl std::fmt::Display for Number128 {
115 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
116 let rem = self.0 % ONE;
118 let decimal_digits = PRECISION as usize;
119 let rem_str = rem.checked_abs().unwrap().to_string();
121 let decimals = "0".repeat(decimal_digits - rem_str.len()) + &*rem_str;
123 let stripped_decimals = decimals.trim_end_matches('0');
124 let pretty_decimals = if stripped_decimals.is_empty() {
125 "0"
126 } else {
127 stripped_decimals
128 };
129 if self.0 < -ONE {
130 let int = self.0 / ONE;
131 write!(f, "{}.{}", int, pretty_decimals)?;
132 } else if self.0 < 0 {
133 write!(f, "-0.{}", pretty_decimals)?;
134 } else if self.0 < ONE {
135 write!(f, "0.{}", pretty_decimals)?;
136 } else {
137 let int = self.0 / ONE;
138 write!(f, "{}.{}", int, pretty_decimals)?;
139 }
140 Ok(())
141 }
142}
143
144impl Add<Number128> for Number128 {
145 type Output = Self;
146
147 fn add(self, rhs: Number128) -> Self::Output {
148 Self(self.0.checked_add(rhs.0).unwrap())
149 }
150}
151
152impl AddAssign<Number128> for Number128 {
153 fn add_assign(&mut self, rhs: Number128) {
154 self.0 = self.0.checked_add(rhs.0).unwrap();
155 }
156}
157
158impl Sub<Number128> for Number128 {
159 type Output = Self;
160
161 fn sub(self, rhs: Number128) -> Self::Output {
162 Self(self.0.checked_sub(rhs.0).unwrap())
163 }
164}
165
166impl SubAssign<Number128> for Number128 {
167 fn sub_assign(&mut self, rhs: Number128) {
168 self.0 = self.0.checked_sub(rhs.0).unwrap();
169 }
170}
171
172impl Mul<Number128> for Number128 {
173 type Output = Number128;
174
175 fn mul(self, rhs: Number128) -> Self::Output {
176 Self(div_by_one(fast_checked_mul(self.0, rhs.0).unwrap()))
178 }
179}
180
181impl MulAssign<Number128> for Number128 {
182 fn mul_assign(&mut self, rhs: Number128) {
183 self.0 = div_by_one(fast_checked_mul(self.0, rhs.0).unwrap())
185 }
186}
187
188impl Div<Number128> for Number128 {
189 type Output = Number128;
190
191 fn div(self, rhs: Number128) -> Self::Output {
192 Self(mul_by_one(self.0).div(rhs.0))
196 }
197}
198
199impl DivAssign<Number128> for Number128 {
200 fn div_assign(&mut self, rhs: Number128) {
201 self.0 = mul_by_one(self.0).div(rhs.0);
204 }
205}
206
207impl<T: Into<i128>> Mul<T> for Number128 {
208 type Output = Number128;
209
210 fn mul(self, rhs: T) -> Self::Output {
211 Self(fast_checked_mul(self.0, rhs.into()).unwrap())
212 }
213}
214
215impl<T: Into<i128>> Div<T> for Number128 {
216 type Output = Number128;
217
218 fn div(self, rhs: T) -> Self::Output {
219 Self(self.0.div(rhs.into()))
222 }
223}
224
225impl<T: Into<i128>> From<T> for Number128 {
226 fn from(n: T) -> Self {
227 Self::from_i128(n.into())
228 }
229}
230
231impl Neg for Number128 {
232 type Output = Number128;
233
234 fn neg(self) -> Self::Output {
235 Number128(-self.0)
236 }
237}
238fn div_by_one(value: i128) -> i128 {
240 let abs_result = (value.abs() >> 10) / (9_765_625_i128);
247
248 if value > 0 || abs_result < 0 {
252 abs_result
253 } else {
254 -abs_result
255 }
256}
257
258const ONE_REPR_BITS: u32 = 34; fn mul_by_one(value: i128) -> i128 {
266 let left_bits = 128 - value.abs().leading_zeros();
274 if (left_bits + ONE_REPR_BITS + 1) > 128 {
275 panic!("Overflow in mul by one")
276 }
277 (value * 9_765_625_i128) << 10
278}
279
280fn fast_checked_mul(left: i128, right: i128) -> Option<i128> {
284 if right == 0 || left == 0 {
285 return Some(0);
286 }
287
288 let left_bits = 128 - left.abs().leading_zeros();
293 let right_bits = 128 - right.abs().leading_zeros();
294
295 if (left_bits + right_bits + 1) > 128 {
300 return None;
301 }
302 Some(left * right)
303}
304
305#[cfg(test)]
306mod tests {
307 use super::*;
308
309 #[test]
310 fn zero_equals_zero() {
311 assert_eq!(Number128::ZERO, Number128::from_decimal(0, 0));
312 }
313
314 #[test]
315 fn one_equals_one() {
316 assert_eq!(Number128::ONE, Number128::from_decimal(1, 0));
317 }
318
319 #[test]
320 fn negative_one_equals_negative_one() {
321 assert_eq!(-Number128::ONE, Number128::from_decimal(-1, 0));
322 }
323
324 #[test]
325 fn one_plus_one_equals_two() {
326 assert_eq!(
327 Number128::from_decimal(2, 0),
328 Number128::ONE + Number128::ONE
329 );
330 }
331
332 #[test]
333 fn one_minus_one_equals_zero() {
334 assert_eq!(Number128::ONE - Number128::ONE, Number128::ZERO);
335 }
336
337 #[test]
338 fn one_times_one_equals_one() {
339 assert_eq!(Number128::ONE, Number128::ONE * Number128::ONE);
341
342 let mut x = Number128::ONE;
344 x *= Number128::ONE;
345 assert_eq!(Number128::ONE, x);
346
347 assert_eq!(Number128::ONE, Number128::ONE * 1);
349 }
350
351 #[test]
352 fn one_divided_by_one_equals_one() {
353 assert_eq!(Number128::ONE, Number128::ONE / Number128::ONE);
355
356 let mut x = Number128::ONE;
358 x /= Number128::ONE;
359 assert_eq!(Number128::ONE, x);
360
361 assert_eq!(Number128::ONE, Number128::ONE / 1);
363 }
364
365 #[test]
366 fn test_mul_by_one() {
367 let one = 10_000_000_000_i128;
368
369 assert_eq!(mul_by_one(one), one * one);
371 assert_eq!(mul_by_one(-one), -one * one);
372
373 assert_eq!(mul_by_one(9_999_999_999_i128), 9_999_999_999_i128 * one);
375 assert_eq!(mul_by_one(1), one);
376 assert_eq!(mul_by_one(0), 0);
377 assert_eq!(mul_by_one(-1), -one);
378 assert_eq!(mul_by_one(-9_999_999_999_i128), -9_999_999_999_i128 * one);
379
380 assert_eq!(mul_by_one(10_000_000_001_i128), 10_000_000_001_i128 * one);
382 assert_eq!(mul_by_one(-10_000_000_001_i128), -10_000_000_001_i128 * one);
383 assert_eq!(mul_by_one(123_456_000_000_000), 123_456_000_000_000 * one);
384 assert_eq!(mul_by_one(-123_456_000_000_000), -123_456_000_000_000 * one);
385
386 let big_value = i128::MAX >> 34;
389 assert_eq!(mul_by_one(big_value), (big_value) * one);
390 let small_value = i128::MIN >> 35;
392 assert_eq!(mul_by_one(small_value), (small_value) * one);
393 }
394
395 #[test]
396 #[should_panic = "Overflow in mul by one"]
397 fn test_mul_by_one_overflow_high() {
398 let one = 10_000_000_000_i128;
399 let big_value = i128::MAX >> 33;
400 let answer = mul_by_one(big_value);
401 assert_eq!(answer, big_value * one);
402 }
403
404 #[test]
405 #[should_panic = "Overflow in mul by one"]
406 fn test_mul_by_one_overflow_low() {
407 let one = 10_000_000_000_i128;
408 let small_value = i128::MIN >> 34;
409 let answer = mul_by_one(small_value);
410 assert_eq!(answer, small_value * one);
411 }
412
413 #[test]
414 #[should_panic = "Overflow in mul by one"]
415 fn test_mul_by_one_overflow_min_i128() {
416 let one = 10_000_000_000_i128;
417 assert_eq!(mul_by_one(i128::MIN), i128::MIN * one);
418 }
419
420 #[test]
421 fn test_div_by_one() {
422 let one = 10_000_000_000_i128;
423
424 assert_eq!(div_by_one(one), one.checked_div(one).unwrap());
426 assert_eq!(div_by_one(-one), -one.checked_div(one).unwrap());
427
428 assert_eq!(
430 div_by_one(9_999_999_999_i128),
431 9_999_999_999_i128.checked_div(one).unwrap()
432 );
433 assert_eq!(div_by_one(1), 1_i128.checked_div(one).unwrap());
434 assert_eq!(div_by_one(0), 0);
435 assert_eq!(div_by_one(-1), -1_i128.checked_div(one).unwrap());
436 assert_eq!(
437 div_by_one(-9_999_999_999_i128),
438 -9_999_999_999_i128.checked_div(one).unwrap()
439 );
440
441 assert_eq!(
443 div_by_one(10_000_000_001_i128),
444 10_000_000_001_i128.checked_div(one).unwrap()
445 );
446 assert_eq!(
447 div_by_one(-10_000_000_001_i128),
448 (-10_000_000_001_i128).checked_div(one).unwrap()
449 );
450 assert_eq!(
451 div_by_one(123_456_000_000_000),
452 123_456_000_000_000_i128.checked_div(one).unwrap()
453 );
454 assert_eq!(
455 div_by_one(-123_456_000_000_000),
456 (-123_456_000_000_000_i128).checked_div(one).unwrap()
457 );
458
459 assert_eq!(div_by_one(i128::MAX), i128::MAX.checked_div(one).unwrap());
461
462 assert_eq!(div_by_one(i128::MIN), i128::MIN.checked_div(one).unwrap());
464 assert_eq!(div_by_one(i128::MIN + 1), (i128::MIN + 1) / one);
465 }
466
467 #[test]
468 fn test_fast_checked_mul() {
469 let test_cases = [
470 (10, 10),
471 (0, 10),
472 (10, 0),
473 (-10, 10),
474 (10, -10),
475 (-10, -10),
476 (1_000_000, 1_000_000),
477 (2_000_000, 2_000_000),
478 (i128::MAX >> 1, 1),
479 (i128::MAX >> 2, 2),
480 (1, i128::MAX >> 1),
481 (2, i128::MAX >> 2),
482 (3_000_000_000, 3_000_000_000), (i128::MAX, 2), (2, i128::MAX), (i128::MIN, -1), (-1, i128::MIN), (i128::MIN, i128::MIN), ];
489
490 for &(left, right) in &test_cases {
491 let answer = fast_checked_mul(left, right);
492 let expected = left.checked_mul(right);
493 assert_eq!(answer, expected);
494 }
495 }
496
497 #[test]
498 fn test_fast_checked_failures() {
499 let test_cases = [
502 (i128::MAX, 1),
503 (i128::MAX >> 1, 2),
504 (i128::MAX >> 2, 4),
505 (i128::MAX >> 3, 8),
506 (i128::MIN + 1, 1),
507 ];
508
509 for &(left, right) in &test_cases {
510 let answer = fast_checked_mul(left, right);
511 let expected = left.checked_mul(right);
512 assert_ne!(answer, expected);
513 }
514 }
515
516 #[test]
517 fn ten_div_100_equals_point_1() {
518 assert_eq!(
520 Number128::from_decimal(1, -1),
521 Number128::from_decimal(1, 1) / Number128::from_decimal(100, 0)
522 );
523
524 let mut x = Number128::from_decimal(1, 1);
526 x /= Number128::from_decimal(100, 0);
527 assert_eq!(Number128::from_decimal(1, -1), x);
528
529 assert_eq!(
531 Number128::from_decimal(1, -1),
532 Number128::from_decimal(1, 1) / 100
533 );
534 }
535
536 #[test]
537 fn comparison() {
538 let a = Number128::from_decimal(1000, -4);
539 let b = Number128::from_decimal(10, -2);
540 assert!(a >= b);
541
542 let c = Number128::from_decimal(1001, -4);
543 assert!(c > a);
544 assert!(c > b);
545
546 let d = Number128::from_decimal(9999999, -8);
547 assert!(d < a);
548 assert!(d < b);
549 assert!(d < c);
550 assert!(d <= d);
551
552 assert_eq!(a.cmp(&b), std::cmp::Ordering::Equal);
553 assert_eq!(a.cmp(&c), std::cmp::Ordering::Less);
554 assert_eq!(a.cmp(&d), std::cmp::Ordering::Greater);
555 }
556
557 #[test]
558 fn multiply_by_u64() {
559 assert_eq!(
560 Number128::from_decimal(3, 1),
561 Number128::from_decimal(1, 1) * 3u64
562 )
563 }
564
565 #[test]
566 fn test_add_assign_101_2() {
567 let mut a = Number128::from_decimal(101, 0);
568 a += Number128::from_decimal(2, 0);
569 assert_eq!(Number128::from_decimal(103, 0), a);
570 }
571
572 #[test]
573 fn test_sub_assign_101_2() {
574 let mut a = Number128::from_decimal(101, 0);
575 a -= Number128::from_decimal(2, 0);
576 assert_eq!(Number128::from_decimal(99, 0), a);
577 }
578
579 #[test]
580 fn test_mul_assign_101_2() {
581 let mut a = Number128::from_decimal(101, 0);
582 a *= Number128::from_decimal(2, 0);
583 assert_eq!(Number128::from_decimal(202, 0).0, a.0);
584 }
585
586 #[test]
587 fn test_div_assign_101_2() {
588 let mut a = Number128::from_decimal(101, 0);
589 a /= Number128::from_decimal(2, 0);
590 assert_eq!(Number128::from_decimal(505, -1), a);
591 }
592
593 #[test]
594 fn test_div_assign_102_3() {
595 let mut a = Number128::from_decimal(1, 1);
596 a /= Number128::from_decimal(100, 0);
597 assert_eq!(Number128::from_decimal(1, -1).0, a.0);
598 }
599
600 #[test]
601 fn div_into_i128() {
602 let a = Number128::from_decimal(1000, 0);
603 let b = a / 500;
604 assert_eq!(Number128::from_decimal(2, 0), b);
605
606 let c = Number128::from_decimal(1000, -3);
607 let d = c / 3;
608 assert_eq!(Number128::from_decimal(3333333333i64, -10).0, d.0);
609 }
610
611 #[test]
612 fn equality() {
613 let a = Number128::from_decimal(1000, -4);
614 let b = Number128::from_decimal(10, -2);
615 assert_eq!(a, b);
616
617 let c = Number128::from_decimal(-1000, -4);
618 assert_ne!(a, c);
619 assert_ne!(b, c);
620 }
621
622 #[test]
623 fn as_u64() {
624 let u64in = 31455;
625 let a = Number128::from_decimal(u64in, -3);
626 let b = a.as_u64(-3);
627 assert_eq!(b, u64in);
628 }
629
630 #[test]
631 #[should_panic = "cannot convert to u64 because value < 0"]
632 fn as_u64_panic_neg() {
633 let a = Number128::from_decimal(-10000, -3);
634 a.as_u64(-3);
635 }
636
637 #[test]
638 #[should_panic = "cannot convert to u64 due to overflow"]
639 fn as_u64_panic_big() {
640 let a = Number128::from_decimal(u64::MAX as i128 + 1, -3);
641 a.as_u64(-3);
642 }
643
644 #[test]
645 fn as_f64() {
646 let n = Number128::from_bps(15000);
647 assert_eq!(1.5, n.as_f64());
648
649 let n = Number128::MIN; assert_eq!(-17014118346046923173168730371.5884105728, n.as_f64());
652
653 let n = Number128::MAX; assert_eq!(17014118346046923173168730371.5884105727, n.as_f64());
656
657 let n = Number128::from_bps(0) - Number128::from_bps(15000);
659 assert_eq!(-1.5, n.as_f64());
660
661 let n = Number128::from_decimal(12345678901i128, -10);
662 assert_eq!(1.2345678901, n.as_f64());
663
664 let n = Number128::from_decimal(-12345678901i128, -10);
665 assert_eq!(-1.2345678901, n.as_f64());
666
667 let n = Number128::from_decimal(-12345678901i128, -9);
668 assert_eq!(-12.345678901, n.as_f64());
669
670 let n = Number128::from_decimal(12345678901i128, -9);
671 assert_eq!(12.345678901, n.as_f64());
672
673 let n = Number128::from_decimal(ONE - 1, 1);
674 assert_eq!(99999999990.0, n.as_f64());
675
676 let n = Number128::from_decimal(12345678901i128, -13);
677 assert_eq!(0.0012345678, n.as_f64());
678
679 let n = Number128::from_decimal(-12345678901i128, -13);
680 assert_eq!(-0.0012345678, n.as_f64());
681 }
682
683 #[test]
684 fn display() {
685 let a = Number128::from_bps(15000);
686 assert_eq!("1.5", a.to_string().as_str());
687
688 let a = Number128::from_bps(0) - Number128::from_bps(15000);
689 assert_eq!("-1.5", a.to_string().as_str());
690
691 let b = Number128::from_decimal(12345678901i128, -10);
692 assert_eq!("1.2345678901", b.to_string().as_str());
693
694 let b = Number128::from_decimal(-12345678901i128, -10);
695 assert_eq!("-1.2345678901", b.to_string().as_str());
696
697 let c = Number128::from_decimal(-12345678901i128, -9);
698 assert_eq!("-12.345678901", c.to_string().as_str());
699
700 let c = Number128::from_decimal(12345678901i128, -9);
701 assert_eq!("12.345678901", c.to_string().as_str());
702
703 let d = Number128::from_decimal(ONE - 1, 1);
704 assert_eq!("99999999990.0", d.to_string().as_str());
705
706 let e = Number128::from_decimal(12345678901i128, -13);
707 assert_eq!("0.0012345678", e.to_string().as_str());
708
709 let e = Number128::from_decimal(-12345678901i128, -13);
710 assert_eq!("-0.0012345678", e.to_string().as_str());
711 }
712
713 #[test]
714 fn into_bits() {
715 let bits = Number128::from_decimal(1242, -3).into_bits();
716 let number = Number128::from_bits(bits);
717
718 assert_eq!(Number128::from_decimal(1242, -3), number);
719 }
720
721 #[test]
722 fn mul_overflow() {
723 let x = Number128::from_decimal(u64::MAX, 0);
725 assert!(std::panic::catch_unwind(|| x * x).is_err());
726
727 let x = Number128::from_i128(i128::MIN);
729 let y = Number128::from_i128(2);
730 assert!(std::panic::catch_unwind(|| x * y).is_err());
731
732 let mut x = Number128::from_i128(i128::MAX) / 2;
734 x += Number128::from_i128(1);
735 assert!(std::panic::catch_unwind(|| x * 2).is_err());
736 }
737
738 #[test]
739 fn mul_assign_overflow() {
740 let mut x = Number128::from_decimal(u64::MAX, 0);
742 let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
743 x *= x;
744 }));
745 assert!(result.is_err());
746
747 let mut x = Number128::from_i128(i128::MIN);
749 let y = Number128::from_i128(2);
750 let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
751 x *= y;
752 }));
753 assert!(result.is_err());
754
755 let mut x = Number128::from_i128(i128::MAX) / 2;
757 x += Number128::from_i128(1);
758 let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| x * 2));
759 assert!(result.is_err());
760 }
761
762 #[test]
763 fn div_overflow() {
764 let x = Number128::from_decimal(u64::MAX, 0);
765 assert!(std::panic::catch_unwind(|| x / x).is_err());
766 let x = Number128::from_i128(i128::MIN);
767 assert!(std::panic::catch_unwind(|| x / -1).is_err());
768 assert!(std::panic::catch_unwind(|| x / 0).is_err());
769 }
770
771 #[test]
772 fn div_assign_overflow() {
773 let mut x = Number128::from_decimal(u64::MAX, 0);
774 let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
775 x /= x;
776 }));
777 assert!(result.is_err());
778
779 let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
780 x /= Number128::from_i128(-1);
781 }));
782 assert!(result.is_err());
783
784 let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
785 x /= Number128::from_i128(0);
786 }));
787 assert!(result.is_err());
788 }
789
790 #[test]
791 fn div_into_overflow() {
792 let x = Number128::from_i128(i128::MIN);
793 assert!(std::panic::catch_unwind(|| x / -1).is_err());
794 assert!(std::panic::catch_unwind(|| x / 0).is_err());
795 }
796}