secret_cosmwasm_std/math/
uint128.rs

1use forward_ref::{forward_ref_binop, forward_ref_op_assign};
2use schemars::JsonSchema;
3use serde::{de, ser, Deserialize, Deserializer, Serialize};
4use std::fmt::{self};
5use std::ops::{
6    Add, AddAssign, Div, DivAssign, Mul, MulAssign, Rem, RemAssign, Shr, ShrAssign, Sub, SubAssign,
7};
8use std::str::FromStr;
9
10use crate::errors::{
11    CheckedMultiplyRatioError, DivideByZeroError, OverflowError, OverflowOperation, StdError,
12};
13use crate::{ConversionOverflowError, Uint256, Uint64};
14
15/// A thin wrapper around u128 that is using strings for JSON encoding/decoding,
16/// such that the full u128 range can be used for clients that convert JSON numbers to floats,
17/// like JavaScript and jq.
18///
19/// # Examples
20///
21/// Use `from` to create instances of this and `u128` to get the value out:
22///
23/// ```
24/// # use secret_cosmwasm_std::Uint128;
25/// let a = Uint128::from(123u128);
26/// assert_eq!(a.u128(), 123);
27///
28/// let b = Uint128::from(42u64);
29/// assert_eq!(b.u128(), 42);
30///
31/// let c = Uint128::from(70u32);
32/// assert_eq!(c.u128(), 70);
33/// ```
34#[derive(Copy, Clone, Default, Debug, PartialEq, Eq, PartialOrd, Ord, JsonSchema)]
35pub struct Uint128(#[schemars(with = "String")] u128);
36
37impl Uint128 {
38    pub const MAX: Self = Self(u128::MAX);
39    pub const MIN: Self = Self(u128::MIN);
40
41    /// Creates a Uint128(value).
42    ///
43    /// This method is less flexible than `from` but can be called in a const context.
44    pub const fn new(value: u128) -> Self {
45        Uint128(value)
46    }
47
48    /// Creates a Uint128(0)
49    #[inline]
50    pub const fn zero() -> Self {
51        Uint128(0)
52    }
53
54    /// Creates a Uint128(1)
55    #[inline]
56    pub const fn one() -> Self {
57        Self(1)
58    }
59
60    /// Returns a copy of the internal data
61    pub const fn u128(&self) -> u128 {
62        self.0
63    }
64
65    /// Returns a copy of the number as big endian bytes.
66    pub const fn to_be_bytes(self) -> [u8; 16] {
67        self.0.to_be_bytes()
68    }
69
70    /// Returns a copy of the number as little endian bytes.
71    pub const fn to_le_bytes(self) -> [u8; 16] {
72        self.0.to_le_bytes()
73    }
74
75    pub const fn is_zero(&self) -> bool {
76        self.0 == 0
77    }
78
79    pub fn pow(self, exp: u32) -> Self {
80        self.0.pow(exp).into()
81    }
82
83    /// Returns `self * numerator / denominator`.
84    ///
85    /// Due to the nature of the integer division involved, the result is always floored.
86    /// E.g. 5 * 99/100 = 4.
87    pub fn multiply_ratio<A: Into<u128>, B: Into<u128>>(
88        &self,
89        numerator: A,
90        denominator: B,
91    ) -> Uint128 {
92        match self.checked_multiply_ratio(numerator, denominator) {
93            Ok(value) => value,
94            Err(CheckedMultiplyRatioError::DivideByZero) => {
95                panic!("Denominator must not be zero")
96            }
97            Err(CheckedMultiplyRatioError::Overflow) => panic!("Multiplication overflow"),
98        }
99    }
100
101    /// Returns `self * numerator / denominator`.
102    ///
103    /// Due to the nature of the integer division involved, the result is always floored.
104    /// E.g. 5 * 99/100 = 4.
105    pub fn checked_multiply_ratio<A: Into<u128>, B: Into<u128>>(
106        &self,
107        numerator: A,
108        denominator: B,
109    ) -> Result<Uint128, CheckedMultiplyRatioError> {
110        let numerator: u128 = numerator.into();
111        let denominator: u128 = denominator.into();
112        if denominator == 0 {
113            return Err(CheckedMultiplyRatioError::DivideByZero);
114        }
115        match (self.full_mul(numerator) / Uint256::from(denominator)).try_into() {
116            Ok(ratio) => Ok(ratio),
117            Err(_) => Err(CheckedMultiplyRatioError::Overflow),
118        }
119    }
120
121    /// Multiplies two u128 values without overflow, producing an
122    /// [`Uint256`].
123    ///
124    /// # Examples
125    ///
126    /// ```
127    /// use secret_cosmwasm_std::Uint128;
128    ///
129    /// let a = Uint128::MAX;
130    /// let result = a.full_mul(2u32);
131    /// assert_eq!(result.to_string(), "680564733841876926926749214863536422910");
132    /// ```
133    pub fn full_mul(self, rhs: impl Into<u128>) -> Uint256 {
134        Uint256::from(self.u128())
135            .checked_mul(Uint256::from(rhs.into()))
136            .unwrap()
137    }
138
139    pub fn checked_add(self, other: Self) -> Result<Self, OverflowError> {
140        self.0
141            .checked_add(other.0)
142            .map(Self)
143            .ok_or_else(|| OverflowError::new(OverflowOperation::Add, self, other))
144    }
145
146    pub fn checked_sub(self, other: Self) -> Result<Self, OverflowError> {
147        self.0
148            .checked_sub(other.0)
149            .map(Self)
150            .ok_or_else(|| OverflowError::new(OverflowOperation::Sub, self, other))
151    }
152
153    pub fn checked_mul(self, other: Self) -> Result<Self, OverflowError> {
154        self.0
155            .checked_mul(other.0)
156            .map(Self)
157            .ok_or_else(|| OverflowError::new(OverflowOperation::Mul, self, other))
158    }
159
160    pub fn checked_pow(self, exp: u32) -> Result<Self, OverflowError> {
161        self.0
162            .checked_pow(exp)
163            .map(Self)
164            .ok_or_else(|| OverflowError::new(OverflowOperation::Pow, self, exp))
165    }
166
167    pub fn checked_div(self, other: Self) -> Result<Self, DivideByZeroError> {
168        self.0
169            .checked_div(other.0)
170            .map(Self)
171            .ok_or_else(|| DivideByZeroError::new(self))
172    }
173
174    pub fn checked_div_euclid(self, other: Self) -> Result<Self, DivideByZeroError> {
175        self.0
176            .checked_div_euclid(other.0)
177            .map(Self)
178            .ok_or_else(|| DivideByZeroError::new(self))
179    }
180
181    pub fn checked_rem(self, other: Self) -> Result<Self, DivideByZeroError> {
182        self.0
183            .checked_rem(other.0)
184            .map(Self)
185            .ok_or_else(|| DivideByZeroError::new(self))
186    }
187
188    #[inline]
189    pub fn wrapping_add(self, other: Self) -> Self {
190        Self(self.0.wrapping_add(other.0))
191    }
192
193    #[inline]
194    pub fn wrapping_sub(self, other: Self) -> Self {
195        Self(self.0.wrapping_sub(other.0))
196    }
197
198    #[inline]
199    pub fn wrapping_mul(self, other: Self) -> Self {
200        Self(self.0.wrapping_mul(other.0))
201    }
202
203    #[inline]
204    pub fn wrapping_pow(self, other: u32) -> Self {
205        Self(self.0.wrapping_pow(other))
206    }
207
208    pub fn saturating_add(self, other: Self) -> Self {
209        Self(self.0.saturating_add(other.0))
210    }
211
212    pub fn saturating_sub(self, other: Self) -> Self {
213        Self(self.0.saturating_sub(other.0))
214    }
215
216    pub fn saturating_mul(self, other: Self) -> Self {
217        Self(self.0.saturating_mul(other.0))
218    }
219
220    pub fn saturating_pow(self, exp: u32) -> Self {
221        Self(self.0.saturating_pow(exp))
222    }
223
224    pub const fn abs_diff(self, other: Self) -> Self {
225        Self(if self.0 < other.0 {
226            other.0 - self.0
227        } else {
228            self.0 - other.0
229        })
230    }
231}
232
233// `From<u{128,64,32,16,8}>` is implemented manually instead of
234// using `impl<T: Into<u128>> From<T> for Uint128` because
235// of the conflict with `TryFrom<&str>` as described here
236// https://stackoverflow.com/questions/63136970/how-do-i-work-around-the-upstream-crates-may-add-a-new-impl-of-trait-error
237
238impl From<Uint64> for Uint128 {
239    fn from(val: Uint64) -> Self {
240        val.u64().into()
241    }
242}
243
244impl From<u128> for Uint128 {
245    fn from(val: u128) -> Self {
246        Uint128(val)
247    }
248}
249
250impl From<u64> for Uint128 {
251    fn from(val: u64) -> Self {
252        Uint128(val.into())
253    }
254}
255
256impl From<u32> for Uint128 {
257    fn from(val: u32) -> Self {
258        Uint128(val.into())
259    }
260}
261
262impl From<u16> for Uint128 {
263    fn from(val: u16) -> Self {
264        Uint128(val.into())
265    }
266}
267
268impl From<u8> for Uint128 {
269    fn from(val: u8) -> Self {
270        Uint128(val.into())
271    }
272}
273
274impl TryFrom<Uint128> for Uint64 {
275    type Error = ConversionOverflowError;
276
277    fn try_from(value: Uint128) -> Result<Self, Self::Error> {
278        Ok(Uint64::new(value.0.try_into().map_err(|_| {
279            ConversionOverflowError::new("Uint128", "Uint64", value.to_string())
280        })?))
281    }
282}
283
284impl TryFrom<&str> for Uint128 {
285    type Error = StdError;
286
287    fn try_from(val: &str) -> Result<Self, Self::Error> {
288        Self::from_str(val)
289    }
290}
291
292impl FromStr for Uint128 {
293    type Err = StdError;
294
295    fn from_str(s: &str) -> Result<Self, Self::Err> {
296        match s.parse::<u128>() {
297            Ok(u) => Ok(Uint128(u)),
298            Err(e) => Err(StdError::generic_err(format!("Parsing u128: {}", e))),
299        }
300    }
301}
302
303impl From<Uint128> for String {
304    fn from(original: Uint128) -> Self {
305        original.to_string()
306    }
307}
308
309impl From<Uint128> for u128 {
310    fn from(original: Uint128) -> Self {
311        original.0
312    }
313}
314
315impl fmt::Display for Uint128 {
316    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
317        self.0.fmt(f)
318    }
319}
320
321impl Add<Uint128> for Uint128 {
322    type Output = Self;
323
324    fn add(self, rhs: Self) -> Self {
325        Uint128(
326            self.u128()
327                .checked_add(rhs.u128())
328                .expect("attempt to add with overflow"),
329        )
330    }
331}
332
333impl<'a> Add<&'a Uint128> for Uint128 {
334    type Output = Self;
335
336    fn add(self, rhs: &'a Uint128) -> Self {
337        self + *rhs
338    }
339}
340
341impl Sub<Uint128> for Uint128 {
342    type Output = Self;
343
344    fn sub(self, rhs: Self) -> Self {
345        Uint128(
346            self.u128()
347                .checked_sub(rhs.u128())
348                .expect("attempt to subtract with overflow"),
349        )
350    }
351}
352forward_ref_binop!(impl Sub, sub for Uint128, Uint128);
353
354impl SubAssign<Uint128> for Uint128 {
355    fn sub_assign(&mut self, rhs: Uint128) {
356        *self = *self - rhs;
357    }
358}
359forward_ref_op_assign!(impl SubAssign, sub_assign for Uint128, Uint128);
360
361impl Mul<Uint128> for Uint128 {
362    type Output = Self;
363
364    fn mul(self, rhs: Self) -> Self::Output {
365        Self(
366            self.u128()
367                .checked_mul(rhs.u128())
368                .expect("attempt to multiply with overflow"),
369        )
370    }
371}
372forward_ref_binop!(impl Mul, mul for Uint128, Uint128);
373
374impl MulAssign<Uint128> for Uint128 {
375    fn mul_assign(&mut self, rhs: Self) {
376        *self = *self * rhs;
377    }
378}
379forward_ref_op_assign!(impl MulAssign, mul_assign for Uint128, Uint128);
380
381impl Div<Uint128> for Uint128 {
382    type Output = Self;
383
384    fn div(self, rhs: Self) -> Self::Output {
385        Self(
386            self.u128()
387                .checked_div(rhs.u128())
388                .expect("attempt to divide by zero"),
389        )
390    }
391}
392
393impl<'a> Div<&'a Uint128> for Uint128 {
394    type Output = Self;
395
396    fn div(self, rhs: &'a Uint128) -> Self::Output {
397        self / *rhs
398    }
399}
400
401impl Shr<u32> for Uint128 {
402    type Output = Self;
403
404    fn shr(self, rhs: u32) -> Self::Output {
405        Self(
406            self.u128()
407                .checked_shr(rhs)
408                .expect("attempt to shift right with overflow"),
409        )
410    }
411}
412
413impl<'a> Shr<&'a u32> for Uint128 {
414    type Output = Self;
415
416    fn shr(self, rhs: &'a u32) -> Self::Output {
417        self >> *rhs
418    }
419}
420
421impl AddAssign<Uint128> for Uint128 {
422    fn add_assign(&mut self, rhs: Uint128) {
423        *self = *self + rhs;
424    }
425}
426
427impl<'a> AddAssign<&'a Uint128> for Uint128 {
428    fn add_assign(&mut self, rhs: &'a Uint128) {
429        *self = *self + rhs;
430    }
431}
432
433impl DivAssign<Uint128> for Uint128 {
434    fn div_assign(&mut self, rhs: Self) {
435        *self = *self / rhs;
436    }
437}
438
439impl<'a> DivAssign<&'a Uint128> for Uint128 {
440    fn div_assign(&mut self, rhs: &'a Uint128) {
441        *self = *self / rhs;
442    }
443}
444
445impl Rem for Uint128 {
446    type Output = Self;
447
448    /// # Panics
449    ///
450    /// This operation will panic if `rhs` is zero.
451    #[inline]
452    fn rem(self, rhs: Self) -> Self {
453        Self(self.0.rem(rhs.0))
454    }
455}
456forward_ref_binop!(impl Rem, rem for Uint128, Uint128);
457
458impl RemAssign<Uint128> for Uint128 {
459    fn rem_assign(&mut self, rhs: Uint128) {
460        *self = *self % rhs;
461    }
462}
463forward_ref_op_assign!(impl RemAssign, rem_assign for Uint128, Uint128);
464
465impl ShrAssign<u32> for Uint128 {
466    fn shr_assign(&mut self, rhs: u32) {
467        *self = *self >> rhs;
468    }
469}
470
471impl<'a> ShrAssign<&'a u32> for Uint128 {
472    fn shr_assign(&mut self, rhs: &'a u32) {
473        *self = *self >> rhs;
474    }
475}
476
477impl Serialize for Uint128 {
478    /// Serializes as an integer string using base 10
479    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
480    where
481        S: ser::Serializer,
482    {
483        serializer.serialize_str(&self.to_string())
484    }
485}
486
487impl<'de> Deserialize<'de> for Uint128 {
488    /// Deserialized from an integer string using base 10
489    fn deserialize<D>(deserializer: D) -> Result<Uint128, D::Error>
490    where
491        D: Deserializer<'de>,
492    {
493        deserializer.deserialize_str(Uint128Visitor)
494    }
495}
496
497struct Uint128Visitor;
498
499impl<'de> de::Visitor<'de> for Uint128Visitor {
500    type Value = Uint128;
501
502    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
503        formatter.write_str("string-encoded integer")
504    }
505
506    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
507    where
508        E: de::Error,
509    {
510        match v.parse::<u128>() {
511            Ok(u) => Ok(Uint128(u)),
512            Err(e) => Err(E::custom(format!("invalid Uint128 '{}' - {}", v, e))),
513        }
514    }
515}
516
517impl<A> std::iter::Sum<A> for Uint128
518where
519    Self: Add<A, Output = Self>,
520{
521    fn sum<I: Iterator<Item = A>>(iter: I) -> Self {
522        iter.fold(Self::zero(), Add::add)
523    }
524}
525
526impl PartialEq<&Uint128> for Uint128 {
527    fn eq(&self, rhs: &&Uint128) -> bool {
528        self == *rhs
529    }
530}
531
532impl PartialEq<Uint128> for &Uint128 {
533    fn eq(&self, rhs: &Uint128) -> bool {
534        *self == rhs
535    }
536}
537
538#[cfg(test)]
539mod tests {
540    use super::*;
541    use crate::{from_slice, to_vec};
542
543    #[test]
544    fn uint128_zero_works() {
545        let zero = Uint128::zero();
546        assert_eq!(
547            zero.to_be_bytes(),
548            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
549        );
550    }
551
552    #[test]
553    fn uint128_one_works() {
554        let one = Uint128::one();
555        assert_eq!(
556            one.to_be_bytes(),
557            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]
558        );
559    }
560
561    #[test]
562    fn uint128_convert_into() {
563        let original = Uint128(12345);
564        let a = u128::from(original);
565        assert_eq!(a, 12345);
566
567        let original = Uint128(12345);
568        let a = String::from(original);
569        assert_eq!(a, "12345");
570    }
571
572    #[test]
573    fn uint128_convert_from() {
574        let a = Uint128::from(5u128);
575        assert_eq!(a.0, 5);
576
577        let a = Uint128::from(5u64);
578        assert_eq!(a.0, 5);
579
580        let a = Uint128::from(5u32);
581        assert_eq!(a.0, 5);
582
583        let a = Uint128::from(5u16);
584        assert_eq!(a.0, 5);
585
586        let a = Uint128::from(5u8);
587        assert_eq!(a.0, 5);
588
589        let result = Uint128::try_from("34567");
590        assert_eq!(result.unwrap().0, 34567);
591
592        let result = Uint128::try_from("1.23");
593        assert!(result.is_err());
594    }
595
596    #[test]
597    fn uint128_implements_display() {
598        let a = Uint128(12345);
599        assert_eq!(format!("Embedded: {}", a), "Embedded: 12345");
600        assert_eq!(a.to_string(), "12345");
601
602        let a = Uint128(0);
603        assert_eq!(format!("Embedded: {}", a), "Embedded: 0");
604        assert_eq!(a.to_string(), "0");
605    }
606
607    #[test]
608    fn uint128_display_padding_works() {
609        let a = Uint128::from(123u64);
610        assert_eq!(format!("Embedded: {:05}", a), "Embedded: 00123");
611    }
612
613    #[test]
614    fn uint128_to_be_bytes_works() {
615        assert_eq!(
616            Uint128::zero().to_be_bytes(),
617            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
618        );
619        assert_eq!(
620            Uint128::MAX.to_be_bytes(),
621            [
622                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
623                0xff, 0xff
624            ]
625        );
626        assert_eq!(
627            Uint128::new(1).to_be_bytes(),
628            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]
629        );
630        // Python: `[b for b in (240282366920938463463374607431768124608).to_bytes(16, "big")]`
631        assert_eq!(
632            Uint128::new(240282366920938463463374607431768124608).to_be_bytes(),
633            [180, 196, 179, 87, 165, 121, 59, 133, 246, 117, 221, 191, 255, 254, 172, 192]
634        );
635    }
636
637    #[test]
638    fn uint128_to_le_bytes_works() {
639        assert_eq!(
640            Uint128::zero().to_le_bytes(),
641            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
642        );
643        assert_eq!(
644            Uint128::MAX.to_le_bytes(),
645            [
646                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
647                0xff, 0xff
648            ]
649        );
650        assert_eq!(
651            Uint128::new(1).to_le_bytes(),
652            [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
653        );
654        // Python: `[b for b in (240282366920938463463374607431768124608).to_bytes(16, "little")]`
655        assert_eq!(
656            Uint128::new(240282366920938463463374607431768124608).to_le_bytes(),
657            [192, 172, 254, 255, 191, 221, 117, 246, 133, 59, 121, 165, 87, 179, 196, 180]
658        );
659    }
660
661    #[test]
662    fn uint128_is_zero_works() {
663        assert!(Uint128::zero().is_zero());
664        assert!(Uint128(0).is_zero());
665
666        assert!(!Uint128(1).is_zero());
667        assert!(!Uint128(123).is_zero());
668    }
669
670    #[test]
671    fn uint128_json() {
672        let orig = Uint128(1234567890987654321);
673        let serialized = to_vec(&orig).unwrap();
674        assert_eq!(serialized.as_slice(), b"\"1234567890987654321\"");
675        let parsed: Uint128 = from_slice(&serialized).unwrap();
676        assert_eq!(parsed, orig);
677    }
678
679    #[test]
680    fn uint128_compare() {
681        let a = Uint128(12345);
682        let b = Uint128(23456);
683
684        assert!(a < b);
685        assert!(b > a);
686        assert_eq!(a, Uint128(12345));
687    }
688
689    #[test]
690    #[allow(clippy::op_ref)]
691    fn uint128_math() {
692        let a = Uint128(12345);
693        let b = Uint128(23456);
694
695        // test + with owned and reference right hand side
696        assert_eq!(a + b, Uint128(35801));
697        assert_eq!(a + &b, Uint128(35801));
698
699        // test - with owned and reference right hand side
700        assert_eq!(b - a, Uint128(11111));
701        assert_eq!(b - &a, Uint128(11111));
702
703        // test += with owned and reference right hand side
704        let mut c = Uint128(300000);
705        c += b;
706        assert_eq!(c, Uint128(323456));
707        let mut d = Uint128(300000);
708        d += &b;
709        assert_eq!(d, Uint128(323456));
710
711        // test -= with owned and reference right hand side
712        let mut c = Uint128(300000);
713        c -= b;
714        assert_eq!(c, Uint128(276544));
715        let mut d = Uint128(300000);
716        d -= &b;
717        assert_eq!(d, Uint128(276544));
718
719        // error result on underflow (- would produce negative result)
720        let underflow_result = a.checked_sub(b);
721        let OverflowError {
722            operand1, operand2, ..
723        } = underflow_result.unwrap_err();
724        assert_eq!((operand1, operand2), (a.to_string(), b.to_string()));
725    }
726
727    #[test]
728    #[should_panic]
729    fn uint128_add_overflow_panics() {
730        // almost_max is 2^128 - 10
731        let almost_max = Uint128(340282366920938463463374607431768211446);
732        let _ = almost_max + Uint128(12);
733    }
734
735    #[test]
736    #[allow(clippy::op_ref)]
737    fn uint128_sub_works() {
738        assert_eq!(Uint128(2) - Uint128(1), Uint128(1));
739        assert_eq!(Uint128(2) - Uint128(0), Uint128(2));
740        assert_eq!(Uint128(2) - Uint128(2), Uint128(0));
741
742        // works for refs
743        let a = Uint128::new(10);
744        let b = Uint128::new(3);
745        let expected = Uint128::new(7);
746        assert_eq!(a - b, expected);
747        assert_eq!(a - &b, expected);
748        assert_eq!(&a - b, expected);
749        assert_eq!(&a - &b, expected);
750    }
751
752    #[test]
753    #[should_panic]
754    fn uint128_sub_overflow_panics() {
755        let _ = Uint128(1) - Uint128(2);
756    }
757
758    #[test]
759    fn uint128_sub_assign_works() {
760        let mut a = Uint128(14);
761        a -= Uint128(2);
762        assert_eq!(a, Uint128(12));
763
764        // works for refs
765        let mut a = Uint128::new(10);
766        let b = Uint128::new(3);
767        let expected = Uint128::new(7);
768        a -= &b;
769        assert_eq!(a, expected);
770    }
771
772    #[test]
773    #[allow(clippy::op_ref)]
774    fn uint128_mul_works() {
775        assert_eq!(
776            Uint128::from(2u32) * Uint128::from(3u32),
777            Uint128::from(6u32)
778        );
779        assert_eq!(Uint128::from(2u32) * Uint128::zero(), Uint128::zero());
780
781        // works for refs
782        let a = Uint128::from(11u32);
783        let b = Uint128::from(3u32);
784        let expected = Uint128::from(33u32);
785        assert_eq!(a * b, expected);
786        assert_eq!(a * &b, expected);
787        assert_eq!(&a * b, expected);
788        assert_eq!(&a * &b, expected);
789    }
790
791    #[test]
792    fn uint128_mul_assign_works() {
793        let mut a = Uint128::from(14u32);
794        a *= Uint128::from(2u32);
795        assert_eq!(a, Uint128::from(28u32));
796
797        // works for refs
798        let mut a = Uint128::from(10u32);
799        let b = Uint128::from(3u32);
800        a *= &b;
801        assert_eq!(a, Uint128::from(30u32));
802    }
803
804    #[test]
805    fn uint128_pow_works() {
806        assert_eq!(Uint128::from(2u32).pow(2), Uint128::from(4u32));
807        assert_eq!(Uint128::from(2u32).pow(10), Uint128::from(1024u32));
808    }
809
810    #[test]
811    #[should_panic]
812    fn uint128_pow_overflow_panics() {
813        Uint128::MAX.pow(2u32);
814    }
815
816    #[test]
817    fn uint128_multiply_ratio_works() {
818        let base = Uint128(500);
819
820        // factor 1/1
821        assert_eq!(base.multiply_ratio(1u128, 1u128), base);
822        assert_eq!(base.multiply_ratio(3u128, 3u128), base);
823        assert_eq!(base.multiply_ratio(654321u128, 654321u128), base);
824        assert_eq!(base.multiply_ratio(u128::MAX, u128::MAX), base);
825
826        // factor 3/2
827        assert_eq!(base.multiply_ratio(3u128, 2u128), Uint128(750));
828        assert_eq!(base.multiply_ratio(333333u128, 222222u128), Uint128(750));
829
830        // factor 2/3 (integer devision always floors the result)
831        assert_eq!(base.multiply_ratio(2u128, 3u128), Uint128(333));
832        assert_eq!(base.multiply_ratio(222222u128, 333333u128), Uint128(333));
833
834        // factor 5/6 (integer devision always floors the result)
835        assert_eq!(base.multiply_ratio(5u128, 6u128), Uint128(416));
836        assert_eq!(base.multiply_ratio(100u128, 120u128), Uint128(416));
837    }
838
839    #[test]
840    fn uint128_multiply_ratio_does_not_overflow_when_result_fits() {
841        // Almost max value for Uint128.
842        let base = Uint128(u128::MAX - 9);
843
844        assert_eq!(base.multiply_ratio(2u128, 2u128), base);
845    }
846
847    #[test]
848    #[should_panic]
849    fn uint128_multiply_ratio_panicks_on_overflow() {
850        // Almost max value for Uint128.
851        let base = Uint128(u128::MAX - 9);
852
853        assert_eq!(base.multiply_ratio(2u128, 1u128), base);
854    }
855
856    #[test]
857    #[should_panic(expected = "Denominator must not be zero")]
858    fn uint128_multiply_ratio_panics_for_zero_denominator() {
859        Uint128(500).multiply_ratio(1u128, 0u128);
860    }
861
862    #[test]
863    fn uint128_checked_multiply_ratio_does_not_panic() {
864        assert_eq!(
865            Uint128(500u128).checked_multiply_ratio(1u128, 0u128),
866            Err(CheckedMultiplyRatioError::DivideByZero),
867        );
868        assert_eq!(
869            Uint128(500u128).checked_multiply_ratio(u128::MAX, 1u128),
870            Err(CheckedMultiplyRatioError::Overflow),
871        );
872    }
873
874    #[test]
875    fn sum_works() {
876        let nums = vec![Uint128(17), Uint128(123), Uint128(540), Uint128(82)];
877        let expected = Uint128(762);
878
879        let sum_as_ref: Uint128 = nums.iter().sum();
880        assert_eq!(expected, sum_as_ref);
881
882        let sum_as_owned: Uint128 = nums.into_iter().sum();
883        assert_eq!(expected, sum_as_owned);
884    }
885
886    #[test]
887    fn uint128_methods() {
888        // checked_*
889        assert!(matches!(
890            Uint128::MAX.checked_add(Uint128(1)),
891            Err(OverflowError { .. })
892        ));
893        assert!(matches!(Uint128(1).checked_add(Uint128(1)), Ok(Uint128(2))));
894        assert!(matches!(
895            Uint128(0).checked_sub(Uint128(1)),
896            Err(OverflowError { .. })
897        ));
898        assert!(matches!(Uint128(2).checked_sub(Uint128(1)), Ok(Uint128(1))));
899        assert!(matches!(
900            Uint128::MAX.checked_mul(Uint128(2)),
901            Err(OverflowError { .. })
902        ));
903        assert!(matches!(Uint128(2).checked_mul(Uint128(2)), Ok(Uint128(4))));
904        assert!(matches!(
905            Uint128::MAX.checked_pow(2u32),
906            Err(OverflowError { .. })
907        ));
908        assert!(matches!(Uint128(2).checked_pow(3), Ok(Uint128(8))));
909        assert!(matches!(
910            Uint128::MAX.checked_div(Uint128(0)),
911            Err(DivideByZeroError { .. })
912        ));
913        assert!(matches!(Uint128(6).checked_div(Uint128(2)), Ok(Uint128(3))));
914        assert!(matches!(
915            Uint128::MAX.checked_div_euclid(Uint128(0)),
916            Err(DivideByZeroError { .. })
917        ));
918        assert!(matches!(
919            Uint128(6).checked_div_euclid(Uint128(2)),
920            Ok(Uint128(3)),
921        ));
922        assert!(matches!(
923            Uint128::MAX.checked_rem(Uint128(0)),
924            Err(DivideByZeroError { .. })
925        ));
926
927        // saturating_*
928        assert_eq!(Uint128::MAX.saturating_add(Uint128(1)), Uint128::MAX);
929        assert_eq!(Uint128(0).saturating_sub(Uint128(1)), Uint128(0));
930        assert_eq!(Uint128::MAX.saturating_mul(Uint128(2)), Uint128::MAX);
931        assert_eq!(Uint128::MAX.saturating_pow(2), Uint128::MAX);
932    }
933
934    #[test]
935    fn uint128_wrapping_methods() {
936        // wrapping_add
937        assert_eq!(Uint128(2).wrapping_add(Uint128(2)), Uint128(4)); // non-wrapping
938        assert_eq!(Uint128::MAX.wrapping_add(Uint128(1)), Uint128(0)); // wrapping
939
940        // wrapping_sub
941        assert_eq!(Uint128(7).wrapping_sub(Uint128(5)), Uint128(2)); // non-wrapping
942        assert_eq!(Uint128(0).wrapping_sub(Uint128(1)), Uint128::MAX); // wrapping
943
944        // wrapping_mul
945        assert_eq!(Uint128(3).wrapping_mul(Uint128(2)), Uint128(6)); // non-wrapping
946        assert_eq!(
947            Uint128::MAX.wrapping_mul(Uint128(2)),
948            Uint128::MAX - Uint128::one()
949        ); // wrapping
950
951        // wrapping_pow
952        assert_eq!(Uint128(2).wrapping_pow(3), Uint128(8)); // non-wrapping
953        assert_eq!(Uint128::MAX.wrapping_pow(2), Uint128(1)); // wrapping
954    }
955
956    #[test]
957    #[allow(clippy::op_ref)]
958    fn uint128_implements_rem() {
959        let a = Uint128::new(10);
960        assert_eq!(a % Uint128::new(10), Uint128::zero());
961        assert_eq!(a % Uint128::new(2), Uint128::zero());
962        assert_eq!(a % Uint128::new(1), Uint128::zero());
963        assert_eq!(a % Uint128::new(3), Uint128::new(1));
964        assert_eq!(a % Uint128::new(4), Uint128::new(2));
965
966        // works for refs
967        let a = Uint128::new(10);
968        let b = Uint128::new(3);
969        let expected = Uint128::new(1);
970        assert_eq!(a % b, expected);
971        assert_eq!(a % &b, expected);
972        assert_eq!(&a % b, expected);
973        assert_eq!(&a % &b, expected);
974    }
975
976    #[test]
977    #[should_panic(expected = "divisor of zero")]
978    fn uint128_rem_panics_for_zero() {
979        let _ = Uint128::new(10) % Uint128::zero();
980    }
981
982    #[test]
983    #[allow(clippy::op_ref)]
984    fn uint128_rem_works() {
985        assert_eq!(
986            Uint128::from(12u32) % Uint128::from(10u32),
987            Uint128::from(2u32)
988        );
989        assert_eq!(Uint128::from(50u32) % Uint128::from(5u32), Uint128::zero());
990
991        // works for refs
992        let a = Uint128::from(42u32);
993        let b = Uint128::from(5u32);
994        let expected = Uint128::from(2u32);
995        assert_eq!(a % b, expected);
996        assert_eq!(a % &b, expected);
997        assert_eq!(&a % b, expected);
998        assert_eq!(&a % &b, expected);
999    }
1000
1001    #[test]
1002    fn uint128_rem_assign_works() {
1003        let mut a = Uint128::from(30u32);
1004        a %= Uint128::from(4u32);
1005        assert_eq!(a, Uint128::from(2u32));
1006
1007        // works for refs
1008        let mut a = Uint128::from(25u32);
1009        let b = Uint128::from(6u32);
1010        a %= &b;
1011        assert_eq!(a, Uint128::from(1u32));
1012    }
1013
1014    #[test]
1015    fn uint128_abs_diff_works() {
1016        let a = Uint128::from(42u32);
1017        let b = Uint128::from(5u32);
1018        let expected = Uint128::from(37u32);
1019        assert_eq!(a.abs_diff(b), expected);
1020        assert_eq!(b.abs_diff(a), expected);
1021    }
1022
1023    #[test]
1024    fn uint128_partial_eq() {
1025        let test_cases = [(1, 1, true), (42, 42, true), (42, 24, false), (0, 0, true)]
1026            .into_iter()
1027            .map(|(lhs, rhs, expected)| (Uint128::new(lhs), Uint128::new(rhs), expected));
1028
1029        #[allow(clippy::op_ref)]
1030        for (lhs, rhs, expected) in test_cases {
1031            assert_eq!(lhs == rhs, expected);
1032            assert_eq!(&lhs == rhs, expected);
1033            assert_eq!(lhs == &rhs, expected);
1034            assert_eq!(&lhs == &rhs, expected);
1035        }
1036    }
1037}