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