//! Type-level signed integers. //! //! //! Type **operators** implemented: //! //! From `core::ops`: `Add`, `Sub`, `Mul`, `Div`, and `Rem`. //! From `typenum`: `Same`, `Cmp`, and `Pow`. //! //! Rather than directly using the structs defined in this module, it is recommended that //! you import and use the relevant aliases from the [consts](../consts/index.html) module. //! //! Note that operators that work on the underlying structure of the number are //! intentionally not implemented. This is because this implementation of signed integers //! does *not* use twos-complement, and implementing them would require making arbitrary //! choices, causing the results of such operators to be difficult to reason about. //! //! # Example //! ```rust //! use std::ops::{Add, Div, Mul, Rem, Sub}; //! use typenum::{Integer, N3, P2}; //! //! assert_eq!(>::Output::to_i32(), -1); //! assert_eq!(>::Output::to_i32(), -5); //! assert_eq!(>::Output::to_i32(), -6); //! assert_eq!(>::Output::to_i32(), -1); //! assert_eq!(>::Output::to_i32(), -1); //! ``` pub use crate::marker_traits::Integer; use crate::{ bit::{Bit, B0, B1}, consts::{N1, P1, U0, U1}, private::{Internal, InternalMarker, PrivateDivInt, PrivateIntegerAdd, PrivateRem}, uint::{UInt, Unsigned}, Cmp, Equal, Greater, Less, NonZero, Pow, PowerOfTwo, ToInt, Zero, }; use core::ops::{Add, Div, Mul, Neg, Rem, Sub}; /// Type-level signed integers with positive sign. #[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Debug, Default)] #[cfg_attr(feature = "scale_info", derive(scale_info::TypeInfo))] pub struct PInt { pub(crate) n: U, } /// Type-level signed integers with negative sign. #[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Debug, Default)] #[cfg_attr(feature = "scale_info", derive(scale_info::TypeInfo))] pub struct NInt { pub(crate) n: U, } impl PInt { /// Instantiates a singleton representing this strictly positive integer. #[inline] pub fn new() -> PInt { PInt::default() } } impl NInt { /// Instantiates a singleton representing this strictly negative integer. #[inline] pub fn new() -> NInt { NInt::default() } } /// The type-level signed integer 0. #[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Debug, Default)] #[cfg_attr(feature = "scale_info", derive(scale_info::TypeInfo))] pub struct Z0; impl Z0 { /// Instantiates a singleton representing the integer 0. #[inline] pub fn new() -> Z0 { Z0 } } impl NonZero for PInt {} impl NonZero for NInt {} impl Zero for Z0 {} impl PowerOfTwo for PInt {} impl Integer for Z0 { const I8: i8 = 0; const I16: i16 = 0; const I32: i32 = 0; const I64: i64 = 0; #[cfg(feature = "i128")] const I128: i128 = 0; const ISIZE: isize = 0; #[inline] fn to_i8() -> i8 { 0 } #[inline] fn to_i16() -> i16 { 0 } #[inline] fn to_i32() -> i32 { 0 } #[inline] fn to_i64() -> i64 { 0 } #[cfg(feature = "i128")] #[inline] fn to_i128() -> i128 { 0 } #[inline] fn to_isize() -> isize { 0 } } impl Integer for PInt { const I8: i8 = U::I8; const I16: i16 = U::I16; const I32: i32 = U::I32; const I64: i64 = U::I64; #[cfg(feature = "i128")] const I128: i128 = U::I128; const ISIZE: isize = U::ISIZE; #[inline] fn to_i8() -> i8 { ::to_i8() } #[inline] fn to_i16() -> i16 { ::to_i16() } #[inline] fn to_i32() -> i32 { ::to_i32() } #[inline] fn to_i64() -> i64 { ::to_i64() } #[cfg(feature = "i128")] #[inline] fn to_i128() -> i128 { ::to_i128() } #[inline] fn to_isize() -> isize { ::to_isize() } } // Simply negating the result of e.g. `U::I8` will result in overflow for `std::i8::MIN`. Instead, // we use the fact that `U: NonZero` by subtracting one from the `U::U8` before negating. impl Integer for NInt { const I8: i8 = -((U::U8 - 1) as i8) - 1; const I16: i16 = -((U::U16 - 1) as i16) - 1; const I32: i32 = -((U::U32 - 1) as i32) - 1; const I64: i64 = -((U::U64 - 1) as i64) - 1; #[cfg(feature = "i128")] const I128: i128 = -((U::U128 - 1) as i128) - 1; const ISIZE: isize = -((U::USIZE - 1) as isize) - 1; #[inline] fn to_i8() -> i8 { Self::I8 } #[inline] fn to_i16() -> i16 { Self::I16 } #[inline] fn to_i32() -> i32 { Self::I32 } #[inline] fn to_i64() -> i64 { Self::I64 } #[cfg(feature = "i128")] #[inline] fn to_i128() -> i128 { Self::I128 } #[inline] fn to_isize() -> isize { Self::ISIZE } } // --------------------------------------------------------------------------------------- // Neg /// `-Z0 = Z0` impl Neg for Z0 { type Output = Z0; #[inline] fn neg(self) -> Self::Output { Z0 } } /// `-PInt = NInt` impl Neg for PInt { type Output = NInt; #[inline] fn neg(self) -> Self::Output { NInt::new() } } /// `-NInt = PInt` impl Neg for NInt { type Output = PInt; #[inline] fn neg(self) -> Self::Output { PInt::new() } } // --------------------------------------------------------------------------------------- // Add /// `Z0 + I = I` impl Add for Z0 { type Output = I; #[inline] fn add(self, rhs: I) -> Self::Output { rhs } } /// `PInt + Z0 = PInt` impl Add for PInt { type Output = PInt; #[inline] fn add(self, _: Z0) -> Self::Output { PInt::new() } } /// `NInt + Z0 = NInt` impl Add for NInt { type Output = NInt; #[inline] fn add(self, _: Z0) -> Self::Output { NInt::new() } } /// `P(Ul) + P(Ur) = P(Ul + Ur)` impl Add> for PInt
    where Ul: Add,
      >::Output: Unsigned + NonZero, { type Output = PInt<
        >::Output>; #[inline] fn add(self, _: PInt) -> Self::Output { PInt::new() } } /// `N(Ul) + N(Ur) = N(Ul + Ur)` impl Add> for NInt
          where Ul: Add,
            >::Output: Unsigned + NonZero, { type Output = NInt<
              >::Output>; #[inline] fn add(self, _: NInt) -> Self::Output { NInt::new() } } /// `P(Ul) + N(Ur)`: We resolve this with our `PrivateAdd` impl Add> for PInt
                where Ul: Cmp + PrivateIntegerAdd<
                  >::Output, Ur>, { type Output =
                    >::Output, Ur>>::Output; #[inline] fn add(self, rhs: NInt) -> Self::Output { let lhs = self.n; let rhs = rhs.n; let lhs_cmp_rhs = lhs.compare::(&rhs); lhs.private_integer_add(lhs_cmp_rhs, rhs) } } /// `N(Ul) + P(Ur)`: We resolve this with our `PrivateAdd` // We just do the same thing as above, swapping Lhs and Rhs impl Add> for NInt
                      where Ur: Cmp
                        + PrivateIntegerAdd<>::Output, Ul>, { type Output = >::Output, Ul>>::Output; #[inline] fn add(self, rhs: PInt) -> Self::Output { let lhs = self.n; let rhs = rhs.n; let rhs_cmp_lhs = rhs.compare::(&lhs); rhs.private_integer_add(rhs_cmp_lhs, lhs) } } /// `P + N = 0` where `P == N` impl PrivateIntegerAdd for P { type Output = Z0; #[inline] fn private_integer_add(self, _: Equal, _: N) -> Self::Output { Z0 } } /// `P + N = Positive` where `P > N` impl PrivateIntegerAdd for P where P: Sub,

                        >::Output: Unsigned + NonZero, { type Output = PInt<

                        >::Output>; #[inline] fn private_integer_add(self, _: Greater, n: N) -> Self::Output { PInt { n: self - n } } } /// `P + N = Negative` where `P < N` impl PrivateIntegerAdd for P where N: Sub

                        , >::Output: Unsigned + NonZero, { type Output = NInt<>::Output>; #[inline] fn private_integer_add(self, _: Less, n: N) -> Self::Output { NInt { n: n - self } } } // --------------------------------------------------------------------------------------- // Sub /// `Z0 - Z0 = Z0` impl Sub for Z0 { type Output = Z0; #[inline] fn sub(self, _: Z0) -> Self::Output { Z0 } } /// `Z0 - P = N` impl Sub> for Z0 { type Output = NInt; #[inline] fn sub(self, _: PInt) -> Self::Output { NInt::new() } } /// `Z0 - N = P` impl Sub> for Z0 { type Output = PInt; #[inline] fn sub(self, _: NInt) -> Self::Output { PInt::new() } } /// `PInt - Z0 = PInt` impl Sub for PInt { type Output = PInt; #[inline] fn sub(self, _: Z0) -> Self::Output { PInt::new() } } /// `NInt - Z0 = NInt` impl Sub for NInt { type Output = NInt; #[inline] fn sub(self, _: Z0) -> Self::Output { NInt::new() } } /// `P(Ul) - N(Ur) = P(Ul + Ur)` impl Sub> for PInt

                          where Ul: Add,
                            >::Output: Unsigned + NonZero, { type Output = PInt<
                              >::Output>; #[inline] fn sub(self, _: NInt) -> Self::Output { PInt::new() } } /// `N(Ul) - P(Ur) = N(Ul + Ur)` impl Sub> for NInt
                                where Ul: Add,
                                  >::Output: Unsigned + NonZero, { type Output = NInt<
                                    >::Output>; #[inline] fn sub(self, _: PInt) -> Self::Output { NInt::new() } } /// `P(Ul) - P(Ur)`: We resolve this with our `PrivateAdd` impl Sub> for PInt
                                      where Ul: Cmp + PrivateIntegerAdd<
                                        >::Output, Ur>, { type Output =
                                          >::Output, Ur>>::Output; #[inline] fn sub(self, rhs: PInt) -> Self::Output { let lhs = self.n; let rhs = rhs.n; let lhs_cmp_rhs = lhs.compare::(&rhs); lhs.private_integer_add(lhs_cmp_rhs, rhs) } } /// `N(Ul) - N(Ur)`: We resolve this with our `PrivateAdd` // We just do the same thing as above, swapping Lhs and Rhs impl Sub> for NInt
                                            where Ur: Cmp
                                              + PrivateIntegerAdd<>::Output, Ul>, { type Output = >::Output, Ul>>::Output; #[inline] fn sub(self, rhs: NInt) -> Self::Output { let lhs = self.n; let rhs = rhs.n; let rhs_cmp_lhs = rhs.compare::(&lhs); rhs.private_integer_add(rhs_cmp_lhs, lhs) } } // --------------------------------------------------------------------------------------- // Mul /// `Z0 * I = Z0` impl Mul for Z0 { type Output = Z0; #[inline] fn mul(self, _: I) -> Self::Output { Z0 } } /// `P * Z0 = Z0` impl Mul for PInt { type Output = Z0; #[inline] fn mul(self, _: Z0) -> Self::Output { Z0 } } /// `N * Z0 = Z0` impl Mul for NInt { type Output = Z0; #[inline] fn mul(self, _: Z0) -> Self::Output { Z0 } } /// P(Ul) * P(Ur) = P(Ul * Ur) impl Mul> for PInt
                                                where Ul: Mul,
                                                  >::Output: Unsigned + NonZero, { type Output = PInt<
                                                    >::Output>; #[inline] fn mul(self, _: PInt) -> Self::Output { PInt::new() } } /// N(Ul) * N(Ur) = P(Ul * Ur) impl Mul> for NInt
                                                      where Ul: Mul,
                                                        >::Output: Unsigned + NonZero, { type Output = PInt<
                                                          >::Output>; #[inline] fn mul(self, _: NInt) -> Self::Output { PInt::new() } } /// P(Ul) * N(Ur) = N(Ul * Ur) impl Mul> for PInt
                                                            where Ul: Mul,
                                                              >::Output: Unsigned + NonZero, { type Output = NInt<
                                                                >::Output>; #[inline] fn mul(self, _: NInt) -> Self::Output { NInt::new() } } /// N(Ul) * P(Ur) = N(Ul * Ur) impl Mul> for NInt
                                                                  where Ul: Mul,
                                                                    >::Output: Unsigned + NonZero, { type Output = NInt<
                                                                      >::Output>; #[inline] fn mul(self, _: PInt) -> Self::Output { NInt::new() } } // --------------------------------------------------------------------------------------- // Div /// `Z0 / I = Z0` where `I != 0` impl Div for Z0 { type Output = Z0; #[inline] fn div(self, _: I) -> Self::Output { Z0 } } macro_rules! impl_int_div { ($A:ident, $B:ident, $R:ident) => { /// `$A
                                                                        / $B = $R
                                                                          ` impl Div<$B> for $A
                                                                            where Ul: Cmp, $A
                                                                              : PrivateDivInt<
                                                                                >::Output, $B>, { type Output = <$A
                                                                                  as PrivateDivInt<
                                                                                    >::Output, $B>>::Output; #[inline] fn div(self, rhs: $B) -> Self::Output { let lhs_cmp_rhs = self.n.compare::(&rhs.n); self.private_div_int(lhs_cmp_rhs, rhs) } } impl PrivateDivInt> for $A
                                                                                      where Ul: Unsigned + NonZero, Ur: Unsigned + NonZero, { type Output = Z0; #[inline] fn private_div_int(self, _: Less, _: $B) -> Self::Output { Z0 } } impl PrivateDivInt> for $A
                                                                                        where Ul: Unsigned + NonZero, Ur: Unsigned + NonZero, { type Output = $R; #[inline] fn private_div_int(self, _: Equal, _: $B) -> Self::Output { $R { n: U1::new() } } } impl PrivateDivInt> for $A
                                                                                          where Ul: Unsigned + NonZero + Div, Ur: Unsigned + NonZero,
                                                                                            >::Output: Unsigned + NonZero, { type Output = $R<
                                                                                              >::Output>; #[inline] fn private_div_int(self, _: Greater, d: $B) -> Self::Output { $R { n: self.n / d.n } } } }; } impl_int_div!(PInt, PInt, PInt); impl_int_div!(PInt, NInt, NInt); impl_int_div!(NInt, PInt, NInt); impl_int_div!(NInt, NInt, PInt); // --------------------------------------------------------------------------------------- // PartialDiv use crate::{PartialDiv, Quot}; impl PartialDiv for M where M: Integer + Div + Rem, { type Output = Quot; #[inline] fn partial_div(self, rhs: N) -> Self::Output { self / rhs } } // --------------------------------------------------------------------------------------- // Cmp /// 0 == 0 impl Cmp for Z0 { type Output = Equal; #[inline] fn compare(&self, _: &Z0) -> Self::Output { Equal } } /// 0 > -X impl Cmp> for Z0 { type Output = Greater; #[inline] fn compare(&self, _: &NInt) -> Self::Output { Greater } } /// 0 < X impl Cmp> for Z0 { type Output = Less; #[inline] fn compare(&self, _: &PInt) -> Self::Output { Less } } /// X > 0 impl Cmp for PInt { type Output = Greater; #[inline] fn compare(&self, _: &Z0) -> Self::Output { Greater } } /// -X < 0 impl Cmp for NInt { type Output = Less; #[inline] fn compare(&self, _: &Z0) -> Self::Output { Less } } /// -X < Y impl Cmp> for NInt { type Output = Less; #[inline] fn compare(&self, _: &PInt

                                                                                              ) -> Self::Output { Less } } /// X > - Y impl Cmp> for PInt

                                                                                              { type Output = Greater; #[inline] fn compare(&self, _: &NInt) -> Self::Output { Greater } } /// X <==> Y impl + Unsigned + NonZero, Pr: Unsigned + NonZero> Cmp> for PInt { type Output = >::Output; #[inline] fn compare(&self, rhs: &PInt) -> Self::Output { self.n.compare::(&rhs.n) } } /// -X <==> -Y impl + Unsigned + NonZero> Cmp> for NInt { type Output = >::Output; #[inline] fn compare(&self, rhs: &NInt) -> Self::Output { rhs.n.compare::(&self.n) } } // --------------------------------------------------------------------------------------- // Rem /// `Z0 % I = Z0` where `I != 0` impl Rem for Z0 { type Output = Z0; #[inline] fn rem(self, _: I) -> Self::Output { Z0 } } macro_rules! impl_int_rem { ($A:ident, $B:ident, $R:ident) => { /// `$A

                                                                                                % $B = $R
                                                                                                  ` impl Rem<$B> for $A
                                                                                                    where Ul: Rem, $A
                                                                                                      : PrivateRem<
                                                                                                        >::Output, $B>, { type Output = <$A
                                                                                                          as PrivateRem<
                                                                                                            >::Output, $B>>::Output; #[inline] fn rem(self, rhs: $B) -> Self::Output { self.private_rem(self.n % rhs.n, rhs) } } impl PrivateRem> for $A
                                                                                                              { type Output = Z0; #[inline] fn private_rem(self, _: U0, _: $B) -> Self::Output { Z0 } } impl PrivateRem, $B> for $A
                                                                                                                where Ul: Unsigned + NonZero, Ur: Unsigned + NonZero, U: Unsigned, B: Bit, { type Output = $R>; #[inline] fn private_rem(self, urem: UInt, _: $B) -> Self::Output { $R { n: urem } } } }; } impl_int_rem!(PInt, PInt, PInt); impl_int_rem!(PInt, NInt, PInt); impl_int_rem!(NInt, PInt, NInt); impl_int_rem!(NInt, NInt, NInt); // --------------------------------------------------------------------------------------- // Pow /// 0^0 = 1 impl Pow for Z0 { type Output = P1; #[inline] fn powi(self, _: Z0) -> Self::Output { P1::new() } } /// 0^P = 0 impl Pow> for Z0 { type Output = Z0; #[inline] fn powi(self, _: PInt) -> Self::Output { Z0 } } /// 0^N = 0 impl Pow> for Z0 { type Output = Z0; #[inline] fn powi(self, _: NInt) -> Self::Output { Z0 } } /// 1^N = 1 impl Pow> for P1 { type Output = P1; #[inline] fn powi(self, _: NInt) -> Self::Output { P1::new() } } /// (-1)^N = 1 if N is even impl Pow>> for N1 { type Output = P1; #[inline] fn powi(self, _: NInt>) -> Self::Output { P1::new() } } /// (-1)^N = -1 if N is odd impl Pow>> for N1 { type Output = N1; #[inline] fn powi(self, _: NInt>) -> Self::Output { N1::new() } } /// P^0 = 1 impl Pow for PInt { type Output = P1; #[inline] fn powi(self, _: Z0) -> Self::Output { P1::new() } } /// N^0 = 1 impl Pow for NInt { type Output = P1; #[inline] fn powi(self, _: Z0) -> Self::Output { P1::new() } } /// P(Ul)^P(Ur) = P(Ul^Ur) impl Pow> for PInt
                                                                                                                  where Ul: Pow,
                                                                                                                    >::Output: Unsigned + NonZero, { type Output = PInt<
                                                                                                                      >::Output>; #[inline] fn powi(self, _: PInt) -> Self::Output { PInt::new() } } /// N(Ul)^P(Ur) = P(Ul^Ur) if Ur is even impl Pow>> for NInt
                                                                                                                        where Ul: Pow>,
                                                                                                                          >>::Output: Unsigned + NonZero, { type Output = PInt<
                                                                                                                            >>::Output>; #[inline] fn powi(self, _: PInt>) -> Self::Output { PInt::new() } } /// N(Ul)^P(Ur) = N(Ul^Ur) if Ur is odd impl Pow>> for NInt
                                                                                                                              where Ul: Pow>,
                                                                                                                                >>::Output: Unsigned + NonZero, { type Output = NInt<
                                                                                                                                  >>::Output>; #[inline] fn powi(self, _: PInt>) -> Self::Output { NInt::new() } } // --------------------------------------------------------------------------------------- // Gcd use crate::{Gcd, Gcf}; impl Gcd for Z0 { type Output = Z0; } impl Gcd> for Z0 where U: Unsigned + NonZero, { type Output = PInt; } impl Gcd for PInt where U: Unsigned + NonZero, { type Output = PInt; } impl Gcd> for Z0 where U: Unsigned + NonZero, { type Output = PInt; } impl Gcd for NInt where U: Unsigned + NonZero, { type Output = PInt; } impl Gcd> for PInt where U1: Unsigned + NonZero + Gcd, U2: Unsigned + NonZero, Gcf: Unsigned + NonZero, { type Output = PInt>; } impl Gcd> for NInt where U1: Unsigned + NonZero + Gcd, U2: Unsigned + NonZero, Gcf: Unsigned + NonZero, { type Output = PInt>; } impl Gcd> for PInt where U1: Unsigned + NonZero + Gcd, U2: Unsigned + NonZero, Gcf: Unsigned + NonZero, { type Output = PInt>; } impl Gcd> for NInt where U1: Unsigned + NonZero + Gcd, U2: Unsigned + NonZero, Gcf: Unsigned + NonZero, { type Output = PInt>; } // --------------------------------------------------------------------------------------- // Min use crate::{Max, Maximum, Min, Minimum}; impl Min for Z0 { type Output = Z0; #[inline] fn min(self, _: Z0) -> Self::Output { self } } impl Min> for Z0 where U: Unsigned + NonZero, { type Output = Z0; #[inline] fn min(self, _: PInt) -> Self::Output { self } } impl Min> for Z0 where U: Unsigned + NonZero, { type Output = NInt; #[inline] fn min(self, rhs: NInt) -> Self::Output { rhs } } impl Min for PInt where U: Unsigned + NonZero, { type Output = Z0; #[inline] fn min(self, rhs: Z0) -> Self::Output { rhs } } impl Min for NInt where U: Unsigned + NonZero, { type Output = NInt; #[inline] fn min(self, _: Z0) -> Self::Output { self } } impl Min> for PInt
                                                                                                                                    where Ul: Unsigned + NonZero + Min, Ur: Unsigned + NonZero, Minimum: Unsigned + NonZero, { type Output = PInt>; #[inline] fn min(self, rhs: PInt) -> Self::Output { PInt { n: self.n.min(rhs.n), } } } impl Min> for NInt
                                                                                                                                      where Ul: Unsigned + NonZero, Ur: Unsigned + NonZero, { type Output = NInt
                                                                                                                                        ; #[inline] fn min(self, _: PInt) -> Self::Output { self } } impl Min> for PInt
                                                                                                                                          where Ul: Unsigned + NonZero, Ur: Unsigned + NonZero, { type Output = NInt; #[inline] fn min(self, rhs: NInt) -> Self::Output { rhs } } impl Min> for NInt
                                                                                                                                            where Ul: Unsigned + NonZero + Max, Ur: Unsigned + NonZero, Maximum: Unsigned + NonZero, { type Output = NInt>; #[inline] fn min(self, rhs: NInt) -> Self::Output { NInt { n: self.n.max(rhs.n), } } } // --------------------------------------------------------------------------------------- // Max impl Max for Z0 { type Output = Z0; #[inline] fn max(self, _: Z0) -> Self::Output { self } } impl Max> for Z0 where U: Unsigned + NonZero, { type Output = PInt; #[inline] fn max(self, rhs: PInt) -> Self::Output { rhs } } impl Max> for Z0 where U: Unsigned + NonZero, { type Output = Z0; #[inline] fn max(self, _: NInt) -> Self::Output { self } } impl Max for PInt where U: Unsigned + NonZero, { type Output = PInt; #[inline] fn max(self, _: Z0) -> Self::Output { self } } impl Max for NInt where U: Unsigned + NonZero, { type Output = Z0; #[inline] fn max(self, rhs: Z0) -> Self::Output { rhs } } impl Max> for PInt
                                                                                                                                              where Ul: Unsigned + NonZero + Max, Ur: Unsigned + NonZero, Maximum: Unsigned + NonZero, { type Output = PInt>; #[inline] fn max(self, rhs: PInt) -> Self::Output { PInt { n: self.n.max(rhs.n), } } } impl Max> for NInt
                                                                                                                                                where Ul: Unsigned + NonZero, Ur: Unsigned + NonZero, { type Output = PInt; #[inline] fn max(self, rhs: PInt) -> Self::Output { rhs } } impl Max> for PInt
                                                                                                                                                  where Ul: Unsigned + NonZero, Ur: Unsigned + NonZero, { type Output = PInt
                                                                                                                                                    ; #[inline] fn max(self, _: NInt) -> Self::Output { self } } impl Max> for NInt
                                                                                                                                                      where Ul: Unsigned + NonZero + Min, Ur: Unsigned + NonZero, Minimum: Unsigned + NonZero, { type Output = NInt>; #[inline] fn max(self, rhs: NInt) -> Self::Output { NInt { n: self.n.min(rhs.n), } } } // ----------------------------------------- // ToInt impl ToInt for Z0 { #[inline] fn to_int() -> i8 { Self::I8 } const INT: i8 = Self::I8; } impl ToInt for Z0 { #[inline] fn to_int() -> i16 { Self::I16 } const INT: i16 = Self::I16; } impl ToInt for Z0 { #[inline] fn to_int() -> i32 { Self::I32 } const INT: i32 = Self::I32; } impl ToInt for Z0 { #[inline] fn to_int() -> i64 { Self::I64 } const INT: i64 = Self::I64; } // negative numbers impl ToInt for NInt where U: Unsigned + NonZero, { #[inline] fn to_int() -> i8 { Self::I8 } const INT: i8 = Self::I8; } impl ToInt for NInt where U: Unsigned + NonZero, { #[inline] fn to_int() -> i16 { Self::I16 } const INT: i16 = Self::I16; } impl ToInt for NInt where U: Unsigned + NonZero, { #[inline] fn to_int() -> i32 { Self::I32 } const INT: i32 = Self::I32; } impl ToInt for NInt where U: Unsigned + NonZero, { #[inline] fn to_int() -> i64 { Self::I64 } const INT: i64 = Self::I64; } // positive numbers impl ToInt for PInt where U: Unsigned + NonZero, { #[inline] fn to_int() -> i8 { Self::I8 } const INT: i8 = Self::I8; } impl ToInt for PInt where U: Unsigned + NonZero, { #[inline] fn to_int() -> i16 { Self::I16 } const INT: i16 = Self::I16; } impl ToInt for PInt where U: Unsigned + NonZero, { #[inline] fn to_int() -> i32 { Self::I32 } const INT: i32 = Self::I32; } impl ToInt for PInt where U: Unsigned + NonZero, { #[inline] fn to_int() -> i64 { Self::I64 } const INT: i64 = Self::I64; } #[cfg(test)] mod tests { use crate::{consts::*, Integer, ToInt}; #[test] fn to_ix_min() { assert_eq!(N128::to_i8(), ::core::i8::MIN); assert_eq!(N32768::to_i16(), ::core::i16::MIN); } #[test] fn int_toint_test() { // i8 assert_eq!(0_i8, Z0::to_int()); assert_eq!(1_i8, P1::to_int()); assert_eq!(2_i8, P2::to_int()); assert_eq!(3_i8, P3::to_int()); assert_eq!(4_i8, P4::to_int()); assert_eq!(-1_i8, N1::to_int()); assert_eq!(-2_i8, N2::to_int()); assert_eq!(-3_i8, N3::to_int()); assert_eq!(-4_i8, N4::to_int()); assert_eq!(0_i8, Z0::INT); assert_eq!(1_i8, P1::INT); assert_eq!(2_i8, P2::INT); assert_eq!(3_i8, P3::INT); assert_eq!(4_i8, P4::INT); assert_eq!(-1_i8, N1::INT); assert_eq!(-2_i8, N2::INT); assert_eq!(-3_i8, N3::INT); assert_eq!(-4_i8, N4::INT); // i16 assert_eq!(0_i16, Z0::to_int()); assert_eq!(1_i16, P1::to_int()); assert_eq!(2_i16, P2::to_int()); assert_eq!(3_i16, P3::to_int()); assert_eq!(4_i16, P4::to_int()); assert_eq!(-1_i16, N1::to_int()); assert_eq!(-2_i16, N2::to_int()); assert_eq!(-3_i16, N3::to_int()); assert_eq!(-4_i16, N4::to_int()); assert_eq!(0_i16, Z0::INT); assert_eq!(1_i16, P1::INT); assert_eq!(2_i16, P2::INT); assert_eq!(3_i16, P3::INT); assert_eq!(4_i16, P4::INT); assert_eq!(-1_i16, N1::INT); assert_eq!(-2_i16, N2::INT); assert_eq!(-3_i16, N3::INT); assert_eq!(-4_i16, N4::INT); // i32 assert_eq!(0_i32, Z0::to_int()); assert_eq!(1_i32, P1::to_int()); assert_eq!(2_i32, P2::to_int()); assert_eq!(3_i32, P3::to_int()); assert_eq!(4_i32, P4::to_int()); assert_eq!(-1_i32, N1::to_int()); assert_eq!(-2_i32, N2::to_int()); assert_eq!(-3_i32, N3::to_int()); assert_eq!(-4_i32, N4::to_int()); assert_eq!(0_i32, Z0::INT); assert_eq!(1_i32, P1::INT); assert_eq!(2_i32, P2::INT); assert_eq!(3_i32, P3::INT); assert_eq!(4_i32, P4::INT); assert_eq!(-1_i32, N1::INT); assert_eq!(-2_i32, N2::INT); assert_eq!(-3_i32, N3::INT); assert_eq!(-4_i32, N4::INT); // i64 assert_eq!(0_i64, Z0::to_int()); assert_eq!(1_i64, P1::to_int()); assert_eq!(2_i64, P2::to_int()); assert_eq!(3_i64, P3::to_int()); assert_eq!(4_i64, P4::to_int()); assert_eq!(-1_i64, N1::to_int()); assert_eq!(-2_i64, N2::to_int()); assert_eq!(-3_i64, N3::to_int()); assert_eq!(-4_i64, N4::to_int()); assert_eq!(0_i64, Z0::INT); assert_eq!(1_i64, P1::INT); assert_eq!(2_i64, P2::INT); assert_eq!(3_i64, P3::INT); assert_eq!(4_i64, P4::INT); assert_eq!(-1_i64, N1::INT); assert_eq!(-2_i64, N2::INT); assert_eq!(-3_i64, N3::INT); assert_eq!(-4_i64, N4::INT); } }