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