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