1use alloc::string::{String, ToString};
2use core::fmt;
3use core::ops::{
4 Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Not, Rem, RemAssign, Shl, ShlAssign, Shr,
5 ShrAssign, Sub, SubAssign,
6};
7use core::str::FromStr;
8
9use crate::errors::{
10 DivideByZeroError, DivisionError, ErrorKind, OverflowError, OverflowOperation, StdError,
11};
12use crate::forward_ref::{forward_ref_binop, forward_ref_op_assign};
13use crate::{
14 CheckedMultiplyRatioError, Int128, Int256, Int512, Uint128, Uint256, Uint512, Uint64,
15 __internal::forward_ref_partial_eq,
16};
17
18use super::conversion::{
19 forward_try_from, from_and_to_bytes, primitive_to_wrapped_int, try_from_int_to_int,
20 wrapped_int_to_primitive,
21};
22use super::impl_int_serde;
23use super::num_consts::NumConsts;
24
25#[derive(
39 Copy,
40 Clone,
41 Default,
42 Debug,
43 PartialEq,
44 Eq,
45 PartialOrd,
46 Ord,
47 schemars::JsonSchema,
48 cw_schema::Schemaifier,
49)]
50#[schemaifier(type = cw_schema::NodeType::Integer { precision: 64, signed: true })]
51pub struct Int64(#[schemars(with = "String")] pub(crate) i64);
52
53impl_int_serde!(Int64);
54forward_ref_partial_eq!(Int64, Int64);
55
56impl Int64 {
57 pub const MAX: Int64 = Int64(i64::MAX);
58 pub const MIN: Int64 = Int64(i64::MIN);
59
60 #[inline]
64 #[must_use]
65 pub const fn new(value: i64) -> Self {
66 Self(value)
67 }
68
69 #[inline]
71 pub const fn zero() -> Self {
72 Int64(0)
73 }
74
75 #[inline]
77 pub const fn one() -> Self {
78 Self(1)
79 }
80
81 pub const fn i64(&self) -> i64 {
83 self.0
84 }
85
86 from_and_to_bytes!(i64, 8);
87
88 #[must_use]
89 pub const fn is_zero(&self) -> bool {
90 self.0 == 0
91 }
92
93 #[must_use]
94 pub const fn is_negative(&self) -> bool {
95 self.0.is_negative()
96 }
97
98 #[must_use = "this returns the result of the operation, without modifying the original"]
99 pub const fn pow(self, exp: u32) -> Self {
100 match self.0.checked_pow(exp) {
101 Some(val) => Self(val),
102 None => panic!("attempt to exponentiate with overflow"),
103 }
104 }
105
106 pub fn checked_multiply_ratio<A: Into<Self>, B: Into<Self>>(
111 &self,
112 numerator: A,
113 denominator: B,
114 ) -> Result<Self, CheckedMultiplyRatioError> {
115 let numerator = numerator.into();
116 let denominator = denominator.into();
117 if denominator.is_zero() {
118 return Err(CheckedMultiplyRatioError::DivideByZero);
119 }
120 match (self.full_mul(numerator) / Int128::from(denominator)).try_into() {
121 Ok(ratio) => Ok(ratio),
122 Err(_) => Err(CheckedMultiplyRatioError::Overflow),
123 }
124 }
125
126 #[must_use = "this returns the result of the operation, without modifying the original"]
139 pub fn full_mul(self, rhs: impl Into<Self>) -> Int128 {
140 Int128::from(self)
141 .checked_mul(Int128::from(rhs.into()))
142 .unwrap()
143 }
144
145 pub fn checked_add(self, other: Self) -> Result<Self, OverflowError> {
146 self.0
147 .checked_add(other.0)
148 .map(Self)
149 .ok_or_else(|| OverflowError::new(OverflowOperation::Add))
150 }
151
152 pub fn checked_sub(self, other: Self) -> Result<Self, OverflowError> {
153 self.0
154 .checked_sub(other.0)
155 .map(Self)
156 .ok_or_else(|| OverflowError::new(OverflowOperation::Sub))
157 }
158
159 pub fn checked_mul(self, other: Self) -> Result<Self, OverflowError> {
160 self.0
161 .checked_mul(other.0)
162 .map(Self)
163 .ok_or_else(|| OverflowError::new(OverflowOperation::Mul))
164 }
165
166 pub fn checked_pow(self, exp: u32) -> Result<Self, OverflowError> {
167 self.0
168 .checked_pow(exp)
169 .map(Self)
170 .ok_or_else(|| OverflowError::new(OverflowOperation::Pow))
171 }
172
173 pub fn checked_div(self, other: Self) -> Result<Self, DivisionError> {
174 if other.is_zero() {
175 return Err(DivisionError::DivideByZero);
176 }
177 self.0
178 .checked_div(other.0)
179 .map(Self)
180 .ok_or(DivisionError::Overflow)
181 }
182
183 pub fn checked_div_euclid(self, other: Self) -> Result<Self, DivisionError> {
184 if other.is_zero() {
185 return Err(DivisionError::DivideByZero);
186 }
187 self.0
188 .checked_div_euclid(other.0)
189 .map(Self)
190 .ok_or(DivisionError::Overflow)
191 }
192
193 pub fn checked_rem(self, other: Self) -> Result<Self, DivideByZeroError> {
194 self.0
195 .checked_rem(other.0)
196 .map(Self)
197 .ok_or(DivideByZeroError)
198 }
199
200 pub fn checked_shr(self, other: u32) -> Result<Self, OverflowError> {
201 if other >= 64 {
202 return Err(OverflowError::new(OverflowOperation::Shr));
203 }
204
205 Ok(Self(self.0.shr(other)))
206 }
207
208 pub fn checked_shl(self, other: u32) -> Result<Self, OverflowError> {
209 if other >= 64 {
210 return Err(OverflowError::new(OverflowOperation::Shl));
211 }
212
213 Ok(Self(self.0.shl(other)))
214 }
215
216 #[must_use = "this returns the result of the operation, without modifying the original"]
217 #[inline]
218 pub fn wrapping_add(self, other: Self) -> Self {
219 Self(self.0.wrapping_add(other.0))
220 }
221
222 #[must_use = "this returns the result of the operation, without modifying the original"]
223 #[inline]
224 pub fn wrapping_sub(self, other: Self) -> Self {
225 Self(self.0.wrapping_sub(other.0))
226 }
227
228 #[must_use = "this returns the result of the operation, without modifying the original"]
229 #[inline]
230 pub fn wrapping_mul(self, other: Self) -> Self {
231 Self(self.0.wrapping_mul(other.0))
232 }
233
234 #[must_use = "this returns the result of the operation, without modifying the original"]
235 #[inline]
236 pub fn wrapping_pow(self, other: u32) -> Self {
237 Self(self.0.wrapping_pow(other))
238 }
239
240 #[must_use = "this returns the result of the operation, without modifying the original"]
241 pub fn saturating_add(self, other: Self) -> Self {
242 Self(self.0.saturating_add(other.0))
243 }
244
245 #[must_use = "this returns the result of the operation, without modifying the original"]
246 pub fn saturating_sub(self, other: Self) -> Self {
247 Self(self.0.saturating_sub(other.0))
248 }
249
250 #[must_use = "this returns the result of the operation, without modifying the original"]
251 pub fn saturating_mul(self, other: Self) -> Self {
252 Self(self.0.saturating_mul(other.0))
253 }
254
255 #[must_use = "this returns the result of the operation, without modifying the original"]
256 pub fn saturating_pow(self, exp: u32) -> Self {
257 Self(self.0.saturating_pow(exp))
258 }
259
260 #[must_use = "this returns the result of the operation, without modifying the original"]
261 pub const fn abs_diff(self, other: Self) -> Uint64 {
262 Uint64(self.0.abs_diff(other.0))
263 }
264
265 #[must_use = "this returns the result of the operation, without modifying the original"]
266 pub const fn abs(self) -> Self {
267 match self.0.checked_abs() {
268 Some(val) => Self(val),
269 None => panic!("attempt to calculate absolute value with overflow"),
270 }
271 }
272
273 #[must_use = "this returns the result of the operation, without modifying the original"]
274 pub const fn unsigned_abs(self) -> Uint64 {
275 Uint64(self.0.unsigned_abs())
276 }
277
278 pub const fn strict_neg(self) -> Self {
282 match self.0.checked_neg() {
283 Some(val) => Self(val),
284 None => panic!("attempt to negate with overflow"),
285 }
286 }
287}
288
289impl NumConsts for Int64 {
290 const ZERO: Self = Self::zero();
291 const ONE: Self = Self::one();
292 const MAX: Self = Self::MAX;
293 const MIN: Self = Self::MIN;
294}
295
296primitive_to_wrapped_int!(u8, Int64);
298primitive_to_wrapped_int!(u16, Int64);
299primitive_to_wrapped_int!(u32, Int64);
300
301primitive_to_wrapped_int!(i8, Int64);
303primitive_to_wrapped_int!(i16, Int64);
304primitive_to_wrapped_int!(i32, Int64);
305primitive_to_wrapped_int!(i64, Int64);
306
307wrapped_int_to_primitive!(Int64, i64);
309wrapped_int_to_primitive!(Int64, i128);
310
311try_from_int_to_int!(Int128, Int64);
313try_from_int_to_int!(Int256, Int64);
314try_from_int_to_int!(Int512, Int64);
315
316forward_try_from!(Uint64, Int64);
318forward_try_from!(Uint128, Int64);
319forward_try_from!(Uint256, Int64);
320forward_try_from!(Uint512, Int64);
321
322impl TryFrom<&str> for Int64 {
323 type Error = StdError;
324
325 fn try_from(val: &str) -> Result<Self, Self::Error> {
326 Self::from_str(val)
327 }
328}
329
330impl FromStr for Int64 {
331 type Err = StdError;
332
333 fn from_str(s: &str) -> Result<Self, Self::Err> {
334 match s.parse::<i64>() {
335 Ok(u) => Ok(Self(u)),
336 Err(e) => {
337 Err(StdError::msg(format_args!("Parsing Int64: {e}")).with_kind(ErrorKind::Parsing))
338 }
339 }
340 }
341}
342
343impl From<Int64> for String {
344 fn from(original: Int64) -> Self {
345 original.to_string()
346 }
347}
348
349impl fmt::Display for Int64 {
350 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
351 self.0.fmt(f)
352 }
353}
354
355impl Add<Int64> for Int64 {
356 type Output = Self;
357
358 fn add(self, rhs: Self) -> Self {
359 Int64(self.0.checked_add(rhs.0).unwrap())
360 }
361}
362forward_ref_binop!(impl Add, add for Int64, Int64);
363
364impl Sub<Int64> for Int64 {
365 type Output = Self;
366
367 fn sub(self, rhs: Self) -> Self {
368 Int64(self.0.checked_sub(rhs.0).unwrap())
369 }
370}
371forward_ref_binop!(impl Sub, sub for Int64, Int64);
372
373impl SubAssign<Int64> for Int64 {
374 fn sub_assign(&mut self, rhs: Int64) {
375 self.0 = self.0.checked_sub(rhs.0).unwrap();
376 }
377}
378forward_ref_op_assign!(impl SubAssign, sub_assign for Int64, Int64);
379
380impl Div<Int64> for Int64 {
381 type Output = Self;
382
383 fn div(self, rhs: Self) -> Self::Output {
384 Self(self.0.checked_div(rhs.0).unwrap())
385 }
386}
387forward_ref_binop!(impl Div, div for Int64, Int64);
388
389impl Rem for Int64 {
390 type Output = Self;
391
392 #[inline]
396 fn rem(self, rhs: Self) -> Self {
397 Self(self.0.rem(rhs.0))
398 }
399}
400forward_ref_binop!(impl Rem, rem for Int64, Int64);
401
402impl Not for Int64 {
403 type Output = Self;
404
405 fn not(self) -> Self::Output {
406 Self(!self.0)
407 }
408}
409
410impl Neg for Int64 {
411 type Output = Self;
412
413 fn neg(self) -> Self::Output {
414 self.strict_neg()
415 }
416}
417
418impl RemAssign<Int64> for Int64 {
419 fn rem_assign(&mut self, rhs: Int64) {
420 *self = *self % rhs;
421 }
422}
423forward_ref_op_assign!(impl RemAssign, rem_assign for Int64, Int64);
424
425impl Mul<Int64> for Int64 {
426 type Output = Self;
427
428 fn mul(self, rhs: Self) -> Self::Output {
429 Self(self.0.checked_mul(rhs.0).unwrap())
430 }
431}
432forward_ref_binop!(impl Mul, mul for Int64, Int64);
433
434impl MulAssign<Int64> for Int64 {
435 fn mul_assign(&mut self, rhs: Self) {
436 self.0 = self.0.checked_mul(rhs.0).unwrap();
437 }
438}
439forward_ref_op_assign!(impl MulAssign, mul_assign for Int64, Int64);
440
441impl Shr<u32> for Int64 {
442 type Output = Self;
443
444 fn shr(self, rhs: u32) -> Self::Output {
445 self.checked_shr(rhs).unwrap_or_else(|_| {
446 panic!("right shift error: {rhs} is larger or equal than the number of bits in Int64",)
447 })
448 }
449}
450forward_ref_binop!(impl Shr, shr for Int64, u32);
451
452impl Shl<u32> for Int64 {
453 type Output = Self;
454
455 fn shl(self, rhs: u32) -> Self::Output {
456 self.checked_shl(rhs).unwrap_or_else(|_| {
457 panic!("left shift error: {rhs} is larger or equal than the number of bits in Int64",)
458 })
459 }
460}
461forward_ref_binop!(impl Shl, shl for Int64, u32);
462
463impl AddAssign<Int64> for Int64 {
464 fn add_assign(&mut self, rhs: Int64) {
465 self.0 = self.0.checked_add(rhs.0).unwrap();
466 }
467}
468forward_ref_op_assign!(impl AddAssign, add_assign for Int64, Int64);
469
470impl DivAssign<Int64> for Int64 {
471 fn div_assign(&mut self, rhs: Self) {
472 self.0 = self.0.checked_div(rhs.0).unwrap();
473 }
474}
475forward_ref_op_assign!(impl DivAssign, div_assign for Int64, Int64);
476
477impl ShrAssign<u32> for Int64 {
478 fn shr_assign(&mut self, rhs: u32) {
479 *self = Shr::<u32>::shr(*self, rhs);
480 }
481}
482forward_ref_op_assign!(impl ShrAssign, shr_assign for Int64, u32);
483
484impl ShlAssign<u32> for Int64 {
485 fn shl_assign(&mut self, rhs: u32) {
486 *self = Shl::<u32>::shl(*self, rhs);
487 }
488}
489forward_ref_op_assign!(impl ShlAssign, shl_assign for Int64, u32);
490
491impl<A> core::iter::Sum<A> for Int64
492where
493 Self: Add<A, Output = Self>,
494{
495 fn sum<I: Iterator<Item = A>>(iter: I) -> Self {
496 iter.fold(Self::zero(), Add::add)
497 }
498}
499
500#[cfg(test)]
501mod tests {
502 use super::*;
503 use crate::math::conversion::test_try_from_uint_to_int;
504
505 #[test]
506 fn size_of_works() {
507 assert_eq!(core::mem::size_of::<Int64>(), 8);
508 }
509
510 #[test]
511 fn int64_from_be_bytes_works() {
512 let original = [0; 8];
514 let num = Int64::from_be_bytes(original);
515 assert!(num.is_zero());
516
517 let original = [0, 0, 0, 0, 0, 0, 0, 1];
519 let num = Int64::from_be_bytes(original);
520 assert_eq!(num.i64(), 1);
521
522 let original = [0, 0, 0, 0, 0, 0, 1, 2];
524 let num = Int64::from_be_bytes(original);
525 assert_eq!(num.i64(), 258);
526
527 let original = [1; 8];
529 let num = Int64::from_be_bytes(original);
530 let a: [u8; 8] = num.to_be_bytes();
531 assert_eq!(a, original);
532
533 let original = [0u8, 222u8, 0u8, 0u8, 0u8, 1u8, 2u8, 3u8];
534 let num = Int64::from_be_bytes(original);
535 let a: [u8; 8] = num.to_be_bytes();
536 assert_eq!(a, original);
537 }
538
539 #[test]
540 fn int64_from_le_bytes_works() {
541 let original = [0; 8];
543 let num = Int64::from_le_bytes(original);
544 assert!(num.is_zero());
545
546 let original = [1, 0, 0, 0, 0, 0, 0, 0];
548 let num = Int64::from_le_bytes(original);
549 assert_eq!(num.i64(), 1);
550
551 let original = [2, 1, 0, 0, 0, 0, 0, 0];
553 let num = Int64::from_le_bytes(original);
554 assert_eq!(num.i64(), 258);
555
556 let original = [1; 8];
558 let num = Int64::from_le_bytes(original);
559 let a: [u8; 8] = num.to_le_bytes();
560 assert_eq!(a, original);
561
562 let original = [0u8, 222u8, 0u8, 0u8, 0u8, 1u8, 2u8, 3u8];
563 let num = Int64::from_le_bytes(original);
564 let a: [u8; 8] = num.to_le_bytes();
565 assert_eq!(a, original);
566 }
567
568 #[test]
569 fn int64_new_works() {
570 let num = Int64::new(222);
571 assert_eq!(num.i64(), 222);
572
573 let num = Int64::new(-222);
574 assert_eq!(num.i64(), -222);
575
576 let num = Int64::new(i64::MAX);
577 assert_eq!(num.i64(), i64::MAX);
578
579 let num = Int64::new(i64::MIN);
580 assert_eq!(num.i64(), i64::MIN);
581 }
582
583 #[test]
584 fn int64_not_works() {
585 assert_eq!(!Int64::new(222), Int64::new(!222));
586 assert_eq!(!Int64::new(-222), Int64::new(!-222));
587
588 assert_eq!(!Int64::MAX, Int64::new(!i64::MAX));
589 assert_eq!(!Int64::MIN, Int64::new(!i64::MIN));
590 }
591
592 #[test]
593 fn int64_zero_works() {
594 let zero = Int64::zero();
595 assert_eq!(zero.to_be_bytes(), [0; 8]);
596 }
597
598 #[test]
599 fn uint64_one_works() {
600 let one = Int64::one();
601 let mut one_be = [0; 8];
602 one_be[7] = 1;
603
604 assert_eq!(one.to_be_bytes(), one_be);
605 }
606
607 #[test]
608 fn int64_endianness() {
609 let be_bytes = [0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 2u8, 3u8];
610 let le_bytes = [3u8, 2u8, 1u8, 0u8, 0u8, 0u8, 0u8, 0u8];
611
612 let num1 = Int64::from_be_bytes(be_bytes);
614 let num2 = Int64::from_le_bytes(le_bytes);
615 assert_eq!(num1, Int64::from(65536u32 + 512 + 3));
616 assert_eq!(num1, num2);
617 }
618
619 #[test]
620 fn int64_convert_to() {
621 let a = Int64::new(5);
622 assert_eq!(i64::from(a), 5);
623
624 let a = Int64::new(5);
625 assert_eq!(i128::from(a), 5);
626 }
627
628 #[test]
629 fn int64_convert_from() {
630 let a = Int64::from(5i64);
631 assert_eq!(a.0, i64::from(5u32));
632
633 let a = Int64::from(5i64);
634 assert_eq!(a.0, i64::from(5u32));
635
636 let a = Int64::from(5u32);
637 assert_eq!(a.0, i64::from(5u32));
638
639 let a = Int64::from(5u16);
640 assert_eq!(a.0, i64::from(5u32));
641
642 let a = Int64::from(5u8);
643 assert_eq!(a.0, i64::from(5u32));
644
645 let a = Int64::from(-5i64);
646 assert_eq!(a.0, i64::from(-5i32));
647
648 let a = Int64::from(-5i64);
649 assert_eq!(a.0, i64::from(-5i32));
650
651 let a = Int64::from(-5i32);
652 assert_eq!(a.0, i64::from(-5i32));
653
654 let a = Int64::from(-5i16);
655 assert_eq!(a.0, i64::from(-5i32));
656
657 let a = Int64::from(-5i8);
658 assert_eq!(a.0, i64::from(-5i32));
659
660 let result = Int64::try_from("34567");
661 assert_eq!(result.unwrap().0, "34567".parse::<i64>().unwrap());
662
663 let result = Int64::try_from("1.23");
664 assert!(result.is_err());
665 }
666
667 #[test]
668 fn int64_try_from_unsigned_works() {
669 test_try_from_uint_to_int::<Uint64, Int64>("Uint64", "Int64");
670 test_try_from_uint_to_int::<Uint128, Int64>("Uint128", "Int64");
671 test_try_from_uint_to_int::<Uint256, Int64>("Uint256", "Int64");
672 test_try_from_uint_to_int::<Uint512, Int64>("Uint512", "Int64");
673 }
674
675 #[test]
676 fn int64_implements_display() {
677 let a = Int64::from(12345u32);
678 assert_eq!(format!("Embedded: {a}"), "Embedded: 12345");
679 assert_eq!(a.to_string(), "12345");
680
681 let a = Int64::from(-12345i32);
682 assert_eq!(format!("Embedded: {a}"), "Embedded: -12345");
683 assert_eq!(a.to_string(), "-12345");
684
685 let a = Int64::zero();
686 assert_eq!(format!("Embedded: {a}"), "Embedded: 0");
687 assert_eq!(a.to_string(), "0");
688 }
689
690 #[test]
691 fn int64_display_padding_works() {
692 let a = Int64::from(123i64);
694 assert_eq!(format!("Embedded: {a:05}"), "Embedded: 00123");
695 let a = Int64::from(-123i64);
696 assert_eq!(format!("Embedded: {a:05}"), "Embedded: -0123");
697
698 let a = Int64::from(123i64);
700 assert_eq!(format!("Embedded: {a:02}"), "Embedded: 123");
701 let a = Int64::from(-123i64);
702 assert_eq!(format!("Embedded: {a:02}"), "Embedded: -123");
703 }
704
705 #[test]
706 fn int64_to_be_bytes_works() {
707 assert_eq!(Int64::zero().to_be_bytes(), [0; 8]);
708
709 let mut max = [0xff; 8];
710 max[0] = 0x7f;
711 assert_eq!(Int64::MAX.to_be_bytes(), max);
712
713 let mut one = [0; 8];
714 one[7] = 1;
715 assert_eq!(Int64::from(1i64).to_be_bytes(), one);
716 assert_eq!(
718 Int64::from(8535972485454015680i64).to_be_bytes(),
719 [118, 117, 221, 191, 255, 254, 172, 192]
720 );
721 assert_eq!(
722 Int64::from_be_bytes([17, 4, 23, 32, 87, 67, 123, 200]).to_be_bytes(),
723 [17, 4, 23, 32, 87, 67, 123, 200]
724 );
725 }
726
727 #[test]
728 fn int64_to_le_bytes_works() {
729 assert_eq!(Int64::zero().to_le_bytes(), [0; 8]);
730
731 let mut max = [0xff; 8];
732 max[7] = 0x7f;
733 assert_eq!(Int64::MAX.to_le_bytes(), max);
734
735 let mut one = [0; 8];
736 one[0] = 1;
737 assert_eq!(Int64::from(1i64).to_le_bytes(), one);
738 assert_eq!(
740 Int64::from(8535972485454015680i64).to_le_bytes(),
741 [192, 172, 254, 255, 191, 221, 117, 118]
742 );
743 assert_eq!(
744 Int64::from_be_bytes([17, 4, 23, 32, 87, 67, 123, 200]).to_le_bytes(),
745 [200, 123, 67, 87, 32, 23, 4, 17]
746 );
747 }
748
749 #[test]
750 fn int64_is_zero_works() {
751 assert!(Int64::zero().is_zero());
752 assert!(Int64(i64::from(0u32)).is_zero());
753
754 assert!(!Int64::from(1u32).is_zero());
755 assert!(!Int64::from(123u32).is_zero());
756 assert!(!Int64::from(-123i32).is_zero());
757 }
758
759 #[test]
760 fn int64_is_negative_works() {
761 assert!(Int64::MIN.is_negative());
762 assert!(Int64::from(-123i32).is_negative());
763
764 assert!(!Int64::MAX.is_negative());
765 assert!(!Int64::zero().is_negative());
766 assert!(!Int64::from(123u32).is_negative());
767 }
768
769 #[test]
770 fn int64_wrapping_methods() {
771 assert_eq!(
773 Int64::from(2u32).wrapping_add(Int64::from(2u32)),
774 Int64::from(4u32)
775 ); assert_eq!(Int64::MAX.wrapping_add(Int64::from(1u32)), Int64::MIN); assert_eq!(
780 Int64::from(7u32).wrapping_sub(Int64::from(5u32)),
781 Int64::from(2u32)
782 ); assert_eq!(Int64::MIN.wrapping_sub(Int64::from(1u32)), Int64::MAX); assert_eq!(
787 Int64::from(3u32).wrapping_mul(Int64::from(2u32)),
788 Int64::from(6u32)
789 ); assert_eq!(
791 Int64::MAX.wrapping_mul(Int64::from(2u32)),
792 Int64::from(-2i32)
793 ); assert_eq!(Int64::from(2u32).wrapping_pow(3), Int64::from(8u32)); assert_eq!(Int64::MAX.wrapping_pow(2), Int64::from(1u32)); }
799
800 #[test]
801 fn int64_json() {
802 let orig = Int64::from(1234567890987654321i64);
803 let serialized = serde_json::to_vec(&orig).unwrap();
804 assert_eq!(serialized.as_slice(), b"\"1234567890987654321\"");
805 let parsed: Int64 = serde_json::from_slice(&serialized).unwrap();
806 assert_eq!(parsed, orig);
807 }
808
809 #[test]
810 fn int64_compare() {
811 let a = Int64::from(12345u32);
812 let b = Int64::from(23456u32);
813
814 assert!(a < b);
815 assert!(b > a);
816 assert_eq!(a, Int64::from(12345u32));
817 }
818
819 #[test]
820 #[allow(clippy::op_ref)]
821 fn int64_math() {
822 let a = Int64::from(-12345i32);
823 let b = Int64::from(23456u32);
824
825 assert_eq!(a + b, Int64::from(11111u32));
827 assert_eq!(a + &b, Int64::from(11111u32));
828
829 assert_eq!(b - a, Int64::from(35801u32));
831 assert_eq!(b - &a, Int64::from(35801u32));
832
833 let mut c = Int64::from(300000u32);
835 c += b;
836 assert_eq!(c, Int64::from(323456u32));
837 let mut d = Int64::from(300000u32);
838 d += &b;
839 assert_eq!(d, Int64::from(323456u32));
840
841 let mut c = Int64::from(300000u32);
843 c -= b;
844 assert_eq!(c, Int64::from(276544u32));
845 let mut d = Int64::from(300000u32);
846 d -= &b;
847 assert_eq!(d, Int64::from(276544u32));
848
849 assert_eq!(a - b, Int64::from(-35801i32));
851 }
852
853 #[test]
854 #[should_panic]
855 fn int64_add_overflow_panics() {
856 let _ = Int64::MAX + Int64::from(12u32);
857 }
858
859 #[test]
860 #[allow(clippy::op_ref)]
861 fn int64_sub_works() {
862 assert_eq!(Int64::from(2u32) - Int64::from(1u32), Int64::from(1u32));
863 assert_eq!(Int64::from(2u32) - Int64::from(0u32), Int64::from(2u32));
864 assert_eq!(Int64::from(2u32) - Int64::from(2u32), Int64::from(0u32));
865 assert_eq!(Int64::from(2u32) - Int64::from(3u32), Int64::from(-1i32));
866
867 let a = Int64::from(10u32);
869 let b = Int64::from(3u32);
870 let expected = Int64::from(7u32);
871 assert_eq!(a - b, expected);
872 assert_eq!(a - &b, expected);
873 assert_eq!(&a - b, expected);
874 assert_eq!(&a - &b, expected);
875 }
876
877 #[test]
878 #[should_panic]
879 fn int64_sub_overflow_panics() {
880 let _ = Int64::MIN + Int64::one() - Int64::from(2u32);
881 }
882
883 #[test]
884 fn int64_sub_assign_works() {
885 let mut a = Int64::from(14u32);
886 a -= Int64::from(2u32);
887 assert_eq!(a, Int64::from(12u32));
888
889 let mut a = Int64::from(10u32);
891 let b = Int64::from(3u32);
892 let expected = Int64::from(7u32);
893 a -= &b;
894 assert_eq!(a, expected);
895 }
896
897 #[test]
898 #[allow(clippy::op_ref)]
899 fn int64_mul_works() {
900 assert_eq!(Int64::from(2u32) * Int64::from(3u32), Int64::from(6u32));
901 assert_eq!(Int64::from(2u32) * Int64::zero(), Int64::zero());
902
903 let a = Int64::from(11u32);
905 let b = Int64::from(3u32);
906 let expected = Int64::from(33u32);
907 assert_eq!(a * b, expected);
908 assert_eq!(a * &b, expected);
909 assert_eq!(&a * b, expected);
910 assert_eq!(&a * &b, expected);
911 }
912
913 #[test]
914 fn int64_mul_assign_works() {
915 let mut a = Int64::from(14u32);
916 a *= Int64::from(2u32);
917 assert_eq!(a, Int64::from(28u32));
918
919 let mut a = Int64::from(10u32);
921 let b = Int64::from(3u32);
922 a *= &b;
923 assert_eq!(a, Int64::from(30u32));
924 }
925
926 #[test]
927 fn int64_pow_works() {
928 assert_eq!(Int64::from(2u32).pow(2), Int64::from(4u32));
929 assert_eq!(Int64::from(2u32).pow(10), Int64::from(1024u32));
930 }
931
932 #[test]
933 #[should_panic]
934 fn int64_pow_overflow_panics() {
935 _ = Int64::MAX.pow(2u32);
936 }
937
938 #[test]
939 fn int64_checked_multiply_ratio_works() {
940 let base = Int64(500);
941
942 assert_eq!(base.checked_multiply_ratio(1i64, 1i64).unwrap(), base);
944 assert_eq!(base.checked_multiply_ratio(3i64, 3i64).unwrap(), base);
945 assert_eq!(
946 base.checked_multiply_ratio(654321i64, 654321i64).unwrap(),
947 base
948 );
949 assert_eq!(
950 base.checked_multiply_ratio(i64::MAX, i64::MAX).unwrap(),
951 base
952 );
953
954 assert_eq!(base.checked_multiply_ratio(3i64, 2i64).unwrap(), Int64(750));
956 assert_eq!(
957 base.checked_multiply_ratio(333333i64, 222222i64).unwrap(),
958 Int64(750)
959 );
960
961 assert_eq!(base.checked_multiply_ratio(2i64, 3i64).unwrap(), Int64(333));
963 assert_eq!(
964 base.checked_multiply_ratio(222222i64, 333333i64).unwrap(),
965 Int64(333)
966 );
967
968 assert_eq!(base.checked_multiply_ratio(5i64, 6i64).unwrap(), Int64(416));
970 assert_eq!(
971 base.checked_multiply_ratio(100i64, 120i64).unwrap(),
972 Int64(416)
973 );
974 }
975
976 #[test]
977 fn int64_checked_multiply_ratio_does_not_panic() {
978 assert_eq!(
979 Int64(500i64).checked_multiply_ratio(1i64, 0i64),
980 Err(CheckedMultiplyRatioError::DivideByZero),
981 );
982 assert_eq!(
983 Int64(500i64).checked_multiply_ratio(i64::MAX, 1i64),
984 Err(CheckedMultiplyRatioError::Overflow),
985 );
986 }
987
988 #[test]
989 fn int64_shr_works() {
990 let original = Int64::from_be_bytes([0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 4u8, 2u8]);
991
992 let shifted = Int64::from_be_bytes([0u8, 0u8, 0u8, 0u8, 0u8, 128u8, 1u8, 0u8]);
993
994 assert_eq!(original >> 2u32, shifted);
995 }
996
997 #[test]
998 #[should_panic]
999 fn int64_shr_overflow_panics() {
1000 let _ = Int64::from(1u32) >> 64u32;
1001 }
1002
1003 #[test]
1004 fn sum_works() {
1005 let nums = vec![
1006 Int64::from(17u32),
1007 Int64::from(123u32),
1008 Int64::from(540u32),
1009 Int64::from(82u32),
1010 ];
1011 let expected = Int64::from(762u32);
1012
1013 let sum_as_ref: Int64 = nums.iter().sum();
1014 assert_eq!(expected, sum_as_ref);
1015
1016 let sum_as_owned: Int64 = nums.into_iter().sum();
1017 assert_eq!(expected, sum_as_owned);
1018 }
1019
1020 #[test]
1021 fn int64_methods() {
1022 assert!(matches!(
1024 Int64::MAX.checked_add(Int64::from(1u32)),
1025 Err(OverflowError { .. })
1026 ));
1027 assert_eq!(
1028 Int64::from(1u32).checked_add(Int64::from(1u32)),
1029 Ok(Int64::from(2u32)),
1030 );
1031 assert!(matches!(
1032 Int64::MIN.checked_sub(Int64::from(1u32)),
1033 Err(OverflowError { .. })
1034 ));
1035 assert_eq!(
1036 Int64::from(2u32).checked_sub(Int64::from(1u32)),
1037 Ok(Int64::from(1u32)),
1038 );
1039 assert!(matches!(
1040 Int64::MAX.checked_mul(Int64::from(2u32)),
1041 Err(OverflowError { .. })
1042 ));
1043 assert_eq!(
1044 Int64::from(2u32).checked_mul(Int64::from(2u32)),
1045 Ok(Int64::from(4u32)),
1046 );
1047 assert!(matches!(
1048 Int64::MAX.checked_pow(2u32),
1049 Err(OverflowError { .. })
1050 ));
1051 assert_eq!(Int64::from(2u32).checked_pow(3u32), Ok(Int64::from(8u32)),);
1052 assert_eq!(
1053 Int64::MAX.checked_div(Int64::from(0u32)),
1054 Err(DivisionError::DivideByZero)
1055 );
1056 assert_eq!(
1057 Int64::from(6u32).checked_div(Int64::from(2u32)),
1058 Ok(Int64::from(3u32)),
1059 );
1060 assert_eq!(
1061 Int64::MAX.checked_div_euclid(Int64::from(0u32)),
1062 Err(DivisionError::DivideByZero)
1063 );
1064 assert_eq!(
1065 Int64::from(6u32).checked_div_euclid(Int64::from(2u32)),
1066 Ok(Int64::from(3u32)),
1067 );
1068 assert_eq!(
1069 Int64::from(7u32).checked_div_euclid(Int64::from(2u32)),
1070 Ok(Int64::from(3u32)),
1071 );
1072 assert!(matches!(
1073 Int64::MAX.checked_rem(Int64::from(0u32)),
1074 Err(DivideByZeroError { .. })
1075 ));
1076 assert_eq!(
1078 Int64::from(-12i32).checked_div(Int64::from(10i32)),
1079 Ok(Int64::from(-1i32)),
1080 );
1081 assert_eq!(Int64::from(-2i32).checked_pow(3u32), Ok(Int64::from(-8i32)),);
1082 assert_eq!(
1083 Int64::from(-6i32).checked_mul(Int64::from(-7i32)),
1084 Ok(Int64::from(42i32)),
1085 );
1086 assert_eq!(
1087 Int64::from(-2i32).checked_add(Int64::from(3i32)),
1088 Ok(Int64::from(1i32)),
1089 );
1090 assert_eq!(
1091 Int64::from(-1i32).checked_div_euclid(Int64::from(-2i32)),
1092 Ok(Int64::from(1u32)),
1093 );
1094
1095 assert_eq!(Int64::MAX.saturating_add(Int64::from(1u32)), Int64::MAX);
1097 assert_eq!(Int64::MIN.saturating_sub(Int64::from(1u32)), Int64::MIN);
1098 assert_eq!(Int64::MAX.saturating_mul(Int64::from(2u32)), Int64::MAX);
1099 assert_eq!(Int64::from(4u32).saturating_pow(2u32), Int64::from(16u32));
1100 assert_eq!(Int64::MAX.saturating_pow(2u32), Int64::MAX);
1101 }
1102
1103 #[test]
1104 #[allow(clippy::op_ref)]
1105 fn int64_implements_rem() {
1106 let a = Int64::from(10u32);
1107 assert_eq!(a % Int64::from(10u32), Int64::zero());
1108 assert_eq!(a % Int64::from(2u32), Int64::zero());
1109 assert_eq!(a % Int64::from(1u32), Int64::zero());
1110 assert_eq!(a % Int64::from(3u32), Int64::from(1u32));
1111 assert_eq!(a % Int64::from(4u32), Int64::from(2u32));
1112
1113 assert_eq!(Int64::from(-12i32) % Int64::from(10i32), Int64::from(-2i32));
1114 assert_eq!(Int64::from(12i32) % Int64::from(-10i32), Int64::from(2i32));
1115 assert_eq!(
1116 Int64::from(-12i32) % Int64::from(-10i32),
1117 Int64::from(-2i32)
1118 );
1119
1120 let a = Int64::from(10u32);
1122 let b = Int64::from(3u32);
1123 let expected = Int64::from(1u32);
1124 assert_eq!(a % b, expected);
1125 assert_eq!(a % &b, expected);
1126 assert_eq!(&a % b, expected);
1127 assert_eq!(&a % &b, expected);
1128 }
1129
1130 #[test]
1131 #[should_panic(expected = "divisor of zero")]
1132 fn int64_rem_panics_for_zero() {
1133 let _ = Int64::from(10u32) % Int64::zero();
1134 }
1135
1136 #[test]
1137 fn int64_rem_assign_works() {
1138 let mut a = Int64::from(30u32);
1139 a %= Int64::from(4u32);
1140 assert_eq!(a, Int64::from(2u32));
1141
1142 let mut a = Int64::from(25u32);
1144 let b = Int64::from(6u32);
1145 a %= &b;
1146 assert_eq!(a, Int64::from(1u32));
1147 }
1148
1149 #[test]
1150 fn int64_shr() {
1151 let x: Int64 = 0x4000_0000_0000_0000i64.into();
1152 assert_eq!(x >> 0, x); assert_eq!(x >> 1, Int64::from(0x2000_0000_0000_0000i64));
1154 assert_eq!(x >> 4, Int64::from(0x0400_0000_0000_0000i64));
1155 assert_eq!(
1157 Int64::MIN >> (core::mem::size_of::<Int64>() as u32 * 8 - 1),
1158 -Int64::one()
1159 );
1160 }
1161
1162 #[test]
1163 fn int64_shl() {
1164 let x: Int64 = 0x0800_0000_0000_0000i64.into();
1165 assert_eq!(x << 0, x); assert_eq!(x << 1, Int64::from(0x1000_0000_0000_0000i64));
1167 assert_eq!(x << 4, Int64::from(0x0800_0000_0000_0000i64 << 4));
1168 assert_eq!(
1170 Int64::one() << (core::mem::size_of::<Int64>() as u32 * 8 - 1),
1171 Int64::MIN
1172 );
1173 }
1174
1175 #[test]
1176 fn int64_abs_diff_works() {
1177 let a = Int64::from(42u32);
1178 let b = Int64::from(5u32);
1179 let expected = Uint64::from(37u32);
1180 assert_eq!(a.abs_diff(b), expected);
1181 assert_eq!(b.abs_diff(a), expected);
1182
1183 let c = Int64::from(-5i32);
1184 assert_eq!(b.abs_diff(c), Uint64::from(10u32));
1185 assert_eq!(c.abs_diff(b), Uint64::from(10u32));
1186 }
1187
1188 #[test]
1189 fn int64_abs_works() {
1190 let a = Int64::from(42i32);
1191 assert_eq!(a.abs(), a);
1192
1193 let b = Int64::from(-42i32);
1194 assert_eq!(b.abs(), a);
1195
1196 assert_eq!(Int64::zero().abs(), Int64::zero());
1197 assert_eq!((Int64::MIN + Int64::one()).abs(), Int64::MAX);
1198 }
1199
1200 #[test]
1201 fn int64_unsigned_abs_works() {
1202 assert_eq!(Int64::zero().unsigned_abs(), Uint64::zero());
1203 assert_eq!(Int64::one().unsigned_abs(), Uint64::one());
1204 assert_eq!(
1205 Int64::MIN.unsigned_abs(),
1206 Uint64::new(Int64::MAX.0 as u64) + Uint64::one()
1207 );
1208
1209 let v = Int64::from(-42i32);
1210 assert_eq!(v.unsigned_abs(), v.abs_diff(Int64::zero()));
1211 }
1212
1213 #[test]
1214 #[should_panic = "attempt to calculate absolute value with overflow"]
1215 fn int64_abs_min_panics() {
1216 _ = Int64::MIN.abs();
1217 }
1218
1219 #[test]
1220 #[should_panic = "attempt to negate with overflow"]
1221 fn int64_neg_min_panics() {
1222 _ = -Int64::MIN;
1223 }
1224
1225 #[test]
1226 fn int64_partial_eq() {
1227 let test_cases = [(1, 1, true), (42, 42, true), (42, 24, false), (0, 0, true)]
1228 .into_iter()
1229 .map(|(lhs, rhs, expected): (i64, i64, bool)| {
1230 (Int64::from(lhs), Int64::from(rhs), expected)
1231 });
1232
1233 #[allow(clippy::op_ref)]
1234 for (lhs, rhs, expected) in test_cases {
1235 assert_eq!(lhs == rhs, expected);
1236 assert_eq!(&lhs == rhs, expected);
1237 assert_eq!(lhs == &rhs, expected);
1238 assert_eq!(&lhs == &rhs, expected);
1239 }
1240 }
1241}