psy_math/
number_128.rs

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/// A fixed-point decimal number 128 bits wide
25#[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    /// Convert this number to fit in a u64
37    ///
38    /// The precision of the number in the u64 is based on the
39    /// exponent provided.
40    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    /// Convert this number to a f64
62    pub fn as_f64(&self) -> f64 {
63        // i128::{MAX|MIN} fits within f64
64        self.to_i128() as f64 / 10_000_000_000.0
65    }
66
67    /// Convert another integer
68    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    /// Convert from basis points
80    pub fn from_bps(basis_points: u16) -> Self {
81        Self::from_decimal(basis_points, crate::BPS_EXPONENT)
82    }
83
84    /// Get the underlying 128-bit representation in bytes.
85    /// Uses the target endianness of the caller
86    pub fn into_bits(self) -> [u8; 16] {
87        self.0.to_ne_bytes()
88    }
89
90    /// Read a number from a raw 128-bit representation, which was previously
91    /// returned by a call to `into_bits`.
92    /// Uses the target endianness of the caller
93    pub fn from_bits(bits: [u8; 16]) -> Self {
94        Self(i128::from_ne_bytes(bits))
95    }
96
97    /// Get the underlying i128 value
98    pub fn to_i128(self) -> i128 {
99        self.0
100    }
101
102    /// Create `Number128` from an `i128`
103    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        // todo optimize
117        let rem = self.0 % ONE;
118        let decimal_digits = PRECISION as usize;
119        // convert to abs to remove sign
120        let rem_str = rem.checked_abs().unwrap().to_string();
121        // regular padding like {:010} doesn't work with i128
122        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        // Product is divided by ONE as RHS is also a fixed point number.
177        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        // Product is divided by ONE as RHS is also a fixed point number.
184        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        // Both div and checked_div panic on overflow or zero division,
193        // so we use div directly.
194        // print!("div: {} / {} = ", mul_by_one(self.0), rhs.0);
195        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        // Both div and checked_div panic on overflow or zero division,
202        // so we use div directly.
203        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        // Both div and checked_div panic on overflow or zero division,
220        // so we use div directly.
221        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}
238/// Divides value by ONE, which is `10_000_000_000_i128`. Supports all values from `i128::MIN` to `MAX`
239fn div_by_one(value: i128) -> i128 {
240    // This is implemented as a right bit-shift (on absolute value) by 10,
241    // followed by a division by `9_765_625` (which is `5^10`), as this is faster
242    // than a division by `10_000_000_000`. The sign is then restored before returning the result.
243
244    // abs_result is expected to be positive unless
245    // value.abs() has overflowed when value == i128::MIN
246    let abs_result = (value.abs() >> 10) / (9_765_625_i128);
247
248    // Return result with sign of original value.
249    // Edge Case: For abs_result < 0, when value == i128::MIN, abs_result is the correct value
250    // without any sign change, as the overflow has already caused the sign to change.
251    if value > 0 || abs_result < 0 {
252        abs_result
253    } else {
254        -abs_result
255    }
256}
257
258const ONE_REPR_BITS: u32 = 34; // bits needed to represent ONE (excluding sign bit)
259
260/// Multiplies value by ONE, which is `10_000_000_000_i128`.
261///
262/// Largest supported input: `i128::MAX >> 34 = 2^93 ~= 9.9^27`
263///
264/// Smallest supported input: `i128::MIN >> 35 = -2^93 ~= -9.9^27`
265fn mul_by_one(value: i128) -> i128 {
266    // This is implemented as multiplication by `9_765_625` (which is `5^10`), followed by
267    // a left bit-shift by 10, as this is faster than a multiplication by `10_000_000_000`.
268
269    // Check that sum of bits required to represent product does not exceed
270    // 128 bits. This is a conservative estimate, so it may return false positives.
271    // Note that checked_abs is not used here, since the overflow case (i128::MIN) would
272    // be caught by the following check.
273    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
280/// Checks if the multiplication of two i128 values will overflow, This is
281/// a conservative estimate, so it may return false positives
282/// (detecting overflow when there is none).
283fn fast_checked_mul(left: i128, right: i128) -> Option<i128> {
284    if right == 0 || left == 0 {
285        return Some(0);
286    }
287
288    // Convert values to positive first, as negative value always have no leading zeros.
289    // Gets bits required to represent the absolute value, excluding the sign bit.
290    // Note that checked_abs is not used here, since the overflow case (for i128::MIN)
291    // would be caught by the following bit check.
292    let left_bits = 128 - left.abs().leading_zeros();
293    let right_bits = 128 - right.abs().leading_zeros();
294
295    // Assume that a conservative case that both right and left value have
296    // ones for left_bits and right_bits respectively. Therefore, the product
297    // of the two values will require left_bits + right_bits bits to represent,
298    // plus one sign bit.z
299    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        // Mul
340        assert_eq!(Number128::ONE, Number128::ONE * Number128::ONE);
341
342        // MulAssign
343        let mut x = Number128::ONE;
344        x *= Number128::ONE;
345        assert_eq!(Number128::ONE, x);
346
347        // Mul Into
348        assert_eq!(Number128::ONE, Number128::ONE * 1);
349    }
350
351    #[test]
352    fn one_divided_by_one_equals_one() {
353        // Div
354        assert_eq!(Number128::ONE, Number128::ONE / Number128::ONE);
355
356        // DivAssign
357        let mut x = Number128::ONE;
358        x /= Number128::ONE;
359        assert_eq!(Number128::ONE, x);
360
361        // Div Into
362        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        // Multiple of ONE or -ONE by ONE
370        assert_eq!(mul_by_one(one), one * one);
371        assert_eq!(mul_by_one(-one), -one * one);
372
373        // Multiple of (abs) values smaller than ONE by ONE.
374        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        // Multiple of (abs) values larger than ONE by ONE.
381        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        // The largest supported value is an i128 where the first 33 bits following
387        // the sign bit are 0 (i128::MAX >> 34)
388        let big_value = i128::MAX >> 34;
389        assert_eq!(mul_by_one(big_value), (big_value) * one);
390        // The smallest supported value is similar, except one more bit is needed.
391        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        // Division of ONE or -ONE by ONE
425        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        // Division of (abs) values smaller than ONE by ONE.
429        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        // Division of (abs) values larger than ONE by ONE.
442        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        // No overflow on MAX value
460        assert_eq!(div_by_one(i128::MAX), i128::MAX.checked_div(one).unwrap());
461
462        // No overflow on MIN value.
463        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), // both overflow
483            (i128::MAX, 2),                 // both overflow
484            (2, i128::MAX),                 // both overflow
485            (i128::MIN, -1),                // both overflow
486            (-1, i128::MIN),                // both overflow
487            (i128::MIN, i128::MIN),         // both overflow
488        ];
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        // Test cases when fast_checked_mul detects false positives
500        // and expects overflow, even when checked_mul does not.
501        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        // Div
519        assert_eq!(
520            Number128::from_decimal(1, -1),
521            Number128::from_decimal(1, 1) / Number128::from_decimal(100, 0)
522        );
523
524        // Div Assign
525        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        // Div Into
530        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        // Test that conversion is within bounds and doesn't lose precision for min
650        let n = Number128::MIN; // -170141183460469231731687303715884105728
651        assert_eq!(-17014118346046923173168730371.5884105728, n.as_f64());
652
653        // Test that conversion is within bounds and doesn't lose precision for max
654        let n = Number128::MAX; // 170141183460469231731687303715884105727
655        assert_eq!(17014118346046923173168730371.5884105727, n.as_f64());
656
657        // More cases
658        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        // Overflow when multiplying u64 max by u64 max.
724        let x = Number128::from_decimal(u64::MAX, 0);
725        assert!(std::panic::catch_unwind(|| x * x).is_err());
726
727        // Overflow when multiplying i128 min by 2
728        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        // Overflow when multiplying ((0.5 * i128 max) + 1) by 2
733        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        // Overflow when multiplying u64 max by u64 max.
741        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        // Overflow when multiplying i128 min by 2
748        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        // Overflow when multiplying ((0.5 * i128 max) + 1) by 2
756        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}