cosmwasm_std/math/
int128.rs

1use alloc::string::{String, ToString};
2use core::fmt;
3use core::ops::{
4    Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Not, Rem, RemAssign, Shl, ShlAssign, Shr,
5    ShrAssign, Sub, SubAssign,
6};
7use core::str::FromStr;
8
9use crate::errors::{DivideByZeroError, DivisionError, OverflowError, OverflowOperation, StdError};
10use crate::forward_ref::{forward_ref_binop, forward_ref_op_assign};
11use crate::{
12    CheckedMultiplyRatioError, Int256, Int512, Int64, Uint128, Uint256, Uint512, Uint64,
13    __internal::forward_ref_partial_eq,
14};
15
16use super::conversion::{
17    forward_try_from, from_and_to_bytes, primitive_to_wrapped_int, try_from_int_to_int,
18    wrapped_int_to_primitive,
19};
20use super::impl_int_serde;
21use super::num_consts::NumConsts;
22
23/// An implementation of i128 that is using strings for JSON encoding/decoding,
24/// such that the full i128 range can be used for clients that convert JSON numbers to floats,
25/// like JavaScript and jq.
26///
27/// # Examples
28///
29/// Use `from` to create instances of this and `i128` to get the value out:
30///
31/// ```
32/// # use cosmwasm_std::Int128;
33/// let a = Int128::from(258i128);
34/// assert_eq!(a.i128(), 258);
35/// ```
36#[derive(Copy, Clone, Default, Debug, PartialEq, Eq, PartialOrd, Ord, schemars::JsonSchema)]
37pub struct Int128(#[schemars(with = "String")] pub(crate) i128);
38
39impl_int_serde!(Int128);
40forward_ref_partial_eq!(Int128, Int128);
41
42impl Int128 {
43    pub const MAX: Int128 = Int128(i128::MAX);
44    pub const MIN: Int128 = Int128(i128::MIN);
45
46    /// Creates a Int128(value).
47    ///
48    /// This method is less flexible than `from` but can be called in a const context.
49    #[inline]
50    #[must_use]
51    pub const fn new(value: i128) -> Self {
52        Self(value)
53    }
54
55    /// Creates a Int128(0)
56    #[inline]
57    pub const fn zero() -> Self {
58        Int128(0)
59    }
60
61    /// Creates a Int128(1)
62    #[inline]
63    pub const fn one() -> Self {
64        Self(1)
65    }
66
67    /// Returns a copy of the internal data
68    pub const fn i128(&self) -> i128 {
69        self.0
70    }
71
72    from_and_to_bytes!(i128, 16);
73
74    #[must_use]
75    pub const fn is_zero(&self) -> bool {
76        self.0 == 0
77    }
78
79    #[must_use]
80    pub const fn is_negative(&self) -> bool {
81        self.0.is_negative()
82    }
83
84    #[must_use = "this returns the result of the operation, without modifying the original"]
85    pub const fn pow(self, exp: u32) -> Self {
86        match self.0.checked_pow(exp) {
87            Some(val) => Self(val),
88            None => panic!("attempt to exponentiate with overflow"),
89        }
90    }
91
92    /// Returns `self * numerator / denominator`.
93    ///
94    /// Due to the nature of the integer division involved, the result is always floored.
95    /// E.g. 5 * 99/100 = 4.
96    pub fn checked_multiply_ratio<A: Into<Self>, B: Into<Self>>(
97        &self,
98        numerator: A,
99        denominator: B,
100    ) -> Result<Self, CheckedMultiplyRatioError> {
101        let numerator = numerator.into();
102        let denominator = denominator.into();
103        if denominator.is_zero() {
104            return Err(CheckedMultiplyRatioError::DivideByZero);
105        }
106        match (self.full_mul(numerator) / Int256::from(denominator)).try_into() {
107            Ok(ratio) => Ok(ratio),
108            Err(_) => Err(CheckedMultiplyRatioError::Overflow),
109        }
110    }
111
112    /// Multiplies two [`Int128`] values without overflow, producing an
113    /// [`Int256`].
114    ///
115    /// # Examples
116    ///
117    /// ```
118    /// use cosmwasm_std::Int128;
119    ///
120    /// let a = Int128::MAX;
121    /// let result = a.full_mul(2i32);
122    /// assert_eq!(result.to_string(), "340282366920938463463374607431768211454");
123    /// ```
124    #[must_use = "this returns the result of the operation, without modifying the original"]
125    pub fn full_mul(self, rhs: impl Into<Self>) -> Int256 {
126        Int256::from(self)
127            .checked_mul(Int256::from(rhs.into()))
128            .unwrap()
129    }
130
131    pub fn checked_add(self, other: Self) -> Result<Self, OverflowError> {
132        self.0
133            .checked_add(other.0)
134            .map(Self)
135            .ok_or_else(|| OverflowError::new(OverflowOperation::Add))
136    }
137
138    pub fn checked_sub(self, other: Self) -> Result<Self, OverflowError> {
139        self.0
140            .checked_sub(other.0)
141            .map(Self)
142            .ok_or_else(|| OverflowError::new(OverflowOperation::Sub))
143    }
144
145    pub fn checked_mul(self, other: Self) -> Result<Self, OverflowError> {
146        self.0
147            .checked_mul(other.0)
148            .map(Self)
149            .ok_or_else(|| OverflowError::new(OverflowOperation::Mul))
150    }
151
152    pub fn checked_pow(self, exp: u32) -> Result<Self, OverflowError> {
153        self.0
154            .checked_pow(exp)
155            .map(Self)
156            .ok_or_else(|| OverflowError::new(OverflowOperation::Pow))
157    }
158
159    pub fn checked_div(self, other: Self) -> Result<Self, DivisionError> {
160        if other.is_zero() {
161            return Err(DivisionError::DivideByZero);
162        }
163        self.0
164            .checked_div(other.0)
165            .map(Self)
166            .ok_or(DivisionError::Overflow)
167    }
168
169    pub fn checked_div_euclid(self, other: Self) -> Result<Self, DivisionError> {
170        if other.is_zero() {
171            return Err(DivisionError::DivideByZero);
172        }
173        self.0
174            .checked_div_euclid(other.0)
175            .map(Self)
176            .ok_or(DivisionError::Overflow)
177    }
178
179    pub fn checked_rem(self, other: Self) -> Result<Self, DivideByZeroError> {
180        self.0
181            .checked_rem(other.0)
182            .map(Self)
183            .ok_or(DivideByZeroError)
184    }
185
186    pub fn checked_shr(self, other: u32) -> Result<Self, OverflowError> {
187        if other >= 128 {
188            return Err(OverflowError::new(OverflowOperation::Shr));
189        }
190
191        Ok(Self(self.0.shr(other)))
192    }
193
194    pub fn checked_shl(self, other: u32) -> Result<Self, OverflowError> {
195        if other >= 128 {
196            return Err(OverflowError::new(OverflowOperation::Shl));
197        }
198
199        Ok(Self(self.0.shl(other)))
200    }
201
202    #[must_use = "this returns the result of the operation, without modifying the original"]
203    #[inline]
204    pub fn wrapping_add(self, other: Self) -> Self {
205        Self(self.0.wrapping_add(other.0))
206    }
207
208    #[must_use = "this returns the result of the operation, without modifying the original"]
209    #[inline]
210    pub fn wrapping_sub(self, other: Self) -> Self {
211        Self(self.0.wrapping_sub(other.0))
212    }
213
214    #[must_use = "this returns the result of the operation, without modifying the original"]
215    #[inline]
216    pub fn wrapping_mul(self, other: Self) -> Self {
217        Self(self.0.wrapping_mul(other.0))
218    }
219
220    #[must_use = "this returns the result of the operation, without modifying the original"]
221    #[inline]
222    pub fn wrapping_pow(self, other: u32) -> Self {
223        Self(self.0.wrapping_pow(other))
224    }
225
226    #[must_use = "this returns the result of the operation, without modifying the original"]
227    pub fn saturating_add(self, other: Self) -> Self {
228        Self(self.0.saturating_add(other.0))
229    }
230
231    #[must_use = "this returns the result of the operation, without modifying the original"]
232    pub fn saturating_sub(self, other: Self) -> Self {
233        Self(self.0.saturating_sub(other.0))
234    }
235
236    #[must_use = "this returns the result of the operation, without modifying the original"]
237    pub fn saturating_mul(self, other: Self) -> Self {
238        Self(self.0.saturating_mul(other.0))
239    }
240
241    #[must_use = "this returns the result of the operation, without modifying the original"]
242    pub fn saturating_pow(self, exp: u32) -> Self {
243        Self(self.0.saturating_pow(exp))
244    }
245
246    #[must_use = "this returns the result of the operation, without modifying the original"]
247    pub const fn abs_diff(self, other: Self) -> Uint128 {
248        Uint128(self.0.abs_diff(other.0))
249    }
250
251    #[must_use = "this returns the result of the operation, without modifying the original"]
252    pub const fn abs(self) -> Self {
253        match self.0.checked_abs() {
254            Some(val) => Self(val),
255            None => panic!("attempt to calculate absolute value with overflow"),
256        }
257    }
258
259    #[must_use = "this returns the result of the operation, without modifying the original"]
260    pub const fn unsigned_abs(self) -> Uint128 {
261        Uint128(self.0.unsigned_abs())
262    }
263
264    /// Strict negation. Computes -self, panicking if self == MIN.
265    ///
266    /// This is the same as [`Int128::neg`] but const.
267    pub const fn strict_neg(self) -> Self {
268        match self.0.checked_neg() {
269            Some(val) => Self(val),
270            None => panic!("attempt to negate with overflow"),
271        }
272    }
273}
274
275impl NumConsts for Int128 {
276    const ZERO: Self = Self::zero();
277    const ONE: Self = Self::one();
278    const MAX: Self = Self::MAX;
279    const MIN: Self = Self::MIN;
280}
281
282// Uint to Int
283impl From<Uint64> for Int128 {
284    fn from(val: Uint64) -> Self {
285        val.u64().into()
286    }
287}
288forward_try_from!(Uint128, Int128);
289forward_try_from!(Uint256, Int128);
290forward_try_from!(Uint512, Int128);
291
292// uint to Int
293primitive_to_wrapped_int!(u8, Int128);
294primitive_to_wrapped_int!(u16, Int128);
295primitive_to_wrapped_int!(u32, Int128);
296primitive_to_wrapped_int!(u64, Int128);
297
298// Int to Int
299impl From<Int64> for Int128 {
300    fn from(val: Int64) -> Self {
301        val.i64().into()
302    }
303}
304
305try_from_int_to_int!(Int256, Int128);
306try_from_int_to_int!(Int512, Int128);
307
308// int to Int
309primitive_to_wrapped_int!(i8, Int128);
310primitive_to_wrapped_int!(i16, Int128);
311primitive_to_wrapped_int!(i32, Int128);
312primitive_to_wrapped_int!(i64, Int128);
313primitive_to_wrapped_int!(i128, Int128);
314
315// Int to int
316wrapped_int_to_primitive!(Int128, i128);
317
318impl TryFrom<&str> for Int128 {
319    type Error = StdError;
320
321    fn try_from(val: &str) -> Result<Self, Self::Error> {
322        Self::from_str(val)
323    }
324}
325
326impl FromStr for Int128 {
327    type Err = StdError;
328
329    fn from_str(s: &str) -> Result<Self, Self::Err> {
330        match s.parse::<i128>() {
331            Ok(u) => Ok(Self(u)),
332            Err(e) => Err(StdError::generic_err(format!("Parsing Int128: {e}"))),
333        }
334    }
335}
336
337impl From<Int128> for String {
338    fn from(original: Int128) -> Self {
339        original.to_string()
340    }
341}
342
343impl fmt::Display for Int128 {
344    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
345        self.0.fmt(f)
346    }
347}
348
349impl Add<Int128> for Int128 {
350    type Output = Self;
351
352    fn add(self, rhs: Self) -> Self {
353        Int128(self.0.checked_add(rhs.0).unwrap())
354    }
355}
356forward_ref_binop!(impl Add, add for Int128, Int128);
357
358impl Sub<Int128> for Int128 {
359    type Output = Self;
360
361    fn sub(self, rhs: Self) -> Self {
362        Int128(self.0.checked_sub(rhs.0).unwrap())
363    }
364}
365forward_ref_binop!(impl Sub, sub for Int128, Int128);
366
367impl SubAssign<Int128> for Int128 {
368    fn sub_assign(&mut self, rhs: Int128) {
369        self.0 = self.0.checked_sub(rhs.0).unwrap();
370    }
371}
372forward_ref_op_assign!(impl SubAssign, sub_assign for Int128, Int128);
373
374impl Div<Int128> for Int128 {
375    type Output = Self;
376
377    fn div(self, rhs: Self) -> Self::Output {
378        Self(self.0.checked_div(rhs.0).unwrap())
379    }
380}
381forward_ref_binop!(impl Div, div for Int128, Int128);
382
383impl Rem for Int128 {
384    type Output = Self;
385
386    /// # Panics
387    ///
388    /// This operation will panic if `rhs` is zero.
389    #[inline]
390    fn rem(self, rhs: Self) -> Self {
391        Self(self.0.rem(rhs.0))
392    }
393}
394forward_ref_binop!(impl Rem, rem for Int128, Int128);
395
396impl Not for Int128 {
397    type Output = Self;
398
399    fn not(self) -> Self::Output {
400        Self(!self.0)
401    }
402}
403
404impl Neg for Int128 {
405    type Output = Self;
406
407    fn neg(self) -> Self::Output {
408        self.strict_neg()
409    }
410}
411
412impl RemAssign<Int128> for Int128 {
413    fn rem_assign(&mut self, rhs: Int128) {
414        *self = *self % rhs;
415    }
416}
417forward_ref_op_assign!(impl RemAssign, rem_assign for Int128, Int128);
418
419impl Mul<Int128> for Int128 {
420    type Output = Self;
421
422    fn mul(self, rhs: Self) -> Self::Output {
423        Self(self.0.checked_mul(rhs.0).unwrap())
424    }
425}
426forward_ref_binop!(impl Mul, mul for Int128, Int128);
427
428impl MulAssign<Int128> for Int128 {
429    fn mul_assign(&mut self, rhs: Self) {
430        self.0 = self.0.checked_mul(rhs.0).unwrap();
431    }
432}
433forward_ref_op_assign!(impl MulAssign, mul_assign for Int128, Int128);
434
435impl Shr<u32> for Int128 {
436    type Output = Self;
437
438    fn shr(self, rhs: u32) -> Self::Output {
439        self.checked_shr(rhs).unwrap_or_else(|_| {
440            panic!("right shift error: {rhs} is larger or equal than the number of bits in Int128",)
441        })
442    }
443}
444forward_ref_binop!(impl Shr, shr for Int128, u32);
445
446impl Shl<u32> for Int128 {
447    type Output = Self;
448
449    fn shl(self, rhs: u32) -> Self::Output {
450        self.checked_shl(rhs).unwrap_or_else(|_| {
451            panic!("left shift error: {rhs} is larger or equal than the number of bits in Int128",)
452        })
453    }
454}
455forward_ref_binop!(impl Shl, shl for Int128, u32);
456
457impl AddAssign<Int128> for Int128 {
458    fn add_assign(&mut self, rhs: Int128) {
459        self.0 = self.0.checked_add(rhs.0).unwrap();
460    }
461}
462forward_ref_op_assign!(impl AddAssign, add_assign for Int128, Int128);
463
464impl DivAssign<Int128> for Int128 {
465    fn div_assign(&mut self, rhs: Self) {
466        self.0 = self.0.checked_div(rhs.0).unwrap();
467    }
468}
469forward_ref_op_assign!(impl DivAssign, div_assign for Int128, Int128);
470
471impl ShrAssign<u32> for Int128 {
472    fn shr_assign(&mut self, rhs: u32) {
473        *self = Shr::<u32>::shr(*self, rhs);
474    }
475}
476forward_ref_op_assign!(impl ShrAssign, shr_assign for Int128, u32);
477
478impl ShlAssign<u32> for Int128 {
479    fn shl_assign(&mut self, rhs: u32) {
480        *self = Shl::<u32>::shl(*self, rhs);
481    }
482}
483forward_ref_op_assign!(impl ShlAssign, shl_assign for Int128, u32);
484
485impl<A> core::iter::Sum<A> for Int128
486where
487    Self: Add<A, Output = Self>,
488{
489    fn sum<I: Iterator<Item = A>>(iter: I) -> Self {
490        iter.fold(Self::zero(), Add::add)
491    }
492}
493
494#[cfg(test)]
495mod tests {
496    use super::*;
497    use crate::math::conversion::test_try_from_uint_to_int;
498
499    #[test]
500    fn size_of_works() {
501        assert_eq!(core::mem::size_of::<Int128>(), 16);
502    }
503
504    #[test]
505    fn int128_from_be_bytes_works() {
506        // zero
507        let original = [0; 16];
508        let num = Int128::from_be_bytes(original);
509        assert!(num.is_zero());
510
511        // one
512        let original = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1];
513        let num = Int128::from_be_bytes(original);
514        assert_eq!(num.i128(), 1);
515
516        // 258
517        let original = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2];
518        let num = Int128::from_be_bytes(original);
519        assert_eq!(num.i128(), 258);
520
521        // 2x roundtrip
522        let original = [1; 16];
523        let num = Int128::from_be_bytes(original);
524        let a: [u8; 16] = num.to_be_bytes();
525        assert_eq!(a, original);
526
527        let original = [
528            0u8, 222u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 2u8, 3u8,
529        ];
530        let num = Int128::from_be_bytes(original);
531        let resulting_bytes: [u8; 16] = num.to_be_bytes();
532        assert_eq!(resulting_bytes, original);
533    }
534
535    #[test]
536    fn int128_from_le_bytes_works() {
537        // zero
538        let original = [0; 16];
539        let num = Int128::from_le_bytes(original);
540        assert!(num.is_zero());
541
542        // one
543        let original = [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
544        let num = Int128::from_le_bytes(original);
545        assert_eq!(num.i128(), 1);
546
547        // 258
548        let original = [2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
549        let num = Int128::from_le_bytes(original);
550        assert_eq!(num.i128(), 258);
551
552        // 2x roundtrip
553        let original = [1; 16];
554        let num = Int128::from_le_bytes(original);
555        let a: [u8; 16] = num.to_le_bytes();
556        assert_eq!(a, original);
557
558        let original = [
559            0u8, 222u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 2u8, 3u8,
560        ];
561        let num = Int128::from_le_bytes(original);
562        let resulting_bytes: [u8; 16] = num.to_le_bytes();
563        assert_eq!(resulting_bytes, original);
564    }
565
566    #[test]
567    fn int128_new_works() {
568        let num = Int128::new(222);
569        assert_eq!(num.i128(), 222);
570
571        let num = Int128::new(-222);
572        assert_eq!(num.i128(), -222);
573
574        let num = Int128::new(i128::MAX);
575        assert_eq!(num.i128(), i128::MAX);
576
577        let num = Int128::new(i128::MIN);
578        assert_eq!(num.i128(), i128::MIN);
579    }
580
581    #[test]
582    fn int128_not_works() {
583        assert_eq!(!Int128::new(222), Int128::new(!222));
584        assert_eq!(!Int128::new(-222), Int128::new(!-222));
585
586        assert_eq!(!Int128::MAX, Int128::new(!i128::MAX));
587        assert_eq!(!Int128::MIN, Int128::new(!i128::MIN));
588    }
589
590    #[test]
591    fn int128_zero_works() {
592        let zero = Int128::zero();
593        assert_eq!(zero.to_be_bytes(), [0; 16]);
594    }
595
596    #[test]
597    fn uint128_one_works() {
598        let one = Int128::one();
599        let mut one_be = [0; 16];
600        one_be[15] = 1;
601
602        assert_eq!(one.to_be_bytes(), one_be);
603    }
604
605    #[test]
606    fn int128_endianness() {
607        let be_bytes = [
608            0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 2u8, 3u8,
609        ];
610        let le_bytes = [
611            3u8, 2u8, 1u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
612        ];
613
614        // These should all be the same.
615        let num1 = Int128::from_be_bytes(be_bytes);
616        let num2 = Int128::from_le_bytes(le_bytes);
617        assert_eq!(num1, Int128::from(65536u32 + 512 + 3));
618        assert_eq!(num1, num2);
619    }
620
621    #[test]
622    fn int128_convert_to() {
623        let a = Int128::new(5);
624        assert_eq!(i128::from(a), 5);
625    }
626
627    #[test]
628    fn int128_convert_from() {
629        let a = Int128::from(5i128);
630        assert_eq!(a.0, i128::from(5u32));
631
632        let a = Int128::from(5u64);
633        assert_eq!(a.0, i128::from(5u32));
634
635        let a = Int128::from(5u32);
636        assert_eq!(a.0, i128::from(5u32));
637
638        let a = Int128::from(5u16);
639        assert_eq!(a.0, i128::from(5u32));
640
641        let a = Int128::from(5u8);
642        assert_eq!(a.0, i128::from(5u32));
643
644        let a = Int128::from(-5i128);
645        assert_eq!(a.0, i128::from(-5i32));
646
647        let a = Int128::from(-5i64);
648        assert_eq!(a.0, i128::from(-5i32));
649
650        let a = Int128::from(-5i32);
651        assert_eq!(a.0, i128::from(-5i32));
652
653        let a = Int128::from(-5i16);
654        assert_eq!(a.0, i128::from(-5i32));
655
656        let a = Int128::from(-5i8);
657        assert_eq!(a.0, i128::from(-5i32));
658
659        let result = Int128::try_from("34567");
660        assert_eq!(result.unwrap().0, "34567".parse::<i128>().unwrap());
661
662        let result = Int128::try_from("1.23");
663        assert!(result.is_err());
664    }
665
666    #[test]
667    fn int128_try_from_unsigned_works() {
668        test_try_from_uint_to_int::<Uint128, Int128>("Uint128", "Int128");
669        test_try_from_uint_to_int::<Uint256, Int128>("Uint256", "Int128");
670        test_try_from_uint_to_int::<Uint512, Int128>("Uint512", "Int128");
671    }
672
673    #[test]
674    fn int128_implements_display() {
675        let a = Int128::from(12345u32);
676        assert_eq!(format!("Embedded: {a}"), "Embedded: 12345");
677        assert_eq!(a.to_string(), "12345");
678
679        let a = Int128::from(-12345i32);
680        assert_eq!(format!("Embedded: {a}"), "Embedded: -12345");
681        assert_eq!(a.to_string(), "-12345");
682
683        let a = Int128::zero();
684        assert_eq!(format!("Embedded: {a}"), "Embedded: 0");
685        assert_eq!(a.to_string(), "0");
686    }
687
688    #[test]
689    fn int128_display_padding_works() {
690        // width > natural representation
691        let a = Int128::from(123u64);
692        assert_eq!(format!("Embedded: {a:05}"), "Embedded: 00123");
693        let a = Int128::from(-123i64);
694        assert_eq!(format!("Embedded: {a:05}"), "Embedded: -0123");
695
696        // width < natural representation
697        let a = Int128::from(123u64);
698        assert_eq!(format!("Embedded: {a:02}"), "Embedded: 123");
699        let a = Int128::from(-123i64);
700        assert_eq!(format!("Embedded: {a:02}"), "Embedded: -123");
701    }
702
703    #[test]
704    fn int128_to_be_bytes_works() {
705        assert_eq!(Int128::zero().to_be_bytes(), [0; 16]);
706
707        let mut max = [0xff; 16];
708        max[0] = 0x7f;
709        assert_eq!(Int128::MAX.to_be_bytes(), max);
710
711        let mut one = [0; 16];
712        one[15] = 1;
713        assert_eq!(Int128::from(1i128).to_be_bytes(), one);
714        // Python: `[b for b in (70141183460469231731687303715884018880).to_bytes(16, "big")]`
715        assert_eq!(
716            Int128::from(70141183460469231731687303715884018880i128).to_be_bytes(),
717            [52, 196, 179, 87, 165, 121, 59, 133, 246, 117, 221, 191, 255, 254, 172, 192]
718        );
719        assert_eq!(
720            Int128::from_be_bytes([17, 4, 23, 32, 87, 67, 123, 200, 58, 91, 0, 38, 33, 21, 67, 78])
721                .to_be_bytes(),
722            [17, 4, 23, 32, 87, 67, 123, 200, 58, 91, 0, 38, 33, 21, 67, 78]
723        );
724    }
725
726    #[test]
727    fn int128_to_le_bytes_works() {
728        assert_eq!(Int128::zero().to_le_bytes(), [0; 16]);
729
730        let mut max = [0xff; 16];
731        max[15] = 0x7f;
732        assert_eq!(Int128::MAX.to_le_bytes(), max);
733
734        let mut one = [0; 16];
735        one[0] = 1;
736        assert_eq!(Int128::from(1i128).to_le_bytes(), one);
737        // Python: `[b for b in (70141183460469231731687303715884018880).to_bytes(16, "little")]`
738        assert_eq!(
739            Int128::from(70141183460469231731687303715884018880i128).to_le_bytes(),
740            [192, 172, 254, 255, 191, 221, 117, 246, 133, 59, 121, 165, 87, 179, 196, 52]
741        );
742        assert_eq!(
743            Int128::from_be_bytes([17, 4, 23, 32, 87, 67, 123, 200, 58, 91, 0, 38, 33, 21, 67, 78])
744                .to_le_bytes(),
745            [78, 67, 21, 33, 38, 0, 91, 58, 200, 123, 67, 87, 32, 23, 4, 17]
746        );
747    }
748
749    #[test]
750    fn int128_is_zero_works() {
751        assert!(Int128::zero().is_zero());
752        assert!(Int128(i128::from(0u32)).is_zero());
753
754        assert!(!Int128::from(1u32).is_zero());
755        assert!(!Int128::from(123u32).is_zero());
756        assert!(!Int128::from(-123i32).is_zero());
757    }
758
759    #[test]
760    fn int128_is_negative_works() {
761        assert!(Int128::MIN.is_negative());
762        assert!(Int128::from(-123i32).is_negative());
763
764        assert!(!Int128::MAX.is_negative());
765        assert!(!Int128::zero().is_negative());
766        assert!(!Int128::from(123u32).is_negative());
767    }
768
769    #[test]
770    fn int128_wrapping_methods() {
771        // wrapping_add
772        assert_eq!(
773            Int128::from(2u32).wrapping_add(Int128::from(2u32)),
774            Int128::from(4u32)
775        ); // non-wrapping
776        assert_eq!(Int128::MAX.wrapping_add(Int128::from(1u32)), Int128::MIN); // wrapping
777
778        // wrapping_sub
779        assert_eq!(
780            Int128::from(7u32).wrapping_sub(Int128::from(5u32)),
781            Int128::from(2u32)
782        ); // non-wrapping
783        assert_eq!(Int128::MIN.wrapping_sub(Int128::from(1u32)), Int128::MAX); // wrapping
784
785        // wrapping_mul
786        assert_eq!(
787            Int128::from(3u32).wrapping_mul(Int128::from(2u32)),
788            Int128::from(6u32)
789        ); // non-wrapping
790        assert_eq!(
791            Int128::MAX.wrapping_mul(Int128::from(2u32)),
792            Int128::from(-2i32)
793        ); // wrapping
794
795        // wrapping_pow
796        assert_eq!(Int128::from(2u32).wrapping_pow(3), Int128::from(8u32)); // non-wrapping
797        assert_eq!(Int128::MAX.wrapping_pow(2), Int128::from(1u32)); // wrapping
798    }
799
800    #[test]
801    fn int128_json() {
802        let orig = Int128::from(1234567890987654321i128);
803        let serialized = serde_json::to_vec(&orig).unwrap();
804        assert_eq!(serialized.as_slice(), b"\"1234567890987654321\"");
805        let parsed: Int128 = serde_json::from_slice(&serialized).unwrap();
806        assert_eq!(parsed, orig);
807    }
808
809    #[test]
810    fn int128_compare() {
811        let a = Int128::from(12345u32);
812        let b = Int128::from(23456u32);
813
814        assert!(a < b);
815        assert!(b > a);
816        assert_eq!(a, Int128::from(12345u32));
817    }
818
819    #[test]
820    #[allow(clippy::op_ref)]
821    fn int128_math() {
822        let a = Int128::from(-12345i32);
823        let b = Int128::from(23456u32);
824
825        // test + with owned and reference right hand side
826        assert_eq!(a + b, Int128::from(11111u32));
827        assert_eq!(a + &b, Int128::from(11111u32));
828
829        // test - with owned and reference right hand side
830        assert_eq!(b - a, Int128::from(35801u32));
831        assert_eq!(b - &a, Int128::from(35801u32));
832
833        // test += with owned and reference right hand side
834        let mut c = Int128::from(300000u32);
835        c += b;
836        assert_eq!(c, Int128::from(323456u32));
837        let mut d = Int128::from(300000u32);
838        d += &b;
839        assert_eq!(d, Int128::from(323456u32));
840
841        // test -= with owned and reference right hand side
842        let mut c = Int128::from(300000u32);
843        c -= b;
844        assert_eq!(c, Int128::from(276544u32));
845        let mut d = Int128::from(300000u32);
846        d -= &b;
847        assert_eq!(d, Int128::from(276544u32));
848
849        // test - with negative result
850        assert_eq!(a - b, Int128::from(-35801i32));
851    }
852
853    #[test]
854    #[should_panic]
855    fn int128_add_overflow_panics() {
856        let _ = Int128::MAX + Int128::from(12u32);
857    }
858
859    #[test]
860    #[allow(clippy::op_ref)]
861    fn int128_sub_works() {
862        assert_eq!(Int128::from(2u32) - Int128::from(1u32), Int128::from(1u32));
863        assert_eq!(Int128::from(2u32) - Int128::from(0u32), Int128::from(2u32));
864        assert_eq!(Int128::from(2u32) - Int128::from(2u32), Int128::from(0u32));
865        assert_eq!(Int128::from(2u32) - Int128::from(3u32), Int128::from(-1i32));
866
867        // works for refs
868        let a = Int128::from(10u32);
869        let b = Int128::from(3u32);
870        let expected = Int128::from(7u32);
871        assert_eq!(a - b, expected);
872        assert_eq!(a - &b, expected);
873        assert_eq!(&a - b, expected);
874        assert_eq!(&a - &b, expected);
875    }
876
877    #[test]
878    #[should_panic]
879    fn int128_sub_overflow_panics() {
880        let _ = Int128::MIN + Int128::one() - Int128::from(2u32);
881    }
882
883    #[test]
884    fn int128_sub_assign_works() {
885        let mut a = Int128::from(14u32);
886        a -= Int128::from(2u32);
887        assert_eq!(a, Int128::from(12u32));
888
889        // works for refs
890        let mut a = Int128::from(10u32);
891        let b = Int128::from(3u32);
892        let expected = Int128::from(7u32);
893        a -= &b;
894        assert_eq!(a, expected);
895    }
896
897    #[test]
898    #[allow(clippy::op_ref)]
899    fn int128_mul_works() {
900        assert_eq!(Int128::from(2u32) * Int128::from(3u32), Int128::from(6u32));
901        assert_eq!(Int128::from(2u32) * Int128::zero(), Int128::zero());
902
903        // works for refs
904        let a = Int128::from(11u32);
905        let b = Int128::from(3u32);
906        let expected = Int128::from(33u32);
907        assert_eq!(a * b, expected);
908        assert_eq!(a * &b, expected);
909        assert_eq!(&a * b, expected);
910        assert_eq!(&a * &b, expected);
911    }
912
913    #[test]
914    fn int128_mul_assign_works() {
915        let mut a = Int128::from(14u32);
916        a *= Int128::from(2u32);
917        assert_eq!(a, Int128::from(28u32));
918
919        // works for refs
920        let mut a = Int128::from(10u32);
921        let b = Int128::from(3u32);
922        a *= &b;
923        assert_eq!(a, Int128::from(30u32));
924    }
925
926    #[test]
927    fn int128_pow_works() {
928        assert_eq!(Int128::from(2u32).pow(2), Int128::from(4u32));
929        assert_eq!(Int128::from(2u32).pow(10), Int128::from(1024u32));
930    }
931
932    #[test]
933    #[should_panic]
934    fn int128_pow_overflow_panics() {
935        _ = Int128::MAX.pow(2u32);
936    }
937
938    #[test]
939    fn int128_checked_multiply_ratio_works() {
940        let base = Int128(500);
941
942        // factor 1/1
943        assert_eq!(base.checked_multiply_ratio(1i128, 1i128).unwrap(), base);
944        assert_eq!(base.checked_multiply_ratio(3i128, 3i128).unwrap(), base);
945        assert_eq!(
946            base.checked_multiply_ratio(654321i128, 654321i128).unwrap(),
947            base
948        );
949        assert_eq!(
950            base.checked_multiply_ratio(i128::MAX, i128::MAX).unwrap(),
951            base
952        );
953
954        // factor 3/2
955        assert_eq!(
956            base.checked_multiply_ratio(3i128, 2i128).unwrap(),
957            Int128(750)
958        );
959        assert_eq!(
960            base.checked_multiply_ratio(333333i128, 222222i128).unwrap(),
961            Int128(750)
962        );
963
964        // factor 2/3 (integer division always floors the result)
965        assert_eq!(
966            base.checked_multiply_ratio(2i128, 3i128).unwrap(),
967            Int128(333)
968        );
969        assert_eq!(
970            base.checked_multiply_ratio(222222i128, 333333i128).unwrap(),
971            Int128(333)
972        );
973
974        // factor 5/6 (integer division always floors the result)
975        assert_eq!(
976            base.checked_multiply_ratio(5i128, 6i128).unwrap(),
977            Int128(416)
978        );
979        assert_eq!(
980            base.checked_multiply_ratio(100i128, 120i128).unwrap(),
981            Int128(416)
982        );
983    }
984
985    #[test]
986    fn int128_checked_multiply_ratio_does_not_panic() {
987        assert_eq!(
988            Int128(500i128).checked_multiply_ratio(1i128, 0i128),
989            Err(CheckedMultiplyRatioError::DivideByZero),
990        );
991        assert_eq!(
992            Int128(500i128).checked_multiply_ratio(i128::MAX, 1i128),
993            Err(CheckedMultiplyRatioError::Overflow),
994        );
995    }
996
997    #[test]
998    fn int128_shr_works() {
999        let original = Int128::from_be_bytes([
1000            0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 4u8, 2u8,
1001        ]);
1002
1003        let shifted = Int128::from_be_bytes([
1004            0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 128u8, 1u8, 0u8,
1005        ]);
1006
1007        assert_eq!(original >> 2u32, shifted);
1008    }
1009
1010    #[test]
1011    #[should_panic]
1012    fn int128_shr_overflow_panics() {
1013        let _ = Int128::from(1u32) >> 128u32;
1014    }
1015
1016    #[test]
1017    fn sum_works() {
1018        let nums = vec![
1019            Int128::from(17u32),
1020            Int128::from(123u32),
1021            Int128::from(540u32),
1022            Int128::from(82u32),
1023        ];
1024        let expected = Int128::from(762u32);
1025
1026        let sum_as_ref: Int128 = nums.iter().sum();
1027        assert_eq!(expected, sum_as_ref);
1028
1029        let sum_as_owned: Int128 = nums.into_iter().sum();
1030        assert_eq!(expected, sum_as_owned);
1031    }
1032
1033    #[test]
1034    fn int128_methods() {
1035        // checked_*
1036        assert!(matches!(
1037            Int128::MAX.checked_add(Int128::from(1u32)),
1038            Err(OverflowError { .. })
1039        ));
1040        assert_eq!(
1041            Int128::from(1u32).checked_add(Int128::from(1u32)),
1042            Ok(Int128::from(2u32)),
1043        );
1044        assert!(matches!(
1045            Int128::MIN.checked_sub(Int128::from(1u32)),
1046            Err(OverflowError { .. })
1047        ));
1048        assert_eq!(
1049            Int128::from(2u32).checked_sub(Int128::from(1u32)),
1050            Ok(Int128::from(1u32)),
1051        );
1052        assert!(matches!(
1053            Int128::MAX.checked_mul(Int128::from(2u32)),
1054            Err(OverflowError { .. })
1055        ));
1056        assert_eq!(
1057            Int128::from(2u32).checked_mul(Int128::from(2u32)),
1058            Ok(Int128::from(4u32)),
1059        );
1060        assert!(matches!(
1061            Int128::MAX.checked_pow(2u32),
1062            Err(OverflowError { .. })
1063        ));
1064        assert_eq!(Int128::from(2u32).checked_pow(3u32), Ok(Int128::from(8u32)),);
1065        assert_eq!(
1066            Int128::MAX.checked_div(Int128::from(0u32)),
1067            Err(DivisionError::DivideByZero)
1068        );
1069        assert_eq!(
1070            Int128::from(6u32).checked_div(Int128::from(2u32)),
1071            Ok(Int128::from(3u32)),
1072        );
1073        assert_eq!(
1074            Int128::MAX.checked_div_euclid(Int128::from(0u32)),
1075            Err(DivisionError::DivideByZero)
1076        );
1077        assert_eq!(
1078            Int128::from(6u32).checked_div_euclid(Int128::from(2u32)),
1079            Ok(Int128::from(3u32)),
1080        );
1081        assert_eq!(
1082            Int128::from(7u32).checked_div_euclid(Int128::from(2u32)),
1083            Ok(Int128::from(3u32)),
1084        );
1085        assert!(matches!(
1086            Int128::MAX.checked_rem(Int128::from(0u32)),
1087            Err(DivideByZeroError { .. })
1088        ));
1089        // checked_* with negative numbers
1090        assert_eq!(
1091            Int128::from(-12i32).checked_div(Int128::from(10i32)),
1092            Ok(Int128::from(-1i32)),
1093        );
1094        assert_eq!(
1095            Int128::from(-2i32).checked_pow(3u32),
1096            Ok(Int128::from(-8i32)),
1097        );
1098        assert_eq!(
1099            Int128::from(-6i32).checked_mul(Int128::from(-7i32)),
1100            Ok(Int128::from(42i32)),
1101        );
1102        assert_eq!(
1103            Int128::from(-2i32).checked_add(Int128::from(3i32)),
1104            Ok(Int128::from(1i32)),
1105        );
1106        assert_eq!(
1107            Int128::from(-1i32).checked_div_euclid(Int128::from(-2i32)),
1108            Ok(Int128::from(1u32)),
1109        );
1110
1111        // saturating_*
1112        assert_eq!(Int128::MAX.saturating_add(Int128::from(1u32)), Int128::MAX);
1113        assert_eq!(Int128::MIN.saturating_sub(Int128::from(1u32)), Int128::MIN);
1114        assert_eq!(Int128::MAX.saturating_mul(Int128::from(2u32)), Int128::MAX);
1115        assert_eq!(Int128::from(4u32).saturating_pow(2u32), Int128::from(16u32));
1116        assert_eq!(Int128::MAX.saturating_pow(2u32), Int128::MAX);
1117    }
1118
1119    #[test]
1120    #[allow(clippy::op_ref)]
1121    fn int128_implements_rem() {
1122        let a = Int128::from(10u32);
1123        assert_eq!(a % Int128::from(10u32), Int128::zero());
1124        assert_eq!(a % Int128::from(2u32), Int128::zero());
1125        assert_eq!(a % Int128::from(1u32), Int128::zero());
1126        assert_eq!(a % Int128::from(3u32), Int128::from(1u32));
1127        assert_eq!(a % Int128::from(4u32), Int128::from(2u32));
1128
1129        assert_eq!(
1130            Int128::from(-12i32) % Int128::from(10i32),
1131            Int128::from(-2i32)
1132        );
1133        assert_eq!(
1134            Int128::from(12i32) % Int128::from(-10i32),
1135            Int128::from(2i32)
1136        );
1137        assert_eq!(
1138            Int128::from(-12i32) % Int128::from(-10i32),
1139            Int128::from(-2i32)
1140        );
1141
1142        // works for refs
1143        let a = Int128::from(10u32);
1144        let b = Int128::from(3u32);
1145        let expected = Int128::from(1u32);
1146        assert_eq!(a % b, expected);
1147        assert_eq!(a % &b, expected);
1148        assert_eq!(&a % b, expected);
1149        assert_eq!(&a % &b, expected);
1150    }
1151
1152    #[test]
1153    #[should_panic(expected = "divisor of zero")]
1154    fn int128_rem_panics_for_zero() {
1155        let _ = Int128::from(10u32) % Int128::zero();
1156    }
1157
1158    #[test]
1159    fn int128_rem_assign_works() {
1160        let mut a = Int128::from(30u32);
1161        a %= Int128::from(4u32);
1162        assert_eq!(a, Int128::from(2u32));
1163
1164        // works for refs
1165        let mut a = Int128::from(25u32);
1166        let b = Int128::from(6u32);
1167        a %= &b;
1168        assert_eq!(a, Int128::from(1u32));
1169    }
1170
1171    #[test]
1172    fn int128_shr() {
1173        let x: Int128 = 0x4000_0000_0000_0000_0000_0000_0000_0000i128.into();
1174        assert_eq!(x >> 0, x); // right shift by 0 should be no-op
1175        assert_eq!(
1176            x >> 1,
1177            Int128::from(0x2000_0000_0000_0000_0000_0000_0000_0000i128)
1178        );
1179        assert_eq!(
1180            x >> 4,
1181            Int128::from(0x0400_0000_0000_0000_0000_0000_0000_0000i128)
1182        );
1183        // right shift of MIN value by the maximum shift value should result in -1 (filled with 1s)
1184        assert_eq!(
1185            Int128::MIN >> (core::mem::size_of::<Int128>() as u32 * 8 - 1),
1186            -Int128::one()
1187        );
1188    }
1189
1190    #[test]
1191    fn int128_shl() {
1192        let x: Int128 = 0x0800_0000_0000_0000_0000_0000_0000_0000i128.into();
1193        assert_eq!(x << 0, x); // left shift by 0 should be no-op
1194        assert_eq!(
1195            x << 1,
1196            Int128::from(0x1000_0000_0000_0000_0000_0000_0000_0000i128)
1197        );
1198        assert_eq!(
1199            x << 4,
1200            Int128::from(0x0800_0000_0000_0000_0000_0000_0000_0000i128 << 4)
1201        );
1202        // left shift by by the maximum shift value should result in MIN
1203        assert_eq!(
1204            Int128::one() << (core::mem::size_of::<Int128>() as u32 * 8 - 1),
1205            Int128::MIN
1206        );
1207    }
1208
1209    #[test]
1210    fn int128_abs_diff_works() {
1211        let a = Int128::from(42u32);
1212        let b = Int128::from(5u32);
1213        let expected = Uint128::from(37u32);
1214        assert_eq!(a.abs_diff(b), expected);
1215        assert_eq!(b.abs_diff(a), expected);
1216
1217        let c = Int128::from(-5i32);
1218        assert_eq!(b.abs_diff(c), Uint128::from(10u32));
1219        assert_eq!(c.abs_diff(b), Uint128::from(10u32));
1220    }
1221
1222    #[test]
1223    fn int128_abs_works() {
1224        let a = Int128::from(42i32);
1225        assert_eq!(a.abs(), a);
1226
1227        let b = Int128::from(-42i32);
1228        assert_eq!(b.abs(), a);
1229
1230        assert_eq!(Int128::zero().abs(), Int128::zero());
1231        assert_eq!((Int128::MIN + Int128::one()).abs(), Int128::MAX);
1232    }
1233
1234    #[test]
1235    fn int128_unsigned_abs_works() {
1236        assert_eq!(Int128::zero().unsigned_abs(), Uint128::zero());
1237        assert_eq!(Int128::one().unsigned_abs(), Uint128::one());
1238        assert_eq!(
1239            Int128::MIN.unsigned_abs(),
1240            Uint128::new(Int128::MAX.0 as u128) + Uint128::one()
1241        );
1242
1243        let v = Int128::from(-42i32);
1244        assert_eq!(v.unsigned_abs(), v.abs_diff(Int128::zero()));
1245    }
1246
1247    #[test]
1248    #[should_panic = "attempt to calculate absolute value with overflow"]
1249    fn int128_abs_min_panics() {
1250        _ = Int128::MIN.abs();
1251    }
1252
1253    #[test]
1254    #[should_panic = "attempt to negate with overflow"]
1255    fn int128_neg_min_panics() {
1256        _ = -Int128::MIN;
1257    }
1258
1259    #[test]
1260    fn int128_partial_eq() {
1261        let test_cases = [(1, 1, true), (42, 42, true), (42, 24, false), (0, 0, true)]
1262            .into_iter()
1263            .map(|(lhs, rhs, expected): (u64, u64, bool)| {
1264                (Int128::from(lhs), Int128::from(rhs), expected)
1265            });
1266
1267        #[allow(clippy::op_ref)]
1268        for (lhs, rhs, expected) in test_cases {
1269            assert_eq!(lhs == rhs, expected);
1270            assert_eq!(&lhs == rhs, expected);
1271            assert_eq!(lhs == &rhs, expected);
1272            assert_eq!(&lhs == &rhs, expected);
1273        }
1274    }
1275}