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(if self.0 < other.0 {
291            other.0 - self.0
292        } else {
293            self.0 - other.0
294        })
295    }
296}
297
298impl NumConsts for Uint64 {
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!(Uint64);
306
307// `From<u{128,64,32,16,8}>` is implemented manually instead of
308// using `impl<T: Into<u64>> From<T> for Uint64` 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, Uint64);
314primitive_to_wrapped_int!(u16, Uint64);
315primitive_to_wrapped_int!(u32, Uint64);
316primitive_to_wrapped_int!(u64, Uint64);
317
318// Uint to uint
319wrapped_int_to_primitive!(Uint64, u64);
320wrapped_int_to_primitive!(Uint64, u128);
321
322// Int to Uint
323forward_try_from!(Int64, Uint64);
324forward_try_from!(Int128, Uint64);
325forward_try_from!(Int256, Uint64);
326forward_try_from!(Int512, Uint64);
327
328impl TryFrom<&str> for Uint64 {
329    type Error = StdError;
330
331    fn try_from(val: &str) -> Result<Self, Self::Error> {
332        match val.parse::<u64>() {
333            Ok(u) => Ok(Uint64(u)),
334            Err(e) => Err(StdError::generic_err(format!("Parsing u64: {e}"))),
335        }
336    }
337}
338
339impl From<Uint64> for String {
340    fn from(original: Uint64) -> Self {
341        original.to_string()
342    }
343}
344
345impl fmt::Display for Uint64 {
346    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
347        self.0.fmt(f)
348    }
349}
350
351impl Add<Uint64> for Uint64 {
352    type Output = Self;
353
354    fn add(self, rhs: Self) -> Self {
355        self.strict_add(rhs)
356    }
357}
358forward_ref_binop!(impl Add, add for Uint64, Uint64);
359
360impl Sub<Uint64> for Uint64 {
361    type Output = Self;
362
363    fn sub(self, rhs: Self) -> Self {
364        self.strict_sub(rhs)
365    }
366}
367forward_ref_binop!(impl Sub, sub for Uint64, Uint64);
368
369impl SubAssign<Uint64> for Uint64 {
370    fn sub_assign(&mut self, rhs: Uint64) {
371        *self = *self - rhs;
372    }
373}
374forward_ref_op_assign!(impl SubAssign, sub_assign for Uint64, Uint64);
375
376impl Mul<Uint64> for Uint64 {
377    type Output = Self;
378
379    fn mul(self, rhs: Self) -> Self::Output {
380        Self(
381            self.u64()
382                .checked_mul(rhs.u64())
383                .expect("attempt to multiply with overflow"),
384        )
385    }
386}
387forward_ref_binop!(impl Mul, mul for Uint64, Uint64);
388
389impl MulAssign<Uint64> for Uint64 {
390    fn mul_assign(&mut self, rhs: Self) {
391        *self = *self * rhs;
392    }
393}
394forward_ref_op_assign!(impl MulAssign, mul_assign for Uint64, Uint64);
395
396impl Div<Uint64> for Uint64 {
397    type Output = Self;
398
399    fn div(self, rhs: Self) -> Self::Output {
400        Self(self.u64().checked_div(rhs.u64()).unwrap())
401    }
402}
403
404impl<'a> Div<&'a Uint64> for Uint64 {
405    type Output = Self;
406
407    fn div(self, rhs: &'a Uint64) -> Self::Output {
408        Self(self.u64().checked_div(rhs.u64()).unwrap())
409    }
410}
411
412impl Rem for Uint64 {
413    type Output = Self;
414
415    /// # Panics
416    ///
417    /// This operation will panic if `rhs` is zero.
418    #[inline]
419    fn rem(self, rhs: Self) -> Self {
420        Self(self.0.rem(rhs.0))
421    }
422}
423forward_ref_binop!(impl Rem, rem for Uint64, Uint64);
424
425impl Not for Uint64 {
426    type Output = Self;
427
428    fn not(self) -> Self::Output {
429        Self(!self.0)
430    }
431}
432
433impl RemAssign<Uint64> for Uint64 {
434    fn rem_assign(&mut self, rhs: Uint64) {
435        *self = *self % rhs;
436    }
437}
438forward_ref_op_assign!(impl RemAssign, rem_assign for Uint64, Uint64);
439
440impl Shr<u32> for Uint64 {
441    type Output = Self;
442
443    fn shr(self, rhs: u32) -> Self::Output {
444        Self(self.u64().checked_shr(rhs).unwrap())
445    }
446}
447
448impl<'a> Shr<&'a u32> for Uint64 {
449    type Output = Self;
450
451    fn shr(self, rhs: &'a u32) -> Self::Output {
452        Self(self.u64().checked_shr(*rhs).unwrap())
453    }
454}
455
456impl Shl<u32> for Uint64 {
457    type Output = Self;
458
459    fn shl(self, rhs: u32) -> Self::Output {
460        Self(
461            self.u64()
462                .checked_shl(rhs)
463                .expect("attempt to shift left with overflow"),
464        )
465    }
466}
467
468impl<'a> Shl<&'a u32> for Uint64 {
469    type Output = Self;
470
471    fn shl(self, rhs: &'a u32) -> Self::Output {
472        self.shl(*rhs)
473    }
474}
475
476impl AddAssign<Uint64> for Uint64 {
477    fn add_assign(&mut self, rhs: Uint64) {
478        self.0 = self.0.checked_add(rhs.u64()).unwrap();
479    }
480}
481
482impl<'a> AddAssign<&'a Uint64> for Uint64 {
483    fn add_assign(&mut self, rhs: &'a Uint64) {
484        self.0 = self.0.checked_add(rhs.u64()).unwrap();
485    }
486}
487
488impl DivAssign<Uint64> for Uint64 {
489    fn div_assign(&mut self, rhs: Self) {
490        self.0 = self.0.checked_div(rhs.u64()).unwrap();
491    }
492}
493
494impl<'a> DivAssign<&'a Uint64> for Uint64 {
495    fn div_assign(&mut self, rhs: &'a Uint64) {
496        self.0 = self.0.checked_div(rhs.u64()).unwrap();
497    }
498}
499
500impl ShrAssign<u32> for Uint64 {
501    fn shr_assign(&mut self, rhs: u32) {
502        self.0 = self.0.checked_shr(rhs).unwrap();
503    }
504}
505
506impl<'a> ShrAssign<&'a u32> for Uint64 {
507    fn shr_assign(&mut self, rhs: &'a u32) {
508        self.0 = self.0.checked_shr(*rhs).unwrap();
509    }
510}
511
512impl ShlAssign<u32> for Uint64 {
513    fn shl_assign(&mut self, rhs: u32) {
514        *self = self.shl(rhs);
515    }
516}
517
518impl<'a> ShlAssign<&'a u32> for Uint64 {
519    fn shl_assign(&mut self, rhs: &'a u32) {
520        *self = self.shl(*rhs);
521    }
522}
523
524impl<A> core::iter::Sum<A> for Uint64
525where
526    Self: Add<A, Output = Self>,
527{
528    fn sum<I: Iterator<Item = A>>(iter: I) -> Self {
529        iter.fold(Self::zero(), Add::add)
530    }
531}
532
533#[cfg(test)]
534mod tests {
535    use super::*;
536    use crate::errors::CheckedMultiplyFractionError::{ConversionOverflow, DivideByZero};
537    use crate::math::conversion::test_try_from_int_to_uint;
538    use crate::ConversionOverflowError;
539
540    use alloc::string::ToString;
541
542    #[test]
543    fn size_of_works() {
544        assert_eq!(core::mem::size_of::<Uint64>(), 8);
545    }
546
547    #[test]
548    fn uint64_not_works() {
549        assert_eq!(!Uint64::new(1234806), Uint64::new(!1234806));
550
551        assert_eq!(!Uint64::MAX, Uint64::new(!u64::MAX));
552        assert_eq!(!Uint64::MIN, Uint64::new(!u64::MIN));
553    }
554
555    #[test]
556    fn uint64_zero_works() {
557        let zero = Uint64::zero();
558        assert_eq!(zero.to_be_bytes(), [0, 0, 0, 0, 0, 0, 0, 0]);
559    }
560
561    #[test]
562    fn uint64_one_works() {
563        let one = Uint64::one();
564        assert_eq!(one.to_be_bytes(), [0, 0, 0, 0, 0, 0, 0, 1]);
565    }
566
567    #[test]
568    fn uint64_from_be_bytes_works() {
569        // zero
570        let original = [0; 8];
571        let num = Uint64::from_be_bytes(original);
572        assert!(num.is_zero());
573
574        // one
575        let original = [0, 0, 0, 0, 0, 0, 0, 1];
576        let num = Uint64::from_be_bytes(original);
577        assert_eq!(num.u64(), 1);
578
579        // 258
580        let original = [0, 0, 0, 0, 0, 0, 1, 2];
581        let num = Uint64::from_be_bytes(original);
582        assert_eq!(num.u64(), 258);
583
584        // 2x roundtrip
585        let original = [1; 8];
586        let num = Uint64::from_be_bytes(original);
587        let a: [u8; 8] = num.to_be_bytes();
588        assert_eq!(a, original);
589
590        let original = [0u8, 222u8, 0u8, 0u8, 0u8, 1u8, 2u8, 3u8];
591        let num = Uint64::from_be_bytes(original);
592        let resulting_bytes: [u8; 8] = num.to_be_bytes();
593        assert_eq!(resulting_bytes, original);
594    }
595
596    #[test]
597    fn uint64_from_le_bytes_works() {
598        // zero
599        let original = [0; 8];
600        let num = Uint64::from_le_bytes(original);
601        assert!(num.is_zero());
602
603        // one
604        let original = [1, 0, 0, 0, 0, 0, 0, 0];
605        let num = Uint64::from_le_bytes(original);
606        assert_eq!(num.u64(), 1);
607
608        // 258
609        let original = [2, 1, 0, 0, 0, 0, 0, 0];
610        let num = Uint64::from_le_bytes(original);
611        assert_eq!(num.u64(), 258);
612
613        // 2x roundtrip
614        let original = [1; 8];
615        let num = Uint64::from_le_bytes(original);
616        let a: [u8; 8] = num.to_le_bytes();
617        assert_eq!(a, original);
618
619        let original = [0u8, 222u8, 0u8, 0u8, 0u8, 1u8, 2u8, 3u8];
620        let num = Uint64::from_le_bytes(original);
621        let resulting_bytes: [u8; 8] = num.to_le_bytes();
622        assert_eq!(resulting_bytes, original);
623    }
624
625    #[test]
626    fn uint64_convert_into() {
627        let original = Uint64(12345);
628        let a = u64::from(original);
629        assert_eq!(a, 12345);
630
631        let original = Uint64(12345);
632        let a = u128::from(original);
633        assert_eq!(a, 12345);
634
635        let original = Uint64(12345);
636        let a = String::from(original);
637        assert_eq!(a, "12345");
638    }
639
640    #[test]
641    fn uint64_convert_from() {
642        let a = Uint64::from(5u64);
643        assert_eq!(a.0, 5);
644
645        let a = Uint64::from(5u32);
646        assert_eq!(a.0, 5);
647
648        let a = Uint64::from(5u16);
649        assert_eq!(a.0, 5);
650
651        let a = Uint64::from(5u8);
652        assert_eq!(a.0, 5);
653
654        let result = Uint64::try_from("34567");
655        assert_eq!(result.unwrap().0, 34567);
656
657        let result = Uint64::try_from("1.23");
658        assert!(result.is_err());
659    }
660
661    #[test]
662    fn uint64_try_from_signed_works() {
663        test_try_from_int_to_uint::<Int64, Uint64>("Int64", "Uint64");
664        test_try_from_int_to_uint::<Int128, Uint64>("Int128", "Uint64");
665        test_try_from_int_to_uint::<Int256, Uint64>("Int256", "Uint64");
666        test_try_from_int_to_uint::<Int512, Uint64>("Int512", "Uint64");
667    }
668
669    #[test]
670    fn uint64_implements_display() {
671        let a = Uint64(12345);
672        assert_eq!(format!("Embedded: {a}"), "Embedded: 12345");
673        assert_eq!(a.to_string(), "12345");
674
675        let a = Uint64(0);
676        assert_eq!(format!("Embedded: {a}"), "Embedded: 0");
677        assert_eq!(a.to_string(), "0");
678    }
679
680    #[test]
681    fn uint64_display_padding_works() {
682        // width > natural representation
683        let a = Uint64::from(123u64);
684        assert_eq!(format!("Embedded: {a:05}"), "Embedded: 00123");
685
686        // width < natural representation
687        let a = Uint64::from(123u64);
688        assert_eq!(format!("Embedded: {a:02}"), "Embedded: 123");
689    }
690
691    #[test]
692    fn uint64_to_be_bytes_works() {
693        assert_eq!(Uint64::zero().to_be_bytes(), [0, 0, 0, 0, 0, 0, 0, 0]);
694        assert_eq!(
695            Uint64::MAX.to_be_bytes(),
696            [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]
697        );
698        assert_eq!(Uint64::new(1).to_be_bytes(), [0, 0, 0, 0, 0, 0, 0, 1]);
699        // Python: `[b for b in (63374607431768124608).to_bytes(8, "big")]`
700        assert_eq!(
701            Uint64::new(874607431768124608).to_be_bytes(),
702            [12, 35, 58, 211, 72, 116, 172, 192]
703        );
704    }
705
706    #[test]
707    fn uint64_to_le_bytes_works() {
708        assert_eq!(Uint64::zero().to_le_bytes(), [0, 0, 0, 0, 0, 0, 0, 0]);
709        assert_eq!(
710            Uint64::MAX.to_le_bytes(),
711            [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]
712        );
713        assert_eq!(Uint64::new(1).to_le_bytes(), [1, 0, 0, 0, 0, 0, 0, 0]);
714        // Python: `[b for b in (240282366920938463463374607431768124608).to_bytes(16, "little")]`
715        assert_eq!(
716            Uint64::new(874607431768124608).to_le_bytes(),
717            [192, 172, 116, 72, 211, 58, 35, 12]
718        );
719    }
720
721    #[test]
722    fn uint64_is_zero_works() {
723        assert!(Uint64::zero().is_zero());
724        assert!(Uint64(0).is_zero());
725
726        assert!(!Uint64(1).is_zero());
727        assert!(!Uint64(123).is_zero());
728    }
729
730    #[test]
731    fn uint64_json() {
732        let orig = Uint64(1234567890987654321);
733        let serialized = serde_json::to_vec(&orig).unwrap();
734        assert_eq!(serialized.as_slice(), b"\"1234567890987654321\"");
735        let parsed: Uint64 = serde_json::from_slice(&serialized).unwrap();
736        assert_eq!(parsed, orig);
737    }
738
739    #[test]
740    fn uint64_compare() {
741        let a = Uint64(12345);
742        let b = Uint64(23456);
743
744        assert!(a < b);
745        assert!(b > a);
746        assert_eq!(a, Uint64(12345));
747    }
748
749    #[test]
750    #[allow(clippy::op_ref)]
751    fn uint64_math() {
752        let a = Uint64(12345);
753        let b = Uint64(23456);
754
755        // test - with owned and reference right hand side
756        assert_eq!((b.checked_sub(a)).unwrap(), Uint64(11111));
757
758        // test += with owned and reference right hand side
759        let mut c = Uint64(300000);
760        c += b;
761        assert_eq!(c, Uint64(323456));
762        let mut d = Uint64(300000);
763        d += &b;
764        assert_eq!(d, Uint64(323456));
765
766        // error result on underflow (- would produce negative result)
767        let underflow_result = a.checked_sub(b);
768        let OverflowError { operation } = underflow_result.unwrap_err();
769        assert_eq!(operation, OverflowOperation::Sub);
770    }
771
772    #[test]
773    #[allow(clippy::op_ref)]
774    fn uint64_add_works() {
775        assert_eq!(Uint64::from(2u32) + Uint64::from(1u32), Uint64::from(3u32));
776        assert_eq!(Uint64::from(2u32) + Uint64::from(0u32), Uint64::from(2u32));
777
778        // works for refs
779        let a = Uint64::from(10u32);
780        let b = Uint64::from(3u32);
781        let expected = Uint64::from(13u32);
782        assert_eq!(a + b, expected);
783        assert_eq!(a + &b, expected);
784        assert_eq!(&a + b, expected);
785        assert_eq!(&a + &b, expected);
786    }
787
788    #[test]
789    #[should_panic(expected = "attempt to add with overflow")]
790    fn uint64_add_overflow_panics() {
791        let max = Uint64::MAX;
792        let _ = max + Uint64(12);
793    }
794
795    #[test]
796    #[allow(clippy::op_ref)]
797    fn uint64_sub_works() {
798        assert_eq!(Uint64(2) - Uint64(1), Uint64(1));
799        assert_eq!(Uint64(2) - Uint64(0), Uint64(2));
800        assert_eq!(Uint64(2) - Uint64(2), Uint64(0));
801
802        // works for refs
803        let a = Uint64::new(10);
804        let b = Uint64::new(3);
805        let expected = Uint64::new(7);
806        assert_eq!(a - b, expected);
807        assert_eq!(a - &b, expected);
808        assert_eq!(&a - b, expected);
809        assert_eq!(&a - &b, expected);
810    }
811
812    #[test]
813    #[should_panic]
814    fn uint64_sub_overflow_panics() {
815        let _ = Uint64(1) - Uint64(2);
816    }
817
818    #[test]
819    fn uint64_sub_assign_works() {
820        let mut a = Uint64(14);
821        a -= Uint64(2);
822        assert_eq!(a, Uint64(12));
823
824        // works for refs
825        let mut a = Uint64::new(10);
826        let b = Uint64::new(3);
827        let expected = Uint64::new(7);
828        a -= &b;
829        assert_eq!(a, expected);
830    }
831
832    #[test]
833    #[allow(clippy::op_ref)]
834    fn uint64_mul_works() {
835        assert_eq!(Uint64::from(2u32) * Uint64::from(3u32), Uint64::from(6u32));
836        assert_eq!(Uint64::from(2u32) * Uint64::zero(), Uint64::zero());
837
838        // works for refs
839        let a = Uint64::from(11u32);
840        let b = Uint64::from(3u32);
841        let expected = Uint64::from(33u32);
842        assert_eq!(a * b, expected);
843        assert_eq!(a * &b, expected);
844        assert_eq!(&a * b, expected);
845        assert_eq!(&a * &b, expected);
846    }
847
848    #[test]
849    fn uint64_mul_assign_works() {
850        let mut a = Uint64::from(14u32);
851        a *= Uint64::from(2u32);
852        assert_eq!(a, Uint64::from(28u32));
853
854        // works for refs
855        let mut a = Uint64::from(10u32);
856        let b = Uint64::from(3u32);
857        a *= &b;
858        assert_eq!(a, Uint64::from(30u32));
859    }
860
861    #[test]
862    fn uint64_pow_works() {
863        assert_eq!(Uint64::from(2u32).pow(2), Uint64::from(4u32));
864        assert_eq!(Uint64::from(2u32).pow(10), Uint64::from(1024u32));
865    }
866
867    #[test]
868    #[should_panic]
869    fn uint64_pow_overflow_panics() {
870        _ = Uint64::MAX.pow(2u32);
871    }
872
873    #[test]
874    #[should_panic]
875    fn uint64_math_overflow_panics() {
876        // almost_max is 2^64 - 10
877        let almost_max = Uint64(18446744073709551606);
878        let _ = almost_max + Uint64(12);
879    }
880
881    #[test]
882    fn uint64_multiply_ratio_works() {
883        let base = Uint64(500);
884
885        // factor 1/1
886        assert_eq!(base.multiply_ratio(1u64, 1u64), base);
887        assert_eq!(base.multiply_ratio(3u64, 3u64), base);
888        assert_eq!(base.multiply_ratio(654321u64, 654321u64), base);
889        assert_eq!(base.multiply_ratio(u64::MAX, u64::MAX), base);
890
891        // factor 3/2
892        assert_eq!(base.multiply_ratio(3u64, 2u64), Uint64(750));
893        assert_eq!(base.multiply_ratio(333333u64, 222222u64), Uint64(750));
894
895        // factor 2/3 (integer division always floors the result)
896        assert_eq!(base.multiply_ratio(2u64, 3u64), Uint64(333));
897        assert_eq!(base.multiply_ratio(222222u64, 333333u64), Uint64(333));
898
899        // factor 5/6 (integer division always floors the result)
900        assert_eq!(base.multiply_ratio(5u64, 6u64), Uint64(416));
901        assert_eq!(base.multiply_ratio(100u64, 120u64), Uint64(416));
902    }
903
904    #[test]
905    fn uint64_multiply_ratio_does_not_overflow_when_result_fits() {
906        // Almost max value for Uint64.
907        let base = Uint64(u64::MAX - 9);
908
909        assert_eq!(base.multiply_ratio(2u64, 2u64), base);
910    }
911
912    #[test]
913    #[should_panic]
914    fn uint64_multiply_ratio_panicks_on_overflow() {
915        // Almost max value for Uint64.
916        let base = Uint64(u64::MAX - 9);
917
918        assert_eq!(base.multiply_ratio(2u64, 1u64), base);
919    }
920
921    #[test]
922    #[should_panic(expected = "Denominator must not be zero")]
923    fn uint64_multiply_ratio_panics_for_zero_denominator() {
924        _ = Uint64(500).multiply_ratio(1u64, 0u64);
925    }
926
927    #[test]
928    fn uint64_checked_multiply_ratio_does_not_panic() {
929        assert_eq!(
930            Uint64(500u64).checked_multiply_ratio(1u64, 0u64),
931            Err(CheckedMultiplyRatioError::DivideByZero),
932        );
933        assert_eq!(
934            Uint64(500u64).checked_multiply_ratio(u64::MAX, 1u64),
935            Err(CheckedMultiplyRatioError::Overflow),
936        );
937    }
938
939    #[test]
940    fn uint64_shr_works() {
941        let original = Uint64::new(u64::from_be_bytes([0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 4u8, 2u8]));
942
943        let shifted = Uint64::new(u64::from_be_bytes([
944            0u8, 0u8, 0u8, 0u8, 0u8, 128u8, 1u8, 0u8,
945        ]));
946
947        assert_eq!(original >> 2u32, shifted);
948    }
949
950    #[test]
951    #[should_panic]
952    fn uint64_shr_overflow_panics() {
953        let _ = Uint64::from(1u32) >> 64u32;
954    }
955
956    #[test]
957    fn uint64_shl_works() {
958        let original = Uint64::new(u64::from_be_bytes([
959            64u8, 128u8, 1u8, 0u8, 0u8, 0u8, 0u8, 0u8,
960        ]));
961
962        let shifted = Uint64::new(u64::from_be_bytes([2u8, 0u8, 4u8, 0u8, 0u8, 0u8, 0u8, 0u8]));
963
964        assert_eq!(original << 2u32, shifted);
965    }
966
967    #[test]
968    #[should_panic]
969    fn uint64_shl_overflow_panics() {
970        let _ = Uint64::from(1u32) << 64u32;
971    }
972
973    #[test]
974    fn sum_works() {
975        let nums = vec![Uint64(17), Uint64(123), Uint64(540), Uint64(82)];
976        let expected = Uint64(762);
977
978        let sum_as_ref: Uint64 = nums.iter().sum();
979        assert_eq!(expected, sum_as_ref);
980
981        let sum_as_owned: Uint64 = nums.into_iter().sum();
982        assert_eq!(expected, sum_as_owned);
983    }
984
985    #[test]
986    fn uint64_methods() {
987        // checked_*
988        assert!(matches!(
989            Uint64::MAX.checked_add(Uint64(1)),
990            Err(OverflowError { .. })
991        ));
992        assert!(matches!(Uint64(1).checked_add(Uint64(1)), Ok(Uint64(2))));
993        assert!(matches!(
994            Uint64(0).checked_sub(Uint64(1)),
995            Err(OverflowError { .. })
996        ));
997        assert!(matches!(Uint64(2).checked_sub(Uint64(1)), Ok(Uint64(1))));
998        assert!(matches!(
999            Uint64::MAX.checked_mul(Uint64(2)),
1000            Err(OverflowError { .. })
1001        ));
1002        assert!(matches!(Uint64(2).checked_mul(Uint64(2)), Ok(Uint64(4))));
1003        assert!(matches!(
1004            Uint64::MAX.checked_pow(2u32),
1005            Err(OverflowError { .. })
1006        ));
1007        assert!(matches!(Uint64(2).checked_pow(3), Ok(Uint64(8))));
1008        assert!(matches!(
1009            Uint64::MAX.checked_div(Uint64(0)),
1010            Err(DivideByZeroError { .. })
1011        ));
1012        assert!(matches!(Uint64(6).checked_div(Uint64(2)), Ok(Uint64(3))));
1013        assert!(matches!(
1014            Uint64::MAX.checked_div_euclid(Uint64(0)),
1015            Err(DivideByZeroError { .. })
1016        ));
1017        assert!(matches!(
1018            Uint64(6).checked_div_euclid(Uint64(2)),
1019            Ok(Uint64(3)),
1020        ));
1021        assert!(matches!(
1022            Uint64::MAX.checked_rem(Uint64(0)),
1023            Err(DivideByZeroError { .. })
1024        ));
1025        assert!(matches!(Uint64(7).checked_rem(Uint64(2)), Ok(Uint64(1))));
1026
1027        // saturating_*
1028        assert_eq!(Uint64::MAX.saturating_add(Uint64(1)), Uint64::MAX);
1029        assert_eq!(Uint64(0).saturating_sub(Uint64(1)), Uint64(0));
1030        assert_eq!(Uint64::MAX.saturating_mul(Uint64(2)), Uint64::MAX);
1031        assert_eq!(Uint64::MAX.saturating_pow(2), Uint64::MAX);
1032    }
1033
1034    #[test]
1035    fn uint64_wrapping_methods() {
1036        // wrapping_add
1037        assert_eq!(Uint64(2).wrapping_add(Uint64(2)), Uint64(4)); // non-wrapping
1038        assert_eq!(Uint64::MAX.wrapping_add(Uint64(1)), Uint64(0)); // wrapping
1039
1040        // wrapping_sub
1041        assert_eq!(Uint64(7).wrapping_sub(Uint64(5)), Uint64(2)); // non-wrapping
1042        assert_eq!(Uint64(0).wrapping_sub(Uint64(1)), Uint64::MAX); // wrapping
1043
1044        // wrapping_mul
1045        assert_eq!(Uint64(3).wrapping_mul(Uint64(2)), Uint64(6)); // non-wrapping
1046        assert_eq!(
1047            Uint64::MAX.wrapping_mul(Uint64(2)),
1048            Uint64::MAX - Uint64::one()
1049        ); // wrapping
1050
1051        // wrapping_pow
1052        assert_eq!(Uint64(2).wrapping_pow(3), Uint64(8)); // non-wrapping
1053        assert_eq!(Uint64::MAX.wrapping_pow(2), Uint64(1)); // wrapping
1054    }
1055
1056    #[test]
1057    #[allow(clippy::op_ref)]
1058    fn uint64_implements_rem() {
1059        let a = Uint64::new(10);
1060        assert_eq!(a % Uint64::new(10), Uint64::zero());
1061        assert_eq!(a % Uint64::new(2), Uint64::zero());
1062        assert_eq!(a % Uint64::new(1), Uint64::zero());
1063        assert_eq!(a % Uint64::new(3), Uint64::new(1));
1064        assert_eq!(a % Uint64::new(4), Uint64::new(2));
1065
1066        // works for refs
1067        let a = Uint64::new(10);
1068        let b = Uint64::new(3);
1069        let expected = Uint64::new(1);
1070        assert_eq!(a % b, expected);
1071        assert_eq!(a % &b, expected);
1072        assert_eq!(&a % b, expected);
1073        assert_eq!(&a % &b, expected);
1074    }
1075
1076    #[test]
1077    #[should_panic(expected = "divisor of zero")]
1078    fn uint64_rem_panics_for_zero() {
1079        let _ = Uint64::new(10) % Uint64::zero();
1080    }
1081
1082    #[test]
1083    #[allow(clippy::op_ref)]
1084    fn uint64_rem_works() {
1085        assert_eq!(
1086            Uint64::from(12u32) % Uint64::from(10u32),
1087            Uint64::from(2u32)
1088        );
1089        assert_eq!(Uint64::from(50u32) % Uint64::from(5u32), Uint64::zero());
1090
1091        // works for refs
1092        let a = Uint64::from(42u32);
1093        let b = Uint64::from(5u32);
1094        let expected = Uint64::from(2u32);
1095        assert_eq!(a % b, expected);
1096        assert_eq!(a % &b, expected);
1097        assert_eq!(&a % b, expected);
1098        assert_eq!(&a % &b, expected);
1099    }
1100
1101    #[test]
1102    fn uint64_rem_assign_works() {
1103        let mut a = Uint64::from(30u32);
1104        a %= Uint64::from(4u32);
1105        assert_eq!(a, Uint64::from(2u32));
1106
1107        // works for refs
1108        let mut a = Uint64::from(25u32);
1109        let b = Uint64::from(6u32);
1110        a %= &b;
1111        assert_eq!(a, Uint64::from(1u32));
1112    }
1113
1114    #[test]
1115    fn uint64_strict_add_works() {
1116        let a = Uint64::new(5);
1117        let b = Uint64::new(3);
1118        assert_eq!(a.strict_add(b), Uint64::new(8));
1119        assert_eq!(b.strict_add(a), Uint64::new(8));
1120    }
1121
1122    #[test]
1123    #[should_panic(expected = "attempt to add with overflow")]
1124    fn uint64_strict_add_panics_on_overflow() {
1125        let a = Uint64::MAX;
1126        let b = Uint64::ONE;
1127        let _ = a.strict_add(b);
1128    }
1129
1130    #[test]
1131    fn uint64_strict_sub_works() {
1132        let a = Uint64::new(5);
1133        let b = Uint64::new(3);
1134        assert_eq!(a.strict_sub(b), Uint64::new(2));
1135    }
1136
1137    #[test]
1138    #[should_panic(expected = "attempt to subtract with overflow")]
1139    fn uint64_strict_sub_panics_on_overflow() {
1140        let a = Uint64::ZERO;
1141        let b = Uint64::ONE;
1142        let _ = a.strict_sub(b);
1143    }
1144
1145    #[test]
1146    fn uint64_abs_diff_works() {
1147        let a = Uint64::from(42u32);
1148        let b = Uint64::from(5u32);
1149        let expected = Uint64::from(37u32);
1150        assert_eq!(a.abs_diff(b), expected);
1151        assert_eq!(b.abs_diff(a), expected);
1152    }
1153
1154    #[test]
1155    fn uint64_partial_eq() {
1156        let test_cases = [(1, 1, true), (42, 42, true), (42, 24, false), (0, 0, true)]
1157            .into_iter()
1158            .map(|(lhs, rhs, expected)| (Uint64::new(lhs), Uint64::new(rhs), expected));
1159
1160        #[allow(clippy::op_ref)]
1161        for (lhs, rhs, expected) in test_cases {
1162            assert_eq!(lhs == rhs, expected);
1163            assert_eq!(&lhs == rhs, expected);
1164            assert_eq!(lhs == &rhs, expected);
1165            assert_eq!(&lhs == &rhs, expected);
1166        }
1167    }
1168
1169    #[test]
1170    fn mul_floor_works_with_zero() {
1171        let fraction = (0u32, 21u32);
1172        let res = Uint64::new(123456).mul_floor(fraction);
1173        assert_eq!(Uint64::zero(), res)
1174    }
1175
1176    #[test]
1177    fn mul_floor_does_nothing_with_one() {
1178        let fraction = (Uint64::one(), Uint64::one());
1179        let res = Uint64::new(123456).mul_floor(fraction);
1180        assert_eq!(Uint64::new(123456), res)
1181    }
1182
1183    #[test]
1184    fn mul_floor_rounds_down_with_normal_case() {
1185        let fraction = (8u64, 21u64);
1186        let res = Uint64::new(123456).mul_floor(fraction); // 47030.8571
1187        assert_eq!(Uint64::new(47030), res)
1188    }
1189
1190    #[test]
1191    fn mul_floor_does_not_round_on_even_divide() {
1192        let fraction = (2u64, 5u64);
1193        let res = Uint64::new(25).mul_floor(fraction);
1194        assert_eq!(Uint64::new(10), res)
1195    }
1196
1197    #[test]
1198    fn mul_floor_works_when_operation_temporarily_takes_above_max() {
1199        let fraction = (8u64, 21u64);
1200        let res = Uint64::MAX.mul_floor(fraction); // 7_027_331_075_698_876_805.71428571
1201        assert_eq!(Uint64::new(7_027_331_075_698_876_805), res)
1202    }
1203
1204    #[test]
1205    #[should_panic(expected = "ConversionOverflowError")]
1206    fn mul_floor_panics_on_overflow() {
1207        let fraction = (21u64, 8u64);
1208        _ = Uint64::MAX.mul_floor(fraction);
1209    }
1210
1211    #[test]
1212    fn checked_mul_floor_does_not_panic_on_overflow() {
1213        let fraction = (21u64, 8u64);
1214        assert_eq!(
1215            Uint64::MAX.checked_mul_floor(fraction),
1216            Err(ConversionOverflow(ConversionOverflowError {
1217                source_type: "Uint128",
1218                target_type: "Uint64",
1219            })),
1220        );
1221    }
1222
1223    #[test]
1224    #[should_panic(expected = "DivideByZeroError")]
1225    fn mul_floor_panics_on_zero_div() {
1226        let fraction = (21u64, 0u64);
1227        _ = Uint64::new(123456).mul_floor(fraction);
1228    }
1229
1230    #[test]
1231    fn checked_mul_floor_does_not_panic_on_zero_div() {
1232        let fraction = (21u64, 0u64);
1233        assert_eq!(
1234            Uint64::new(123456).checked_mul_floor(fraction),
1235            Err(DivideByZero(DivideByZeroError)),
1236        );
1237    }
1238
1239    #[test]
1240    fn mul_ceil_works_with_zero() {
1241        let fraction = (Uint64::zero(), Uint64::new(21));
1242        let res = Uint64::new(123456).mul_ceil(fraction);
1243        assert_eq!(Uint64::zero(), res)
1244    }
1245
1246    #[test]
1247    fn mul_ceil_does_nothing_with_one() {
1248        let fraction = (Uint64::one(), Uint64::one());
1249        let res = Uint64::new(123456).mul_ceil(fraction);
1250        assert_eq!(Uint64::new(123456), res)
1251    }
1252
1253    #[test]
1254    fn mul_ceil_rounds_up_with_normal_case() {
1255        let fraction = (8u64, 21u64);
1256        let res = Uint64::new(123456).mul_ceil(fraction); // 47030.8571
1257        assert_eq!(Uint64::new(47031), res)
1258    }
1259
1260    #[test]
1261    fn mul_ceil_does_not_round_on_even_divide() {
1262        let fraction = (2u64, 5u64);
1263        let res = Uint64::new(25).mul_ceil(fraction);
1264        assert_eq!(Uint64::new(10), res)
1265    }
1266
1267    #[test]
1268    fn mul_ceil_works_when_operation_temporarily_takes_above_max() {
1269        let fraction = (8u64, 21u64);
1270        let res = Uint64::MAX.mul_ceil(fraction); // 7_027_331_075_698_876_805.71428571
1271        assert_eq!(Uint64::new(7_027_331_075_698_876_806), res)
1272    }
1273
1274    #[test]
1275    #[should_panic(expected = "ConversionOverflowError")]
1276    fn mul_ceil_panics_on_overflow() {
1277        let fraction = (21u64, 8u64);
1278        _ = Uint64::MAX.mul_ceil(fraction);
1279    }
1280
1281    #[test]
1282    fn checked_mul_ceil_does_not_panic_on_overflow() {
1283        let fraction = (21u64, 8u64);
1284        assert_eq!(
1285            Uint64::MAX.checked_mul_ceil(fraction),
1286            Err(ConversionOverflow(ConversionOverflowError {
1287                source_type: "Uint128",
1288                target_type: "Uint64",
1289            })),
1290        );
1291    }
1292
1293    #[test]
1294    #[should_panic(expected = "DivideByZeroError")]
1295    fn mul_ceil_panics_on_zero_div() {
1296        let fraction = (21u64, 0u64);
1297        _ = Uint64::new(123456).mul_ceil(fraction);
1298    }
1299
1300    #[test]
1301    fn checked_mul_ceil_does_not_panic_on_zero_div() {
1302        let fraction = (21u64, 0u64);
1303        assert_eq!(
1304            Uint64::new(123456).checked_mul_ceil(fraction),
1305            Err(DivideByZero(DivideByZeroError)),
1306        );
1307    }
1308
1309    #[test]
1310    #[should_panic(expected = "DivideByZeroError")]
1311    fn div_floor_raises_with_zero() {
1312        let fraction = (Uint64::zero(), Uint64::new(21));
1313        _ = Uint64::new(123456).div_floor(fraction);
1314    }
1315
1316    #[test]
1317    fn div_floor_does_nothing_with_one() {
1318        let fraction = (Uint64::one(), Uint64::one());
1319        let res = Uint64::new(123456).div_floor(fraction);
1320        assert_eq!(Uint64::new(123456), res)
1321    }
1322
1323    #[test]
1324    fn div_floor_rounds_down_with_normal_case() {
1325        let fraction = (5u64, 21u64);
1326        let res = Uint64::new(123456).div_floor(fraction); // 518515.2
1327        assert_eq!(Uint64::new(518515), res)
1328    }
1329
1330    #[test]
1331    fn div_floor_does_not_round_on_even_divide() {
1332        let fraction = (5u64, 2u64);
1333        let res = Uint64::new(25).div_floor(fraction);
1334        assert_eq!(Uint64::new(10), res)
1335    }
1336
1337    #[test]
1338    fn div_floor_works_when_operation_temporarily_takes_above_max() {
1339        let fraction = (21u64, 8u64);
1340        let res = Uint64::MAX.div_floor(fraction); // 7_027_331_075_698_876_805.71428
1341        assert_eq!(Uint64::new(7_027_331_075_698_876_805), res)
1342    }
1343
1344    #[test]
1345    #[should_panic(expected = "ConversionOverflowError")]
1346    fn div_floor_panics_on_overflow() {
1347        let fraction = (8u64, 21u64);
1348        _ = Uint64::MAX.div_floor(fraction);
1349    }
1350
1351    #[test]
1352    fn div_floor_does_not_panic_on_overflow() {
1353        let fraction = (8u64, 21u64);
1354        assert_eq!(
1355            Uint64::MAX.checked_div_floor(fraction),
1356            Err(ConversionOverflow(ConversionOverflowError {
1357                source_type: "Uint128",
1358                target_type: "Uint64",
1359            })),
1360        );
1361    }
1362
1363    #[test]
1364    #[should_panic(expected = "DivideByZeroError")]
1365    fn div_ceil_raises_with_zero() {
1366        let fraction = (Uint64::zero(), Uint64::new(21));
1367        _ = Uint64::new(123456).div_ceil(fraction);
1368    }
1369
1370    #[test]
1371    fn div_ceil_does_nothing_with_one() {
1372        let fraction = (Uint64::one(), Uint64::one());
1373        let res = Uint64::new(123456).div_ceil(fraction);
1374        assert_eq!(Uint64::new(123456), res)
1375    }
1376
1377    #[test]
1378    fn div_ceil_rounds_up_with_normal_case() {
1379        let fraction = (5u64, 21u64);
1380        let res = Uint64::new(123456).div_ceil(fraction); // 518515.2
1381        assert_eq!(Uint64::new(518516), res)
1382    }
1383
1384    #[test]
1385    fn div_ceil_does_not_round_on_even_divide() {
1386        let fraction = (5u64, 2u64);
1387        let res = Uint64::new(25).div_ceil(fraction);
1388        assert_eq!(Uint64::new(10), res)
1389    }
1390
1391    #[test]
1392    fn div_ceil_works_when_operation_temporarily_takes_above_max() {
1393        let fraction = (21u64, 8u64);
1394        let res = Uint64::MAX.div_ceil(fraction); // 7_027_331_075_698_876_805.71428
1395        assert_eq!(Uint64::new(7_027_331_075_698_876_806), res)
1396    }
1397
1398    #[test]
1399    #[should_panic(expected = "ConversionOverflowError")]
1400    fn div_ceil_panics_on_overflow() {
1401        let fraction = (8u64, 21u64);
1402        _ = Uint64::MAX.div_ceil(fraction);
1403    }
1404
1405    #[test]
1406    fn div_ceil_does_not_panic_on_overflow() {
1407        let fraction = (8u64, 21u64);
1408        assert_eq!(
1409            Uint64::MAX.checked_div_ceil(fraction),
1410            Err(ConversionOverflow(ConversionOverflowError {
1411                source_type: "Uint128",
1412                target_type: "Uint64",
1413            })),
1414        );
1415    }
1416}