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(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 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!(err, ParseSignedError::Ruint(ParseError::InvalidDigit('i')));
657
658 let err = <$i_struct>::from_dec_str(&format!("1{}", <$u_struct>::MAX)).unwrap_err();
659 assert_eq!(err, ParseSignedError::IntegerOverflow);
660
661 let err = <$i_struct>::from_dec_str(&format!("-{}", <$u_struct>::MAX)).unwrap_err();
662 assert_eq!(err, ParseSignedError::IntegerOverflow);
663
664 let value = <$i_struct>::from_dec_str(&format!("-{}", min_abs)).unwrap();
665 assert_eq!(value.into_sign_and_abs(), (Sign::Negative, min_abs));
666
667 let err = <$i_struct>::from_dec_str(&format!("{}", min_abs)).unwrap_err();
668 assert_eq!(err, ParseSignedError::IntegerOverflow);
669 };
670 }
671
672 assert_eq!(I0::from_dec_str("0"), Ok(I0::default()));
673 assert_eq!(I1::from_dec_str("0"), Ok(I1::ZERO));
674 assert_eq!(I1::from_dec_str("-1"), Ok(I1::MINUS_ONE));
675 assert_eq!(I1::from_dec_str("1"), Err(ParseSignedError::IntegerOverflow));
676
677 run_test!(I96, U96);
678 run_test!(I128, U128);
679 run_test!(I160, U160);
680 run_test!(I192, U192);
681 run_test!(I256, U256);
682 }
683
684 #[test]
685 fn from_hex_str() {
686 macro_rules! run_test {
687 ($i_struct:ty, $u_struct:ty) => {
688 let min_abs = <$i_struct>::MIN.0;
689 let unsigned = <$u_struct>::from_str_radix("3141592653589793", 10).unwrap();
690
691 let value = <$i_struct>::from_hex_str(&format!("-{unsigned:x}")).unwrap();
692 assert_eq!(value.into_sign_and_abs(), (Sign::Negative, unsigned));
693
694 let value = <$i_struct>::from_hex_str(&format!("-0x{unsigned:x}")).unwrap();
695 assert_eq!(value.into_sign_and_abs(), (Sign::Negative, unsigned));
696
697 let value = <$i_struct>::from_hex_str(&format!("{unsigned:x}")).unwrap();
698 assert_eq!(value.into_sign_and_abs(), (Sign::Positive, unsigned));
699
700 let value = <$i_struct>::from_hex_str(&format!("0x{unsigned:x}")).unwrap();
701 assert_eq!(value.into_sign_and_abs(), (Sign::Positive, unsigned));
702
703 let value = <$i_struct>::from_hex_str(&format!("+0x{unsigned:x}")).unwrap();
704 assert_eq!(value.into_sign_and_abs(), (Sign::Positive, unsigned));
705
706 let err = <$i_struct>::from_hex_str("invalid string").unwrap_err();
707 assert!(matches!(err, ParseSignedError::Ruint(_)));
708
709 let err =
710 <$i_struct>::from_hex_str(&format!("1{:x}", <$u_struct>::MAX)).unwrap_err();
711 assert!(matches!(err, ParseSignedError::IntegerOverflow));
712
713 let err =
714 <$i_struct>::from_hex_str(&format!("-{:x}", <$u_struct>::MAX)).unwrap_err();
715 assert!(matches!(err, ParseSignedError::IntegerOverflow));
716
717 let value = <$i_struct>::from_hex_str(&format!("-{:x}", min_abs)).unwrap();
718 assert_eq!(value.into_sign_and_abs(), (Sign::Negative, min_abs));
719
720 let err = <$i_struct>::from_hex_str(&format!("{:x}", min_abs)).unwrap_err();
721 assert!(matches!(err, ParseSignedError::IntegerOverflow));
722 };
723 }
724
725 assert_eq!(I0::from_hex_str("0x0"), Ok(I0::default()));
726 assert_eq!(I1::from_hex_str("0x0"), Ok(I1::ZERO));
727 assert_eq!(I1::from_hex_str("0x0"), Ok(I1::ZERO));
728 assert_eq!(I1::from_hex_str("-0x1"), Ok(I1::MINUS_ONE));
729 assert_eq!(I1::from_hex_str("0x1"), Err(ParseSignedError::IntegerOverflow));
730
731 run_test!(I96, U96);
732 run_test!(I128, U128);
733 run_test!(I160, U160);
734 run_test!(I192, U192);
735 run_test!(I256, U256);
736 }
737
738 #[test]
739 fn parse() {
740 assert_eq!("0x0".parse::<I0>(), Ok(I0::default()));
741 assert_eq!("+0x0".parse::<I0>(), Ok(I0::default()));
742 assert_eq!("0x0".parse::<I1>(), Ok(I1::ZERO));
743 assert_eq!("+0x0".parse::<I1>(), Ok(I1::ZERO));
744 assert_eq!("-0x1".parse::<I1>(), Ok(I1::MINUS_ONE));
745 assert_eq!("0x1".parse::<I1>(), Err(ParseSignedError::IntegerOverflow));
746
747 assert_eq!("0".parse::<I0>(), Ok(I0::default()));
748 assert_eq!("+0".parse::<I0>(), Ok(I0::default()));
749 assert_eq!("0".parse::<I1>(), Ok(I1::ZERO));
750 assert_eq!("+0".parse::<I1>(), Ok(I1::ZERO));
751 assert_eq!("-1".parse::<I1>(), Ok(I1::MINUS_ONE));
752 assert_eq!("1".parse::<I1>(), Err(ParseSignedError::IntegerOverflow));
753 }
754
755 #[test]
756 fn formatting() {
757 macro_rules! run_test {
758 ($i_struct:ty, $u_struct:ty) => {
759 let unsigned = <$u_struct>::from_str_radix("3141592653589793", 10).unwrap();
760 let unsigned_negative = -unsigned;
761 let positive = <$i_struct>::try_from(unsigned).unwrap();
762 let negative = -positive;
763
764 assert_eq!(format!("{positive}"), format!("{unsigned}"));
765 assert_eq!(format!("{negative}"), format!("-{unsigned}"));
766 assert_eq!(format!("{positive:+}"), format!("+{unsigned}"));
767 assert_eq!(format!("{negative:+}"), format!("-{unsigned}"));
768
769 assert_eq!(format!("{positive:x}"), format!("{unsigned:x}"));
770 assert_eq!(format!("{negative:x}"), format!("{unsigned_negative:x}"));
771 assert_eq!(format!("{positive:+x}"), format!("+{unsigned:x}"));
772 assert_eq!(format!("{negative:+x}"), format!("+{unsigned_negative:x}"));
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 }
780
781 let z = I0::default();
782 let o = I1::default();
783 let m = I1::MINUS_ONE;
784 assert_eq!(format!("{z} {o} {m}"), "0 0 -1");
785
786 run_test!(I96, U96);
787 run_test!(I128, U128);
788 run_test!(I160, U160);
789 run_test!(I192, U192);
790 run_test!(I256, U256);
791 }
792
793 #[test]
794 fn signs() {
795 macro_rules! run_test {
796 ($i_struct:ty, $u_struct:ty) => {
797 assert_eq!(<$i_struct>::MAX.sign(), Sign::Positive);
798 assert!(<$i_struct>::MAX.is_positive());
799 assert!(!<$i_struct>::MAX.is_negative());
800 assert!(!<$i_struct>::MAX.is_zero());
801
802 assert_eq!(<$i_struct>::ONE.sign(), Sign::Positive);
803 assert!(<$i_struct>::ONE.is_positive());
804 assert!(!<$i_struct>::ONE.is_negative());
805 assert!(!<$i_struct>::ONE.is_zero());
806
807 assert_eq!(<$i_struct>::MIN.sign(), Sign::Negative);
808 assert!(!<$i_struct>::MIN.is_positive());
809 assert!(<$i_struct>::MIN.is_negative());
810 assert!(!<$i_struct>::MIN.is_zero());
811
812 assert_eq!(<$i_struct>::MINUS_ONE.sign(), Sign::Negative);
813 assert!(!<$i_struct>::MINUS_ONE.is_positive());
814 assert!(<$i_struct>::MINUS_ONE.is_negative());
815 assert!(!<$i_struct>::MINUS_ONE.is_zero());
816
817 assert_eq!(<$i_struct>::ZERO.sign(), Sign::Positive);
818 assert!(!<$i_struct>::ZERO.is_positive());
819 assert!(!<$i_struct>::ZERO.is_negative());
820 assert!(<$i_struct>::ZERO.is_zero());
821 };
822 }
823
824 let z = I0::default();
825 let o = I1::default();
826 let m = I1::MINUS_ONE;
827 assert_eq!(z.sign(), Sign::Positive);
828 assert_eq!(o.sign(), Sign::Positive);
829 assert_eq!(m.sign(), Sign::Negative);
830
831 run_test!(I96, U96);
832 run_test!(I128, U128);
833 run_test!(I160, U160);
834 run_test!(I192, U192);
835 run_test!(I256, U256);
836 }
837
838 #[test]
839 fn abs() {
840 macro_rules! run_test {
841 ($i_struct:ty, $u_struct:ty) => {
842 let positive = <$i_struct>::from_dec_str("3141592653589793").unwrap();
843 let negative = <$i_struct>::from_dec_str("-27182818284590").unwrap();
844
845 assert_eq!(positive.sign(), Sign::Positive);
846 assert_eq!(positive.abs().sign(), Sign::Positive);
847 assert_eq!(positive, positive.abs());
848 assert_ne!(negative, negative.abs());
849 assert_eq!(negative.sign(), Sign::Negative);
850 assert_eq!(negative.abs().sign(), Sign::Positive);
851 assert_eq!(<$i_struct>::ZERO.abs(), <$i_struct>::ZERO);
852 assert_eq!(<$i_struct>::MAX.abs(), <$i_struct>::MAX);
853 assert_eq!((-<$i_struct>::MAX).abs(), <$i_struct>::MAX);
854 assert_eq!(<$i_struct>::MIN.checked_abs(), None);
855 };
856 }
857
858 let z = I0::default();
859 let o = I1::default();
860 let m = I1::MINUS_ONE;
861 assert_eq!(z.abs(), z);
862 assert_eq!(o.abs(), o);
863 assert_eq!(m.checked_abs(), None);
864
865 run_test!(I96, U96);
866 run_test!(I128, U128);
867 run_test!(I160, U160);
868 run_test!(I192, U192);
869 run_test!(I256, U256);
870 }
871
872 #[test]
873 fn neg() {
874 macro_rules! run_test {
875 ($i_struct:ty, $u_struct:ty) => {
876 let positive = <$i_struct>::from_dec_str("3141592653589793").unwrap().sign();
877 let negative = -positive;
878
879 assert_eq!(-positive, negative);
880 assert_eq!(-negative, positive);
881
882 assert_eq!(-<$i_struct>::ZERO, <$i_struct>::ZERO);
883 assert_eq!(-(-<$i_struct>::MAX), <$i_struct>::MAX);
884 assert_eq!(<$i_struct>::MIN.checked_neg(), None);
885 };
886 }
887
888 let z = I0::default();
889 let o = I1::default();
890 let m = I1::MINUS_ONE;
891 assert_eq!(-z, z);
892 assert_eq!(-o, o);
893 assert_eq!(m.checked_neg(), None);
894
895 run_test!(I96, U96);
896 run_test!(I128, U128);
897 run_test!(I160, U160);
898 run_test!(I192, U192);
899 run_test!(I256, U256);
900 }
901
902 #[test]
903 fn bits() {
904 macro_rules! run_test {
905 ($i_struct:ty, $u_struct:ty) => {
906 assert_eq!(<$i_struct>::try_from(0b1000).unwrap().bits(), 5);
907 assert_eq!(<$i_struct>::try_from(-0b1000).unwrap().bits(), 4);
908
909 assert_eq!(<$i_struct>::try_from(i64::MAX).unwrap().bits(), 64);
910 assert_eq!(<$i_struct>::try_from(i64::MIN).unwrap().bits(), 64);
911
912 assert_eq!(<$i_struct>::MAX.bits(), <$i_struct>::BITS as u32);
913 assert_eq!(<$i_struct>::MIN.bits(), <$i_struct>::BITS as u32);
914
915 assert_eq!(<$i_struct>::ZERO.bits(), 0);
916 };
917 }
918
919 let z = I0::default();
920 let o = I1::default();
921 let m = I1::MINUS_ONE;
922 assert_eq!(z.bits(), 0);
923 assert_eq!(o.bits(), 0);
924 assert_eq!(m.bits(), 1);
925
926 run_test!(I96, U96);
927 run_test!(I128, U128);
928 run_test!(I160, U160);
929 run_test!(I192, U192);
930 run_test!(I256, U256);
931 }
932
933 #[test]
934 fn bit_shift() {
935 macro_rules! run_test {
936 ($i_struct:ty, $u_struct:ty) => {
937 assert_eq!(<$i_struct>::ONE << <$i_struct>::BITS - 1, <$i_struct>::MIN);
938 assert_eq!(<$i_struct>::MIN >> <$i_struct>::BITS - 1, <$i_struct>::ONE);
939 };
940 }
941
942 let z = I0::default();
943 let o = I1::default();
944 let m = I1::MINUS_ONE;
945 assert_eq!(z << 1, z >> 1);
946 assert_eq!(o << 1, o >> 0);
947 assert_eq!(m << 1, o);
948 assert_eq!(m >> 1, o);
949
950 run_test!(I96, U96);
951 run_test!(I128, U128);
952 run_test!(I160, U160);
953 run_test!(I192, U192);
954 run_test!(I256, U256);
955 }
956
957 #[test]
958 fn arithmetic_shift_right() {
959 macro_rules! run_test {
960 ($i_struct:ty, $u_struct:ty) => {
961 let exp = <$i_struct>::BITS - 2;
962 let shift = <$i_struct>::BITS - 3;
963
964 let value =
965 <$i_struct>::from_raw(<$u_struct>::from(2u8).pow(<$u_struct>::from(exp))).neg();
966
967 let expected_result =
968 <$i_struct>::from_raw(<$u_struct>::MAX - <$u_struct>::from(1u8));
969 assert_eq!(
970 value.asr(shift),
971 expected_result,
972 "1011...1111 >> 253 was not 1111...1110"
973 );
974
975 let value = <$i_struct>::MINUS_ONE;
976 let expected_result = <$i_struct>::MINUS_ONE;
977 assert_eq!(value.asr(250), expected_result, "-1 >> any_amount was not -1");
978
979 let value = <$i_struct>::from_raw(
980 <$u_struct>::from(2u8).pow(<$u_struct>::from(<$i_struct>::BITS - 2)),
981 )
982 .neg();
983 let expected_result = <$i_struct>::MINUS_ONE;
984 assert_eq!(
985 value.asr(<$i_struct>::BITS - 1),
986 expected_result,
987 "1011...1111 >> 255 was not -1"
988 );
989
990 let value = <$i_struct>::from_raw(
991 <$u_struct>::from(2u8).pow(<$u_struct>::from(<$i_struct>::BITS - 2)),
992 )
993 .neg();
994 let expected_result = <$i_struct>::MINUS_ONE;
995 assert_eq!(value.asr(1024), expected_result, "1011...1111 >> 1024 was not -1");
996
997 let value = <$i_struct>::try_from(1024i32).unwrap();
998 let expected_result = <$i_struct>::try_from(32i32).unwrap();
999 assert_eq!(value.asr(5), expected_result, "1024 >> 5 was not 32");
1000
1001 let value = <$i_struct>::MAX;
1002 let expected_result = <$i_struct>::ZERO;
1003 assert_eq!(value.asr(255), expected_result, "<$i_struct>::MAX >> 255 was not 0");
1004
1005 let value =
1006 <$i_struct>::from_raw(<$u_struct>::from(2u8).pow(<$u_struct>::from(exp))).neg();
1007 let expected_result = value;
1008 assert_eq!(value.asr(0), expected_result, "1011...1111 >> 0 was not 1011...111");
1009 };
1010 }
1011
1012 let z = I0::default();
1013 let o = I1::default();
1014 let m = I1::MINUS_ONE;
1015 assert_eq!(z.asr(1), z);
1016 assert_eq!(o.asr(1), o);
1017 assert_eq!(m.asr(1), m);
1018 assert_eq!(m.asr(1000), m);
1019
1020 run_test!(I96, U96);
1021 run_test!(I128, U128);
1022 run_test!(I160, U160);
1023 run_test!(I192, U192);
1024 run_test!(I256, U256);
1025 }
1026
1027 #[test]
1028 fn arithmetic_shift_left() {
1029 macro_rules! run_test {
1030 ($i_struct:ty, $u_struct:ty) => {
1031 let value = <$i_struct>::MINUS_ONE;
1032 let expected_result = Some(value);
1033 assert_eq!(value.asl(0), expected_result, "-1 << 0 was not -1");
1034
1035 let value = <$i_struct>::MINUS_ONE;
1036 let expected_result = None;
1037 assert_eq!(
1038 value.asl(256),
1039 expected_result,
1040 "-1 << 256 did not overflow (result should be 0000...0000)"
1041 );
1042
1043 let value = <$i_struct>::MINUS_ONE;
1044 let expected_result = Some(<$i_struct>::from_raw(
1045 <$u_struct>::from(2u8).pow(<$u_struct>::from(<$i_struct>::BITS - 1)),
1046 ));
1047 assert_eq!(
1048 value.asl(<$i_struct>::BITS - 1),
1049 expected_result,
1050 "-1 << 255 was not 1000...0000"
1051 );
1052
1053 let value = <$i_struct>::try_from(-1024i32).unwrap();
1054 let expected_result = Some(<$i_struct>::try_from(-32768i32).unwrap());
1055 assert_eq!(value.asl(5), expected_result, "-1024 << 5 was not -32768");
1056
1057 let value = <$i_struct>::try_from(1024i32).unwrap();
1058 let expected_result = Some(<$i_struct>::try_from(32768i32).unwrap());
1059 assert_eq!(value.asl(5), expected_result, "1024 << 5 was not 32768");
1060
1061 let value = <$i_struct>::try_from(1024i32).unwrap();
1062 let expected_result = None;
1063 assert_eq!(
1064 value.asl(<$i_struct>::BITS - 11),
1065 expected_result,
1066 "1024 << 245 did not overflow (result should be 1000...0000)"
1067 );
1068
1069 let value = <$i_struct>::ZERO;
1070 let expected_result = Some(value);
1071 assert_eq!(value.asl(1024), expected_result, "0 << anything was not 0");
1072 };
1073 }
1074
1075 let z = I0::default();
1076 let o = I1::default();
1077 let m = I1::MINUS_ONE;
1078 assert_eq!(z.asl(1), Some(z));
1079 assert_eq!(o.asl(1), Some(o));
1080 assert_eq!(m.asl(1), None);
1081
1082 run_test!(I96, U96);
1083 run_test!(I128, U128);
1084 run_test!(I160, U160);
1085 run_test!(I192, U192);
1086 run_test!(I256, U256);
1087 }
1088
1089 #[test]
1090 fn addition() {
1091 macro_rules! run_test {
1092 ($i_struct:ty, $u_struct:ty) => {
1093 assert_eq!(
1094 <$i_struct>::MIN.overflowing_add(<$i_struct>::MIN),
1095 (<$i_struct>::ZERO, true)
1096 );
1097 assert_eq!(
1098 <$i_struct>::MAX.overflowing_add(<$i_struct>::MAX),
1099 (<$i_struct>::try_from(-2).unwrap(), true)
1100 );
1101
1102 assert_eq!(
1103 <$i_struct>::MIN.overflowing_add(<$i_struct>::MINUS_ONE),
1104 (<$i_struct>::MAX, true)
1105 );
1106 assert_eq!(
1107 <$i_struct>::MAX.overflowing_add(<$i_struct>::ONE),
1108 (<$i_struct>::MIN, true)
1109 );
1110
1111 assert_eq!(<$i_struct>::MAX + <$i_struct>::MIN, <$i_struct>::MINUS_ONE);
1112 assert_eq!(
1113 <$i_struct>::try_from(2).unwrap() + <$i_struct>::try_from(40).unwrap(),
1114 <$i_struct>::try_from(42).unwrap()
1115 );
1116
1117 assert_eq!(<$i_struct>::ZERO + <$i_struct>::ZERO, <$i_struct>::ZERO);
1118
1119 assert_eq!(<$i_struct>::MAX.saturating_add(<$i_struct>::MAX), <$i_struct>::MAX);
1120 assert_eq!(
1121 <$i_struct>::MIN.saturating_add(<$i_struct>::MINUS_ONE),
1122 <$i_struct>::MIN
1123 );
1124 };
1125 }
1126
1127 let z = I0::default();
1128 let o = I1::default();
1129 let m = I1::MINUS_ONE;
1130 assert_eq!(z + z, z);
1131 assert_eq!(o + o, o);
1132 assert_eq!(m + o, m);
1133 assert_eq!(m.overflowing_add(m), (o, true));
1134
1135 run_test!(I96, U96);
1136 run_test!(I128, U128);
1137 run_test!(I160, U160);
1138 run_test!(I192, U192);
1139 run_test!(I256, U256);
1140 }
1141
1142 #[test]
1143 fn subtraction() {
1144 macro_rules! run_test {
1145 ($i_struct:ty, $u_struct:ty) => {
1146 assert_eq!(
1147 <$i_struct>::MIN.overflowing_sub(<$i_struct>::MAX),
1148 (<$i_struct>::ONE, true)
1149 );
1150 assert_eq!(
1151 <$i_struct>::MAX.overflowing_sub(<$i_struct>::MIN),
1152 (<$i_struct>::MINUS_ONE, true)
1153 );
1154
1155 assert_eq!(
1156 <$i_struct>::MIN.overflowing_sub(<$i_struct>::ONE),
1157 (<$i_struct>::MAX, true)
1158 );
1159 assert_eq!(
1160 <$i_struct>::MAX.overflowing_sub(<$i_struct>::MINUS_ONE),
1161 (<$i_struct>::MIN, true)
1162 );
1163
1164 assert_eq!(
1165 <$i_struct>::ZERO.overflowing_sub(<$i_struct>::MIN),
1166 (<$i_struct>::MIN, true)
1167 );
1168
1169 assert_eq!(<$i_struct>::MAX - <$i_struct>::MAX, <$i_struct>::ZERO);
1170 assert_eq!(
1171 <$i_struct>::try_from(2).unwrap() - <$i_struct>::try_from(44).unwrap(),
1172 <$i_struct>::try_from(-42).unwrap()
1173 );
1174
1175 assert_eq!(<$i_struct>::ZERO - <$i_struct>::ZERO, <$i_struct>::ZERO);
1176
1177 assert_eq!(<$i_struct>::MAX.saturating_sub(<$i_struct>::MIN), <$i_struct>::MAX);
1178 assert_eq!(<$i_struct>::MIN.saturating_sub(<$i_struct>::ONE), <$i_struct>::MIN);
1179 };
1180 }
1181
1182 let z = I0::default();
1183 let o = I1::default();
1184 let m = I1::MINUS_ONE;
1185 assert_eq!(z - z, z);
1186 assert_eq!(o - o, o);
1187 assert_eq!(m - o, m);
1188 assert_eq!(m - m, o);
1189 assert_eq!(o.overflowing_sub(m), (m, true));
1190
1191 run_test!(I96, U96);
1192 run_test!(I128, U128);
1193 run_test!(I160, U160);
1194 run_test!(I192, U192);
1195 run_test!(I256, U256);
1196 }
1197
1198 #[test]
1199 fn multiplication() {
1200 macro_rules! run_test {
1201 ($i_struct:ty, $u_struct:ty) => {
1202 assert_eq!(
1203 <$i_struct>::MIN.overflowing_mul(<$i_struct>::MAX),
1204 (<$i_struct>::MIN, true)
1205 );
1206 assert_eq!(
1207 <$i_struct>::MAX.overflowing_mul(<$i_struct>::MIN),
1208 (<$i_struct>::MIN, true)
1209 );
1210
1211 assert_eq!(<$i_struct>::MIN * <$i_struct>::ONE, <$i_struct>::MIN);
1212 assert_eq!(
1213 <$i_struct>::try_from(2).unwrap() * <$i_struct>::try_from(-21).unwrap(),
1214 <$i_struct>::try_from(-42).unwrap()
1215 );
1216
1217 assert_eq!(<$i_struct>::MAX.saturating_mul(<$i_struct>::MAX), <$i_struct>::MAX);
1218 assert_eq!(
1219 <$i_struct>::MAX.saturating_mul(<$i_struct>::try_from(2).unwrap()),
1220 <$i_struct>::MAX
1221 );
1222 assert_eq!(
1223 <$i_struct>::MIN.saturating_mul(<$i_struct>::try_from(-2).unwrap()),
1224 <$i_struct>::MAX
1225 );
1226
1227 assert_eq!(<$i_struct>::MIN.saturating_mul(<$i_struct>::MAX), <$i_struct>::MIN);
1228 assert_eq!(
1229 <$i_struct>::MIN.saturating_mul(<$i_struct>::try_from(2).unwrap()),
1230 <$i_struct>::MIN
1231 );
1232 assert_eq!(
1233 <$i_struct>::MAX.saturating_mul(<$i_struct>::try_from(-2).unwrap()),
1234 <$i_struct>::MIN
1235 );
1236
1237 assert_eq!(<$i_struct>::ZERO * <$i_struct>::ZERO, <$i_struct>::ZERO);
1238 assert_eq!(<$i_struct>::ONE * <$i_struct>::ZERO, <$i_struct>::ZERO);
1239 assert_eq!(<$i_struct>::MAX * <$i_struct>::ZERO, <$i_struct>::ZERO);
1240 assert_eq!(<$i_struct>::MIN * <$i_struct>::ZERO, <$i_struct>::ZERO);
1241 };
1242 }
1243
1244 let z = I0::default();
1245 let o = I1::default();
1246 let m = I1::MINUS_ONE;
1247 assert_eq!(z * z, z);
1248 assert_eq!(o * o, o);
1249 assert_eq!(m * o, o);
1250 assert_eq!(m.overflowing_mul(m), (m, true));
1251
1252 run_test!(I96, U96);
1253 run_test!(I128, U128);
1254 run_test!(I160, U160);
1255 run_test!(I192, U192);
1256 run_test!(I256, U256);
1257 }
1258
1259 #[test]
1260 fn division() {
1261 macro_rules! run_test {
1262 ($i_struct:ty, $u_struct:ty) => {
1263 assert_eq!(
1265 <$i_struct>::MIN.overflowing_div(<$i_struct>::try_from(-1).unwrap()),
1266 (<$i_struct>::MIN, true)
1267 );
1268
1269 assert_eq!(<$i_struct>::MIN / <$i_struct>::MAX, <$i_struct>::try_from(-1).unwrap());
1270 assert_eq!(<$i_struct>::MAX / <$i_struct>::MIN, <$i_struct>::ZERO);
1271
1272 assert_eq!(<$i_struct>::MIN / <$i_struct>::ONE, <$i_struct>::MIN);
1273 assert_eq!(
1274 <$i_struct>::try_from(-42).unwrap() / <$i_struct>::try_from(-21).unwrap(),
1275 <$i_struct>::try_from(2).unwrap()
1276 );
1277 assert_eq!(
1278 <$i_struct>::try_from(-42).unwrap() / <$i_struct>::try_from(2).unwrap(),
1279 <$i_struct>::try_from(-21).unwrap()
1280 );
1281 assert_eq!(
1282 <$i_struct>::try_from(42).unwrap() / <$i_struct>::try_from(-21).unwrap(),
1283 <$i_struct>::try_from(-2).unwrap()
1284 );
1285 assert_eq!(
1286 <$i_struct>::try_from(42).unwrap() / <$i_struct>::try_from(21).unwrap(),
1287 <$i_struct>::try_from(2).unwrap()
1288 );
1289
1290 assert_eq!(
1292 <$i_struct>::MIN.saturating_div(<$i_struct>::try_from(-1).unwrap()),
1293 <$i_struct>::MAX
1294 );
1295 };
1296 }
1297
1298 let z = I0::default();
1299 let o = I1::default();
1300 let m = I1::MINUS_ONE;
1301 assert_eq!(z.checked_div(z), None);
1302 assert_eq!(o.checked_div(o), None);
1303 assert_eq!(m.checked_div(o), None);
1304 assert_eq!(m.overflowing_div(m), (m, true));
1305
1306 run_test!(I96, U96);
1307 run_test!(I128, U128);
1308 run_test!(I160, U160);
1309 run_test!(I192, U192);
1310 run_test!(I256, U256);
1311 }
1312
1313 #[test]
1314 fn division_by_zero() {
1315 macro_rules! run_test {
1316 ($i_struct:ty, $u_struct:ty) => {
1317 assert_eq!(<$i_struct>::ONE.checked_div(<$i_struct>::ZERO), None);
1318 };
1319 }
1320
1321 run_test!(I0, U0);
1322 run_test!(I1, U1);
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 fn div_euclid() {
1332 macro_rules! run_test {
1333 ($i_struct:ty, $u_struct:ty) => {
1334 let a = <$i_struct>::try_from(7).unwrap();
1335 let b = <$i_struct>::try_from(4).unwrap();
1336
1337 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!(
1344 <$i_struct>::MIN.overflowing_div_euclid(<$i_struct>::MINUS_ONE),
1345 (<$i_struct>::MIN, true)
1346 );
1347 assert_eq!(
1349 <$i_struct>::MIN.wrapping_div_euclid(<$i_struct>::MINUS_ONE),
1350 <$i_struct>::MIN
1351 );
1352 assert_eq!(<$i_struct>::MIN.checked_div_euclid(<$i_struct>::MINUS_ONE), None);
1354 assert_eq!(<$i_struct>::ONE.checked_div_euclid(<$i_struct>::ZERO), None);
1355 };
1356 }
1357
1358 let z = I0::default();
1359 let o = I1::default();
1360 let m = I1::MINUS_ONE;
1361 assert_eq!(z.checked_div_euclid(z), None);
1362 assert_eq!(o.checked_div_euclid(o), None);
1363 assert_eq!(m.checked_div_euclid(o), None);
1364 assert_eq!(m.overflowing_div_euclid(m), (m, true));
1365
1366 run_test!(I96, U96);
1367 run_test!(I128, U128);
1368 run_test!(I160, U160);
1369 run_test!(I192, U192);
1370 run_test!(I256, U256);
1371 }
1372
1373 #[test]
1374 fn rem_euclid() {
1375 macro_rules! run_test {
1376 ($i_struct:ty, $u_struct:ty) => {
1377 let a = <$i_struct>::try_from(7).unwrap(); let b = <$i_struct>::try_from(4).unwrap();
1379
1380 assert_eq!(a.rem_euclid(b), <$i_struct>::try_from(3).unwrap());
1381 assert_eq!((-a).rem_euclid(b), <$i_struct>::ONE);
1382 assert_eq!(a.rem_euclid(-b), <$i_struct>::try_from(3).unwrap());
1383 assert_eq!((-a).rem_euclid(-b), <$i_struct>::ONE);
1384
1385 assert_eq!(a.overflowing_rem_euclid(b), (<$i_struct>::try_from(3).unwrap(), false));
1387 assert_eq!(
1388 <$i_struct>::MIN.overflowing_rem_euclid(<$i_struct>::MINUS_ONE),
1389 (<$i_struct>::ZERO, true)
1390 );
1391
1392 assert_eq!(
1394 <$i_struct>::try_from(100)
1395 .unwrap()
1396 .wrapping_rem_euclid(<$i_struct>::try_from(10).unwrap()),
1397 <$i_struct>::ZERO
1398 );
1399 assert_eq!(
1400 <$i_struct>::MIN.wrapping_rem_euclid(<$i_struct>::MINUS_ONE),
1401 <$i_struct>::ZERO
1402 );
1403
1404 assert_eq!(a.checked_rem_euclid(b), Some(<$i_struct>::try_from(3).unwrap()));
1406 assert_eq!(a.checked_rem_euclid(<$i_struct>::ZERO), None);
1407 assert_eq!(<$i_struct>::MIN.checked_rem_euclid(<$i_struct>::MINUS_ONE), None);
1408 };
1409 }
1410
1411 let z = I0::default();
1412 let o = I1::default();
1413 let m = I1::MINUS_ONE;
1414 assert_eq!(z.checked_rem_euclid(z), None);
1415 assert_eq!(o.checked_rem_euclid(o), None);
1416 assert_eq!(m.checked_rem_euclid(o), None);
1417 assert_eq!(m.overflowing_rem_euclid(m), (o, true));
1418
1419 run_test!(I96, U96);
1420 run_test!(I128, U128);
1421 run_test!(I160, U160);
1422 run_test!(I192, U192);
1423 run_test!(I256, U256);
1424 }
1425
1426 #[test]
1427 fn div_euclid_by_zero() {
1428 macro_rules! run_test {
1429 ($i_struct:ty, $u_struct:ty) => {
1430 assert_eq!(<$i_struct>::ONE.checked_div_euclid(<$i_struct>::ZERO), None);
1431 assert_eq!(<$i_struct>::MIN.checked_div_euclid(<$i_struct>::MINUS_ONE), None);
1432 };
1433 }
1434
1435 run_test!(I0, U0);
1436 run_test!(I1, U1);
1437
1438 run_test!(I96, U96);
1439 run_test!(I128, U128);
1440 run_test!(I160, U160);
1441 run_test!(I192, U192);
1442 run_test!(I256, U256);
1443 }
1444
1445 #[test]
1446 fn div_euclid_overflow() {
1447 macro_rules! run_test {
1448 ($i_struct:ty, $u_struct:ty) => {
1449 assert_eq!(<$i_struct>::MIN.checked_div_euclid(<$i_struct>::MINUS_ONE), None);
1450 };
1451 }
1452 run_test!(I96, U96);
1453 run_test!(I128, U128);
1454 run_test!(I160, U160);
1455 run_test!(I192, U192);
1456 run_test!(I256, U256);
1457 }
1458
1459 #[test]
1460 fn mod_by_zero() {
1461 macro_rules! run_test {
1462 ($i_struct:ty, $u_struct:ty) => {
1463 assert_eq!(<$i_struct>::ONE.checked_rem(<$i_struct>::ZERO), None);
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 fn remainder() {
1479 macro_rules! run_test {
1480 ($i_struct:ty, $u_struct:ty) => {
1481 assert_eq!(
1483 <$i_struct>::MIN.overflowing_rem(<$i_struct>::try_from(-1).unwrap()),
1484 (<$i_struct>::ZERO, true)
1485 );
1486 assert_eq!(
1487 <$i_struct>::try_from(-5).unwrap() % <$i_struct>::try_from(-2).unwrap(),
1488 <$i_struct>::try_from(-1).unwrap()
1489 );
1490 assert_eq!(
1491 <$i_struct>::try_from(5).unwrap() % <$i_struct>::try_from(-2).unwrap(),
1492 <$i_struct>::ONE
1493 );
1494 assert_eq!(
1495 <$i_struct>::try_from(-5).unwrap() % <$i_struct>::try_from(2).unwrap(),
1496 <$i_struct>::try_from(-1).unwrap()
1497 );
1498 assert_eq!(
1499 <$i_struct>::try_from(5).unwrap() % <$i_struct>::try_from(2).unwrap(),
1500 <$i_struct>::ONE
1501 );
1502
1503 assert_eq!(<$i_struct>::MIN.checked_rem(<$i_struct>::try_from(-1).unwrap()), None);
1504 assert_eq!(<$i_struct>::ONE.checked_rem(<$i_struct>::ONE), Some(<$i_struct>::ZERO));
1505 };
1506 }
1507
1508 let z = I0::default();
1509 let o = I1::default();
1510 let m = I1::MINUS_ONE;
1511 assert_eq!(z.checked_rem(z), None);
1512 assert_eq!(o.checked_rem(o), None);
1513 assert_eq!(m.checked_rem(o), None);
1514 assert_eq!(m.overflowing_rem(m), (o, true));
1515
1516 run_test!(I96, U96);
1517 run_test!(I128, U128);
1518 run_test!(I160, U160);
1519 run_test!(I192, U192);
1520 run_test!(I256, U256);
1521 }
1522
1523 #[test]
1524 fn exponentiation() {
1525 macro_rules! run_test {
1526 ($i_struct:ty, $u_struct:ty) => {
1527 assert_eq!(
1528 <$i_struct>::unchecked_from(1000).saturating_pow(<$u_struct>::from(1000)),
1529 <$i_struct>::MAX
1530 );
1531 assert_eq!(
1532 <$i_struct>::unchecked_from(-1000).saturating_pow(<$u_struct>::from(1001)),
1533 <$i_struct>::MIN
1534 );
1535
1536 assert_eq!(
1537 <$i_struct>::unchecked_from(2).pow(<$u_struct>::from(64)),
1538 <$i_struct>::unchecked_from(1u128 << 64)
1539 );
1540 assert_eq!(
1541 <$i_struct>::unchecked_from(-2).pow(<$u_struct>::from(63)),
1542 <$i_struct>::unchecked_from(i64::MIN)
1543 );
1544
1545 assert_eq!(<$i_struct>::ZERO.pow(<$u_struct>::from(42)), <$i_struct>::ZERO);
1546 assert_eq!(<$i_struct>::exp10(18).to_string(), "1000000000000000000");
1547 };
1548 }
1549
1550 let z = I0::default();
1551 let o = I1::default();
1552 let m = I1::MINUS_ONE;
1553 assert_eq!(z.pow(U0::default()), z);
1554 assert_eq!(o.overflowing_pow(U1::default()), (m, true));
1555 assert_eq!(o.overflowing_pow(U1::from(1u8)), (o, false));
1556 assert_eq!(m.overflowing_pow(U1::from(1u8)), (m, false));
1557 assert_eq!(m.overflowing_pow(U1::default()), (m, true));
1558
1559 run_test!(I96, U96);
1560 run_test!(I128, U128);
1561 run_test!(I160, U160);
1562 run_test!(I192, U192);
1563 run_test!(I256, U256);
1564 }
1565
1566 #[test]
1567 fn iterators() {
1568 macro_rules! run_test {
1569 ($i_struct:ty, $u_struct:ty) => {
1570 assert_eq!(
1571 (1..=5).map(<$i_struct>::try_from).map(Result::unwrap).sum::<$i_struct>(),
1572 <$i_struct>::try_from(15).unwrap()
1573 );
1574 assert_eq!(
1575 (1..=5).map(<$i_struct>::try_from).map(Result::unwrap).product::<$i_struct>(),
1576 <$i_struct>::try_from(120).unwrap()
1577 );
1578 };
1579 }
1580
1581 let z = I0::default();
1582 let o = I1::default();
1583 let m = I1::MINUS_ONE;
1584 assert_eq!([z; 0].into_iter().sum::<I0>(), z);
1585 assert_eq!([o; 1].into_iter().sum::<I1>(), o);
1586 assert_eq!([m; 1].into_iter().sum::<I1>(), m);
1587
1588 run_test!(I96, U96);
1589 run_test!(I128, U128);
1590 run_test!(I160, U160);
1591 run_test!(I192, U192);
1592 run_test!(I256, U256);
1593 }
1594
1595 #[test]
1596 fn twos_complement() {
1597 macro_rules! assert_twos_complement {
1598 ($i_struct:ty, $u_struct:ty, $signed:ty, $unsigned:ty) => {
1599 if <$u_struct>::BITS as u32 >= <$unsigned>::BITS {
1600 assert_eq!(
1601 <$i_struct>::try_from(<$signed>::MAX).unwrap().twos_complement(),
1602 <$u_struct>::try_from(<$signed>::MAX).unwrap()
1603 );
1604 assert_eq!(
1605 <$i_struct>::try_from(<$signed>::MIN).unwrap().twos_complement(),
1606 <$u_struct>::try_from(<$signed>::MIN.unsigned_abs()).unwrap()
1607 );
1608 }
1609
1610 assert_eq!(
1611 <$i_struct>::try_from(0 as $signed).unwrap().twos_complement(),
1612 <$u_struct>::try_from(0 as $signed).unwrap()
1613 );
1614
1615 assert_eq!(
1616 <$i_struct>::try_from(0 as $unsigned).unwrap().twos_complement(),
1617 <$u_struct>::try_from(0 as $unsigned).unwrap()
1618 );
1619 };
1620 }
1621 macro_rules! run_test {
1622 ($i_struct:ty, $u_struct:ty) => {
1623 assert_twos_complement!($i_struct, $u_struct, i8, u8);
1624 assert_twos_complement!($i_struct, $u_struct, i16, u16);
1625 assert_twos_complement!($i_struct, $u_struct, i32, u32);
1626 assert_twos_complement!($i_struct, $u_struct, i64, u64);
1627 assert_twos_complement!($i_struct, $u_struct, i128, u128);
1628 assert_twos_complement!($i_struct, $u_struct, isize, usize);
1629 };
1630 }
1631
1632 let z = I0::default();
1633 let o = I1::default();
1634 let m = I1::MINUS_ONE;
1635 assert_eq!(z.twos_complement(), U0::default());
1636 assert_eq!(o.twos_complement(), U1::default());
1637 assert_eq!(m.twos_complement(), U1::from(1));
1638
1639 run_test!(I96, U96);
1640 run_test!(I128, U128);
1641 run_test!(I160, U160);
1642 run_test!(I192, U192);
1643 run_test!(I256, U256);
1644 }
1645
1646 #[test]
1647 fn test_overflowing_from_sign_and_abs() {
1648 let a = Uint::<8, 1>::ZERO;
1649 let (_, overflow) = Signed::overflowing_from_sign_and_abs(Sign::Negative, a);
1650 assert!(!overflow);
1651
1652 let a = Uint::<8, 1>::from(128u8);
1653 let (_, overflow) = Signed::overflowing_from_sign_and_abs(Sign::Negative, a);
1654 assert!(!overflow);
1655
1656 let a = Uint::<8, 1>::from(129u8);
1657 let (_, overflow) = Signed::overflowing_from_sign_and_abs(Sign::Negative, a);
1658 assert!(overflow);
1659 }
1660
1661 #[test]
1662 fn test_int_conversion() {
1663 let m_i256 = I256::unchecked_from(-4);
1665 let m_i24 = I24::from(m_i256);
1666 assert_eq!(m_i24, I24::from_dec_str("-4").unwrap());
1667 assert_eq!(m_i24.to::<I256>(), m_i256);
1668 let m_i56 = I56::from(m_i24);
1669 assert_eq!(m_i56, I56::from_dec_str("-4").unwrap());
1670 assert_eq!(m_i56.to::<I24>(), m_i24);
1671 let m_i128 = I128::from(m_i56);
1672 assert_eq!(m_i128, I128::from_dec_str("-4").unwrap());
1673 assert_eq!(m_i128.to::<I56>(), m_i56);
1674 let m_i96 = I96::from(m_i128);
1675 assert_eq!(m_i96, I96::from_dec_str("-4").unwrap());
1676 assert_eq!(m_i96.to::<I128>(), m_i128);
1677
1678 assert_eq!(U24::from(I24::from_hex_str("0x7FFFFF").unwrap()), U24::from(0x7FFFFF));
1680 assert_eq!(I24::from_hex_str("0x7FFFFF").unwrap().to::<U24>(), U24::from(0x7FFFFF));
1681
1682 assert_eq!(I24::from(U24::from(0x7FFFFF)), I24::from_hex_str("0x7FFFFF").unwrap());
1684 assert_eq!(U24::from(0x7FFFFF).to::<I24>(), I24::from_hex_str("0x7FFFFF").unwrap());
1685 assert_eq!(I24::from(U96::from(0x7FFFFF)), I24::from_hex_str("0x7FFFFF").unwrap());
1686 assert_eq!(U96::from(0x7FFFFF).to::<I24>(), I24::from_hex_str("0x7FFFFF").unwrap());
1687
1688 assert!(U24::uint_try_from(m_i24).is_err());
1690 assert!(<I24 as UintTryTo<U24>>::uint_try_to(&m_i24).is_err());
1691
1692 assert!(I24::uint_try_from(U24::from(0x800000)).is_err());
1694 assert!(<U24 as UintTryTo<I24>>::uint_try_to(&U24::from(0x800000)).is_err());
1695
1696 assert!(I24::uint_try_from(I128::MIN).is_err());
1698 assert!(<I128 as UintTryTo<I24>>::uint_try_to(&I128::MIN).is_err());
1699 assert!(I24::uint_try_from(I128::MAX).is_err());
1700 assert!(<I128 as UintTryTo<I24>>::uint_try_to(&I128::MAX).is_err());
1701 }
1702}