Skip to main content

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