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