Skip to main content

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