|  | //! Integers used for wide operations, larger than `u128`. | 
|  |  | 
|  | #[cfg(test)] | 
|  | mod tests; | 
|  |  | 
|  | use core::ops; | 
|  |  | 
|  | use super::{DInt, HInt, Int, MinInt}; | 
|  |  | 
|  | const U128_LO_MASK: u128 = u64::MAX as u128; | 
|  |  | 
|  | /// A 256-bit unsigned integer represented as two 128-bit native-endian limbs. | 
|  | #[allow(non_camel_case_types)] | 
|  | #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Eq, Ord)] | 
|  | pub struct u256 { | 
|  | pub hi: u128, | 
|  | pub lo: u128, | 
|  | } | 
|  |  | 
|  | impl u256 { | 
|  | #[cfg(any(test, feature = "unstable-public-internals"))] | 
|  | pub const MAX: Self = Self { | 
|  | lo: u128::MAX, | 
|  | hi: u128::MAX, | 
|  | }; | 
|  |  | 
|  | /// Reinterpret as a signed integer | 
|  | pub fn signed(self) -> i256 { | 
|  | i256 { | 
|  | lo: self.lo, | 
|  | hi: self.hi as i128, | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | /// A 256-bit signed integer represented as two 128-bit native-endian limbs. | 
|  | #[allow(non_camel_case_types)] | 
|  | #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Eq, Ord)] | 
|  | pub struct i256 { | 
|  | pub hi: i128, | 
|  | pub lo: u128, | 
|  | } | 
|  |  | 
|  | impl i256 { | 
|  | /// Reinterpret as an unsigned integer | 
|  | #[cfg(any(test, feature = "unstable-public-internals"))] | 
|  | pub fn unsigned(self) -> u256 { | 
|  | u256 { | 
|  | lo: self.lo, | 
|  | hi: self.hi as u128, | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | impl MinInt for u256 { | 
|  | type OtherSign = i256; | 
|  |  | 
|  | type Unsigned = u256; | 
|  |  | 
|  | const SIGNED: bool = false; | 
|  | const BITS: u32 = 256; | 
|  | const ZERO: Self = Self { lo: 0, hi: 0 }; | 
|  | const ONE: Self = Self { lo: 1, hi: 0 }; | 
|  | const MIN: Self = Self { lo: 0, hi: 0 }; | 
|  | const MAX: Self = Self { | 
|  | lo: u128::MAX, | 
|  | hi: u128::MAX, | 
|  | }; | 
|  | } | 
|  |  | 
|  | impl MinInt for i256 { | 
|  | type OtherSign = u256; | 
|  |  | 
|  | type Unsigned = u256; | 
|  |  | 
|  | const SIGNED: bool = true; | 
|  | const BITS: u32 = 256; | 
|  | const ZERO: Self = Self { lo: 0, hi: 0 }; | 
|  | const ONE: Self = Self { lo: 1, hi: 0 }; | 
|  | const MIN: Self = Self { | 
|  | lo: u128::MIN, | 
|  | hi: i128::MIN, | 
|  | }; | 
|  | const MAX: Self = Self { | 
|  | lo: u128::MAX, | 
|  | hi: i128::MAX, | 
|  | }; | 
|  | } | 
|  |  | 
|  | macro_rules! impl_common { | 
|  | ($ty:ty) => { | 
|  | impl ops::BitOr for $ty { | 
|  | type Output = Self; | 
|  |  | 
|  | fn bitor(mut self, rhs: Self) -> Self::Output { | 
|  | self.lo |= rhs.lo; | 
|  | self.hi |= rhs.hi; | 
|  | self | 
|  | } | 
|  | } | 
|  |  | 
|  | impl ops::Not for $ty { | 
|  | type Output = Self; | 
|  |  | 
|  | fn not(mut self) -> Self::Output { | 
|  | self.lo = !self.lo; | 
|  | self.hi = !self.hi; | 
|  | self | 
|  | } | 
|  | } | 
|  |  | 
|  | impl ops::Add<Self> for $ty { | 
|  | type Output = Self; | 
|  |  | 
|  | fn add(self, rhs: Self) -> Self::Output { | 
|  | let (lo, carry) = self.lo.overflowing_add(rhs.lo); | 
|  | let (hi, of) = Int::carrying_add(self.hi, rhs.hi, carry); | 
|  | debug_assert!(!of, "attempt to add with overflow"); | 
|  | Self { lo, hi } | 
|  | } | 
|  | } | 
|  |  | 
|  | impl ops::Sub<Self> for $ty { | 
|  | type Output = Self; | 
|  |  | 
|  | fn sub(self, rhs: Self) -> Self::Output { | 
|  | let (lo, borrow) = self.lo.overflowing_sub(rhs.lo); | 
|  | let (hi, of) = Int::borrowing_sub(self.hi, rhs.hi, borrow); | 
|  | debug_assert!(!of, "attempt to subtract with overflow"); | 
|  | Self { lo, hi } | 
|  | } | 
|  | } | 
|  |  | 
|  | impl ops::Shl<u32> for $ty { | 
|  | type Output = Self; | 
|  |  | 
|  | fn shl(mut self, rhs: u32) -> Self::Output { | 
|  | debug_assert!(rhs < Self::BITS, "attempt to shift left with overflow"); | 
|  |  | 
|  | let half_bits = Self::BITS / 2; | 
|  | let low_mask = half_bits - 1; | 
|  | let s = rhs & low_mask; | 
|  |  | 
|  | let lo = self.lo; | 
|  | let hi = self.hi; | 
|  |  | 
|  | self.lo = lo << s; | 
|  |  | 
|  | if rhs & half_bits == 0 { | 
|  | self.hi = (lo >> (low_mask ^ s) >> 1) as _; | 
|  | self.hi |= hi << s; | 
|  | } else { | 
|  | self.hi = self.lo as _; | 
|  | self.lo = 0; | 
|  | } | 
|  | self | 
|  | } | 
|  | } | 
|  |  | 
|  | impl ops::Shr<u32> for $ty { | 
|  | type Output = Self; | 
|  |  | 
|  | fn shr(mut self, rhs: u32) -> Self::Output { | 
|  | debug_assert!(rhs < Self::BITS, "attempt to shift right with overflow"); | 
|  |  | 
|  | let half_bits = Self::BITS / 2; | 
|  | let low_mask = half_bits - 1; | 
|  | let s = rhs & low_mask; | 
|  |  | 
|  | let lo = self.lo; | 
|  | let hi = self.hi; | 
|  |  | 
|  | self.hi = hi >> s; | 
|  |  | 
|  | #[allow(unused_comparisons)] | 
|  | if rhs & half_bits == 0 { | 
|  | self.lo = (hi << (low_mask ^ s) << 1) as _; | 
|  | self.lo |= lo >> s; | 
|  | } else { | 
|  | self.lo = self.hi as _; | 
|  | self.hi = if hi < 0 { !0 } else { 0 }; | 
|  | } | 
|  | self | 
|  | } | 
|  | } | 
|  | }; | 
|  | } | 
|  |  | 
|  | impl_common!(i256); | 
|  | impl_common!(u256); | 
|  |  | 
|  | impl HInt for u128 { | 
|  | type D = u256; | 
|  |  | 
|  | fn widen(self) -> Self::D { | 
|  | u256 { lo: self, hi: 0 } | 
|  | } | 
|  |  | 
|  | fn zero_widen(self) -> Self::D { | 
|  | self.widen() | 
|  | } | 
|  |  | 
|  | fn zero_widen_mul(self, rhs: Self) -> Self::D { | 
|  | let l0 = self & U128_LO_MASK; | 
|  | let l1 = rhs & U128_LO_MASK; | 
|  | let h0 = self >> 64; | 
|  | let h1 = rhs >> 64; | 
|  |  | 
|  | let p_ll: u128 = l0.overflowing_mul(l1).0; | 
|  | let p_lh: u128 = l0.overflowing_mul(h1).0; | 
|  | let p_hl: u128 = h0.overflowing_mul(l1).0; | 
|  | let p_hh: u128 = h0.overflowing_mul(h1).0; | 
|  |  | 
|  | let s0 = p_hl + (p_ll >> 64); | 
|  | let s1 = (p_ll & U128_LO_MASK) + (s0 << 64); | 
|  | let s2 = p_lh + (s1 >> 64); | 
|  |  | 
|  | let lo = (p_ll & U128_LO_MASK) + (s2 << 64); | 
|  | let hi = p_hh + (s0 >> 64) + (s2 >> 64); | 
|  |  | 
|  | u256 { lo, hi } | 
|  | } | 
|  |  | 
|  | fn widen_mul(self, rhs: Self) -> Self::D { | 
|  | self.zero_widen_mul(rhs) | 
|  | } | 
|  |  | 
|  | fn widen_hi(self) -> Self::D { | 
|  | u256 { lo: 0, hi: self } | 
|  | } | 
|  | } | 
|  |  | 
|  | impl HInt for i128 { | 
|  | type D = i256; | 
|  |  | 
|  | fn widen(self) -> Self::D { | 
|  | i256 { | 
|  | lo: self as u128, | 
|  | hi: if self < 0 { -1 } else { 0 }, | 
|  | } | 
|  | } | 
|  |  | 
|  | fn zero_widen(self) -> Self::D { | 
|  | self.unsigned().zero_widen().signed() | 
|  | } | 
|  |  | 
|  | fn zero_widen_mul(self, rhs: Self) -> Self::D { | 
|  | self.unsigned().zero_widen_mul(rhs.unsigned()).signed() | 
|  | } | 
|  |  | 
|  | fn widen_mul(self, _rhs: Self) -> Self::D { | 
|  | unimplemented!("signed i128 widening multiply is not used") | 
|  | } | 
|  |  | 
|  | fn widen_hi(self) -> Self::D { | 
|  | i256 { lo: 0, hi: self } | 
|  | } | 
|  | } | 
|  |  | 
|  | impl DInt for u256 { | 
|  | type H = u128; | 
|  |  | 
|  | fn lo(self) -> Self::H { | 
|  | self.lo | 
|  | } | 
|  |  | 
|  | fn hi(self) -> Self::H { | 
|  | self.hi | 
|  | } | 
|  | } | 
|  |  | 
|  | impl DInt for i256 { | 
|  | type H = i128; | 
|  |  | 
|  | fn lo(self) -> Self::H { | 
|  | self.lo as i128 | 
|  | } | 
|  |  | 
|  | fn hi(self) -> Self::H { | 
|  | self.hi | 
|  | } | 
|  | } |