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