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