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