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