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