1use super::{ParseSignedError, Sign, utils::*};
2use alloc::string::String;
3use core::fmt;
4use ruint::{BaseConvertError, Uint, UintTryFrom, UintTryTo};
5
6#[derive(Clone, Copy, Default, PartialEq, Eq, Hash)]
54#[cfg_attr(feature = "arbitrary", derive(derive_arbitrary::Arbitrary, proptest_derive::Arbitrary))]
55pub struct Signed<const BITS: usize, const LIMBS: usize>(pub(crate) Uint<BITS, LIMBS>);
56
57impl<const BITS: usize, const LIMBS: usize> fmt::Debug for Signed<BITS, LIMBS> {
59 #[inline]
60 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
61 fmt::Display::fmt(self, f)
62 }
63}
64
65impl<const BITS: usize, const LIMBS: usize> fmt::Display for Signed<BITS, LIMBS> {
66 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
67 let (sign, abs) = self.into_sign_and_abs();
68 sign.fmt(f)?;
69 if f.sign_plus() { write!(f, "{abs}") } else { abs.fmt(f) }
70 }
71}
72
73impl<const BITS: usize, const LIMBS: usize> fmt::Binary for Signed<BITS, LIMBS> {
74 #[inline]
75 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
76 self.0.fmt(f)
77 }
78}
79
80impl<const BITS: usize, const LIMBS: usize> fmt::Octal for Signed<BITS, LIMBS> {
81 #[inline]
82 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
83 self.0.fmt(f)
84 }
85}
86
87impl<const BITS: usize, const LIMBS: usize> fmt::LowerHex for Signed<BITS, LIMBS> {
88 #[inline]
89 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
90 self.0.fmt(f)
91 }
92}
93
94impl<const BITS: usize, const LIMBS: usize> fmt::UpperHex for Signed<BITS, LIMBS> {
95 #[inline]
96 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
97 self.0.fmt(f)
98 }
99}
100
101impl<const BITS: usize, const LIMBS: usize> Signed<BITS, LIMBS> {
102 pub(crate) const MASK: u64 = ruint::mask(BITS);
104
105 pub(crate) const SIGN_BIT: u64 = sign_bit(BITS);
107
108 pub const BITS: usize = BITS;
110
111 pub const BYTES: usize = Uint::<BITS, LIMBS>::BYTES;
114
115 pub const MIN: Self = min();
117
118 pub const MAX: Self = max();
120
121 pub const ZERO: Self = zero();
123
124 pub const ONE: Self = one();
126
127 pub const MINUS_ONE: Self = Self(Uint::<BITS, LIMBS>::MAX);
129
130 #[inline]
133 pub const fn from_raw(val: Uint<BITS, LIMBS>) -> Self {
134 Self(val)
135 }
136
137 #[inline]
143 #[track_caller]
144 pub fn unchecked_from<T>(val: T) -> Self
145 where
146 T: TryInto<Self>,
147 <T as TryInto<Self>>::Error: fmt::Debug,
148 {
149 val.try_into().unwrap()
150 }
151
152 #[inline]
160 #[track_caller]
161 pub fn from<T>(value: T) -> Self
162 where
163 Self: UintTryFrom<T>,
164 {
165 match Self::uint_try_from(value) {
166 Ok(n) => n,
167 Err(e) => panic!("Uint conversion error: {e}"),
168 }
169 }
170
171 #[inline]
176 #[track_caller]
177 pub fn to<T>(&self) -> T
178 where
179 Self: UintTryTo<T>,
180 T: fmt::Debug,
181 {
182 self.uint_try_to().expect("Uint conversion error")
183 }
184
185 #[inline]
191 #[track_caller]
192 pub fn unchecked_into<T>(self) -> T
193 where
194 Self: TryInto<T>,
195 <Self as TryInto<T>>::Error: fmt::Debug,
196 {
197 self.try_into().unwrap()
198 }
199
200 #[inline]
204 pub const fn into_raw(self) -> Uint<BITS, LIMBS> {
205 self.0
206 }
207
208 #[inline]
210 pub const fn sign(&self) -> Sign {
211 if let Some(limb) = self.0.as_limbs().last() {
215 if *limb >= Self::SIGN_BIT {
216 return Sign::Negative;
217 }
218 }
219 Sign::Positive
220 }
221
222 #[inline]
224 pub const fn is_odd(&self) -> bool {
225 if BITS == 0 { false } else { self.as_limbs()[0] % 2 == 1 }
226 }
227
228 #[inline]
230 pub const fn const_eq(&self, other: &Self) -> bool {
231 const_eq(self, other)
232 }
233
234 #[inline]
237 pub const fn is_zero(&self) -> bool {
238 self.const_eq(&Self::ZERO)
239 }
240
241 #[inline]
244 pub const fn is_positive(&self) -> bool {
245 !self.is_zero() && matches!(self.sign(), Sign::Positive)
246 }
247
248 #[inline]
251 pub const fn is_negative(&self) -> bool {
252 matches!(self.sign(), Sign::Negative)
253 }
254
255 #[inline]
257 pub const fn count_ones(&self) -> usize {
258 self.0.count_ones()
259 }
260
261 #[inline]
263 pub const fn count_zeros(&self) -> usize {
264 self.0.count_zeros()
265 }
266
267 #[inline]
270 pub const fn leading_zeros(&self) -> usize {
271 self.0.leading_zeros()
272 }
273
274 #[inline]
277 pub fn trailing_zeros(&self) -> usize {
278 self.0.trailing_zeros()
279 }
280
281 #[inline]
284 pub fn trailing_ones(&self) -> usize {
285 self.0.trailing_ones()
286 }
287
288 #[inline]
292 pub const fn bit(&self, index: usize) -> bool {
293 self.0.bit(index)
294 }
295
296 #[inline]
303 #[track_caller]
304 pub const fn byte(&self, index: usize) -> u8 {
305 self.0.byte(index)
306 }
307
308 #[inline]
310 pub fn bits(&self) -> u32 {
311 let unsigned = self.unsigned_abs();
312 let unsigned_bits = unsigned.bit_len();
313
314 let bits = if self.count_zeros() == self.trailing_zeros() {
329 unsigned_bits
331 } else {
332 unsigned_bits + 1
333 };
334
335 bits as u32
336 }
337
338 #[inline]
341 pub fn overflowing_from_sign_and_abs(sign: Sign, abs: Uint<BITS, LIMBS>) -> (Self, bool) {
342 let value = Self(match sign {
343 Sign::Positive => abs,
344 Sign::Negative => twos_complement(abs),
345 });
346
347 (value, value.sign() != sign && value != Self::ZERO)
348 }
349
350 #[inline]
353 pub fn checked_from_sign_and_abs(sign: Sign, abs: Uint<BITS, LIMBS>) -> Option<Self> {
354 let (result, overflow) = Self::overflowing_from_sign_and_abs(sign, abs);
355 if overflow { None } else { Some(result) }
356 }
357
358 pub fn from_dec_str(value: &str) -> Result<Self, ParseSignedError> {
360 let (sign, value) = match value.as_bytes().first() {
361 Some(b'+') => (Sign::Positive, &value[1..]),
362 Some(b'-') => (Sign::Negative, &value[1..]),
363 _ => (Sign::Positive, value),
364 };
365 let abs = Uint::<BITS, LIMBS>::from_str_radix(value, 10)?;
366 Self::checked_from_sign_and_abs(sign, abs).ok_or(ParseSignedError::IntegerOverflow)
367 }
368
369 pub fn to_dec_string(&self) -> String {
371 let sign = self.sign();
372 let abs = self.unsigned_abs();
373
374 format!("{sign}{abs}")
375 }
376
377 pub fn from_hex_str(value: &str) -> Result<Self, ParseSignedError> {
379 let (sign, value) = match value.as_bytes().first() {
380 Some(b'+') => (Sign::Positive, &value[1..]),
381 Some(b'-') => (Sign::Negative, &value[1..]),
382 _ => (Sign::Positive, value),
383 };
384
385 let value = value.strip_prefix("0x").unwrap_or(value);
386
387 if value.len() > 64 {
388 return Err(ParseSignedError::IntegerOverflow);
389 }
390
391 let abs = Uint::<BITS, LIMBS>::from_str_radix(value, 16)?;
392 Self::checked_from_sign_and_abs(sign, abs).ok_or(ParseSignedError::IntegerOverflow)
393 }
394
395 pub fn to_hex_string(&self) -> String {
397 let sign = self.sign();
398 let abs = self.unsigned_abs();
399
400 format!("{sign}0x{abs:x}")
401 }
402
403 #[inline]
405 pub fn into_sign_and_abs(&self) -> (Sign, Uint<BITS, LIMBS>) {
406 let sign = self.sign();
407 let abs = match sign {
408 Sign::Positive => self.0,
409 Sign::Negative => twos_complement(self.0),
410 };
411 (sign, abs)
412 }
413
414 #[inline]
425 pub const fn to_be_bytes<const BYTES: usize>(&self) -> [u8; BYTES] {
426 self.0.to_be_bytes()
427 }
428
429 #[inline]
440 pub const fn to_le_bytes<const BYTES: usize>(&self) -> [u8; BYTES] {
441 self.0.to_le_bytes()
442 }
443
444 #[inline]
456 pub const fn from_be_bytes<const BYTES: usize>(bytes: [u8; BYTES]) -> Self {
457 Self(Uint::from_be_bytes::<BYTES>(bytes))
458 }
459
460 #[inline]
466 #[track_caller]
467 pub const fn from_le_bytes<const BYTES: usize>(bytes: [u8; BYTES]) -> Self {
468 Self(Uint::from_le_bytes::<BYTES>(bytes))
469 }
470
471 pub fn try_from_be_slice(slice: &[u8]) -> Option<Self> {
478 Uint::try_from_be_slice(slice).map(Self)
479 }
480
481 pub fn try_from_le_slice(slice: &[u8]) -> Option<Self> {
488 Uint::try_from_le_slice(slice).map(Self)
489 }
490
491 #[inline(always)]
493 #[must_use]
494 pub const fn as_limbs(&self) -> &[u64; LIMBS] {
495 self.0.as_limbs()
496 }
497
498 #[inline(always)]
502 pub const fn into_limbs(self) -> [u64; LIMBS] {
503 self.0.into_limbs()
504 }
505
506 #[inline(always)]
514 #[track_caller]
515 #[must_use]
516 pub const fn from_limbs(limbs: [u64; LIMBS]) -> Self {
517 Self(Uint::from_limbs(limbs))
518 }
519
520 pub fn from_base_be<I: IntoIterator<Item = u64>>(
529 base: u64,
530 digits: I,
531 ) -> Result<Self, BaseConvertError> {
532 Ok(Self(Uint::from_base_be(base, digits)?))
533 }
534}
535
536#[cfg(test)]
537mod tests {
538 use super::*;
539 use crate::{BigIntConversionError, ParseSignedError, aliases::*};
540 use alloc::string::ToString;
541 use core::ops::Neg;
542 use ruint::{
543 BaseConvertError, ParseError,
544 aliases::{U0, U1, U128, U160, U256},
545 };
546
547 type I96 = Signed<96, 2>;
549 type U96 = Uint<96, 2>;
550
551 #[test]
552 fn identities() {
553 macro_rules! test_identities {
554 ($signed:ty, $max:literal, $min:literal) => {
555 assert_eq!(<$signed>::ZERO.to_string(), "0");
556 assert_eq!(<$signed>::ONE.to_string(), "1");
557 assert_eq!(<$signed>::MINUS_ONE.to_string(), "-1");
558 assert_eq!(<$signed>::MAX.to_string(), $max);
559 assert_eq!(<$signed>::MIN.to_string(), $min);
560 };
561 }
562
563 assert_eq!(I0::ZERO.to_string(), "0");
564 assert_eq!(I1::ZERO.to_string(), "0");
565 assert_eq!(I1::ONE.to_string(), "-1");
566
567 test_identities!(I96, "39614081257132168796771975167", "-39614081257132168796771975168");
568 test_identities!(
569 I128,
570 "170141183460469231731687303715884105727",
571 "-170141183460469231731687303715884105728"
572 );
573 test_identities!(
574 I192,
575 "3138550867693340381917894711603833208051177722232017256447",
576 "-3138550867693340381917894711603833208051177722232017256448"
577 );
578 test_identities!(
579 I256,
580 "57896044618658097711785492504343953926634992332820282019728792003956564819967",
581 "-57896044618658097711785492504343953926634992332820282019728792003956564819968"
582 );
583 }
584
585 #[test]
586 fn std_num_conversion() {
587 macro_rules! run_test {
590 ($i_struct:ty, $u_struct:ty, $i:ty, $u:ty) => {
591 assert_eq!(<$i_struct>::try_from(-42 as $i).unwrap().to_string(), "-42");
593 assert_eq!(<$i_struct>::try_from(42 as $i).unwrap().to_string(), "42");
594 assert_eq!(<$i_struct>::try_from(42 as $u).unwrap().to_string(), "42");
595
596 if <$u_struct>::BITS as u32 >= <$u>::BITS {
597 assert_eq!(
598 <$i_struct>::try_from(<$i>::MAX).unwrap().to_string(),
599 <$i>::MAX.to_string(),
600 );
601 assert_eq!(
602 <$i_struct>::try_from(<$i>::MIN).unwrap().to_string(),
603 <$i>::MIN.to_string(),
604 );
605 } else {
606 assert_eq!(
607 <$i_struct>::try_from(<$i>::MAX).unwrap_err(),
608 BigIntConversionError,
609 );
610 }
611 };
612
613 ($i_struct:ty, $u_struct:ty) => {
614 run_test!($i_struct, $u_struct, i8, u8);
615 run_test!($i_struct, $u_struct, i16, u16);
616 run_test!($i_struct, $u_struct, i32, u32);
617 run_test!($i_struct, $u_struct, i64, u64);
618 run_test!($i_struct, $u_struct, i128, u128);
619 run_test!($i_struct, $u_struct, isize, usize);
620 };
621 }
622
623 assert_eq!(I0::unchecked_from(0), I0::default());
625 assert_eq!(I0::try_from(1u8), Err(BigIntConversionError));
626 assert_eq!(I0::try_from(1i8), Err(BigIntConversionError));
627 assert_eq!(I1::unchecked_from(0), I1::default());
628 assert_eq!(I1::try_from(1u8), Err(BigIntConversionError));
629 assert_eq!(I1::try_from(1i8), Err(BigIntConversionError));
630 assert_eq!(I1::try_from(-1), Ok(I1::MINUS_ONE));
631
632 run_test!(I96, U96);
633 run_test!(I128, U128);
634 run_test!(I160, U160);
635 run_test!(I192, U192);
636 run_test!(I256, U256);
637 }
638
639 #[test]
640 fn from_dec_str() {
641 macro_rules! run_test {
642 ($i_struct:ty, $u_struct:ty) => {
643 let min_abs: $u_struct = <$i_struct>::MIN.0;
644 let unsigned = <$u_struct>::from_str_radix("3141592653589793", 10).unwrap();
645
646 let value = <$i_struct>::from_dec_str(&format!("-{unsigned}")).unwrap();
647 assert_eq!(value.into_sign_and_abs(), (Sign::Negative, unsigned));
648
649 let value = <$i_struct>::from_dec_str(&format!("{unsigned}")).unwrap();
650 assert_eq!(value.into_sign_and_abs(), (Sign::Positive, unsigned));
651
652 let value = <$i_struct>::from_dec_str(&format!("+{unsigned}")).unwrap();
653 assert_eq!(value.into_sign_and_abs(), (Sign::Positive, unsigned));
654
655 let err = <$i_struct>::from_dec_str("invalid string").unwrap_err();
656 assert_eq!(
657 err,
658 ParseSignedError::Ruint(ParseError::BaseConvertError(
659 BaseConvertError::InvalidDigit(18, 10)
660 ))
661 );
662
663 let err = <$i_struct>::from_dec_str(&format!("1{}", <$u_struct>::MAX)).unwrap_err();
664 assert_eq!(err, ParseSignedError::IntegerOverflow);
665
666 let err = <$i_struct>::from_dec_str(&format!("-{}", <$u_struct>::MAX)).unwrap_err();
667 assert_eq!(err, ParseSignedError::IntegerOverflow);
668
669 let value = <$i_struct>::from_dec_str(&format!("-{}", min_abs)).unwrap();
670 assert_eq!(value.into_sign_and_abs(), (Sign::Negative, min_abs));
671
672 let err = <$i_struct>::from_dec_str(&format!("{}", min_abs)).unwrap_err();
673 assert_eq!(err, ParseSignedError::IntegerOverflow);
674 };
675 }
676
677 assert_eq!(I0::from_dec_str("0"), Ok(I0::default()));
678 assert_eq!(I1::from_dec_str("0"), Ok(I1::ZERO));
679 assert_eq!(I1::from_dec_str("-1"), Ok(I1::MINUS_ONE));
680 assert_eq!(I1::from_dec_str("1"), Err(ParseSignedError::IntegerOverflow));
681
682 run_test!(I96, U96);
683 run_test!(I128, U128);
684 run_test!(I160, U160);
685 run_test!(I192, U192);
686 run_test!(I256, U256);
687 }
688
689 #[test]
690 fn from_hex_str() {
691 macro_rules! run_test {
692 ($i_struct:ty, $u_struct:ty) => {
693 let min_abs = <$i_struct>::MIN.0;
694 let unsigned = <$u_struct>::from_str_radix("3141592653589793", 10).unwrap();
695
696 let value = <$i_struct>::from_hex_str(&format!("-{unsigned:x}")).unwrap();
697 assert_eq!(value.into_sign_and_abs(), (Sign::Negative, unsigned));
698
699 let value = <$i_struct>::from_hex_str(&format!("-0x{unsigned:x}")).unwrap();
700 assert_eq!(value.into_sign_and_abs(), (Sign::Negative, unsigned));
701
702 let value = <$i_struct>::from_hex_str(&format!("{unsigned:x}")).unwrap();
703 assert_eq!(value.into_sign_and_abs(), (Sign::Positive, unsigned));
704
705 let value = <$i_struct>::from_hex_str(&format!("0x{unsigned:x}")).unwrap();
706 assert_eq!(value.into_sign_and_abs(), (Sign::Positive, unsigned));
707
708 let value = <$i_struct>::from_hex_str(&format!("+0x{unsigned:x}")).unwrap();
709 assert_eq!(value.into_sign_and_abs(), (Sign::Positive, unsigned));
710
711 let err = <$i_struct>::from_hex_str("invalid string").unwrap_err();
712 assert!(matches!(err, ParseSignedError::Ruint(_)));
713
714 let err =
715 <$i_struct>::from_hex_str(&format!("1{:x}", <$u_struct>::MAX)).unwrap_err();
716 assert!(matches!(err, ParseSignedError::IntegerOverflow));
717
718 let err =
719 <$i_struct>::from_hex_str(&format!("-{:x}", <$u_struct>::MAX)).unwrap_err();
720 assert!(matches!(err, ParseSignedError::IntegerOverflow));
721
722 let value = <$i_struct>::from_hex_str(&format!("-{:x}", min_abs)).unwrap();
723 assert_eq!(value.into_sign_and_abs(), (Sign::Negative, min_abs));
724
725 let err = <$i_struct>::from_hex_str(&format!("{:x}", min_abs)).unwrap_err();
726 assert!(matches!(err, ParseSignedError::IntegerOverflow));
727 };
728 }
729
730 assert_eq!(I0::from_hex_str("0x0"), Ok(I0::default()));
731 assert_eq!(I1::from_hex_str("0x0"), Ok(I1::ZERO));
732 assert_eq!(I1::from_hex_str("0x0"), Ok(I1::ZERO));
733 assert_eq!(I1::from_hex_str("-0x1"), Ok(I1::MINUS_ONE));
734 assert_eq!(I1::from_hex_str("0x1"), Err(ParseSignedError::IntegerOverflow));
735
736 run_test!(I96, U96);
737 run_test!(I128, U128);
738 run_test!(I160, U160);
739 run_test!(I192, U192);
740 run_test!(I256, U256);
741 }
742
743 #[test]
744 fn parse() {
745 assert_eq!("0x0".parse::<I0>(), Ok(I0::default()));
746 assert_eq!("+0x0".parse::<I0>(), Ok(I0::default()));
747 assert_eq!("0x0".parse::<I1>(), Ok(I1::ZERO));
748 assert_eq!("+0x0".parse::<I1>(), Ok(I1::ZERO));
749 assert_eq!("-0x1".parse::<I1>(), Ok(I1::MINUS_ONE));
750 assert_eq!("0x1".parse::<I1>(), Err(ParseSignedError::IntegerOverflow));
751
752 assert_eq!("0".parse::<I0>(), Ok(I0::default()));
753 assert_eq!("+0".parse::<I0>(), Ok(I0::default()));
754 assert_eq!("0".parse::<I1>(), Ok(I1::ZERO));
755 assert_eq!("+0".parse::<I1>(), Ok(I1::ZERO));
756 assert_eq!("-1".parse::<I1>(), Ok(I1::MINUS_ONE));
757 assert_eq!("1".parse::<I1>(), Err(ParseSignedError::IntegerOverflow));
758 }
759
760 #[test]
761 fn formatting() {
762 macro_rules! run_test {
763 ($i_struct:ty, $u_struct:ty) => {
764 let unsigned = <$u_struct>::from_str_radix("3141592653589793", 10).unwrap();
765 let unsigned_negative = -unsigned;
766 let positive = <$i_struct>::try_from(unsigned).unwrap();
767 let negative = -positive;
768
769 assert_eq!(format!("{positive}"), format!("{unsigned}"));
770 assert_eq!(format!("{negative}"), format!("-{unsigned}"));
771 assert_eq!(format!("{positive:+}"), format!("+{unsigned}"));
772 assert_eq!(format!("{negative:+}"), format!("-{unsigned}"));
773
774 assert_eq!(format!("{positive:x}"), format!("{unsigned:x}"));
775 assert_eq!(format!("{negative:x}"), format!("{unsigned_negative:x}"));
776 assert_eq!(format!("{positive:+x}"), format!("+{unsigned:x}"));
777 assert_eq!(format!("{negative:+x}"), format!("+{unsigned_negative:x}"));
778
779 assert_eq!(format!("{positive:X}"), format!("{unsigned:X}"));
780 assert_eq!(format!("{negative:X}"), format!("{unsigned_negative:X}"));
781 assert_eq!(format!("{positive:+X}"), format!("+{unsigned:X}"));
782 assert_eq!(format!("{negative:+X}"), format!("+{unsigned_negative:X}"));
783 };
784 }
785
786 let z = I0::default();
787 let o = I1::default();
788 let m = I1::MINUS_ONE;
789 assert_eq!(format!("{z} {o} {m}"), "0 0 -1");
790
791 run_test!(I96, U96);
792 run_test!(I128, U128);
793 run_test!(I160, U160);
794 run_test!(I192, U192);
795 run_test!(I256, U256);
796 }
797
798 #[test]
799 fn signs() {
800 macro_rules! run_test {
801 ($i_struct:ty, $u_struct:ty) => {
802 assert_eq!(<$i_struct>::MAX.sign(), Sign::Positive);
803 assert!(<$i_struct>::MAX.is_positive());
804 assert!(!<$i_struct>::MAX.is_negative());
805 assert!(!<$i_struct>::MAX.is_zero());
806
807 assert_eq!(<$i_struct>::ONE.sign(), Sign::Positive);
808 assert!(<$i_struct>::ONE.is_positive());
809 assert!(!<$i_struct>::ONE.is_negative());
810 assert!(!<$i_struct>::ONE.is_zero());
811
812 assert_eq!(<$i_struct>::MIN.sign(), Sign::Negative);
813 assert!(!<$i_struct>::MIN.is_positive());
814 assert!(<$i_struct>::MIN.is_negative());
815 assert!(!<$i_struct>::MIN.is_zero());
816
817 assert_eq!(<$i_struct>::MINUS_ONE.sign(), Sign::Negative);
818 assert!(!<$i_struct>::MINUS_ONE.is_positive());
819 assert!(<$i_struct>::MINUS_ONE.is_negative());
820 assert!(!<$i_struct>::MINUS_ONE.is_zero());
821
822 assert_eq!(<$i_struct>::ZERO.sign(), Sign::Positive);
823 assert!(!<$i_struct>::ZERO.is_positive());
824 assert!(!<$i_struct>::ZERO.is_negative());
825 assert!(<$i_struct>::ZERO.is_zero());
826 };
827 }
828
829 let z = I0::default();
830 let o = I1::default();
831 let m = I1::MINUS_ONE;
832 assert_eq!(z.sign(), Sign::Positive);
833 assert_eq!(o.sign(), Sign::Positive);
834 assert_eq!(m.sign(), Sign::Negative);
835
836 run_test!(I96, U96);
837 run_test!(I128, U128);
838 run_test!(I160, U160);
839 run_test!(I192, U192);
840 run_test!(I256, U256);
841 }
842
843 #[test]
844 fn abs() {
845 macro_rules! run_test {
846 ($i_struct:ty, $u_struct:ty) => {
847 let positive = <$i_struct>::from_dec_str("3141592653589793").unwrap();
848 let negative = <$i_struct>::from_dec_str("-27182818284590").unwrap();
849
850 assert_eq!(positive.sign(), Sign::Positive);
851 assert_eq!(positive.abs().sign(), Sign::Positive);
852 assert_eq!(positive, positive.abs());
853 assert_ne!(negative, negative.abs());
854 assert_eq!(negative.sign(), Sign::Negative);
855 assert_eq!(negative.abs().sign(), Sign::Positive);
856 assert_eq!(<$i_struct>::ZERO.abs(), <$i_struct>::ZERO);
857 assert_eq!(<$i_struct>::MAX.abs(), <$i_struct>::MAX);
858 assert_eq!((-<$i_struct>::MAX).abs(), <$i_struct>::MAX);
859 assert_eq!(<$i_struct>::MIN.checked_abs(), None);
860 };
861 }
862
863 let z = I0::default();
864 let o = I1::default();
865 let m = I1::MINUS_ONE;
866 assert_eq!(z.abs(), z);
867 assert_eq!(o.abs(), o);
868 assert_eq!(m.checked_abs(), None);
869
870 run_test!(I96, U96);
871 run_test!(I128, U128);
872 run_test!(I160, U160);
873 run_test!(I192, U192);
874 run_test!(I256, U256);
875 }
876
877 #[test]
878 fn neg() {
879 macro_rules! run_test {
880 ($i_struct:ty, $u_struct:ty) => {
881 let positive = <$i_struct>::from_dec_str("3141592653589793").unwrap().sign();
882 let negative = -positive;
883
884 assert_eq!(-positive, negative);
885 assert_eq!(-negative, positive);
886
887 assert_eq!(-<$i_struct>::ZERO, <$i_struct>::ZERO);
888 assert_eq!(-(-<$i_struct>::MAX), <$i_struct>::MAX);
889 assert_eq!(<$i_struct>::MIN.checked_neg(), None);
890 };
891 }
892
893 let z = I0::default();
894 let o = I1::default();
895 let m = I1::MINUS_ONE;
896 assert_eq!(-z, z);
897 assert_eq!(-o, o);
898 assert_eq!(m.checked_neg(), None);
899
900 run_test!(I96, U96);
901 run_test!(I128, U128);
902 run_test!(I160, U160);
903 run_test!(I192, U192);
904 run_test!(I256, U256);
905 }
906
907 #[test]
908 fn bits() {
909 macro_rules! run_test {
910 ($i_struct:ty, $u_struct:ty) => {
911 assert_eq!(<$i_struct>::try_from(0b1000).unwrap().bits(), 5);
912 assert_eq!(<$i_struct>::try_from(-0b1000).unwrap().bits(), 4);
913
914 assert_eq!(<$i_struct>::try_from(i64::MAX).unwrap().bits(), 64);
915 assert_eq!(<$i_struct>::try_from(i64::MIN).unwrap().bits(), 64);
916
917 assert_eq!(<$i_struct>::MAX.bits(), <$i_struct>::BITS as u32);
918 assert_eq!(<$i_struct>::MIN.bits(), <$i_struct>::BITS as u32);
919
920 assert_eq!(<$i_struct>::ZERO.bits(), 0);
921 };
922 }
923
924 let z = I0::default();
925 let o = I1::default();
926 let m = I1::MINUS_ONE;
927 assert_eq!(z.bits(), 0);
928 assert_eq!(o.bits(), 0);
929 assert_eq!(m.bits(), 1);
930
931 run_test!(I96, U96);
932 run_test!(I128, U128);
933 run_test!(I160, U160);
934 run_test!(I192, U192);
935 run_test!(I256, U256);
936 }
937
938 #[test]
939 fn bit_shift() {
940 macro_rules! run_test {
941 ($i_struct:ty, $u_struct:ty) => {
942 assert_eq!(<$i_struct>::ONE << <$i_struct>::BITS - 1, <$i_struct>::MIN);
943 assert_eq!(<$i_struct>::MIN >> <$i_struct>::BITS - 1, <$i_struct>::ONE);
944 };
945 }
946
947 let z = I0::default();
948 let o = I1::default();
949 let m = I1::MINUS_ONE;
950 assert_eq!(z << 1, z >> 1);
951 assert_eq!(o << 1, o >> 0);
952 assert_eq!(m << 1, o);
953 assert_eq!(m >> 1, o);
954
955 run_test!(I96, U96);
956 run_test!(I128, U128);
957 run_test!(I160, U160);
958 run_test!(I192, U192);
959 run_test!(I256, U256);
960 }
961
962 #[test]
963 fn arithmetic_shift_right() {
964 macro_rules! run_test {
965 ($i_struct:ty, $u_struct:ty) => {
966 let exp = <$i_struct>::BITS - 2;
967 let shift = <$i_struct>::BITS - 3;
968
969 let value =
970 <$i_struct>::from_raw(<$u_struct>::from(2u8).pow(<$u_struct>::from(exp))).neg();
971
972 let expected_result =
973 <$i_struct>::from_raw(<$u_struct>::MAX - <$u_struct>::from(1u8));
974 assert_eq!(
975 value.asr(shift),
976 expected_result,
977 "1011...1111 >> 253 was not 1111...1110"
978 );
979
980 let value = <$i_struct>::MINUS_ONE;
981 let expected_result = <$i_struct>::MINUS_ONE;
982 assert_eq!(value.asr(250), expected_result, "-1 >> any_amount was not -1");
983
984 let value = <$i_struct>::from_raw(
985 <$u_struct>::from(2u8).pow(<$u_struct>::from(<$i_struct>::BITS - 2)),
986 )
987 .neg();
988 let expected_result = <$i_struct>::MINUS_ONE;
989 assert_eq!(
990 value.asr(<$i_struct>::BITS - 1),
991 expected_result,
992 "1011...1111 >> 255 was not -1"
993 );
994
995 let value = <$i_struct>::from_raw(
996 <$u_struct>::from(2u8).pow(<$u_struct>::from(<$i_struct>::BITS - 2)),
997 )
998 .neg();
999 let expected_result = <$i_struct>::MINUS_ONE;
1000 assert_eq!(value.asr(1024), expected_result, "1011...1111 >> 1024 was not -1");
1001
1002 let value = <$i_struct>::try_from(1024i32).unwrap();
1003 let expected_result = <$i_struct>::try_from(32i32).unwrap();
1004 assert_eq!(value.asr(5), expected_result, "1024 >> 5 was not 32");
1005
1006 let value = <$i_struct>::MAX;
1007 let expected_result = <$i_struct>::ZERO;
1008 assert_eq!(value.asr(255), expected_result, "<$i_struct>::MAX >> 255 was not 0");
1009
1010 let value =
1011 <$i_struct>::from_raw(<$u_struct>::from(2u8).pow(<$u_struct>::from(exp))).neg();
1012 let expected_result = value;
1013 assert_eq!(value.asr(0), expected_result, "1011...1111 >> 0 was not 1011...111");
1014 };
1015 }
1016
1017 let z = I0::default();
1018 let o = I1::default();
1019 let m = I1::MINUS_ONE;
1020 assert_eq!(z.asr(1), z);
1021 assert_eq!(o.asr(1), o);
1022 assert_eq!(m.asr(1), m);
1023 assert_eq!(m.asr(1000), m);
1024
1025 run_test!(I96, U96);
1026 run_test!(I128, U128);
1027 run_test!(I160, U160);
1028 run_test!(I192, U192);
1029 run_test!(I256, U256);
1030 }
1031
1032 #[test]
1033 fn arithmetic_shift_left() {
1034 macro_rules! run_test {
1035 ($i_struct:ty, $u_struct:ty) => {
1036 let value = <$i_struct>::MINUS_ONE;
1037 let expected_result = Some(value);
1038 assert_eq!(value.asl(0), expected_result, "-1 << 0 was not -1");
1039
1040 let value = <$i_struct>::MINUS_ONE;
1041 let expected_result = None;
1042 assert_eq!(
1043 value.asl(256),
1044 expected_result,
1045 "-1 << 256 did not overflow (result should be 0000...0000)"
1046 );
1047
1048 let value = <$i_struct>::MINUS_ONE;
1049 let expected_result = Some(<$i_struct>::from_raw(
1050 <$u_struct>::from(2u8).pow(<$u_struct>::from(<$i_struct>::BITS - 1)),
1051 ));
1052 assert_eq!(
1053 value.asl(<$i_struct>::BITS - 1),
1054 expected_result,
1055 "-1 << 255 was not 1000...0000"
1056 );
1057
1058 let value = <$i_struct>::try_from(-1024i32).unwrap();
1059 let expected_result = Some(<$i_struct>::try_from(-32768i32).unwrap());
1060 assert_eq!(value.asl(5), expected_result, "-1024 << 5 was not -32768");
1061
1062 let value = <$i_struct>::try_from(1024i32).unwrap();
1063 let expected_result = Some(<$i_struct>::try_from(32768i32).unwrap());
1064 assert_eq!(value.asl(5), expected_result, "1024 << 5 was not 32768");
1065
1066 let value = <$i_struct>::try_from(1024i32).unwrap();
1067 let expected_result = None;
1068 assert_eq!(
1069 value.asl(<$i_struct>::BITS - 11),
1070 expected_result,
1071 "1024 << 245 did not overflow (result should be 1000...0000)"
1072 );
1073
1074 let value = <$i_struct>::ZERO;
1075 let expected_result = Some(value);
1076 assert_eq!(value.asl(1024), expected_result, "0 << anything was not 0");
1077 };
1078 }
1079
1080 let z = I0::default();
1081 let o = I1::default();
1082 let m = I1::MINUS_ONE;
1083 assert_eq!(z.asl(1), Some(z));
1084 assert_eq!(o.asl(1), Some(o));
1085 assert_eq!(m.asl(1), None);
1086
1087 run_test!(I96, U96);
1088 run_test!(I128, U128);
1089 run_test!(I160, U160);
1090 run_test!(I192, U192);
1091 run_test!(I256, U256);
1092 }
1093
1094 #[test]
1095 fn addition() {
1096 macro_rules! run_test {
1097 ($i_struct:ty, $u_struct:ty) => {
1098 assert_eq!(
1099 <$i_struct>::MIN.overflowing_add(<$i_struct>::MIN),
1100 (<$i_struct>::ZERO, true)
1101 );
1102 assert_eq!(
1103 <$i_struct>::MAX.overflowing_add(<$i_struct>::MAX),
1104 (<$i_struct>::try_from(-2).unwrap(), true)
1105 );
1106
1107 assert_eq!(
1108 <$i_struct>::MIN.overflowing_add(<$i_struct>::MINUS_ONE),
1109 (<$i_struct>::MAX, true)
1110 );
1111 assert_eq!(
1112 <$i_struct>::MAX.overflowing_add(<$i_struct>::ONE),
1113 (<$i_struct>::MIN, true)
1114 );
1115
1116 assert_eq!(<$i_struct>::MAX + <$i_struct>::MIN, <$i_struct>::MINUS_ONE);
1117 assert_eq!(
1118 <$i_struct>::try_from(2).unwrap() + <$i_struct>::try_from(40).unwrap(),
1119 <$i_struct>::try_from(42).unwrap()
1120 );
1121
1122 assert_eq!(<$i_struct>::ZERO + <$i_struct>::ZERO, <$i_struct>::ZERO);
1123
1124 assert_eq!(<$i_struct>::MAX.saturating_add(<$i_struct>::MAX), <$i_struct>::MAX);
1125 assert_eq!(
1126 <$i_struct>::MIN.saturating_add(<$i_struct>::MINUS_ONE),
1127 <$i_struct>::MIN
1128 );
1129 };
1130 }
1131
1132 let z = I0::default();
1133 let o = I1::default();
1134 let m = I1::MINUS_ONE;
1135 assert_eq!(z + z, z);
1136 assert_eq!(o + o, o);
1137 assert_eq!(m + o, m);
1138 assert_eq!(m.overflowing_add(m), (o, true));
1139
1140 run_test!(I96, U96);
1141 run_test!(I128, U128);
1142 run_test!(I160, U160);
1143 run_test!(I192, U192);
1144 run_test!(I256, U256);
1145 }
1146
1147 #[test]
1148 fn subtraction() {
1149 macro_rules! run_test {
1150 ($i_struct:ty, $u_struct:ty) => {
1151 assert_eq!(
1152 <$i_struct>::MIN.overflowing_sub(<$i_struct>::MAX),
1153 (<$i_struct>::ONE, true)
1154 );
1155 assert_eq!(
1156 <$i_struct>::MAX.overflowing_sub(<$i_struct>::MIN),
1157 (<$i_struct>::MINUS_ONE, true)
1158 );
1159
1160 assert_eq!(
1161 <$i_struct>::MIN.overflowing_sub(<$i_struct>::ONE),
1162 (<$i_struct>::MAX, true)
1163 );
1164 assert_eq!(
1165 <$i_struct>::MAX.overflowing_sub(<$i_struct>::MINUS_ONE),
1166 (<$i_struct>::MIN, true)
1167 );
1168
1169 assert_eq!(
1170 <$i_struct>::ZERO.overflowing_sub(<$i_struct>::MIN),
1171 (<$i_struct>::MIN, true)
1172 );
1173
1174 assert_eq!(<$i_struct>::MAX - <$i_struct>::MAX, <$i_struct>::ZERO);
1175 assert_eq!(
1176 <$i_struct>::try_from(2).unwrap() - <$i_struct>::try_from(44).unwrap(),
1177 <$i_struct>::try_from(-42).unwrap()
1178 );
1179
1180 assert_eq!(<$i_struct>::ZERO - <$i_struct>::ZERO, <$i_struct>::ZERO);
1181
1182 assert_eq!(<$i_struct>::MAX.saturating_sub(<$i_struct>::MIN), <$i_struct>::MAX);
1183 assert_eq!(<$i_struct>::MIN.saturating_sub(<$i_struct>::ONE), <$i_struct>::MIN);
1184 };
1185 }
1186
1187 let z = I0::default();
1188 let o = I1::default();
1189 let m = I1::MINUS_ONE;
1190 assert_eq!(z - z, z);
1191 assert_eq!(o - o, o);
1192 assert_eq!(m - o, m);
1193 assert_eq!(m - m, o);
1194 assert_eq!(o.overflowing_sub(m), (m, true));
1195
1196 run_test!(I96, U96);
1197 run_test!(I128, U128);
1198 run_test!(I160, U160);
1199 run_test!(I192, U192);
1200 run_test!(I256, U256);
1201 }
1202
1203 #[test]
1204 fn multiplication() {
1205 macro_rules! run_test {
1206 ($i_struct:ty, $u_struct:ty) => {
1207 assert_eq!(
1208 <$i_struct>::MIN.overflowing_mul(<$i_struct>::MAX),
1209 (<$i_struct>::MIN, true)
1210 );
1211 assert_eq!(
1212 <$i_struct>::MAX.overflowing_mul(<$i_struct>::MIN),
1213 (<$i_struct>::MIN, true)
1214 );
1215
1216 assert_eq!(<$i_struct>::MIN * <$i_struct>::ONE, <$i_struct>::MIN);
1217 assert_eq!(
1218 <$i_struct>::try_from(2).unwrap() * <$i_struct>::try_from(-21).unwrap(),
1219 <$i_struct>::try_from(-42).unwrap()
1220 );
1221
1222 assert_eq!(<$i_struct>::MAX.saturating_mul(<$i_struct>::MAX), <$i_struct>::MAX);
1223 assert_eq!(
1224 <$i_struct>::MAX.saturating_mul(<$i_struct>::try_from(2).unwrap()),
1225 <$i_struct>::MAX
1226 );
1227 assert_eq!(
1228 <$i_struct>::MIN.saturating_mul(<$i_struct>::try_from(-2).unwrap()),
1229 <$i_struct>::MAX
1230 );
1231
1232 assert_eq!(<$i_struct>::MIN.saturating_mul(<$i_struct>::MAX), <$i_struct>::MIN);
1233 assert_eq!(
1234 <$i_struct>::MIN.saturating_mul(<$i_struct>::try_from(2).unwrap()),
1235 <$i_struct>::MIN
1236 );
1237 assert_eq!(
1238 <$i_struct>::MAX.saturating_mul(<$i_struct>::try_from(-2).unwrap()),
1239 <$i_struct>::MIN
1240 );
1241
1242 assert_eq!(<$i_struct>::ZERO * <$i_struct>::ZERO, <$i_struct>::ZERO);
1243 assert_eq!(<$i_struct>::ONE * <$i_struct>::ZERO, <$i_struct>::ZERO);
1244 assert_eq!(<$i_struct>::MAX * <$i_struct>::ZERO, <$i_struct>::ZERO);
1245 assert_eq!(<$i_struct>::MIN * <$i_struct>::ZERO, <$i_struct>::ZERO);
1246 };
1247 }
1248
1249 let z = I0::default();
1250 let o = I1::default();
1251 let m = I1::MINUS_ONE;
1252 assert_eq!(z * z, z);
1253 assert_eq!(o * o, o);
1254 assert_eq!(m * o, o);
1255 assert_eq!(m.overflowing_mul(m), (m, true));
1256
1257 run_test!(I96, U96);
1258 run_test!(I128, U128);
1259 run_test!(I160, U160);
1260 run_test!(I192, U192);
1261 run_test!(I256, U256);
1262 }
1263
1264 #[test]
1265 fn division() {
1266 macro_rules! run_test {
1267 ($i_struct:ty, $u_struct:ty) => {
1268 assert_eq!(
1270 <$i_struct>::MIN.overflowing_div(<$i_struct>::try_from(-1).unwrap()),
1271 (<$i_struct>::MIN, true)
1272 );
1273
1274 assert_eq!(<$i_struct>::MIN / <$i_struct>::MAX, <$i_struct>::try_from(-1).unwrap());
1275 assert_eq!(<$i_struct>::MAX / <$i_struct>::MIN, <$i_struct>::ZERO);
1276
1277 assert_eq!(<$i_struct>::MIN / <$i_struct>::ONE, <$i_struct>::MIN);
1278 assert_eq!(
1279 <$i_struct>::try_from(-42).unwrap() / <$i_struct>::try_from(-21).unwrap(),
1280 <$i_struct>::try_from(2).unwrap()
1281 );
1282 assert_eq!(
1283 <$i_struct>::try_from(-42).unwrap() / <$i_struct>::try_from(2).unwrap(),
1284 <$i_struct>::try_from(-21).unwrap()
1285 );
1286 assert_eq!(
1287 <$i_struct>::try_from(42).unwrap() / <$i_struct>::try_from(-21).unwrap(),
1288 <$i_struct>::try_from(-2).unwrap()
1289 );
1290 assert_eq!(
1291 <$i_struct>::try_from(42).unwrap() / <$i_struct>::try_from(21).unwrap(),
1292 <$i_struct>::try_from(2).unwrap()
1293 );
1294
1295 assert_eq!(
1297 <$i_struct>::MIN.saturating_div(<$i_struct>::try_from(-1).unwrap()),
1298 <$i_struct>::MAX
1299 );
1300 };
1301 }
1302
1303 let z = I0::default();
1304 let o = I1::default();
1305 let m = I1::MINUS_ONE;
1306 assert_eq!(z.checked_div(z), None);
1307 assert_eq!(o.checked_div(o), None);
1308 assert_eq!(m.checked_div(o), None);
1309 assert_eq!(m.overflowing_div(m), (m, true));
1310
1311 run_test!(I96, U96);
1312 run_test!(I128, U128);
1313 run_test!(I160, U160);
1314 run_test!(I192, U192);
1315 run_test!(I256, U256);
1316 }
1317
1318 #[test]
1319 #[cfg(feature = "std")]
1320 fn division_by_zero() {
1321 macro_rules! run_test {
1322 ($i_struct:ty, $u_struct:ty) => {
1323 let err = std::panic::catch_unwind(|| {
1324 let _ = <$i_struct>::ONE / <$i_struct>::ZERO;
1325 });
1326 assert!(err.is_err());
1327 };
1328 }
1329
1330 run_test!(I0, U0);
1331 run_test!(I1, U1);
1332 run_test!(I96, U96);
1333 run_test!(I128, U128);
1334 run_test!(I160, U160);
1335 run_test!(I192, U192);
1336 run_test!(I256, U256);
1337 }
1338
1339 #[test]
1340 fn div_euclid() {
1341 macro_rules! run_test {
1342 ($i_struct:ty, $u_struct:ty) => {
1343 let a = <$i_struct>::try_from(7).unwrap();
1344 let b = <$i_struct>::try_from(4).unwrap();
1345
1346 assert_eq!(a.div_euclid(b), <$i_struct>::ONE); assert_eq!(a.div_euclid(-b), <$i_struct>::MINUS_ONE); assert_eq!((-a).div_euclid(b), -<$i_struct>::try_from(2).unwrap()); assert_eq!((-a).div_euclid(-b), <$i_struct>::try_from(2).unwrap()); assert_eq!(
1353 <$i_struct>::MIN.overflowing_div_euclid(<$i_struct>::MINUS_ONE),
1354 (<$i_struct>::MIN, true)
1355 );
1356 assert_eq!(
1358 <$i_struct>::MIN.wrapping_div_euclid(<$i_struct>::MINUS_ONE),
1359 <$i_struct>::MIN
1360 );
1361 assert_eq!(<$i_struct>::MIN.checked_div_euclid(<$i_struct>::MINUS_ONE), None);
1363 assert_eq!(<$i_struct>::ONE.checked_div_euclid(<$i_struct>::ZERO), None);
1364 };
1365 }
1366
1367 let z = I0::default();
1368 let o = I1::default();
1369 let m = I1::MINUS_ONE;
1370 assert_eq!(z.checked_div_euclid(z), None);
1371 assert_eq!(o.checked_div_euclid(o), None);
1372 assert_eq!(m.checked_div_euclid(o), None);
1373 assert_eq!(m.overflowing_div_euclid(m), (m, true));
1374
1375 run_test!(I96, U96);
1376 run_test!(I128, U128);
1377 run_test!(I160, U160);
1378 run_test!(I192, U192);
1379 run_test!(I256, U256);
1380 }
1381
1382 #[test]
1383 fn rem_euclid() {
1384 macro_rules! run_test {
1385 ($i_struct:ty, $u_struct:ty) => {
1386 let a = <$i_struct>::try_from(7).unwrap(); let b = <$i_struct>::try_from(4).unwrap();
1388
1389 assert_eq!(a.rem_euclid(b), <$i_struct>::try_from(3).unwrap());
1390 assert_eq!((-a).rem_euclid(b), <$i_struct>::ONE);
1391 assert_eq!(a.rem_euclid(-b), <$i_struct>::try_from(3).unwrap());
1392 assert_eq!((-a).rem_euclid(-b), <$i_struct>::ONE);
1393
1394 assert_eq!(a.overflowing_rem_euclid(b), (<$i_struct>::try_from(3).unwrap(), false));
1396 assert_eq!(
1397 <$i_struct>::MIN.overflowing_rem_euclid(<$i_struct>::MINUS_ONE),
1398 (<$i_struct>::ZERO, true)
1399 );
1400
1401 assert_eq!(
1403 <$i_struct>::try_from(100)
1404 .unwrap()
1405 .wrapping_rem_euclid(<$i_struct>::try_from(10).unwrap()),
1406 <$i_struct>::ZERO
1407 );
1408 assert_eq!(
1409 <$i_struct>::MIN.wrapping_rem_euclid(<$i_struct>::MINUS_ONE),
1410 <$i_struct>::ZERO
1411 );
1412
1413 assert_eq!(a.checked_rem_euclid(b), Some(<$i_struct>::try_from(3).unwrap()));
1415 assert_eq!(a.checked_rem_euclid(<$i_struct>::ZERO), None);
1416 assert_eq!(<$i_struct>::MIN.checked_rem_euclid(<$i_struct>::MINUS_ONE), None);
1417 };
1418 }
1419
1420 let z = I0::default();
1421 let o = I1::default();
1422 let m = I1::MINUS_ONE;
1423 assert_eq!(z.checked_rem_euclid(z), None);
1424 assert_eq!(o.checked_rem_euclid(o), None);
1425 assert_eq!(m.checked_rem_euclid(o), None);
1426 assert_eq!(m.overflowing_rem_euclid(m), (o, true));
1427
1428 run_test!(I96, U96);
1429 run_test!(I128, U128);
1430 run_test!(I160, U160);
1431 run_test!(I192, U192);
1432 run_test!(I256, U256);
1433 }
1434
1435 #[test]
1436 #[cfg(feature = "std")]
1437 fn div_euclid_by_zero() {
1438 macro_rules! run_test {
1439 ($i_struct:ty, $u_struct:ty) => {
1440 let err = std::panic::catch_unwind(|| {
1441 let _ = <$i_struct>::ONE.div_euclid(<$i_struct>::ZERO);
1442 });
1443 assert!(err.is_err());
1444
1445 let err = std::panic::catch_unwind(|| {
1446 assert_eq!(
1447 <$i_struct>::MIN.div_euclid(<$i_struct>::MINUS_ONE),
1448 <$i_struct>::MAX
1449 );
1450 });
1451 assert!(err.is_err());
1452 };
1453 }
1454
1455 run_test!(I0, U0);
1456 run_test!(I1, U1);
1457
1458 run_test!(I96, U96);
1459 run_test!(I128, U128);
1460 run_test!(I160, U160);
1461 run_test!(I192, U192);
1462 run_test!(I256, U256);
1463 }
1464
1465 #[test]
1466 #[cfg(feature = "std")]
1467 fn div_euclid_overflow() {
1468 macro_rules! run_test {
1469 ($i_struct:ty, $u_struct:ty) => {
1470 let err = std::panic::catch_unwind(|| {
1471 let _ = <$i_struct>::MIN.div_euclid(<$i_struct>::MINUS_ONE);
1472 });
1473 assert!(err.is_err());
1474 };
1475 }
1476 run_test!(I96, U96);
1477 run_test!(I128, U128);
1478 run_test!(I160, U160);
1479 run_test!(I192, U192);
1480 run_test!(I256, U256);
1481 }
1482
1483 #[test]
1484 #[cfg(feature = "std")]
1485 fn mod_by_zero() {
1486 macro_rules! run_test {
1487 ($i_struct:ty, $u_struct:ty) => {
1488 let err = std::panic::catch_unwind(|| {
1489 let _ = <$i_struct>::ONE % <$i_struct>::ZERO;
1490 });
1491 assert!(err.is_err());
1492 };
1493 }
1494
1495 run_test!(I0, U0);
1496 run_test!(I1, U1);
1497
1498 run_test!(I96, U96);
1499 run_test!(I128, U128);
1500 run_test!(I160, U160);
1501 run_test!(I192, U192);
1502 run_test!(I256, U256);
1503 }
1504
1505 #[test]
1506 fn remainder() {
1507 macro_rules! run_test {
1508 ($i_struct:ty, $u_struct:ty) => {
1509 assert_eq!(
1511 <$i_struct>::MIN.overflowing_rem(<$i_struct>::try_from(-1).unwrap()),
1512 (<$i_struct>::ZERO, true)
1513 );
1514 assert_eq!(
1515 <$i_struct>::try_from(-5).unwrap() % <$i_struct>::try_from(-2).unwrap(),
1516 <$i_struct>::try_from(-1).unwrap()
1517 );
1518 assert_eq!(
1519 <$i_struct>::try_from(5).unwrap() % <$i_struct>::try_from(-2).unwrap(),
1520 <$i_struct>::ONE
1521 );
1522 assert_eq!(
1523 <$i_struct>::try_from(-5).unwrap() % <$i_struct>::try_from(2).unwrap(),
1524 <$i_struct>::try_from(-1).unwrap()
1525 );
1526 assert_eq!(
1527 <$i_struct>::try_from(5).unwrap() % <$i_struct>::try_from(2).unwrap(),
1528 <$i_struct>::ONE
1529 );
1530
1531 assert_eq!(<$i_struct>::MIN.checked_rem(<$i_struct>::try_from(-1).unwrap()), None);
1532 assert_eq!(<$i_struct>::ONE.checked_rem(<$i_struct>::ONE), Some(<$i_struct>::ZERO));
1533 };
1534 }
1535
1536 let z = I0::default();
1537 let o = I1::default();
1538 let m = I1::MINUS_ONE;
1539 assert_eq!(z.checked_rem(z), None);
1540 assert_eq!(o.checked_rem(o), None);
1541 assert_eq!(m.checked_rem(o), None);
1542 assert_eq!(m.overflowing_rem(m), (o, true));
1543
1544 run_test!(I96, U96);
1545 run_test!(I128, U128);
1546 run_test!(I160, U160);
1547 run_test!(I192, U192);
1548 run_test!(I256, U256);
1549 }
1550
1551 #[test]
1552 fn exponentiation() {
1553 macro_rules! run_test {
1554 ($i_struct:ty, $u_struct:ty) => {
1555 assert_eq!(
1556 <$i_struct>::unchecked_from(1000).saturating_pow(<$u_struct>::from(1000)),
1557 <$i_struct>::MAX
1558 );
1559 assert_eq!(
1560 <$i_struct>::unchecked_from(-1000).saturating_pow(<$u_struct>::from(1001)),
1561 <$i_struct>::MIN
1562 );
1563
1564 assert_eq!(
1565 <$i_struct>::unchecked_from(2).pow(<$u_struct>::from(64)),
1566 <$i_struct>::unchecked_from(1u128 << 64)
1567 );
1568 assert_eq!(
1569 <$i_struct>::unchecked_from(-2).pow(<$u_struct>::from(63)),
1570 <$i_struct>::unchecked_from(i64::MIN)
1571 );
1572
1573 assert_eq!(<$i_struct>::ZERO.pow(<$u_struct>::from(42)), <$i_struct>::ZERO);
1574 assert_eq!(<$i_struct>::exp10(18).to_string(), "1000000000000000000");
1575 };
1576 }
1577
1578 let z = I0::default();
1579 let o = I1::default();
1580 let m = I1::MINUS_ONE;
1581 assert_eq!(z.pow(U0::default()), z);
1582 assert_eq!(o.overflowing_pow(U1::default()), (m, true));
1583 assert_eq!(o.overflowing_pow(U1::from(1u8)), (o, false));
1584 assert_eq!(m.overflowing_pow(U1::from(1u8)), (m, false));
1585 assert_eq!(m.overflowing_pow(U1::default()), (m, true));
1586
1587 run_test!(I96, U96);
1588 run_test!(I128, U128);
1589 run_test!(I160, U160);
1590 run_test!(I192, U192);
1591 run_test!(I256, U256);
1592 }
1593
1594 #[test]
1595 fn iterators() {
1596 macro_rules! run_test {
1597 ($i_struct:ty, $u_struct:ty) => {
1598 assert_eq!(
1599 (1..=5).map(<$i_struct>::try_from).map(Result::unwrap).sum::<$i_struct>(),
1600 <$i_struct>::try_from(15).unwrap()
1601 );
1602 assert_eq!(
1603 (1..=5).map(<$i_struct>::try_from).map(Result::unwrap).product::<$i_struct>(),
1604 <$i_struct>::try_from(120).unwrap()
1605 );
1606 };
1607 }
1608
1609 let z = I0::default();
1610 let o = I1::default();
1611 let m = I1::MINUS_ONE;
1612 assert_eq!([z; 0].into_iter().sum::<I0>(), z);
1613 assert_eq!([o; 1].into_iter().sum::<I1>(), o);
1614 assert_eq!([m; 1].into_iter().sum::<I1>(), m);
1615
1616 run_test!(I96, U96);
1617 run_test!(I128, U128);
1618 run_test!(I160, U160);
1619 run_test!(I192, U192);
1620 run_test!(I256, U256);
1621 }
1622
1623 #[test]
1624 fn twos_complement() {
1625 macro_rules! assert_twos_complement {
1626 ($i_struct:ty, $u_struct:ty, $signed:ty, $unsigned:ty) => {
1627 if <$u_struct>::BITS as u32 >= <$unsigned>::BITS {
1628 assert_eq!(
1629 <$i_struct>::try_from(<$signed>::MAX).unwrap().twos_complement(),
1630 <$u_struct>::try_from(<$signed>::MAX).unwrap()
1631 );
1632 assert_eq!(
1633 <$i_struct>::try_from(<$signed>::MIN).unwrap().twos_complement(),
1634 <$u_struct>::try_from(<$signed>::MIN.unsigned_abs()).unwrap()
1635 );
1636 }
1637
1638 assert_eq!(
1639 <$i_struct>::try_from(0 as $signed).unwrap().twos_complement(),
1640 <$u_struct>::try_from(0 as $signed).unwrap()
1641 );
1642
1643 assert_eq!(
1644 <$i_struct>::try_from(0 as $unsigned).unwrap().twos_complement(),
1645 <$u_struct>::try_from(0 as $unsigned).unwrap()
1646 );
1647 };
1648 }
1649 macro_rules! run_test {
1650 ($i_struct:ty, $u_struct:ty) => {
1651 assert_twos_complement!($i_struct, $u_struct, i8, u8);
1652 assert_twos_complement!($i_struct, $u_struct, i16, u16);
1653 assert_twos_complement!($i_struct, $u_struct, i32, u32);
1654 assert_twos_complement!($i_struct, $u_struct, i64, u64);
1655 assert_twos_complement!($i_struct, $u_struct, i128, u128);
1656 assert_twos_complement!($i_struct, $u_struct, isize, usize);
1657 };
1658 }
1659
1660 let z = I0::default();
1661 let o = I1::default();
1662 let m = I1::MINUS_ONE;
1663 assert_eq!(z.twos_complement(), U0::default());
1664 assert_eq!(o.twos_complement(), U1::default());
1665 assert_eq!(m.twos_complement(), U1::from(1));
1666
1667 run_test!(I96, U96);
1668 run_test!(I128, U128);
1669 run_test!(I160, U160);
1670 run_test!(I192, U192);
1671 run_test!(I256, U256);
1672 }
1673
1674 #[test]
1675 fn test_overflowing_from_sign_and_abs() {
1676 let a = Uint::<8, 1>::ZERO;
1677 let (_, overflow) = Signed::overflowing_from_sign_and_abs(Sign::Negative, a);
1678 assert!(!overflow);
1679
1680 let a = Uint::<8, 1>::from(128u8);
1681 let (_, overflow) = Signed::overflowing_from_sign_and_abs(Sign::Negative, a);
1682 assert!(!overflow);
1683
1684 let a = Uint::<8, 1>::from(129u8);
1685 let (_, overflow) = Signed::overflowing_from_sign_and_abs(Sign::Negative, a);
1686 assert!(overflow);
1687 }
1688
1689 #[test]
1690 fn test_int_conversion() {
1691 let m_i256 = I256::unchecked_from(-4);
1693 let m_i24 = I24::from(m_i256);
1694 assert_eq!(m_i24, I24::from_dec_str("-4").unwrap());
1695 let m_i56 = I56::from(m_i24);
1696 assert_eq!(m_i56, I56::from_dec_str("-4").unwrap());
1697 let m_i128 = I128::from(m_i56);
1698 assert_eq!(m_i128, I128::from_dec_str("-4").unwrap());
1699 let m_i96 = I96::from(m_i128);
1700 assert_eq!(m_i96, I96::from_dec_str("-4").unwrap());
1701
1702 assert_eq!(U24::from(I24::from_hex_str("0x7FFFFF").unwrap()), U24::from(0x7FFFFF));
1704
1705 assert_eq!(I24::from(U24::from(0x7FFFFF)), I24::from_hex_str("0x7FFFFF").unwrap());
1707 assert_eq!(I24::from(U96::from(0x7FFFFF)), I24::from_hex_str("0x7FFFFF").unwrap());
1708
1709 assert!(U24::uint_try_from(m_i24).is_err());
1711
1712 assert!(I24::uint_try_from(U24::from(0x800000)).is_err());
1714
1715 assert!(I24::uint_try_from(I128::MIN).is_err());
1717 assert!(I24::uint_try_from(I128::MAX).is_err());
1718 }
1719}