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#[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 pub const fn new(value: u64) -> Self {
51 Uint64(value)
52 }
53
54 #[inline]
56 pub const fn zero() -> Self {
57 Uint64(0)
58 }
59
60 #[inline]
62 pub const fn one() -> Self {
63 Self(1)
64 }
65
66 pub const fn u64(&self) -> u64 {
68 self.0
69 }
70
71 #[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 #[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 #[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 #[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 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 #[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 #[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 #[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
314impl 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
344forward_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 #[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 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 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 let a = Uint64::from(123u64);
690 assert_eq!(format!("Embedded: {a:05}"), "Embedded: 00123");
691
692 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 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 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 assert_eq!((b.checked_sub(a)).unwrap(), Uint64(11111));
763
764 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 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 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 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 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 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 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 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 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 assert_eq!(base.multiply_ratio(3u64, 2u64), Uint64(750));
899 assert_eq!(base.multiply_ratio(333333u64, 222222u64), Uint64(750));
900
901 assert_eq!(base.multiply_ratio(2u64, 3u64), Uint64(333));
903 assert_eq!(base.multiply_ratio(222222u64, 333333u64), Uint64(333));
904
905 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 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 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 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 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 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!(
1053 Uint64::MAX.wrapping_mul(Uint64(2)),
1054 Uint64::MAX - Uint64::one()
1055 ); assert_eq!(Uint64(2).wrapping_pow(3), Uint64(8)); assert_eq!(Uint64::MAX.wrapping_pow(2), Uint64(1)); }
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 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 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 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); 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); 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); 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); 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); 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); 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); 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); 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}