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