Skip to main content

alloy_primitives/signed/
int.rs

1use super::{ParseSignedError, Sign, utils::*};
2use alloc::string::String;
3use core::fmt;
4use ruint::{BaseConvertError, Uint, UintTryFrom, UintTryTo};
5
6/// Signed integer wrapping a `ruint::Uint`.
7///
8/// This signed integer implementation is fully abstract across the number of
9/// bits. It wraps a [`ruint::Uint`], and co-opts the most significant bit to
10/// represent the sign. The number is represented in two's complement, using the
11/// underlying `Uint`'s `u64` limbs. The limbs can be accessed via the
12/// [`Signed::as_limbs()`] method, and are least-significant first.
13///
14/// ## Aliases
15///
16/// We provide aliases for every bit-width divisible by 8, from 8 to 256. These
17/// are located in [`crate::aliases`] and are named `I256`, `I248` etc. Most
18/// users will want [`crate::I256`].
19///
20/// # Usage
21///
22/// ```
23/// # use alloy_primitives::I256;
24/// // Instantiate from a number
25/// let a = I256::unchecked_from(1);
26/// // Use `try_from` if you're not sure it'll fit
27/// let b = I256::try_from(200000382).unwrap();
28///
29/// // Or parse from a string :)
30/// let c = "100".parse::<I256>().unwrap();
31/// let d = "-0x138f".parse::<I256>().unwrap();
32///
33/// // Preceding plus is allowed but not recommended
34/// let e = "+0xdeadbeef".parse::<I256>().unwrap();
35///
36/// // Underscores are ignored
37/// let f = "1_000_000".parse::<I256>().unwrap();
38///
39/// // But invalid chars are not
40/// assert!("^31".parse::<I256>().is_err());
41///
42/// // Math works great :)
43/// let g = a * b + c - d;
44///
45/// // And so do comparisons!
46/// assert!(e > a);
47///
48/// // We have some useful constants too
49/// assert_eq!(I256::ZERO, I256::unchecked_from(0));
50/// assert_eq!(I256::ONE, I256::unchecked_from(1));
51/// assert_eq!(I256::MINUS_ONE, I256::unchecked_from(-1));
52/// ```
53#[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
57// formatting
58impl<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    /// Mask for the highest limb.
103    pub(crate) const MASK: u64 = ruint::mask(BITS);
104
105    /// Location of the sign bit within the highest limb.
106    pub(crate) const SIGN_BIT: u64 = sign_bit(BITS);
107
108    /// Number of bits.
109    pub const BITS: usize = BITS;
110
111    /// The size of this integer type in bytes. Note that some bits may be
112    /// forced zero if BITS is not cleanly divisible by eight.
113    pub const BYTES: usize = Uint::<BITS, LIMBS>::BYTES;
114
115    /// The minimum value.
116    pub const MIN: Self = min();
117
118    /// The maximum value.
119    pub const MAX: Self = max();
120
121    /// Zero (additive identity) of this type.
122    pub const ZERO: Self = zero();
123
124    /// One (multiplicative identity) of this type.
125    pub const ONE: Self = one();
126
127    /// Minus one (multiplicative inverse) of this type.
128    pub const MINUS_ONE: Self = Self(Uint::<BITS, LIMBS>::MAX);
129
130    /// Coerces an unsigned integer into a signed one. If the unsigned integer is greater than or
131    /// equal to `1 << 255`, then the result will overflow into a negative value.
132    #[inline]
133    pub const fn from_raw(val: Uint<BITS, LIMBS>) -> Self {
134        Self(val)
135    }
136
137    /// Shortcut for `val.try_into().unwrap()`.
138    ///
139    /// # Panics
140    ///
141    /// Panics if the conversion fails.
142    #[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    /// Construct a new [`Signed`] from the value.
153    ///
154    /// # Panics
155    ///
156    /// Panics if the conversion fails, for example if the value is too large
157    /// for the bit-size of the [`Signed`]. The panic will be attributed to the
158    /// call site.
159    #[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    /// # Panics
172    ///
173    /// Panics if the conversion fails, for example if the value is too large
174    /// for the bit-size of the target type.
175    #[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    /// Shortcut for `self.try_into().unwrap()`.
186    ///
187    /// # Panics
188    ///
189    /// Panics if the conversion fails.
190    #[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    /// Returns the signed integer as a unsigned integer. If the value of `self`
201    /// negative, then the two's complement of its absolute value will be
202    /// returned.
203    #[inline]
204    pub const fn into_raw(self) -> Uint<BITS, LIMBS> {
205        self.0
206    }
207
208    /// Returns the sign of self.
209    #[inline]
210    pub const fn sign(&self) -> Sign {
211        // if the last limb contains the sign bit, then we're negative
212        // because we can't set any higher bits to 1, we use >= as a proxy
213        // check to avoid bit comparison
214        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    /// Determines if the integer is odd.
223    #[inline]
224    pub const fn is_odd(&self) -> bool {
225        if BITS == 0 { false } else { self.as_limbs()[0] % 2 == 1 }
226    }
227
228    /// Compile-time equality. NOT constant-time equality.
229    #[inline]
230    pub const fn const_eq(&self, other: &Self) -> bool {
231        const_eq(self, other)
232    }
233
234    /// Returns `true` if `self` is zero and `false` if the number is negative
235    /// or positive.
236    #[inline]
237    pub const fn is_zero(&self) -> bool {
238        self.const_eq(&Self::ZERO)
239    }
240
241    /// Returns `true` if `self` is positive and `false` if the number is zero
242    /// or negative.
243    #[inline]
244    pub const fn is_positive(&self) -> bool {
245        !self.is_zero() && matches!(self.sign(), Sign::Positive)
246    }
247
248    /// Returns `true` if `self` is negative and `false` if the number is zero
249    /// or positive.
250    #[inline]
251    pub const fn is_negative(&self) -> bool {
252        matches!(self.sign(), Sign::Negative)
253    }
254
255    /// Returns the number of ones in the binary representation of `self`.
256    #[inline]
257    pub const fn count_ones(&self) -> usize {
258        self.0.count_ones()
259    }
260
261    /// Returns the number of zeros in the binary representation of `self`.
262    #[inline]
263    pub const fn count_zeros(&self) -> usize {
264        self.0.count_zeros()
265    }
266
267    /// Returns the number of leading zeros in the binary representation of
268    /// `self`.
269    #[inline]
270    pub const fn leading_zeros(&self) -> usize {
271        self.0.leading_zeros()
272    }
273
274    /// Returns the number of trailing zeros in the binary representation of
275    /// `self`.
276    #[inline]
277    #[allow(clippy::missing_const_for_fn)] // `ruint` exposes this as const only in newer versions.
278    pub fn trailing_zeros(&self) -> usize {
279        self.0.trailing_zeros()
280    }
281
282    /// Returns the number of trailing ones in the binary representation of
283    /// `self`.
284    #[inline]
285    #[allow(clippy::missing_const_for_fn)] // `ruint` exposes this as const only in newer versions.
286    pub fn trailing_ones(&self) -> usize {
287        self.0.trailing_ones()
288    }
289
290    /// Returns whether a specific bit is set.
291    ///
292    /// Returns `false` if `index` exceeds the bit width of the number.
293    #[inline]
294    pub const fn bit(&self, index: usize) -> bool {
295        self.0.bit(index)
296    }
297
298    /// Returns a specific byte. The byte at index `0` is the least significant
299    /// byte (little endian).
300    ///
301    /// # Panics
302    ///
303    /// Panics if `index` exceeds the byte width of the number.
304    #[inline]
305    #[track_caller]
306    pub const fn byte(&self, index: usize) -> u8 {
307        self.0.byte(index)
308    }
309
310    /// Return the least number of bits needed to represent the number.
311    #[inline]
312    pub fn bits(&self) -> u32 {
313        let unsigned = self.unsigned_abs();
314        let unsigned_bits = unsigned.bit_len();
315
316        // NOTE: We need to deal with two special cases:
317        //   - the number is 0
318        //   - the number is a negative power of `2`. These numbers are written as `0b11..1100..00`.
319        //   In the case of a negative power of two, the number of bits required
320        //   to represent the negative signed value is equal to the number of
321        //   bits required to represent its absolute value as an unsigned
322        //   integer. This is best illustrated by an example: the number of bits
323        //   required to represent `-128` is `8` since it is equal to `i8::MIN`
324        //   and, therefore, obviously fits in `8` bits. This is equal to the
325        //   number of bits required to represent `128` as an unsigned integer
326        //   (which fits in a `u8`).  However, the number of bits required to
327        //   represent `128` as a signed integer is `9`, as it is greater than
328        //   `i8::MAX`.  In the general case, an extra bit is needed to
329        //   represent the sign.
330        let bits = if self.count_zeros() == self.trailing_zeros() {
331            // `self` is zero or a negative power of two
332            unsigned_bits
333        } else {
334            unsigned_bits + 1
335        };
336
337        bits as u32
338    }
339
340    /// Creates a `Signed` from a sign and an absolute value. Returns the value
341    /// and a bool that is true if the conversion caused an overflow.
342    #[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    /// Creates a `Signed` from an absolute value and a negative flag. Returns
353    /// `None` if it would overflow as `Signed`.
354    #[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    /// Convert from a decimal string.
361    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    /// Convert to a decimal string.
372    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    /// Convert from a hex string.
380    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    /// Convert to a hex string.
398    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    /// Splits a Signed into its absolute value and negative flag.
406    #[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    /// Converts `self` to a big-endian byte array of size exactly
417    /// [`Self::BYTES`].
418    ///
419    /// # Panics
420    ///
421    /// Panics if the generic parameter `BYTES` is not exactly [`Self::BYTES`].
422    /// Ideally this would be a compile time error, but this is blocked by
423    /// Rust issue [#60551].
424    ///
425    /// [#60551]: https://github.com/rust-lang/rust/issues/60551
426    #[inline]
427    pub const fn to_be_bytes<const BYTES: usize>(&self) -> [u8; BYTES] {
428        self.0.to_be_bytes()
429    }
430
431    /// Converts `self` to a little-endian byte array of size exactly
432    /// [`Self::BYTES`].
433    ///
434    /// # Panics
435    ///
436    /// Panics if the generic parameter `BYTES` is not exactly [`Self::BYTES`].
437    /// Ideally this would be a compile time error, but this is blocked by
438    /// Rust issue [#60551].
439    ///
440    /// [#60551]: https://github.com/rust-lang/rust/issues/60551
441    #[inline]
442    pub const fn to_le_bytes<const BYTES: usize>(&self) -> [u8; BYTES] {
443        self.0.to_le_bytes()
444    }
445
446    /// Converts a big-endian byte array of size exactly [`Self::BYTES`].
447    ///
448    /// # Panics
449    ///
450    /// Panics if the generic parameter `BYTES` is not exactly [`Self::BYTES`].
451    /// Ideally this would be a compile time error, but this is blocked by
452    /// Rust issue [#60551].
453    ///
454    /// [#60551]: https://github.com/rust-lang/rust/issues/60551
455    ///
456    /// Panics if the value is too large for the bit-size of the Uint.
457    #[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    /// Convert from an array in LE format
463    ///
464    /// # Panics
465    ///
466    /// Panics if the given array is not the correct length.
467    #[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    /// Creates a new integer from a big endian slice of bytes.
474    ///
475    /// The slice is interpreted as a big endian number. Leading zeros
476    /// are ignored. The slice can be any length.
477    ///
478    /// Returns [`None`] if the value is larger than fits the [`Uint`].
479    pub fn try_from_be_slice(slice: &[u8]) -> Option<Self> {
480        Uint::try_from_be_slice(slice).map(Self)
481    }
482
483    /// Creates a new integer from a little endian slice of bytes.
484    ///
485    /// The slice is interpreted as a big endian number. Leading zeros
486    /// are ignored. The slice can be any length.
487    ///
488    /// Returns [`None`] if the value is larger than fits the [`Uint`].
489    pub fn try_from_le_slice(slice: &[u8]) -> Option<Self> {
490        Uint::try_from_le_slice(slice).map(Self)
491    }
492
493    /// View the array of limbs.
494    #[inline(always)]
495    #[must_use]
496    pub const fn as_limbs(&self) -> &[u64; LIMBS] {
497        self.0.as_limbs()
498    }
499
500    /// Convert to a array of limbs.
501    ///
502    /// Limbs are least significant first.
503    #[inline(always)]
504    pub const fn into_limbs(self) -> [u64; LIMBS] {
505        self.0.into_limbs()
506    }
507
508    /// Construct a new integer from little-endian a array of limbs.
509    ///
510    /// # Panics
511    ///
512    /// Panics if `LIMBS` is not equal to `nlimbs(BITS)`.
513    ///
514    /// Panics if the value is to large for the bit-size of the Uint.
515    #[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    /// Constructs the [`Signed`] from digits in the base `base` in big-endian.
523    /// Wrapper around ruint's from_base_be
524    ///
525    /// # Errors
526    ///
527    /// * [`BaseConvertError::InvalidBase`] if the base is less than 2.
528    /// * [`BaseConvertError::InvalidDigit`] if a digit is out of range.
529    /// * [`BaseConvertError::Overflow`] if the number is too large to fit.
530    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 U2 = Uint<2, 1>;
550    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        // test conversion from basic types
590
591        macro_rules! run_test {
592            ($i_struct:ty, $u_struct:ty, $i:ty, $u:ty) => {
593                // Test a specific number
594                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        // edge cases
626        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                // The only case for overflow.
1266                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                // The only saturating corner case.
1293                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); // 7 >= 4 * 1
1340                assert_eq!(a.div_euclid(-b), <$i_struct>::MINUS_ONE); // 7 >= -4 * -1
1341                assert_eq!((-a).div_euclid(b), -<$i_struct>::try_from(2).unwrap()); // -7 >= 4 * -2
1342                assert_eq!((-a).div_euclid(-b), <$i_struct>::try_from(2).unwrap()); // -7 >= -4 * 2
1343
1344                // Overflowing
1345                assert_eq!(
1346                    <$i_struct>::MIN.overflowing_div_euclid(<$i_struct>::MINUS_ONE),
1347                    (<$i_struct>::MIN, true)
1348                );
1349                // Wrapping
1350                assert_eq!(
1351                    <$i_struct>::MIN.wrapping_div_euclid(<$i_struct>::MINUS_ONE),
1352                    <$i_struct>::MIN
1353                );
1354                // // Checked
1355                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(); // or any other integer type
1380                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                // Overflowing
1388                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                // Wrapping
1395                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                // Checked
1407                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                // The only case for overflow.
1484                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        // can convert between signed of different sizes when value is within bounds
1666        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        // convert positive signed to unsigned
1681        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        // convert unsigned to positive signed
1685        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        // can't convert negative signed to unsigned
1691        assert!(U24::uint_try_from(m_i24).is_err());
1692        assert!(<I24 as UintTryTo<U24>>::uint_try_to(&m_i24).is_err());
1693
1694        // can't convert unsigned to positive signed if too large
1695        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        // out-of-bounds conversions
1699        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}