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