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