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