//! Type-level unsigned integers. //! //! //! **Type operators** implemented: //! //! From `core::ops`: `BitAnd`, `BitOr`, `BitXor`, `Shl`, `Shr`, `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. //! //! # Example //! ```rust //! use std::ops::{BitAnd, BitOr, BitXor, Shl, Shr, Add, Sub, Mul, Div, Rem}; //! use typenum::{Unsigned, U1, U2, U3, U4}; //! //! assert_eq!(>::Output::to_u32(), 2); //! assert_eq!(>::Output::to_u32(), 7); //! assert_eq!(>::Output::to_u32(), 1); //! assert_eq!(>::Output::to_u32(), 6); //! assert_eq!(>::Output::to_u32(), 1); //! assert_eq!(>::Output::to_u32(), 5); //! assert_eq!(>::Output::to_u32(), 1); //! assert_eq!(>::Output::to_u32(), 6); //! assert_eq!(>::Output::to_u32(), 1); //! assert_eq!(>::Output::to_u32(), 1); //! ``` //! use core::ops::{Add, BitAnd, BitOr, BitXor, Mul, Shl, Shr, Sub}; use { Cmp, Equal, Gcd, Greater, IsGreaterOrEqual, Len, Less, Logarithm2, Maximum, Minimum, NonZero, Ord, Pow, SquareRoot, }; use bit::{Bit, B0, B1}; use private::{ BitDiff, PrivateAnd, PrivateCmp, PrivateLogarithm2, PrivatePow, PrivateSquareRoot, PrivateSub, PrivateXor, Trim, }; use private::{ BitDiffOut, PrivateAndOut, PrivateCmpOut, PrivatePowOut, PrivateSubOut, PrivateXorOut, TrimOut, }; use private::{Internal, InternalMarker}; use consts::{U0, U1}; use {Add1, Double, Gcf, GrEq, Length, Log2, Or, Prod, Shleft, Shright, Sqrt, Square, Sub1, Sum}; pub use marker_traits::{PowerOfTwo, Unsigned}; /// The terminating type for `UInt`; it always comes after the most significant /// bit. `UTerm` by itself represents zero, which is aliased to `U0`. #[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Debug, Default)] pub struct UTerm; impl UTerm { /// Instantiates a singleton representing this unsigned integer. #[inline] pub fn new() -> UTerm { UTerm } } impl Unsigned for UTerm { const U8: u8 = 0; const U16: u16 = 0; const U32: u32 = 0; const U64: u64 = 0; #[cfg(feature = "i128")] const U128: u128 = 0; const USIZE: usize = 0; 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_u8() -> u8 { 0 } #[inline] fn to_u16() -> u16 { 0 } #[inline] fn to_u32() -> u32 { 0 } #[inline] fn to_u64() -> u64 { 0 } #[cfg(feature = "i128")] #[inline] fn to_u128() -> u128 { 0 } #[inline] fn to_usize() -> usize { 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 } } /// `UInt` is defined recursively, where `B` is the least significant bit and `U` is the rest /// of the number. Conceptually, `U` should be bound by the trait `Unsigned` and `B` should /// be bound by the trait `Bit`, but enforcing these bounds causes linear instead of /// logrithmic scaling in some places, so they are left off for now. They may be enforced in /// future. /// /// In order to keep numbers unique, leading zeros are not allowed, so `UInt` is /// forbidden. /// /// # Example /// ```rust /// use typenum::{B0, B1, UInt, UTerm}; /// /// # #[allow(dead_code)] /// type U6 = UInt, B1>, B0>; /// ``` #[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Debug, Default)] pub struct UInt { /// The more significant bits of `Self`. pub(crate) msb: U, /// The least significant bit of `Self`. pub(crate) lsb: B, } impl UInt { /// Instantiates a singleton representing this unsigned integer. #[inline] pub fn new() -> UInt { UInt::default() } } impl Unsigned for UInt { const U8: u8 = B::U8 | U::U8 << 1; const U16: u16 = B::U8 as u16 | U::U16 << 1; const U32: u32 = B::U8 as u32 | U::U32 << 1; const U64: u64 = B::U8 as u64 | U::U64 << 1; #[cfg(feature = "i128")] const U128: u128 = B::U8 as u128 | U::U128 << 1; const USIZE: usize = B::U8 as usize | U::USIZE << 1; const I8: i8 = B::U8 as i8 | U::I8 << 1; const I16: i16 = B::U8 as i16 | U::I16 << 1; const I32: i32 = B::U8 as i32 | U::I32 << 1; const I64: i64 = B::U8 as i64 | U::I64 << 1; #[cfg(feature = "i128")] const I128: i128 = B::U8 as i128 | U::I128 << 1; const ISIZE: isize = B::U8 as isize | U::ISIZE << 1; #[inline] fn to_u8() -> u8 { B::to_u8() | U::to_u8() << 1 } #[inline] fn to_u16() -> u16 { u16::from(B::to_u8()) | U::to_u16() << 1 } #[inline] fn to_u32() -> u32 { u32::from(B::to_u8()) | U::to_u32() << 1 } #[inline] fn to_u64() -> u64 { u64::from(B::to_u8()) | U::to_u64() << 1 } #[cfg(feature = "i128")] #[inline] fn to_u128() -> u128 { u128::from(B::to_u8()) | U::to_u128() << 1 } #[inline] fn to_usize() -> usize { usize::from(B::to_u8()) | U::to_usize() << 1 } #[inline] fn to_i8() -> i8 { B::to_u8() as i8 | U::to_i8() << 1 } #[inline] fn to_i16() -> i16 { i16::from(B::to_u8()) | U::to_i16() << 1 } #[inline] fn to_i32() -> i32 { i32::from(B::to_u8()) | U::to_i32() << 1 } #[inline] fn to_i64() -> i64 { i64::from(B::to_u8()) | U::to_i64() << 1 } #[cfg(feature = "i128")] #[inline] fn to_i128() -> i128 { i128::from(B::to_u8()) | U::to_i128() << 1 } #[inline] fn to_isize() -> isize { B::to_u8() as isize | U::to_isize() << 1 } } impl NonZero for UInt {} impl PowerOfTwo for UInt {} impl PowerOfTwo for UInt {} // --------------------------------------------------------------------------------------- // Getting length of unsigned integers, which is defined as the number of bits before `UTerm` /// Length of `UTerm` by itself is 0 impl Len for UTerm { type Output = U0; #[inline] fn len(&self) -> Self::Output { UTerm } } /// Length of a bit is 1 impl Len for UInt where U: Len, Length: Add, Add1>: Unsigned, { type Output = Add1>; #[inline] fn len(&self) -> Self::Output { self.msb.len() + B1 } } // --------------------------------------------------------------------------------------- // Adding bits to unsigned integers /// `UTerm + B0 = UTerm` impl Add for UTerm { type Output = UTerm; #[inline] fn add(self, _: B0) -> Self::Output { UTerm } } /// `U + B0 = U` impl Add for UInt { type Output = UInt; #[inline] fn add(self, _: B0) -> Self::Output { UInt::new() } } /// `UTerm + B1 = UInt` impl Add for UTerm { type Output = UInt; #[inline] fn add(self, _: B1) -> Self::Output { UInt::new() } } /// `UInt + B1 = UInt` impl Add for UInt { type Output = UInt; #[inline] fn add(self, _: B1) -> Self::Output { UInt::new() } } /// `UInt + B1 = UInt` impl Add for UInt where U: Add, Add1: Unsigned, { type Output = UInt, B0>; #[inline] fn add(self, _: B1) -> Self::Output { UInt::new() } } // --------------------------------------------------------------------------------------- // Adding unsigned integers /// `UTerm + U = U` impl Add for UTerm { type Output = U; #[inline] fn add(self, rhs: U) -> Self::Output { rhs } } /// `UInt + UTerm = UInt` impl Add for UInt { type Output = UInt; #[inline] fn add(self, _: UTerm) -> Self::Output { UInt::new() } } /// `UInt + UInt = UInt
    ` impl Add> for UInt where Ul: Add, { type Output = UInt, B0>; #[inline] fn add(self, rhs: UInt) -> Self::Output { UInt { msb: self.msb + rhs.msb, lsb: B0, } } } /// `UInt + UInt = UInt
      ` impl Add> for UInt where Ul: Add, { type Output = UInt, B1>; #[inline] fn add(self, rhs: UInt) -> Self::Output { UInt { msb: self.msb + rhs.msb, lsb: B1, } } } /// `UInt + UInt = UInt
        ` impl Add> for UInt where Ul: Add, { type Output = UInt, B1>; #[inline] fn add(self, rhs: UInt) -> Self::Output { UInt { msb: self.msb + rhs.msb, lsb: B1, } } } /// `UInt + UInt = UInt<(Ul + Ur) + B1, B0>` impl Add> for UInt where Ul: Add, Sum: Add, { type Output = UInt>, B0>; #[inline] fn add(self, rhs: UInt) -> Self::Output { UInt { msb: self.msb + rhs.msb + B1, lsb: B0, } } } // --------------------------------------------------------------------------------------- // Subtracting bits from unsigned integers /// `UTerm - B0 = Term` impl Sub for UTerm { type Output = UTerm; #[inline] fn sub(self, _: B0) -> Self::Output { UTerm } } /// `UInt - B0 = UInt` impl Sub for UInt { type Output = UInt; #[inline] fn sub(self, _: B0) -> Self::Output { UInt::new() } } /// `UInt - B1 = UInt` impl Sub for UInt, B1> { type Output = UInt, B0>; #[inline] fn sub(self, _: B1) -> Self::Output { UInt::new() } } /// `UInt - B1 = UTerm` impl Sub for UInt { type Output = UTerm; #[inline] fn sub(self, _: B1) -> Self::Output { UTerm } } /// `UInt - B1 = UInt` impl Sub for UInt where U: Sub, Sub1: Unsigned, { type Output = UInt, B1>; #[inline] fn sub(self, _: B1) -> Self::Output { UInt::new() } } // --------------------------------------------------------------------------------------- // Subtracting unsigned integers /// `UTerm - UTerm = UTerm` impl Sub for UTerm { type Output = UTerm; #[inline] fn sub(self, _: UTerm) -> Self::Output { UTerm } } /// Subtracting unsigned integers. We just do our `PrivateSub` and then `Trim` the output. impl Sub for UInt where UInt: PrivateSub, PrivateSubOut, Ur>: Trim, { type Output = TrimOut, Ur>>; #[inline] fn sub(self, rhs: Ur) -> Self::Output { self.private_sub(rhs).trim() } } /// `U - UTerm = U` impl PrivateSub for U { type Output = U; #[inline] fn private_sub(self, _: UTerm) -> Self::Output { self } } /// `UInt - UInt = UInt
          ` impl PrivateSub> for UInt where Ul: PrivateSub, { type Output = UInt, B0>; #[inline] fn private_sub(self, rhs: UInt) -> Self::Output { UInt { msb: self.msb.private_sub(rhs.msb), lsb: B0, } } } /// `UInt - UInt = UInt<(Ul - Ur) - B1, B1>` impl PrivateSub> for UInt where Ul: PrivateSub, PrivateSubOut: Sub, { type Output = UInt>, B1>; #[inline] fn private_sub(self, rhs: UInt) -> Self::Output { UInt { msb: self.msb.private_sub(rhs.msb) - B1, lsb: B1, } } } /// `UInt - UInt = UInt
            ` impl PrivateSub> for UInt where Ul: PrivateSub, { type Output = UInt, B1>; #[inline] fn private_sub(self, rhs: UInt) -> Self::Output { UInt { msb: self.msb.private_sub(rhs.msb), lsb: B1, } } } /// `UInt - UInt = UInt
              ` impl PrivateSub> for UInt where Ul: PrivateSub, { type Output = UInt, B0>; #[inline] fn private_sub(self, rhs: UInt) -> Self::Output { UInt { msb: self.msb.private_sub(rhs.msb), lsb: B0, } } } // --------------------------------------------------------------------------------------- // And unsigned integers /// 0 & X = 0 impl BitAnd for UTerm { type Output = UTerm; #[inline] fn bitand(self, _: Ur) -> Self::Output { UTerm } } /// Anding unsigned integers. /// We use our `PrivateAnd` operator and then `Trim` the output. impl BitAnd for UInt where UInt: PrivateAnd, PrivateAndOut, Ur>: Trim, { type Output = TrimOut, Ur>>; #[inline] fn bitand(self, rhs: Ur) -> Self::Output { self.private_and(rhs).trim() } } /// `UTerm & X = UTerm` impl PrivateAnd for UTerm { type Output = UTerm; #[inline] fn private_and(self, _: U) -> Self::Output { UTerm } } /// `X & UTerm = UTerm` impl PrivateAnd for UInt { type Output = UTerm; #[inline] fn private_and(self, _: UTerm) -> Self::Output { UTerm } } /// `UInt & UInt = UInt
                ` impl PrivateAnd> for UInt where Ul: PrivateAnd, { type Output = UInt, B0>; #[inline] fn private_and(self, rhs: UInt) -> Self::Output { UInt { msb: self.msb.private_and(rhs.msb), lsb: B0, } } } /// `UInt & UInt = UInt
                  ` impl PrivateAnd> for UInt where Ul: PrivateAnd, { type Output = UInt, B0>; #[inline] fn private_and(self, rhs: UInt) -> Self::Output { UInt { msb: self.msb.private_and(rhs.msb), lsb: B0, } } } /// `UInt & UInt = UInt
                    ` impl PrivateAnd> for UInt where Ul: PrivateAnd, { type Output = UInt, B0>; #[inline] fn private_and(self, rhs: UInt) -> Self::Output { UInt { msb: self.msb.private_and(rhs.msb), lsb: B0, } } } /// `UInt & UInt = UInt
                      ` impl PrivateAnd> for UInt where Ul: PrivateAnd, { type Output = UInt, B1>; #[inline] fn private_and(self, rhs: UInt) -> Self::Output { UInt { msb: self.msb.private_and(rhs.msb), lsb: B1, } } } // --------------------------------------------------------------------------------------- // Or unsigned integers /// `UTerm | X = X` impl BitOr for UTerm { type Output = U; #[inline] fn bitor(self, rhs: U) -> Self::Output { rhs } } /// `X | UTerm = X` impl BitOr for UInt { type Output = Self; #[inline] fn bitor(self, _: UTerm) -> Self::Output { UInt::new() } } /// `UInt | UInt = UInt
                        ` impl BitOr> for UInt where Ul: BitOr, { type Output = UInt<
                          >::Output, B0>; #[inline] fn bitor(self, rhs: UInt) -> Self::Output { UInt { msb: self.msb.bitor(rhs.msb), lsb: B0, } } } /// `UInt | UInt = UInt
                            ` impl BitOr> for UInt where Ul: BitOr, { type Output = UInt, B1>; #[inline] fn bitor(self, rhs: UInt) -> Self::Output { UInt { msb: self.msb.bitor(rhs.msb), lsb: self.lsb.bitor(rhs.lsb), } } } /// `UInt | UInt = UInt
                              ` impl BitOr> for UInt where Ul: BitOr, { type Output = UInt, B1>; #[inline] fn bitor(self, rhs: UInt) -> Self::Output { UInt { msb: self.msb.bitor(rhs.msb), lsb: self.lsb.bitor(rhs.lsb), } } } /// `UInt | UInt = UInt
                                ` impl BitOr> for UInt where Ul: BitOr, { type Output = UInt, B1>; #[inline] fn bitor(self, rhs: UInt) -> Self::Output { UInt { msb: self.msb.bitor(rhs.msb), lsb: self.lsb.bitor(rhs.lsb), } } } // --------------------------------------------------------------------------------------- // Xor unsigned integers /// 0 ^ X = X impl BitXor for UTerm { type Output = Ur; #[inline] fn bitxor(self, rhs: Ur) -> Self::Output { rhs } } /// Xoring unsigned integers. /// We use our `PrivateXor` operator and then `Trim` the output. impl BitXor for UInt where UInt: PrivateXor, PrivateXorOut, Ur>: Trim, { type Output = TrimOut, Ur>>; #[inline] fn bitxor(self, rhs: Ur) -> Self::Output { self.private_xor(rhs).trim() } } /// `UTerm ^ X = X` impl PrivateXor for UTerm { type Output = U; #[inline] fn private_xor(self, rhs: U) -> Self::Output { rhs } } /// `X ^ UTerm = X` impl PrivateXor for UInt { type Output = Self; #[inline] fn private_xor(self, _: UTerm) -> Self::Output { self } } /// `UInt ^ UInt = UInt
                                  ` impl PrivateXor> for UInt where Ul: PrivateXor, { type Output = UInt, B0>; #[inline] fn private_xor(self, rhs: UInt) -> Self::Output { UInt { msb: self.msb.private_xor(rhs.msb), lsb: B0, } } } /// `UInt ^ UInt = UInt
                                    ` impl PrivateXor> for UInt where Ul: PrivateXor, { type Output = UInt, B1>; #[inline] fn private_xor(self, rhs: UInt) -> Self::Output { UInt { msb: self.msb.private_xor(rhs.msb), lsb: B1, } } } /// `UInt ^ UInt = UInt
                                      ` impl PrivateXor> for UInt where Ul: PrivateXor, { type Output = UInt, B1>; #[inline] fn private_xor(self, rhs: UInt) -> Self::Output { UInt { msb: self.msb.private_xor(rhs.msb), lsb: B1, } } } /// `UInt ^ UInt = UInt
                                        ` impl PrivateXor> for UInt where Ul: PrivateXor, { type Output = UInt, B0>; #[inline] fn private_xor(self, rhs: UInt) -> Self::Output { UInt { msb: self.msb.private_xor(rhs.msb), lsb: B0, } } } // --------------------------------------------------------------------------------------- // Shl unsigned integers /// Shifting `UTerm` by a 0 bit: `UTerm << B0 = UTerm` impl Shl for UTerm { type Output = UTerm; #[inline] fn shl(self, _: B0) -> Self::Output { UTerm } } /// Shifting `UTerm` by a 1 bit: `UTerm << B1 = UTerm` impl Shl for UTerm { type Output = UTerm; #[inline] fn shl(self, _: B1) -> Self::Output { UTerm } } /// Shifting left any unsigned by a zero bit: `U << B0 = U` impl Shl for UInt { type Output = UInt; #[inline] fn shl(self, _: B0) -> Self::Output { UInt::new() } } /// Shifting left a `UInt` by a one bit: `UInt << B1 = UInt, B0>` impl Shl for UInt { type Output = UInt, B0>; #[inline] fn shl(self, _: B1) -> Self::Output { UInt::new() } } /// Shifting left `UInt` by `UTerm`: `UInt << UTerm = UInt` impl Shl for UInt { type Output = UInt; #[inline] fn shl(self, _: UTerm) -> Self::Output { UInt::new() } } /// Shifting left `UTerm` by an unsigned integer: `UTerm << U = UTerm` impl Shl for UTerm { type Output = UTerm; #[inline] fn shl(self, _: U) -> Self::Output { UTerm } } /// Shifting left `UInt` by `UInt`: `X << Y` = `UInt(X, B0) << (Y - 1)` impl Shl> for UInt where UInt: Sub, UInt, B0>: Shl>>, { type Output = Shleft, B0>, Sub1>>; #[inline] fn shl(self, rhs: UInt) -> Self::Output { (UInt { msb: self, lsb: B0 }).shl(rhs - B1) } } // --------------------------------------------------------------------------------------- // Shr unsigned integers /// Shifting right a `UTerm` by an unsigned integer: `UTerm >> U = UTerm` impl Shr for UTerm { type Output = UTerm; #[inline] fn shr(self, _: U) -> Self::Output { UTerm } } /// Shifting right `UInt` by `UTerm`: `UInt >> UTerm = UInt` impl Shr for UInt { type Output = UInt; #[inline] fn shr(self, _: UTerm) -> Self::Output { UInt::new() } } /// Shifting right `UTerm` by a 0 bit: `UTerm >> B0 = UTerm` impl Shr for UTerm { type Output = UTerm; #[inline] fn shr(self, _: B0) -> Self::Output { UTerm } } /// Shifting right `UTerm` by a 1 bit: `UTerm >> B1 = UTerm` impl Shr for UTerm { type Output = UTerm; #[inline] fn shr(self, _: B1) -> Self::Output { UTerm } } /// Shifting right any unsigned by a zero bit: `U >> B0 = U` impl Shr for UInt { type Output = UInt; #[inline] fn shr(self, _: B0) -> Self::Output { UInt::new() } } /// Shifting right a `UInt` by a 1 bit: `UInt >> B1 = U` impl Shr for UInt { type Output = U; #[inline] fn shr(self, _: B1) -> Self::Output { self.msb } } /// Shifting right `UInt` by `UInt`: `UInt(U, B) >> Y` = `U >> (Y - 1)` impl Shr> for UInt where UInt: Sub, U: Shr>>, { type Output = Shright>>; #[inline] fn shr(self, rhs: UInt) -> Self::Output { self.msb.shr(rhs - B1) } } // --------------------------------------------------------------------------------------- // Multiply unsigned integers /// `UInt * B0 = UTerm` impl Mul for UInt { type Output = UTerm; #[inline] fn mul(self, _: B0) -> Self::Output { UTerm } } /// `UTerm * B0 = UTerm` impl Mul for UTerm { type Output = UTerm; #[inline] fn mul(self, _: B0) -> Self::Output { UTerm } } /// `UTerm * B1 = UTerm` impl Mul for UTerm { type Output = UTerm; #[inline] fn mul(self, _: B1) -> Self::Output { UTerm } } /// `UInt * B1 = UInt` impl Mul for UInt { type Output = UInt; #[inline] fn mul(self, _: B1) -> Self::Output { UInt::new() } } /// `UInt * UTerm = UTerm` impl Mul for UInt { type Output = UTerm; #[inline] fn mul(self, _: UTerm) -> Self::Output { UTerm } } /// `UTerm * U = UTerm` impl Mul for UTerm { type Output = UTerm; #[inline] fn mul(self, _: U) -> Self::Output { UTerm } } /// `UInt * UInt = UInt<(Ul * UInt), B0>` impl Mul> for UInt where Ul: Mul>, { type Output = UInt>, B0>; #[inline] fn mul(self, rhs: UInt) -> Self::Output { UInt { msb: self.msb * rhs, lsb: B0, } } } /// `UInt * UInt = UInt<(Ul * UInt), B0> + UInt` impl Mul> for UInt where Ul: Mul>, UInt>, B0>: Add>, { type Output = Sum>, B0>, UInt>; #[inline] fn mul(self, rhs: UInt) -> Self::Output { UInt { msb: self.msb * rhs, lsb: B0, } + rhs } } // --------------------------------------------------------------------------------------- // Compare unsigned integers /// Zero == Zero impl Cmp for UTerm { type Output = Equal; #[inline] fn compare(&self, _: &UTerm) -> Self::Output { Equal } } /// Nonzero > Zero impl Cmp for UInt { type Output = Greater; #[inline] fn compare(&self, _: &UTerm) -> Self::Output { Greater } } /// Zero < Nonzero impl Cmp> for UTerm { type Output = Less; #[inline] fn compare(&self, _: &UInt) -> Self::Output { Less } } /// `UInt` cmp with `UInt`: `SoFar` is `Equal` impl Cmp> for UInt where Ul: PrivateCmp, { type Output = PrivateCmpOut; #[inline] fn compare(&self, rhs: &UInt) -> Self::Output { self.msb.private_cmp(&rhs.msb, Equal) } } /// `UInt` cmp with `UInt`: `SoFar` is `Equal` impl Cmp> for UInt where Ul: PrivateCmp, { type Output = PrivateCmpOut; #[inline] fn compare(&self, rhs: &UInt) -> Self::Output { self.msb.private_cmp(&rhs.msb, Equal) } } /// `UInt` cmp with `UInt`: `SoFar` is `Less` impl Cmp> for UInt where Ul: PrivateCmp, { type Output = PrivateCmpOut; #[inline] fn compare(&self, rhs: &UInt) -> Self::Output { self.msb.private_cmp(&rhs.msb, Less) } } /// `UInt` cmp with `UInt`: `SoFar` is `Greater` impl Cmp> for UInt where Ul: PrivateCmp, { type Output = PrivateCmpOut; #[inline] fn compare(&self, rhs: &UInt) -> Self::Output { self.msb.private_cmp(&rhs.msb, Greater) } } /// Comparing non-terimal bits, with both having bit `B0`. /// These are `Equal`, so we propogate `SoFar`. impl PrivateCmp, SoFar> for UInt where Ul: Unsigned, Ur: Unsigned, SoFar: Ord, Ul: PrivateCmp, { type Output = PrivateCmpOut; #[inline] fn private_cmp(&self, rhs: &UInt, so_far: SoFar) -> Self::Output { self.msb.private_cmp(&rhs.msb, so_far) } } /// Comparing non-terimal bits, with both having bit `B1`. /// These are `Equal`, so we propogate `SoFar`. impl PrivateCmp, SoFar> for UInt where Ul: Unsigned, Ur: Unsigned, SoFar: Ord, Ul: PrivateCmp, { type Output = PrivateCmpOut; #[inline] fn private_cmp(&self, rhs: &UInt, so_far: SoFar) -> Self::Output { self.msb.private_cmp(&rhs.msb, so_far) } } /// Comparing non-terimal bits, with `Lhs` having bit `B0` and `Rhs` having bit `B1`. /// `SoFar`, Lhs is `Less`. impl PrivateCmp, SoFar> for UInt where Ul: Unsigned, Ur: Unsigned, SoFar: Ord, Ul: PrivateCmp, { type Output = PrivateCmpOut; #[inline] fn private_cmp(&self, rhs: &UInt, _: SoFar) -> Self::Output { self.msb.private_cmp(&rhs.msb, Less) } } /// Comparing non-terimal bits, with `Lhs` having bit `B1` and `Rhs` having bit `B0`. /// `SoFar`, Lhs is `Greater`. impl PrivateCmp, SoFar> for UInt where Ul: Unsigned, Ur: Unsigned, SoFar: Ord, Ul: PrivateCmp, { type Output = PrivateCmpOut; #[inline] fn private_cmp(&self, rhs: &UInt, _: SoFar) -> Self::Output { self.msb.private_cmp(&rhs.msb, Greater) } } /// Got to the end of just the `Lhs`. It's `Less`. impl PrivateCmp, SoFar> for UTerm { type Output = Less; #[inline] fn private_cmp(&self, _: &UInt, _: SoFar) -> Self::Output { Less } } /// Got to the end of just the `Rhs`. `Lhs` is `Greater`. impl PrivateCmp for UInt { type Output = Greater; #[inline] fn private_cmp(&self, _: &UTerm, _: SoFar) -> Self::Output { Greater } } /// Got to the end of both! Return `SoFar` impl PrivateCmp for UTerm { type Output = SoFar; #[inline] fn private_cmp(&self, _: &UTerm, so_far: SoFar) -> Self::Output { so_far } } // --------------------------------------------------------------------------------------- // Getting difference in number of bits impl BitDiff> for UInt where Ul: Unsigned, Bl: Bit, Ur: Unsigned, Br: Bit, Ul: BitDiff, { type Output = BitDiffOut; } impl
                                          BitDiff for Ul where Ul: Unsigned + Len, { type Output = Length
                                            ; } // --------------------------------------------------------------------------------------- // Shifting one number until it's the size of another use private::ShiftDiff; impl ShiftDiff for Ul where Ur: BitDiff
                                              , Ul: Shl>, { type Output = Shleft>; } // --------------------------------------------------------------------------------------- // Powers of unsigned integers /// X^N impl Pow for X where X: PrivatePow, { type Output = PrivatePowOut; #[inline] fn powi(self, n: N) -> Self::Output { self.private_pow(U1::new(), n) } } impl PrivatePow for X { type Output = Y; #[inline] fn private_pow(self, y: Y, _: U0) -> Self::Output { y } } impl PrivatePow for X where X: Mul, { type Output = Prod; #[inline] fn private_pow(self, y: Y, _: U1) -> Self::Output { self * y } } /// N is even impl PrivatePow, B0>> for X where X: Mul, Square: PrivatePow>, { type Output = PrivatePowOut, Y, UInt>; #[inline] fn private_pow(self, y: Y, n: UInt, B0>) -> Self::Output { (self * self).private_pow(y, n.msb) } } /// N is odd impl PrivatePow, B1>> for X where X: Mul + Mul, Square: PrivatePow, UInt>, { type Output = PrivatePowOut, Prod, UInt>; #[inline] fn private_pow(self, y: Y, n: UInt, B1>) -> Self::Output { (self * self).private_pow(self * y, n.msb) } } //------------------------------------------ // Greatest Common Divisor /// The even number 2*N #[allow(unused)] // Silence spurious warning on older versions of rust type Even = UInt; /// The odd number 2*N + 1 type Odd = UInt; /// gcd(0, 0) = 0 impl Gcd for U0 { type Output = U0; } /// gcd(x, 0) = x impl Gcd for X where X: Unsigned + NonZero, { type Output = X; } /// gcd(0, y) = y impl Gcd for U0 where Y: Unsigned + NonZero, { type Output = Y; } /// gcd(x, y) = 2*gcd(x/2, y/2) if both x and y even impl Gcd> for Even where Xp: Gcd, Even: NonZero, Even: NonZero, { type Output = UInt, B0>; } /// gcd(x, y) = gcd(x, y/2) if x odd and y even impl Gcd> for Odd where Odd: Gcd, Even: NonZero, { type Output = Gcf, Yp>; } /// gcd(x, y) = gcd(x/2, y) if x even and y odd impl Gcd> for Even where Xp: Gcd>, Even: NonZero, { type Output = Gcf>; } /// gcd(x, y) = gcd([max(x, y) - min(x, y)], min(x, y)) if both x and y odd /// /// This will immediately invoke the case for x even and y odd because the difference of two odd /// numbers is an even number. impl Gcd> for Odd where Odd: Max> + Min>, Odd: Max> + Min>, Maximum, Odd>: Sub, Odd>>, Diff, Odd>, Minimum, Odd>>: Gcd, Odd>>, { type Output = Gcf, Odd>, Minimum, Odd>>, Minimum, Odd>>; } #[cfg(test)] mod gcd_tests { use super::*; use consts::*; macro_rules! gcd_test { ( $( $a:ident, $b:ident => $c:ident ),* $(,)* ) => { $( assert_eq!( as Unsigned>::to_usize(), $c::to_usize()); assert_eq!( as Unsigned>::to_usize(), $c::to_usize()); )* } } #[test] fn gcd() { gcd_test! { U0, U0 => U0, U0, U42 => U42, U12, U8 => U4, U13, U1013 => U1, // Two primes U9, U26 => U1, // Not prime but coprime U143, U273 => U13, U117, U273 => U39, } } } // ----------------------------------------- // GetBit #[allow(missing_docs)] pub trait GetBit { #[allow(missing_docs)] type Output; #[doc(hidden)] fn get_bit(&self, &I) -> Self::Output; } #[allow(missing_docs)] pub type GetBitOut = >::Output; // Base case impl GetBit for UInt where Bn: Copy, { type Output = Bn; #[inline] fn get_bit(&self, _: &U0) -> Self::Output { self.lsb } } // Recursion case impl GetBit> for UInt where UInt: Copy + Sub, Un: GetBit>>, { type Output = GetBitOut>>; #[inline] fn get_bit(&self, i: &UInt) -> Self::Output { self.msb.get_bit::(&(*i - B1)) } } // Ran out of bits impl GetBit for UTerm { type Output = B0; #[inline] fn get_bit(&self, _: &I) -> Self::Output { B0 } } #[test] fn test_get_bit() { use consts::*; use Same; type T1 = as Same>::Output; type T2 = as Same>::Output; type T3 = as Same>::Output; ::to_bool(); ::to_bool(); ::to_bool(); } // ----------------------------------------- // SetBit /// A **type operator** that, when implemented for unsigned integer `N`, sets the bit at position /// `I` to `B`. pub trait SetBit { #[allow(missing_docs)] type Output; #[doc(hidden)] fn set_bit(self, I, B) -> Self::Output; } /// Alias for the result of calling `SetBit`: `SetBitOut = >::Output`. pub type SetBitOut = >::Output; use private::{PrivateSetBit, PrivateSetBitOut}; // Call private one then trim it impl SetBit for N where N: PrivateSetBit, PrivateSetBitOut: Trim, { type Output = TrimOut>; #[inline] fn set_bit(self, i: I, b: B) -> Self::Output { self.private_set_bit(i, b).trim() } } // Base case impl PrivateSetBit for UInt { type Output = UInt; #[inline] fn private_set_bit(self, _: U0, b: B) -> Self::Output { UInt { msb: self.msb, lsb: b, } } } // Recursion case impl PrivateSetBit, B> for UInt where UInt: Sub, Un: PrivateSetBit>, B>, { type Output = UInt>, B>, Bn>; #[inline] fn private_set_bit(self, i: UInt, b: B) -> Self::Output { UInt { msb: self.msb.private_set_bit(i - B1, b), lsb: self.lsb, } } } // Ran out of bits, setting B0 impl PrivateSetBit for UTerm { type Output = UTerm; #[inline] fn private_set_bit(self, _: I, _: B0) -> Self::Output { UTerm } } // Ran out of bits, setting B1 impl PrivateSetBit for UTerm where U1: Shl, { type Output = Shleft; #[inline] fn private_set_bit(self, i: I, _: B1) -> Self::Output { >::shl(U1::new(), i) } } #[test] fn test_set_bit() { use consts::*; use Same; type T1 = as Same>::Output; type T2 = as Same>::Output; type T3 = as Same>::Output; type T4 = as Same>::Output; type T5 = as Same>::Output; type T6 = as Same>::Output; type T7 = as Same>::Output; type T8 = as Same>::Output; type T9 = as Same>::Output; type T10 = as Same>::Output; type T11 = as Same>::Output; ::to_u32(); ::to_u32(); ::to_u32(); ::to_u32(); ::to_u32(); ::to_u32(); ::to_u32(); ::to_u32(); ::to_u32(); ::to_u32(); ::to_u32(); } // ----------------------------------------- // Division algorithm: // We have N / D: // let Q = 0, R = 0 // NBits = len(N) // for I in NBits-1..0: // R <<=1 // R[0] = N[i] // let C = R.cmp(D) // if C == Equal or Greater: // R -= D // Q[i] = 1 #[cfg(tests)] mod tests { macro_rules! test_div { ($a:ident / $b:ident = $c:ident) => {{ type R = Quot<$a, $b>; assert_eq!(::to_usize(), $c::to_usize()); }}; } #[test] fn test_div() { use consts::*; use {Quot, Same}; test_div!(U0 / U1 = U0); test_div!(U1 / U1 = U1); test_div!(U2 / U1 = U2); test_div!(U3 / U1 = U3); test_div!(U4 / U1 = U4); test_div!(U0 / U2 = U0); test_div!(U1 / U2 = U0); test_div!(U2 / U2 = U1); test_div!(U3 / U2 = U1); test_div!(U4 / U2 = U2); test_div!(U6 / U2 = U3); test_div!(U7 / U2 = U3); type T = as Same>::Output; ::to_u32(); } } // ----------------------------------------- // Div use core::ops::Div; // 0 // N impl Div> for UTerm { type Output = UTerm; #[inline] fn div(self, _: UInt) -> Self::Output { UTerm } } // M // N impl Div> for UInt where UInt: Len, Length>: Sub, (): PrivateDiv, UInt, U0, U0, Sub1>>>, { type Output = PrivateDivQuot, UInt, U0, U0, Sub1>>>; #[inline] #[cfg_attr(feature = "cargo-clippy", allow(clippy::suspicious_arithmetic_impl))] fn div(self, rhs: UInt) -> Self::Output { ().private_div_quotient(self, rhs, U0::new(), U0::new(), self.len() - B1) } } // ----------------------------------------- // Rem use core::ops::Rem; // 0 % N impl Rem> for UTerm { type Output = UTerm; #[inline] fn rem(self, _: UInt) -> Self::Output { UTerm } } // M % N impl Rem> for UInt where UInt: Len, Length>: Sub, (): PrivateDiv, UInt, U0, U0, Sub1>>>, { type Output = PrivateDivRem, UInt, U0, U0, Sub1>>>; #[inline] fn rem(self, rhs: UInt) -> Self::Output { ().private_div_remainder(self, rhs, UTerm, UTerm, self.len() - B1) } } // ----------------------------------------- // PrivateDiv use private::{PrivateDiv, PrivateDivQuot, PrivateDivRem}; use Compare; // R == 0: We set R = UInt, then call out to PrivateDivIf for the if statement impl PrivateDiv for () where N: GetBit, UInt>: Trim, TrimOut>>: Cmp, (): PrivateDivIf< N, D, Q, TrimOut>>, I, Compare>>, D>, >, { type Quotient = PrivateDivIfQuot< N, D, Q, TrimOut>>, I, Compare>>, D>, >; type Remainder = PrivateDivIfRem< N, D, Q, TrimOut>>, I, Compare>>, D>, >; #[inline] fn private_div_quotient(self, n: N, d: D, q: Q, _: U0, i: I) -> Self::Quotient where { let r = (UInt { msb: UTerm, lsb: n.get_bit::(&i), }) .trim(); let r_cmp_d = r.compare::(&d); ().private_div_if_quotient(n, d, q, r, i, r_cmp_d) } #[inline] fn private_div_remainder(self, n: N, d: D, q: Q, _: U0, i: I) -> Self::Remainder { let r = (UInt { msb: UTerm, lsb: n.get_bit::(&i), }) .trim(); let r_cmp_d = r.compare::(&d); ().private_div_if_remainder(n, d, q, r, i, r_cmp_d) } } // R > 0: We perform R <<= 1 and R[0] = N[i], then call out to PrivateDivIf for the if statement impl PrivateDiv, I> for () where N: GetBit, UInt, GetBitOut>: Cmp, (): PrivateDivIf< N, D, Q, UInt, GetBitOut>, I, Compare, GetBitOut>, D>, >, { type Quotient = PrivateDivIfQuot< N, D, Q, UInt, GetBitOut>, I, Compare, GetBitOut>, D>, >; type Remainder = PrivateDivIfRem< N, D, Q, UInt, GetBitOut>, I, Compare, GetBitOut>, D>, >; #[inline] fn private_div_quotient(self, n: N, d: D, q: Q, r: UInt, i: I) -> Self::Quotient { let r = UInt { msb: r, lsb: n.get_bit::(&i), }; let r_cmp_d = r.compare::(&d); ().private_div_if_quotient(n, d, q, r, i, r_cmp_d) } #[inline] fn private_div_remainder(self, n: N, d: D, q: Q, r: UInt, i: I) -> Self::Remainder { let r = UInt { msb: r, lsb: n.get_bit::(&i), }; let r_cmp_d = r.compare::(&d); ().private_div_if_remainder(n, d, q, r, i, r_cmp_d) } } // ----------------------------------------- // PrivateDivIf use private::{PrivateDivIf, PrivateDivIfQuot, PrivateDivIfRem}; // R < D, I > 0, we do nothing and recurse impl PrivateDivIf, Less> for () where UInt: Sub, (): PrivateDiv>>, { type Quotient = PrivateDivQuot>>; type Remainder = PrivateDivRem>>; #[inline] fn private_div_if_quotient( self, n: N, d: D, q: Q, r: R, i: UInt, _: Less, ) -> Self::Quotient where { ().private_div_quotient(n, d, q, r, i - B1) } #[inline] fn private_div_if_remainder( self, n: N, d: D, q: Q, r: R, i: UInt, _: Less, ) -> Self::Remainder where { ().private_div_remainder(n, d, q, r, i - B1) } } // R == D, I > 0, we set R = 0, Q[I] = 1 and recurse impl PrivateDivIf, Equal> for () where UInt: Copy + Sub, Q: SetBit, B1>, (): PrivateDiv, B1>, U0, Sub1>>, { type Quotient = PrivateDivQuot, B1>, U0, Sub1>>; type Remainder = PrivateDivRem, B1>, U0, Sub1>>; #[inline] fn private_div_if_quotient( self, n: N, d: D, q: Q, _: R, i: UInt, _: Equal, ) -> Self::Quotient where { ().private_div_quotient(n, d, q.set_bit::(i, B1), U0::new(), i - B1) } #[inline] fn private_div_if_remainder( self, n: N, d: D, q: Q, _: R, i: UInt, _: Equal, ) -> Self::Remainder where { ().private_div_remainder(n, d, q.set_bit::(i, B1), U0::new(), i - B1) } } use Diff; // R > D, I > 0, we set R -= D, Q[I] = 1 and recurse impl PrivateDivIf, Greater> for () where D: Copy, UInt: Copy + Sub, R: Sub, Q: SetBit, B1>, (): PrivateDiv, B1>, Diff, Sub1>>, { type Quotient = PrivateDivQuot, B1>, Diff, Sub1>>; type Remainder = PrivateDivRem, B1>, Diff, Sub1>>; #[inline] fn private_div_if_quotient( self, n: N, d: D, q: Q, r: R, i: UInt, _: Greater, ) -> Self::Quotient where { ().private_div_quotient(n, d, q.set_bit::(i, B1), r - d, i - B1) } #[inline] fn private_div_if_remainder( self, n: N, d: D, q: Q, r: R, i: UInt, _: Greater, ) -> Self::Remainder where { ().private_div_remainder(n, d, q.set_bit::(i, B1), r - d, i - B1) } } // R < D, I == 0: we do nothing, and return impl PrivateDivIf for () { type Quotient = Q; type Remainder = R; #[inline] fn private_div_if_quotient(self, _: N, _: D, q: Q, _: R, _: U0, _: Less) -> Self::Quotient { q } #[inline] fn private_div_if_remainder(self, _: N, _: D, _: Q, r: R, _: U0, _: Less) -> Self::Remainder { r } } // R == D, I == 0: we set R = 0, Q[I] = 1, and return impl PrivateDivIf for () where Q: SetBit, { type Quotient = SetBitOut; type Remainder = U0; #[inline] fn private_div_if_quotient(self, _: N, _: D, q: Q, _: R, i: U0, _: Equal) -> Self::Quotient { q.set_bit::(i, B1) } #[inline] fn private_div_if_remainder(self, _: N, _: D, _: Q, _: R, i: U0, _: Equal) -> Self::Remainder { i } } // R > D, I == 0: We set R -= D, Q[I] = 1, and return impl PrivateDivIf for () where R: Sub, Q: SetBit, { type Quotient = SetBitOut; type Remainder = Diff; #[inline] fn private_div_if_quotient(self, _: N, _: D, q: Q, _: R, i: U0, _: Greater) -> Self::Quotient { q.set_bit::(i, B1) } #[inline] fn private_div_if_remainder( self, _: N, d: D, _: Q, r: R, _: U0, _: Greater, ) -> Self::Remainder { r - d } } // ----------------------------------------- // PartialDiv use {PartialDiv, Quot}; impl PartialDiv> for UTerm { type Output = UTerm; #[inline] fn partial_div(self, _: UInt) -> Self::Output { UTerm } } // M / N impl PartialDiv> for UInt where UInt: Div> + Rem, Output = U0>, { type Output = Quot, UInt>; #[inline] fn partial_div(self, rhs: UInt) -> Self::Output { self / rhs } } // ----------------------------------------- // PrivateMin use private::{PrivateMin, PrivateMinOut}; impl PrivateMin for UInt where Ur: Unsigned, U: Unsigned, B: Bit, { type Output = UInt; #[inline] fn private_min(self, _: Ur) -> Self::Output { self } } impl PrivateMin for UInt where Ur: Unsigned, U: Unsigned, B: Bit, { type Output = UInt; #[inline] fn private_min(self, _: Ur) -> Self::Output { self } } impl PrivateMin for UInt where Ur: Unsigned, U: Unsigned, B: Bit, { type Output = Ur; #[inline] fn private_min(self, rhs: Ur) -> Self::Output { rhs } } // ----------------------------------------- // Min use Min; impl Min for UTerm where U: Unsigned, { type Output = UTerm; #[inline] fn min(self, _: U) -> Self::Output { self } } impl Min for UInt where U: Unsigned, B: Bit, Ur: Unsigned, UInt: Cmp + PrivateMin, Ur>>, { type Output = PrivateMinOut, Ur, Compare, Ur>>; #[inline] fn min(self, rhs: Ur) -> Self::Output { self.private_min(rhs) } } // ----------------------------------------- // PrivateMax use private::{PrivateMax, PrivateMaxOut}; impl PrivateMax for UInt where Ur: Unsigned, U: Unsigned, B: Bit, { type Output = UInt; #[inline] fn private_max(self, _: Ur) -> Self::Output { self } } impl PrivateMax for UInt where Ur: Unsigned, U: Unsigned, B: Bit, { type Output = Ur; #[inline] fn private_max(self, rhs: Ur) -> Self::Output { rhs } } impl PrivateMax for UInt where Ur: Unsigned, U: Unsigned, B: Bit, { type Output = UInt; #[inline] fn private_max(self, _: Ur) -> Self::Output { self } } // ----------------------------------------- // Max use Max; impl Max for UTerm where U: Unsigned, { type Output = U; #[inline] fn max(self, rhs: U) -> Self::Output { rhs } } impl Max for UInt where U: Unsigned, B: Bit, Ur: Unsigned, UInt: Cmp + PrivateMax, Ur>>, { type Output = PrivateMaxOut, Ur, Compare, Ur>>; #[inline] fn max(self, rhs: Ur) -> Self::Output { self.private_max(rhs) } } // ----------------------------------------- // SquareRoot impl SquareRoot for N where N: PrivateSquareRoot, { type Output = ::Output; } // sqrt(0) = 0. impl PrivateSquareRoot for UTerm { type Output = UTerm; } // sqrt(1) = 1. impl PrivateSquareRoot for UInt { type Output = UInt; } // General case of sqrt(Self) where Self >= 2. If a and b are // bit-valued and Self = 4*u + 2*a + b, then the integer-valued // (fractional part truncated) square root of Self is either 2*sqrt(u) // or 2*sqrt(u)+1. Guess and check by comparing (2*sqrt(u)+1)^2 // against Self. Since the `typenum` result of that comparison is a // bit, directly add that bit to 2*sqrt(u). // // Use `Sum>, GrEq<...>>` instead of `UInt, // GrEq<...>>` because `Sqrt` can turn out to be `UTerm` and // `GrEq<...>` can turn out to be `B0`, which would not be a valid // UInt as leading zeros are disallowed. impl PrivateSquareRoot for UInt, Bb> where U: Unsigned, Ba: Bit, Bb: Bit, U: SquareRoot, Sqrt: Shl, Double>: Add, Add1>>: Mul, Self: IsGreaterOrEqual>>>>, Double>: Add>>>>>, { type Output = Sum>, GrEq>>>>>; } #[test] fn sqrt_test() { use consts::*; assert_eq!(0, >::to_u32()); assert_eq!(1, >::to_u32()); assert_eq!(1, >::to_u32()); assert_eq!(1, >::to_u32()); assert_eq!(2, >::to_u32()); assert_eq!(2, >::to_u32()); assert_eq!(2, >::to_u32()); assert_eq!(2, >::to_u32()); assert_eq!(2, >::to_u32()); assert_eq!(3, >::to_u32()); assert_eq!(3, >::to_u32()); assert_eq!(3, >::to_u32()); assert_eq!(3, >::to_u32()); assert_eq!(3, >::to_u32()); assert_eq!(3, >::to_u32()); assert_eq!(3, >::to_u32()); assert_eq!(4, >::to_u32()); assert_eq!(4, >::to_u32()); assert_eq!(4, >::to_u32()); assert_eq!(4, >::to_u32()); assert_eq!(4, >::to_u32()); assert_eq!(4, >::to_u32()); assert_eq!(4, >::to_u32()); assert_eq!(4, >::to_u32()); assert_eq!(4, >::to_u32()); assert_eq!(5, >::to_u32()); assert_eq!(5, >::to_u32()); // ... } // ----------------------------------------- // Logarithm2 impl Logarithm2 for N where N: PrivateLogarithm2, { type Output = ::Output; } // log2(1) = 0. impl PrivateLogarithm2 for UInt { type Output = U0; } // General case of log2(Self) where Self >= 2. impl PrivateLogarithm2 for UInt where U: Unsigned + Logarithm2, B: Bit, Log2: Add, { type Output = Add1>; } #[test] fn log2_test() { use consts::*; assert_eq!(0, >::to_u32()); assert_eq!(1, >::to_u32()); assert_eq!(1, >::to_u32()); assert_eq!(2, >::to_u32()); assert_eq!(2, >::to_u32()); assert_eq!(2, >::to_u32()); assert_eq!(2, >::to_u32()); assert_eq!(3, >::to_u32()); assert_eq!(3, >::to_u32()); assert_eq!(3, >::to_u32()); assert_eq!(3, >::to_u32()); assert_eq!(3, >::to_u32()); assert_eq!(3, >::to_u32()); assert_eq!(3, >::to_u32()); assert_eq!(3, >::to_u32()); assert_eq!(4, >::to_u32()); assert_eq!(4, >::to_u32()); assert_eq!(4, >::to_u32()); assert_eq!(4, >::to_u32()); assert_eq!(4, >::to_u32()); assert_eq!(4, >::to_u32()); assert_eq!(4, >::to_u32()); assert_eq!(4, >::to_u32()); assert_eq!(4, >::to_u32()); assert_eq!(4, >::to_u32()); assert_eq!(4, >::to_u32()); assert_eq!(4, >::to_u32()); assert_eq!(4, >::to_u32()); assert_eq!(4, >::to_u32()); assert_eq!(4, >::to_u32()); assert_eq!(4, >::to_u32()); assert_eq!(5, >::to_u32()); assert_eq!(5, >::to_u32()); // ... }