cosmwasm_std/math/
uint128.rs

1use alloc::string::{String, ToString};
2use core::fmt;
3use core::ops::{
4    Add, AddAssign, Div, DivAssign, Mul, MulAssign, Not, Rem, RemAssign, Shl, ShlAssign, Shr,
5    ShrAssign, Sub, SubAssign,
6};
7use core::str::FromStr;
8
9use crate::errors::{
10    CheckedMultiplyFractionError, CheckedMultiplyRatioError, DivideByZeroError, OverflowError,
11    OverflowOperation, StdError,
12};
13use crate::forward_ref::{forward_ref_binop, forward_ref_op_assign};
14use crate::{
15    __internal::forward_ref_partial_eq, impl_mul_fraction, Fraction, Int128, Int256, Int512, Int64,
16    Uint256, Uint64,
17};
18
19use super::conversion::{
20    forward_try_from, from_and_to_bytes, primitive_to_wrapped_int, wrapped_int_to_primitive,
21};
22use super::impl_int_serde;
23use super::num_consts::NumConsts;
24
25/// A thin wrapper around u128 that is using strings for JSON encoding/decoding,
26/// such that the full u128 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 `u128` to get the value out:
32///
33/// ```
34/// # use cosmwasm_std::Uint128;
35/// let a = Uint128::from(123u128);
36/// assert_eq!(a.u128(), 123);
37///
38/// let b = Uint128::from(42u64);
39/// assert_eq!(b.u128(), 42);
40///
41/// let c = Uint128::from(70u32);
42/// assert_eq!(c.u128(), 70);
43/// ```
44#[derive(Copy, Clone, Default, Debug, PartialEq, Eq, PartialOrd, Ord, schemars::JsonSchema)]
45pub struct Uint128(#[schemars(with = "String")] pub(crate) u128);
46
47impl_int_serde!(Uint128);
48forward_ref_partial_eq!(Uint128, Uint128);
49
50impl Uint128 {
51    pub const MAX: Self = Self(u128::MAX);
52    pub const MIN: Self = Self(u128::MIN);
53
54    /// Creates a Uint128(value).
55    ///
56    /// This method is less flexible than `from` but can be called in a const context.
57    #[inline]
58    #[must_use]
59    pub const fn new(value: u128) -> Self {
60        Uint128(value)
61    }
62
63    /// Creates a Uint128(0)
64    #[inline]
65    pub const fn zero() -> Self {
66        Uint128(0)
67    }
68
69    /// Creates a Uint128(1)
70    #[inline]
71    pub const fn one() -> Self {
72        Self(1)
73    }
74
75    /// Returns a copy of the internal data
76    pub const fn u128(&self) -> u128 {
77        self.0
78    }
79
80    from_and_to_bytes!(u128, 16);
81
82    #[must_use]
83    pub const fn is_zero(&self) -> bool {
84        self.0 == 0
85    }
86
87    #[must_use = "this returns the result of the operation, without modifying the original"]
88    pub const fn pow(self, exp: u32) -> Self {
89        match self.0.checked_pow(exp) {
90            Some(val) => Self(val),
91            None => panic!("attempt to exponentiate with overflow"),
92        }
93    }
94
95    /// Returns the base 2 logarithm of the number, rounded down.
96    ///
97    /// # Panics
98    ///
99    /// This function will panic if `self` is zero.
100    #[must_use = "this returns the result of the operation, without modifying the original"]
101    pub fn ilog2(self) -> u32 {
102        self.0.checked_ilog2().unwrap()
103    }
104
105    /// Returns `self * numerator / denominator`.
106    ///
107    /// Due to the nature of the integer division involved, the result is always floored.
108    /// E.g. 5 * 99/100 = 4.
109    #[must_use = "this returns the result of the operation, without modifying the original"]
110    pub fn multiply_ratio<A: Into<u128>, B: Into<u128>>(
111        &self,
112        numerator: A,
113        denominator: B,
114    ) -> Uint128 {
115        match self.checked_multiply_ratio(numerator, denominator) {
116            Ok(value) => value,
117            Err(CheckedMultiplyRatioError::DivideByZero) => {
118                panic!("Denominator must not be zero")
119            }
120            Err(CheckedMultiplyRatioError::Overflow) => panic!("Multiplication overflow"),
121        }
122    }
123
124    /// Returns `self * numerator / denominator`.
125    ///
126    /// Due to the nature of the integer division involved, the result is always floored.
127    /// E.g. 5 * 99/100 = 4.
128    pub fn checked_multiply_ratio<A: Into<u128>, B: Into<u128>>(
129        &self,
130        numerator: A,
131        denominator: B,
132    ) -> Result<Uint128, CheckedMultiplyRatioError> {
133        let numerator: u128 = numerator.into();
134        let denominator: u128 = denominator.into();
135        if denominator == 0 {
136            return Err(CheckedMultiplyRatioError::DivideByZero);
137        }
138        match (self.full_mul(numerator) / Uint256::from(denominator)).try_into() {
139            Ok(ratio) => Ok(ratio),
140            Err(_) => Err(CheckedMultiplyRatioError::Overflow),
141        }
142    }
143
144    /// Multiplies two u128 values without overflow, producing an
145    /// [`Uint256`].
146    ///
147    /// # Examples
148    ///
149    /// ```
150    /// use cosmwasm_std::Uint128;
151    ///
152    /// let a = Uint128::MAX;
153    /// let result = a.full_mul(2u32);
154    /// assert_eq!(result.to_string(), "680564733841876926926749214863536422910");
155    /// ```
156    #[must_use = "this returns the result of the operation, without modifying the original"]
157    pub fn full_mul(self, rhs: impl Into<Self>) -> Uint256 {
158        Uint256::from(self)
159            .checked_mul(Uint256::from(rhs.into()))
160            .unwrap()
161    }
162
163    pub fn checked_add(self, other: Self) -> Result<Self, OverflowError> {
164        self.0
165            .checked_add(other.0)
166            .map(Self)
167            .ok_or_else(|| OverflowError::new(OverflowOperation::Add))
168    }
169
170    pub fn checked_sub(self, other: Self) -> Result<Self, OverflowError> {
171        self.0
172            .checked_sub(other.0)
173            .map(Self)
174            .ok_or_else(|| OverflowError::new(OverflowOperation::Sub))
175    }
176
177    pub fn checked_mul(self, other: Self) -> Result<Self, OverflowError> {
178        self.0
179            .checked_mul(other.0)
180            .map(Self)
181            .ok_or_else(|| OverflowError::new(OverflowOperation::Mul))
182    }
183
184    pub fn checked_pow(self, exp: u32) -> Result<Self, OverflowError> {
185        self.0
186            .checked_pow(exp)
187            .map(Self)
188            .ok_or_else(|| OverflowError::new(OverflowOperation::Pow))
189    }
190
191    pub fn checked_div(self, other: Self) -> Result<Self, DivideByZeroError> {
192        self.0
193            .checked_div(other.0)
194            .map(Self)
195            .ok_or(DivideByZeroError)
196    }
197
198    pub fn checked_div_euclid(self, other: Self) -> Result<Self, DivideByZeroError> {
199        self.0
200            .checked_div_euclid(other.0)
201            .map(Self)
202            .ok_or(DivideByZeroError)
203    }
204
205    pub fn checked_rem(self, other: Self) -> Result<Self, DivideByZeroError> {
206        self.0
207            .checked_rem(other.0)
208            .map(Self)
209            .ok_or(DivideByZeroError)
210    }
211
212    pub fn checked_shr(self, other: u32) -> Result<Self, OverflowError> {
213        if other >= 128 {
214            return Err(OverflowError::new(OverflowOperation::Shr));
215        }
216
217        Ok(Self(self.0.shr(other)))
218    }
219
220    pub fn checked_shl(self, other: u32) -> Result<Self, OverflowError> {
221        if other >= 128 {
222            return Err(OverflowError::new(OverflowOperation::Shl));
223        }
224
225        Ok(Self(self.0.shl(other)))
226    }
227
228    #[must_use = "this returns the result of the operation, without modifying the original"]
229    #[inline]
230    pub fn wrapping_add(self, other: Self) -> Self {
231        Self(self.0.wrapping_add(other.0))
232    }
233
234    #[must_use = "this returns the result of the operation, without modifying the original"]
235    #[inline]
236    pub fn wrapping_sub(self, other: Self) -> Self {
237        Self(self.0.wrapping_sub(other.0))
238    }
239
240    #[must_use = "this returns the result of the operation, without modifying the original"]
241    #[inline]
242    pub fn wrapping_mul(self, other: Self) -> Self {
243        Self(self.0.wrapping_mul(other.0))
244    }
245
246    #[must_use = "this returns the result of the operation, without modifying the original"]
247    #[inline]
248    pub fn wrapping_pow(self, other: u32) -> Self {
249        Self(self.0.wrapping_pow(other))
250    }
251
252    #[must_use = "this returns the result of the operation, without modifying the original"]
253    pub fn saturating_add(self, other: Self) -> Self {
254        Self(self.0.saturating_add(other.0))
255    }
256
257    #[must_use = "this returns the result of the operation, without modifying the original"]
258    pub fn saturating_sub(self, other: Self) -> Self {
259        Self(self.0.saturating_sub(other.0))
260    }
261
262    #[must_use = "this returns the result of the operation, without modifying the original"]
263    pub fn saturating_mul(self, other: Self) -> Self {
264        Self(self.0.saturating_mul(other.0))
265    }
266
267    #[must_use = "this returns the result of the operation, without modifying the original"]
268    pub fn saturating_pow(self, exp: u32) -> Self {
269        Self(self.0.saturating_pow(exp))
270    }
271
272    /// Strict integer addition. Computes `self + rhs`, panicking if overflow occurred.
273    ///
274    /// This is the same as [`Uint128::add`] but const.
275    #[must_use = "this returns the result of the operation, without modifying the original"]
276    pub const fn strict_add(self, rhs: Self) -> Self {
277        match self.0.checked_add(rhs.u128()) {
278            None => panic!("attempt to add with overflow"),
279            Some(sum) => Self(sum),
280        }
281    }
282
283    /// Strict integer subtraction. Computes `self - rhs`, panicking if overflow occurred.
284    ///
285    /// This is the same as [`Uint128::sub`] but const.
286    #[must_use = "this returns the result of the operation, without modifying the original"]
287    pub const fn strict_sub(self, other: Self) -> Self {
288        match self.0.checked_sub(other.u128()) {
289            None => panic!("attempt to subtract with overflow"),
290            Some(diff) => Self(diff),
291        }
292    }
293
294    #[must_use = "this returns the result of the operation, without modifying the original"]
295    pub const fn abs_diff(self, other: Self) -> Self {
296        Self(if self.0 < other.0 {
297            other.0 - self.0
298        } else {
299            self.0 - other.0
300        })
301    }
302}
303
304impl NumConsts for Uint128 {
305    const ZERO: Self = Self::zero();
306    const ONE: Self = Self::one();
307    const MAX: Self = Self::MAX;
308    const MIN: Self = Self::MIN;
309}
310
311impl_mul_fraction!(Uint128);
312
313// `From<u{128,64,32,16,8}>` is implemented manually instead of
314// using `impl<T: Into<u128>> From<T> for Uint128` because
315// of the conflict with `TryFrom<&str>` as described here
316// https://stackoverflow.com/questions/63136970/how-do-i-work-around-the-upstream-crates-may-add-a-new-impl-of-trait-error
317
318// uint to Uint
319primitive_to_wrapped_int!(u8, Uint128);
320primitive_to_wrapped_int!(u16, Uint128);
321primitive_to_wrapped_int!(u32, Uint128);
322primitive_to_wrapped_int!(u64, Uint128);
323primitive_to_wrapped_int!(u128, Uint128);
324
325// Uint to uint
326wrapped_int_to_primitive!(Uint128, u128);
327
328impl From<Uint64> for Uint128 {
329    fn from(val: Uint64) -> Self {
330        val.u64().into()
331    }
332}
333
334forward_try_from!(Uint128, Uint64);
335
336// Int to Uint
337forward_try_from!(Int64, Uint128);
338forward_try_from!(Int128, Uint128);
339forward_try_from!(Int256, Uint128);
340forward_try_from!(Int512, Uint128);
341
342impl TryFrom<&str> for Uint128 {
343    type Error = StdError;
344
345    fn try_from(val: &str) -> Result<Self, Self::Error> {
346        Self::from_str(val)
347    }
348}
349
350impl FromStr for Uint128 {
351    type Err = StdError;
352
353    fn from_str(s: &str) -> Result<Self, Self::Err> {
354        match s.parse::<u128>() {
355            Ok(u) => Ok(Uint128(u)),
356            Err(e) => Err(StdError::generic_err(format!("Parsing u128: {e}"))),
357        }
358    }
359}
360
361impl From<Uint128> for String {
362    fn from(original: Uint128) -> Self {
363        original.to_string()
364    }
365}
366
367impl fmt::Display for Uint128 {
368    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
369        self.0.fmt(f)
370    }
371}
372
373impl Add<Uint128> for Uint128 {
374    type Output = Self;
375
376    fn add(self, rhs: Self) -> Self {
377        self.strict_add(rhs)
378    }
379}
380forward_ref_binop!(impl Add, add for Uint128, Uint128);
381
382impl Sub<Uint128> for Uint128 {
383    type Output = Self;
384
385    fn sub(self, rhs: Self) -> Self {
386        self.strict_sub(rhs)
387    }
388}
389forward_ref_binop!(impl Sub, sub for Uint128, Uint128);
390
391impl SubAssign<Uint128> for Uint128 {
392    fn sub_assign(&mut self, rhs: Uint128) {
393        *self = *self - rhs;
394    }
395}
396forward_ref_op_assign!(impl SubAssign, sub_assign for Uint128, Uint128);
397
398impl Mul<Uint128> for Uint128 {
399    type Output = Self;
400
401    fn mul(self, rhs: Self) -> Self::Output {
402        Self(
403            self.u128()
404                .checked_mul(rhs.u128())
405                .expect("attempt to multiply with overflow"),
406        )
407    }
408}
409forward_ref_binop!(impl Mul, mul for Uint128, Uint128);
410
411impl MulAssign<Uint128> for Uint128 {
412    fn mul_assign(&mut self, rhs: Self) {
413        *self = *self * rhs;
414    }
415}
416forward_ref_op_assign!(impl MulAssign, mul_assign for Uint128, Uint128);
417
418impl Div<Uint128> for Uint128 {
419    type Output = Self;
420
421    fn div(self, rhs: Self) -> Self::Output {
422        Self(
423            self.u128()
424                .checked_div(rhs.u128())
425                .expect("attempt to divide by zero"),
426        )
427    }
428}
429
430impl<'a> Div<&'a Uint128> for Uint128 {
431    type Output = Self;
432
433    fn div(self, rhs: &'a Uint128) -> Self::Output {
434        self / *rhs
435    }
436}
437
438impl Shr<u32> for Uint128 {
439    type Output = Self;
440
441    fn shr(self, rhs: u32) -> Self::Output {
442        Self(
443            self.u128()
444                .checked_shr(rhs)
445                .expect("attempt to shift right with overflow"),
446        )
447    }
448}
449
450impl<'a> Shr<&'a u32> for Uint128 {
451    type Output = Self;
452
453    fn shr(self, rhs: &'a u32) -> Self::Output {
454        self >> *rhs
455    }
456}
457
458impl Shl<u32> for Uint128 {
459    type Output = Self;
460
461    fn shl(self, rhs: u32) -> Self::Output {
462        Self(
463            self.u128()
464                .checked_shl(rhs)
465                .expect("attempt to shift left with overflow"),
466        )
467    }
468}
469
470impl<'a> Shl<&'a u32> for Uint128 {
471    type Output = Self;
472
473    fn shl(self, rhs: &'a u32) -> Self::Output {
474        self.shl(*rhs)
475    }
476}
477
478impl AddAssign<Uint128> for Uint128 {
479    fn add_assign(&mut self, rhs: Uint128) {
480        *self = *self + rhs;
481    }
482}
483
484impl<'a> AddAssign<&'a Uint128> for Uint128 {
485    fn add_assign(&mut self, rhs: &'a Uint128) {
486        *self = *self + rhs;
487    }
488}
489
490impl DivAssign<Uint128> for Uint128 {
491    fn div_assign(&mut self, rhs: Self) {
492        *self = *self / rhs;
493    }
494}
495
496impl<'a> DivAssign<&'a Uint128> for Uint128 {
497    fn div_assign(&mut self, rhs: &'a Uint128) {
498        *self = *self / rhs;
499    }
500}
501
502impl Rem for Uint128 {
503    type Output = Self;
504
505    /// # Panics
506    ///
507    /// This operation will panic if `rhs` is zero.
508    #[inline]
509    fn rem(self, rhs: Self) -> Self {
510        Self(self.0.rem(rhs.0))
511    }
512}
513forward_ref_binop!(impl Rem, rem for Uint128, Uint128);
514
515impl Not for Uint128 {
516    type Output = Self;
517
518    fn not(self) -> Self::Output {
519        Self(!self.0)
520    }
521}
522
523impl RemAssign<Uint128> for Uint128 {
524    fn rem_assign(&mut self, rhs: Uint128) {
525        *self = *self % rhs;
526    }
527}
528forward_ref_op_assign!(impl RemAssign, rem_assign for Uint128, Uint128);
529
530impl ShrAssign<u32> for Uint128 {
531    fn shr_assign(&mut self, rhs: u32) {
532        *self = *self >> rhs;
533    }
534}
535
536impl<'a> ShrAssign<&'a u32> for Uint128 {
537    fn shr_assign(&mut self, rhs: &'a u32) {
538        *self = *self >> rhs;
539    }
540}
541
542impl ShlAssign<u32> for Uint128 {
543    fn shl_assign(&mut self, rhs: u32) {
544        *self = Shl::<u32>::shl(*self, rhs);
545    }
546}
547
548impl<'a> ShlAssign<&'a u32> for Uint128 {
549    fn shl_assign(&mut self, rhs: &'a u32) {
550        *self = Shl::<u32>::shl(*self, *rhs);
551    }
552}
553
554impl<A> core::iter::Sum<A> for Uint128
555where
556    Self: Add<A, Output = Self>,
557{
558    fn sum<I: Iterator<Item = A>>(iter: I) -> Self {
559        iter.fold(Self::zero(), Add::add)
560    }
561}
562
563#[cfg(test)]
564mod tests {
565    use crate::errors::CheckedMultiplyFractionError::{ConversionOverflow, DivideByZero};
566    use crate::math::conversion::test_try_from_int_to_uint;
567    use crate::{ConversionOverflowError, Decimal};
568
569    use super::*;
570
571    #[test]
572    fn size_of_works() {
573        assert_eq!(core::mem::size_of::<Uint128>(), 16);
574    }
575
576    #[test]
577    fn uint128_not_works() {
578        assert_eq!(!Uint128::new(1234806), Uint128::new(!1234806));
579
580        assert_eq!(!Uint128::MAX, Uint128::new(!u128::MAX));
581        assert_eq!(!Uint128::MIN, Uint128::new(!u128::MIN));
582    }
583
584    #[test]
585    fn uint128_zero_works() {
586        let zero = Uint128::zero();
587        assert_eq!(
588            zero.to_be_bytes(),
589            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
590        );
591    }
592
593    #[test]
594    fn uint128_one_works() {
595        let one = Uint128::one();
596        assert_eq!(
597            one.to_be_bytes(),
598            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]
599        );
600    }
601
602    #[test]
603    fn uint128_from_be_bytes_works() {
604        // zero
605        let original = [0; 16];
606        let num = Uint128::from_be_bytes(original);
607        assert!(num.is_zero());
608
609        // one
610        let original = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1];
611        let num = Uint128::from_be_bytes(original);
612        assert_eq!(num.u128(), 1);
613
614        // 258
615        let original = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2];
616        let num = Uint128::from_be_bytes(original);
617        assert_eq!(num.u128(), 258);
618
619        // 2x roundtrip
620        let original = [1; 16];
621        let num = Uint128::from_be_bytes(original);
622        let a: [u8; 16] = num.to_be_bytes();
623        assert_eq!(a, original);
624
625        let original = [
626            0u8, 222u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 2u8, 3u8,
627        ];
628        let num = Uint128::from_be_bytes(original);
629        let resulting_bytes: [u8; 16] = num.to_be_bytes();
630        assert_eq!(resulting_bytes, original);
631    }
632
633    #[test]
634    fn uint128_from_le_bytes_works() {
635        // zero
636        let original = [0; 16];
637        let num = Uint128::from_le_bytes(original);
638        assert!(num.is_zero());
639
640        // one
641        let original = [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
642        let num = Uint128::from_le_bytes(original);
643        assert_eq!(num.u128(), 1);
644
645        // 258
646        let original = [2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
647        let num = Uint128::from_le_bytes(original);
648        assert_eq!(num.u128(), 258);
649
650        // 2x roundtrip
651        let original = [1; 16];
652        let num = Uint128::from_le_bytes(original);
653        let a: [u8; 16] = num.to_le_bytes();
654        assert_eq!(a, original);
655
656        let original = [
657            0u8, 222u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 2u8, 3u8,
658        ];
659        let num = Uint128::from_le_bytes(original);
660        let resulting_bytes: [u8; 16] = num.to_le_bytes();
661        assert_eq!(resulting_bytes, original);
662    }
663
664    #[test]
665    fn uint128_convert_into() {
666        let original = Uint128(12345);
667        let a = u128::from(original);
668        assert_eq!(a, 12345);
669
670        let original = Uint128(12345);
671        let a = String::from(original);
672        assert_eq!(a, "12345");
673    }
674
675    #[test]
676    fn uint128_convert_from() {
677        let a = Uint128::from(5u128);
678        assert_eq!(a.0, 5);
679
680        let a = Uint128::from(5u64);
681        assert_eq!(a.0, 5);
682
683        let a = Uint128::from(5u32);
684        assert_eq!(a.0, 5);
685
686        let a = Uint128::from(5u16);
687        assert_eq!(a.0, 5);
688
689        let a = Uint128::from(5u8);
690        assert_eq!(a.0, 5);
691
692        let result = Uint128::try_from("34567");
693        assert_eq!(result.unwrap().0, 34567);
694
695        let result = Uint128::try_from("1.23");
696        assert!(result.is_err());
697    }
698
699    #[test]
700    fn uint128_try_from_signed_works() {
701        test_try_from_int_to_uint::<Int64, Uint128>("Int64", "Uint128");
702        test_try_from_int_to_uint::<Int128, Uint128>("Int128", "Uint128");
703        test_try_from_int_to_uint::<Int256, Uint128>("Int256", "Uint128");
704        test_try_from_int_to_uint::<Int512, Uint128>("Int512", "Uint128");
705    }
706
707    #[test]
708    fn uint128_try_into() {
709        assert!(Uint64::try_from(Uint128::MAX).is_err());
710
711        assert_eq!(Uint64::try_from(Uint128::zero()), Ok(Uint64::zero()));
712
713        assert_eq!(
714            Uint64::try_from(Uint128::from(42u64)),
715            Ok(Uint64::from(42u64))
716        );
717    }
718
719    #[test]
720    fn uint128_implements_display() {
721        let a = Uint128(12345);
722        assert_eq!(format!("Embedded: {a}"), "Embedded: 12345");
723        assert_eq!(a.to_string(), "12345");
724
725        let a = Uint128(0);
726        assert_eq!(format!("Embedded: {a}"), "Embedded: 0");
727        assert_eq!(a.to_string(), "0");
728    }
729
730    #[test]
731    fn uint128_display_padding_works() {
732        // width > natural representation
733        let a = Uint128::from(123u64);
734        assert_eq!(format!("Embedded: {a:05}"), "Embedded: 00123");
735
736        // width < natural representation
737        let a = Uint128::from(123u64);
738        assert_eq!(format!("Embedded: {a:02}"), "Embedded: 123");
739    }
740
741    #[test]
742    fn uint128_to_be_bytes_works() {
743        assert_eq!(
744            Uint128::zero().to_be_bytes(),
745            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
746        );
747        assert_eq!(
748            Uint128::MAX.to_be_bytes(),
749            [
750                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
751                0xff, 0xff
752            ]
753        );
754        assert_eq!(
755            Uint128::new(1).to_be_bytes(),
756            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]
757        );
758        // Python: `[b for b in (240282366920938463463374607431768124608).to_bytes(16, "big")]`
759        assert_eq!(
760            Uint128::new(240282366920938463463374607431768124608).to_be_bytes(),
761            [180, 196, 179, 87, 165, 121, 59, 133, 246, 117, 221, 191, 255, 254, 172, 192]
762        );
763    }
764
765    #[test]
766    fn uint128_to_le_bytes_works() {
767        assert_eq!(
768            Uint128::zero().to_le_bytes(),
769            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
770        );
771        assert_eq!(
772            Uint128::MAX.to_le_bytes(),
773            [
774                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
775                0xff, 0xff
776            ]
777        );
778        assert_eq!(
779            Uint128::new(1).to_le_bytes(),
780            [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
781        );
782        // Python: `[b for b in (240282366920938463463374607431768124608).to_bytes(16, "little")]`
783        assert_eq!(
784            Uint128::new(240282366920938463463374607431768124608).to_le_bytes(),
785            [192, 172, 254, 255, 191, 221, 117, 246, 133, 59, 121, 165, 87, 179, 196, 180]
786        );
787    }
788
789    #[test]
790    fn uint128_is_zero_works() {
791        assert!(Uint128::zero().is_zero());
792        assert!(Uint128(0).is_zero());
793
794        assert!(!Uint128(1).is_zero());
795        assert!(!Uint128(123).is_zero());
796    }
797
798    #[test]
799    fn uint128_json() {
800        let orig = Uint128(1234567890987654321);
801        let serialized = serde_json::to_vec(&orig).unwrap();
802        assert_eq!(serialized.as_slice(), b"\"1234567890987654321\"");
803        let parsed: Uint128 = serde_json::from_slice(&serialized).unwrap();
804        assert_eq!(parsed, orig);
805    }
806
807    #[test]
808    fn uint128_compare() {
809        let a = Uint128(12345);
810        let b = Uint128(23456);
811
812        assert!(a < b);
813        assert!(b > a);
814        assert_eq!(a, Uint128(12345));
815    }
816
817    #[test]
818    #[allow(clippy::op_ref)]
819    fn uint128_math() {
820        let a = Uint128(12345);
821        let b = Uint128(23456);
822
823        // test - with owned and reference right hand side
824        assert_eq!(b - a, Uint128(11111));
825        assert_eq!(b - &a, Uint128(11111));
826
827        // test += with owned and reference right hand side
828        let mut c = Uint128(300000);
829        c += b;
830        assert_eq!(c, Uint128(323456));
831        let mut d = Uint128(300000);
832        d += &b;
833        assert_eq!(d, Uint128(323456));
834
835        // test -= with owned and reference right hand side
836        let mut c = Uint128(300000);
837        c -= b;
838        assert_eq!(c, Uint128(276544));
839        let mut d = Uint128(300000);
840        d -= &b;
841        assert_eq!(d, Uint128(276544));
842
843        // error result on underflow (- would produce negative result)
844        let underflow_result = a.checked_sub(b);
845        let OverflowError { operation } = underflow_result.unwrap_err();
846        assert_eq!(operation, OverflowOperation::Sub);
847    }
848
849    #[test]
850    #[allow(clippy::op_ref)]
851    fn uint128_add_works() {
852        assert_eq!(
853            Uint128::from(2u32) + Uint128::from(1u32),
854            Uint128::from(3u32)
855        );
856        assert_eq!(
857            Uint128::from(2u32) + Uint128::from(0u32),
858            Uint128::from(2u32)
859        );
860
861        // works for refs
862        let a = Uint128::from(10u32);
863        let b = Uint128::from(3u32);
864        let expected = Uint128::from(13u32);
865        assert_eq!(a + b, expected);
866        assert_eq!(a + &b, expected);
867        assert_eq!(&a + b, expected);
868        assert_eq!(&a + &b, expected);
869    }
870
871    #[test]
872    #[should_panic(expected = "attempt to add with overflow")]
873    fn uint128_add_overflow_panics() {
874        let max = Uint128::MAX;
875        let _ = max + Uint128(12);
876    }
877
878    #[test]
879    #[allow(clippy::op_ref)]
880    fn uint128_sub_works() {
881        assert_eq!(Uint128(2) - Uint128(1), Uint128(1));
882        assert_eq!(Uint128(2) - Uint128(0), Uint128(2));
883        assert_eq!(Uint128(2) - Uint128(2), Uint128(0));
884
885        // works for refs
886        let a = Uint128::new(10);
887        let b = Uint128::new(3);
888        let expected = Uint128::new(7);
889        assert_eq!(a - b, expected);
890        assert_eq!(a - &b, expected);
891        assert_eq!(&a - b, expected);
892        assert_eq!(&a - &b, expected);
893    }
894
895    #[test]
896    #[should_panic]
897    fn uint128_sub_overflow_panics() {
898        let _ = Uint128(1) - Uint128(2);
899    }
900
901    #[test]
902    fn uint128_sub_assign_works() {
903        let mut a = Uint128(14);
904        a -= Uint128(2);
905        assert_eq!(a, Uint128(12));
906
907        // works for refs
908        let mut a = Uint128::new(10);
909        let b = Uint128::new(3);
910        let expected = Uint128::new(7);
911        a -= &b;
912        assert_eq!(a, expected);
913    }
914
915    #[test]
916    #[allow(clippy::op_ref)]
917    fn uint128_mul_works() {
918        assert_eq!(
919            Uint128::from(2u32) * Uint128::from(3u32),
920            Uint128::from(6u32)
921        );
922        assert_eq!(Uint128::from(2u32) * Uint128::zero(), Uint128::zero());
923
924        // works for refs
925        let a = Uint128::from(11u32);
926        let b = Uint128::from(3u32);
927        let expected = Uint128::from(33u32);
928        assert_eq!(a * b, expected);
929        assert_eq!(a * &b, expected);
930        assert_eq!(&a * b, expected);
931        assert_eq!(&a * &b, expected);
932    }
933
934    #[test]
935    fn uint128_mul_assign_works() {
936        let mut a = Uint128::from(14u32);
937        a *= Uint128::from(2u32);
938        assert_eq!(a, Uint128::from(28u32));
939
940        // works for refs
941        let mut a = Uint128::from(10u32);
942        let b = Uint128::from(3u32);
943        a *= &b;
944        assert_eq!(a, Uint128::from(30u32));
945    }
946
947    #[test]
948    fn uint128_pow_works() {
949        assert_eq!(Uint128::from(2u32).pow(2), Uint128::from(4u32));
950        assert_eq!(Uint128::from(2u32).pow(10), Uint128::from(1024u32));
951    }
952
953    #[test]
954    #[should_panic]
955    fn uint128_pow_overflow_panics() {
956        _ = Uint128::MAX.pow(2u32);
957    }
958
959    #[test]
960    fn uint128_multiply_ratio_works() {
961        let base = Uint128(500);
962
963        // factor 1/1
964        assert_eq!(base.multiply_ratio(1u128, 1u128), base);
965        assert_eq!(base.multiply_ratio(3u128, 3u128), base);
966        assert_eq!(base.multiply_ratio(654321u128, 654321u128), base);
967        assert_eq!(base.multiply_ratio(u128::MAX, u128::MAX), base);
968
969        // factor 3/2
970        assert_eq!(base.multiply_ratio(3u128, 2u128), Uint128(750));
971        assert_eq!(base.multiply_ratio(333333u128, 222222u128), Uint128(750));
972
973        // factor 2/3 (integer division always floors the result)
974        assert_eq!(base.multiply_ratio(2u128, 3u128), Uint128(333));
975        assert_eq!(base.multiply_ratio(222222u128, 333333u128), Uint128(333));
976
977        // factor 5/6 (integer division always floors the result)
978        assert_eq!(base.multiply_ratio(5u128, 6u128), Uint128(416));
979        assert_eq!(base.multiply_ratio(100u128, 120u128), Uint128(416));
980    }
981
982    #[test]
983    fn uint128_multiply_ratio_does_not_overflow_when_result_fits() {
984        // Almost max value for Uint128.
985        let base = Uint128(u128::MAX - 9);
986
987        assert_eq!(base.multiply_ratio(2u128, 2u128), base);
988    }
989
990    #[test]
991    #[should_panic]
992    fn uint128_multiply_ratio_panicks_on_overflow() {
993        // Almost max value for Uint128.
994        let base = Uint128(u128::MAX - 9);
995
996        assert_eq!(base.multiply_ratio(2u128, 1u128), base);
997    }
998
999    #[test]
1000    #[should_panic(expected = "Denominator must not be zero")]
1001    fn uint128_multiply_ratio_panics_for_zero_denominator() {
1002        _ = Uint128(500).multiply_ratio(1u128, 0u128);
1003    }
1004
1005    #[test]
1006    fn uint128_checked_multiply_ratio_does_not_panic() {
1007        assert_eq!(
1008            Uint128(500u128).checked_multiply_ratio(1u128, 0u128),
1009            Err(CheckedMultiplyRatioError::DivideByZero),
1010        );
1011        assert_eq!(
1012            Uint128(500u128).checked_multiply_ratio(u128::MAX, 1u128),
1013            Err(CheckedMultiplyRatioError::Overflow),
1014        );
1015    }
1016
1017    #[test]
1018    fn uint128_shr_works() {
1019        let original = Uint128::new(u128::from_be_bytes([
1020            0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 4u8, 2u8,
1021        ]));
1022
1023        let shifted = Uint128::new(u128::from_be_bytes([
1024            0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 128u8, 1u8, 0u8,
1025        ]));
1026
1027        assert_eq!(original >> 2u32, shifted);
1028    }
1029
1030    #[test]
1031    #[should_panic]
1032    fn uint128_shr_overflow_panics() {
1033        let _ = Uint128::from(1u32) >> 128u32;
1034    }
1035
1036    #[test]
1037    fn uint128_shl_works() {
1038        let original = Uint128::new(u128::from_be_bytes([
1039            64u8, 128u8, 1u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
1040        ]));
1041
1042        let shifted = Uint128::new(u128::from_be_bytes([
1043            2u8, 0u8, 4u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
1044        ]));
1045
1046        assert_eq!(original << 2u32, shifted);
1047    }
1048
1049    #[test]
1050    #[should_panic]
1051    fn uint128_shl_overflow_panics() {
1052        let _ = Uint128::from(1u32) << 128u32;
1053    }
1054
1055    #[test]
1056    fn sum_works() {
1057        let nums = vec![Uint128(17), Uint128(123), Uint128(540), Uint128(82)];
1058        let expected = Uint128(762);
1059
1060        let sum_as_ref: Uint128 = nums.iter().sum();
1061        assert_eq!(expected, sum_as_ref);
1062
1063        let sum_as_owned: Uint128 = nums.into_iter().sum();
1064        assert_eq!(expected, sum_as_owned);
1065    }
1066
1067    #[test]
1068    fn uint128_methods() {
1069        // checked_*
1070        assert!(matches!(
1071            Uint128::MAX.checked_add(Uint128(1)),
1072            Err(OverflowError { .. })
1073        ));
1074        assert!(matches!(Uint128(1).checked_add(Uint128(1)), Ok(Uint128(2))));
1075        assert!(matches!(
1076            Uint128(0).checked_sub(Uint128(1)),
1077            Err(OverflowError { .. })
1078        ));
1079        assert!(matches!(Uint128(2).checked_sub(Uint128(1)), Ok(Uint128(1))));
1080        assert!(matches!(
1081            Uint128::MAX.checked_mul(Uint128(2)),
1082            Err(OverflowError { .. })
1083        ));
1084        assert!(matches!(Uint128(2).checked_mul(Uint128(2)), Ok(Uint128(4))));
1085        assert!(matches!(
1086            Uint128::MAX.checked_pow(2u32),
1087            Err(OverflowError { .. })
1088        ));
1089        assert!(matches!(Uint128(2).checked_pow(3), Ok(Uint128(8))));
1090        assert!(matches!(
1091            Uint128::MAX.checked_div(Uint128(0)),
1092            Err(DivideByZeroError { .. })
1093        ));
1094        assert!(matches!(Uint128(6).checked_div(Uint128(2)), Ok(Uint128(3))));
1095        assert!(matches!(
1096            Uint128::MAX.checked_div_euclid(Uint128(0)),
1097            Err(DivideByZeroError { .. })
1098        ));
1099        assert!(matches!(
1100            Uint128(6).checked_div_euclid(Uint128(2)),
1101            Ok(Uint128(3)),
1102        ));
1103        assert!(matches!(
1104            Uint128::MAX.checked_rem(Uint128(0)),
1105            Err(DivideByZeroError { .. })
1106        ));
1107
1108        // saturating_*
1109        assert_eq!(Uint128::MAX.saturating_add(Uint128(1)), Uint128::MAX);
1110        assert_eq!(Uint128(0).saturating_sub(Uint128(1)), Uint128(0));
1111        assert_eq!(Uint128::MAX.saturating_mul(Uint128(2)), Uint128::MAX);
1112        assert_eq!(Uint128::MAX.saturating_pow(2), Uint128::MAX);
1113    }
1114
1115    #[test]
1116    fn uint128_wrapping_methods() {
1117        // wrapping_add
1118        assert_eq!(Uint128(2).wrapping_add(Uint128(2)), Uint128(4)); // non-wrapping
1119        assert_eq!(Uint128::MAX.wrapping_add(Uint128(1)), Uint128(0)); // wrapping
1120
1121        // wrapping_sub
1122        assert_eq!(Uint128(7).wrapping_sub(Uint128(5)), Uint128(2)); // non-wrapping
1123        assert_eq!(Uint128(0).wrapping_sub(Uint128(1)), Uint128::MAX); // wrapping
1124
1125        // wrapping_mul
1126        assert_eq!(Uint128(3).wrapping_mul(Uint128(2)), Uint128(6)); // non-wrapping
1127        assert_eq!(
1128            Uint128::MAX.wrapping_mul(Uint128(2)),
1129            Uint128::MAX - Uint128::one()
1130        ); // wrapping
1131
1132        // wrapping_pow
1133        assert_eq!(Uint128(2).wrapping_pow(3), Uint128(8)); // non-wrapping
1134        assert_eq!(Uint128::MAX.wrapping_pow(2), Uint128(1)); // wrapping
1135    }
1136
1137    #[test]
1138    #[allow(clippy::op_ref)]
1139    fn uint128_implements_rem() {
1140        let a = Uint128::new(10);
1141        assert_eq!(a % Uint128::new(10), Uint128::zero());
1142        assert_eq!(a % Uint128::new(2), Uint128::zero());
1143        assert_eq!(a % Uint128::new(1), Uint128::zero());
1144        assert_eq!(a % Uint128::new(3), Uint128::new(1));
1145        assert_eq!(a % Uint128::new(4), Uint128::new(2));
1146
1147        // works for refs
1148        let a = Uint128::new(10);
1149        let b = Uint128::new(3);
1150        let expected = Uint128::new(1);
1151        assert_eq!(a % b, expected);
1152        assert_eq!(a % &b, expected);
1153        assert_eq!(&a % b, expected);
1154        assert_eq!(&a % &b, expected);
1155    }
1156
1157    #[test]
1158    #[should_panic(expected = "divisor of zero")]
1159    fn uint128_rem_panics_for_zero() {
1160        let _ = Uint128::new(10) % Uint128::zero();
1161    }
1162
1163    #[test]
1164    #[allow(clippy::op_ref)]
1165    fn uint128_rem_works() {
1166        assert_eq!(
1167            Uint128::from(12u32) % Uint128::from(10u32),
1168            Uint128::from(2u32)
1169        );
1170        assert_eq!(Uint128::from(50u32) % Uint128::from(5u32), Uint128::zero());
1171
1172        // works for refs
1173        let a = Uint128::from(42u32);
1174        let b = Uint128::from(5u32);
1175        let expected = Uint128::from(2u32);
1176        assert_eq!(a % b, expected);
1177        assert_eq!(a % &b, expected);
1178        assert_eq!(&a % b, expected);
1179        assert_eq!(&a % &b, expected);
1180    }
1181
1182    #[test]
1183    fn uint128_rem_assign_works() {
1184        let mut a = Uint128::from(30u32);
1185        a %= Uint128::from(4u32);
1186        assert_eq!(a, Uint128::from(2u32));
1187
1188        // works for refs
1189        let mut a = Uint128::from(25u32);
1190        let b = Uint128::from(6u32);
1191        a %= &b;
1192        assert_eq!(a, Uint128::from(1u32));
1193    }
1194
1195    #[test]
1196    fn uint128_strict_add_works() {
1197        let a = Uint128::new(5);
1198        let b = Uint128::new(3);
1199        assert_eq!(a.strict_add(b), Uint128::new(8));
1200        assert_eq!(b.strict_add(a), Uint128::new(8));
1201    }
1202
1203    #[test]
1204    #[should_panic(expected = "attempt to add with overflow")]
1205    fn uint128_strict_add_panics_on_overflow() {
1206        let a = Uint128::MAX;
1207        let b = Uint128::ONE;
1208        let _ = a.strict_add(b);
1209    }
1210
1211    #[test]
1212    fn uint128_strict_sub_works() {
1213        let a = Uint128::new(5);
1214        let b = Uint128::new(3);
1215        assert_eq!(a.strict_sub(b), Uint128::new(2));
1216    }
1217
1218    #[test]
1219    #[should_panic(expected = "attempt to subtract with overflow")]
1220    fn uint128_strict_sub_panics_on_overflow() {
1221        let a = Uint128::ZERO;
1222        let b = Uint128::ONE;
1223        let _ = a.strict_sub(b);
1224    }
1225
1226    #[test]
1227    fn uint128_abs_diff_works() {
1228        let a = Uint128::from(42u32);
1229        let b = Uint128::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
1235    #[test]
1236    fn uint128_partial_eq() {
1237        let test_cases = [(1, 1, true), (42, 42, true), (42, 24, false), (0, 0, true)]
1238            .into_iter()
1239            .map(|(lhs, rhs, expected)| (Uint128::new(lhs), Uint128::new(rhs), expected));
1240
1241        #[allow(clippy::op_ref)]
1242        for (lhs, rhs, expected) in test_cases {
1243            assert_eq!(lhs == rhs, expected);
1244            assert_eq!(&lhs == rhs, expected);
1245            assert_eq!(lhs == &rhs, expected);
1246            assert_eq!(&lhs == &rhs, expected);
1247        }
1248    }
1249
1250    #[test]
1251    fn mul_floor_works_with_zero() {
1252        let fraction = (Uint128::zero(), Uint128::new(21));
1253        let res = Uint128::new(123456).mul_floor(fraction);
1254        assert_eq!(Uint128::zero(), res)
1255    }
1256
1257    #[test]
1258    fn mul_floor_does_nothing_with_one() {
1259        let fraction = (Uint128::one(), Uint128::one());
1260        let res = Uint128::new(123456).mul_floor(fraction);
1261        assert_eq!(Uint128::new(123456), res)
1262    }
1263
1264    #[test]
1265    fn mul_floor_rounds_down_with_normal_case() {
1266        let fraction = (8u128, 21u128);
1267        let res = Uint128::new(123456).mul_floor(fraction); // 47030.8571
1268        assert_eq!(Uint128::new(47030), res)
1269    }
1270
1271    #[test]
1272    fn mul_floor_does_not_round_on_even_divide() {
1273        let fraction = (2u128, 5u128);
1274        let res = Uint128::new(25).mul_floor(fraction);
1275        assert_eq!(Uint128::new(10), res)
1276    }
1277
1278    #[test]
1279    fn mul_floor_works_when_operation_temporarily_takes_above_max() {
1280        let fraction = (8u128, 21u128);
1281        let res = Uint128::MAX.mul_floor(fraction); // 129_631_377_874_643_224_176_523_659_974_006_937_697.14285
1282        assert_eq!(
1283            Uint128::new(129_631_377_874_643_224_176_523_659_974_006_937_697),
1284            res
1285        )
1286    }
1287
1288    #[test]
1289    fn mul_floor_works_with_decimal() {
1290        let decimal = Decimal::from_ratio(8u128, 21u128);
1291        let res = Uint128::new(123456).mul_floor(decimal); // 47030.8571
1292        assert_eq!(Uint128::new(47030), res)
1293    }
1294
1295    #[test]
1296    #[should_panic(expected = "ConversionOverflowError")]
1297    fn mul_floor_panics_on_overflow() {
1298        let fraction = (21u128, 8u128);
1299        _ = Uint128::MAX.mul_floor(fraction);
1300    }
1301
1302    #[test]
1303    fn checked_mul_floor_does_not_panic_on_overflow() {
1304        let fraction = (21u128, 8u128);
1305        assert_eq!(
1306            Uint128::MAX.checked_mul_floor(fraction),
1307            Err(ConversionOverflow(ConversionOverflowError {
1308                source_type: "Uint256",
1309                target_type: "Uint128",
1310            })),
1311        );
1312    }
1313
1314    #[test]
1315    #[should_panic(expected = "DivideByZeroError")]
1316    fn mul_floor_panics_on_zero_div() {
1317        let fraction = (21u128, 0u128);
1318        _ = Uint128::new(123456).mul_floor(fraction);
1319    }
1320
1321    #[test]
1322    fn checked_mul_floor_does_not_panic_on_zero_div() {
1323        let fraction = (21u128, 0u128);
1324        assert_eq!(
1325            Uint128::new(123456).checked_mul_floor(fraction),
1326            Err(DivideByZero(DivideByZeroError)),
1327        );
1328    }
1329
1330    #[test]
1331    fn mul_ceil_works_with_zero() {
1332        let fraction = (Uint128::zero(), Uint128::new(21));
1333        let res = Uint128::new(123456).mul_ceil(fraction);
1334        assert_eq!(Uint128::zero(), res)
1335    }
1336
1337    #[test]
1338    fn mul_ceil_does_nothing_with_one() {
1339        let fraction = (Uint128::one(), Uint128::one());
1340        let res = Uint128::new(123456).mul_ceil(fraction);
1341        assert_eq!(Uint128::new(123456), res)
1342    }
1343
1344    #[test]
1345    fn mul_ceil_rounds_up_with_normal_case() {
1346        let fraction = (8u128, 21u128);
1347        let res = Uint128::new(123456).mul_ceil(fraction); // 47030.8571
1348        assert_eq!(Uint128::new(47031), res)
1349    }
1350
1351    #[test]
1352    fn mul_ceil_does_not_round_on_even_divide() {
1353        let fraction = (2u128, 5u128);
1354        let res = Uint128::new(25).mul_ceil(fraction);
1355        assert_eq!(Uint128::new(10), res)
1356    }
1357
1358    #[test]
1359    fn mul_ceil_works_when_operation_temporarily_takes_above_max() {
1360        let fraction = (8u128, 21u128);
1361        let res = Uint128::MAX.mul_ceil(fraction); // 129_631_377_874_643_224_176_523_659_974_006_937_697.14285
1362        assert_eq!(
1363            Uint128::new(129_631_377_874_643_224_176_523_659_974_006_937_698),
1364            res
1365        )
1366    }
1367
1368    #[test]
1369    fn mul_ceil_works_with_decimal() {
1370        let decimal = Decimal::from_ratio(8u128, 21u128);
1371        let res = Uint128::new(123456).mul_ceil(decimal); // 47030.8571
1372        assert_eq!(Uint128::new(47031), res)
1373    }
1374
1375    #[test]
1376    #[should_panic(expected = "ConversionOverflowError")]
1377    fn mul_ceil_panics_on_overflow() {
1378        let fraction = (21u128, 8u128);
1379        _ = Uint128::MAX.mul_ceil(fraction);
1380    }
1381
1382    #[test]
1383    fn checked_mul_ceil_does_not_panic_on_overflow() {
1384        let fraction = (21u128, 8u128);
1385        assert_eq!(
1386            Uint128::MAX.checked_mul_ceil(fraction),
1387            Err(ConversionOverflow(ConversionOverflowError {
1388                source_type: "Uint256",
1389                target_type: "Uint128",
1390            })),
1391        );
1392    }
1393
1394    #[test]
1395    #[should_panic(expected = "DivideByZeroError")]
1396    fn mul_ceil_panics_on_zero_div() {
1397        let fraction = (21u128, 0u128);
1398        _ = Uint128::new(123456).mul_ceil(fraction);
1399    }
1400
1401    #[test]
1402    fn checked_mul_ceil_does_not_panic_on_zero_div() {
1403        let fraction = (21u128, 0u128);
1404        assert_eq!(
1405            Uint128::new(123456).checked_mul_ceil(fraction),
1406            Err(DivideByZero(DivideByZeroError)),
1407        );
1408    }
1409
1410    #[test]
1411    #[should_panic(expected = "DivideByZeroError")]
1412    fn div_floor_raises_with_zero() {
1413        let fraction = (Uint128::zero(), Uint128::new(21));
1414        _ = Uint128::new(123456).div_floor(fraction);
1415    }
1416
1417    #[test]
1418    fn div_floor_does_nothing_with_one() {
1419        let fraction = (Uint128::one(), Uint128::one());
1420        let res = Uint128::new(123456).div_floor(fraction);
1421        assert_eq!(Uint128::new(123456), res)
1422    }
1423
1424    #[test]
1425    fn div_floor_rounds_down_with_normal_case() {
1426        let fraction = (5u128, 21u128);
1427        let res = Uint128::new(123456).div_floor(fraction); // 518515.2
1428        assert_eq!(Uint128::new(518515), res)
1429    }
1430
1431    #[test]
1432    fn div_floor_does_not_round_on_even_divide() {
1433        let fraction = (5u128, 2u128);
1434        let res = Uint128::new(25).div_floor(fraction);
1435        assert_eq!(Uint128::new(10), res)
1436    }
1437
1438    #[test]
1439    fn div_floor_works_when_operation_temporarily_takes_above_max() {
1440        let fraction = (21u128, 8u128);
1441        let res = Uint128::MAX.div_floor(fraction); // 129_631_377_874_643_224_176_523_659_974_006_937_697.1428
1442        assert_eq!(
1443            Uint128::new(129_631_377_874_643_224_176_523_659_974_006_937_697),
1444            res
1445        )
1446    }
1447
1448    #[test]
1449    fn div_floor_works_with_decimal() {
1450        let decimal = Decimal::from_ratio(21u128, 8u128);
1451        let res = Uint128::new(123456).div_floor(decimal); // 47030.8571
1452        assert_eq!(Uint128::new(47030), res)
1453    }
1454
1455    #[test]
1456    fn div_floor_works_with_decimal_evenly() {
1457        let res = Uint128::new(60).div_floor(Decimal::from_atomics(6u128, 0).unwrap());
1458        assert_eq!(res, Uint128::new(10));
1459    }
1460
1461    #[test]
1462    #[should_panic(expected = "ConversionOverflowError")]
1463    fn div_floor_panics_on_overflow() {
1464        let fraction = (8u128, 21u128);
1465        _ = Uint128::MAX.div_floor(fraction);
1466    }
1467
1468    #[test]
1469    fn div_floor_does_not_panic_on_overflow() {
1470        let fraction = (8u128, 21u128);
1471        assert_eq!(
1472            Uint128::MAX.checked_div_floor(fraction),
1473            Err(ConversionOverflow(ConversionOverflowError {
1474                source_type: "Uint256",
1475                target_type: "Uint128",
1476            })),
1477        );
1478    }
1479
1480    #[test]
1481    #[should_panic(expected = "DivideByZeroError")]
1482    fn div_ceil_raises_with_zero() {
1483        let fraction = (Uint128::zero(), Uint128::new(21));
1484        _ = Uint128::new(123456).div_ceil(fraction);
1485    }
1486
1487    #[test]
1488    fn div_ceil_does_nothing_with_one() {
1489        let fraction = (Uint128::one(), Uint128::one());
1490        let res = Uint128::new(123456).div_ceil(fraction);
1491        assert_eq!(Uint128::new(123456), res)
1492    }
1493
1494    #[test]
1495    fn div_ceil_rounds_up_with_normal_case() {
1496        let fraction = (5u128, 21u128);
1497        let res = Uint128::new(123456).div_ceil(fraction); // 518515.2
1498        assert_eq!(Uint128::new(518516), res)
1499    }
1500
1501    #[test]
1502    fn div_ceil_does_not_round_on_even_divide() {
1503        let fraction = (5u128, 2u128);
1504        let res = Uint128::new(25).div_ceil(fraction);
1505        assert_eq!(Uint128::new(10), res)
1506    }
1507
1508    #[test]
1509    fn div_ceil_works_when_operation_temporarily_takes_above_max() {
1510        let fraction = (21u128, 8u128);
1511        let res = Uint128::MAX.div_ceil(fraction); // 129_631_377_874_643_224_176_523_659_974_006_937_697.1428
1512        assert_eq!(
1513            Uint128::new(129_631_377_874_643_224_176_523_659_974_006_937_698),
1514            res
1515        )
1516    }
1517
1518    #[test]
1519    fn div_ceil_works_with_decimal() {
1520        let decimal = Decimal::from_ratio(21u128, 8u128);
1521        let res = Uint128::new(123456).div_ceil(decimal); // 47030.8571
1522        assert_eq!(Uint128::new(47031), res)
1523    }
1524
1525    #[test]
1526    fn div_ceil_works_with_decimal_evenly() {
1527        let res = Uint128::new(60).div_ceil(Decimal::from_atomics(6u128, 0).unwrap());
1528        assert_eq!(res, Uint128::new(10));
1529    }
1530
1531    #[test]
1532    #[should_panic(expected = "ConversionOverflowError")]
1533    fn div_ceil_panics_on_overflow() {
1534        let fraction = (8u128, 21u128);
1535        _ = Uint128::MAX.div_ceil(fraction);
1536    }
1537
1538    #[test]
1539    fn div_ceil_does_not_panic_on_overflow() {
1540        let fraction = (8u128, 21u128);
1541        assert_eq!(
1542            Uint128::MAX.checked_div_ceil(fraction),
1543            Err(ConversionOverflow(ConversionOverflowError {
1544                source_type: "Uint256",
1545                target_type: "Uint128",
1546            })),
1547        );
1548    }
1549}