1#[cfg(test)]
4mod tests;
5
6use core::ops;
7
8use super::{DInt, HInt, Int, MinInt};
9
10const U128_LO_MASK: u128 = u64::MAX as u128;
11
12#[allow(non_camel_case_types)]
14#[derive(#[automatically_derived]
#[allow(non_camel_case_types)]
impl ::core::clone::Clone for u256 {
#[inline]
fn clone(&self) -> u256 {
let _: ::core::clone::AssertParamIsClone<u128>;
*self
}
}Clone, #[automatically_derived]
#[allow(non_camel_case_types)]
impl ::core::marker::Copy for u256 { }Copy, #[automatically_derived]
#[allow(non_camel_case_types)]
impl ::core::fmt::Debug for u256 {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field2_finish(f, "u256", "hi",
&self.hi, "lo", &&self.lo)
}
}Debug, #[automatically_derived]
#[allow(non_camel_case_types)]
impl ::core::cmp::PartialEq for u256 {
#[inline]
fn eq(&self, other: &u256) -> bool {
self.hi == other.hi && self.lo == other.lo
}
}PartialEq, #[automatically_derived]
#[allow(non_camel_case_types)]
impl ::core::cmp::PartialOrd for u256 {
#[inline]
fn partial_cmp(&self, other: &u256)
-> ::core::option::Option<::core::cmp::Ordering> {
match ::core::cmp::PartialOrd::partial_cmp(&self.hi, &other.hi) {
::core::option::Option::Some(::core::cmp::Ordering::Equal) =>
::core::cmp::PartialOrd::partial_cmp(&self.lo, &other.lo),
cmp => cmp,
}
}
}PartialOrd, #[automatically_derived]
#[allow(non_camel_case_types)]
impl ::core::cmp::Eq for u256 {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<u128>;
}
}Eq, #[automatically_derived]
#[allow(non_camel_case_types)]
impl ::core::cmp::Ord for u256 {
#[inline]
fn cmp(&self, other: &u256) -> ::core::cmp::Ordering {
match ::core::cmp::Ord::cmp(&self.hi, &other.hi) {
::core::cmp::Ordering::Equal =>
::core::cmp::Ord::cmp(&self.lo, &other.lo),
cmp => cmp,
}
}
}Ord)]
15pub struct u256 {
16 pub hi: u128,
17 pub lo: u128,
18}
19
20impl u256 {
21 #[cfg(any(test, feature = "unstable-public-internals"))]
22 pub const MAX: Self = Self {
23 lo: u128::MAX,
24 hi: u128::MAX,
25 };
26
27 pub fn signed(self) -> i256 {
29 i256 {
30 lo: self.lo,
31 hi: self.hi as i128,
32 }
33 }
34}
35
36#[allow(non_camel_case_types)]
38#[derive(#[automatically_derived]
#[allow(non_camel_case_types)]
impl ::core::clone::Clone for i256 {
#[inline]
fn clone(&self) -> i256 {
let _: ::core::clone::AssertParamIsClone<i128>;
let _: ::core::clone::AssertParamIsClone<u128>;
*self
}
}Clone, #[automatically_derived]
#[allow(non_camel_case_types)]
impl ::core::marker::Copy for i256 { }Copy, #[automatically_derived]
#[allow(non_camel_case_types)]
impl ::core::fmt::Debug for i256 {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field2_finish(f, "i256", "hi",
&self.hi, "lo", &&self.lo)
}
}Debug, #[automatically_derived]
#[allow(non_camel_case_types)]
impl ::core::cmp::PartialEq for i256 {
#[inline]
fn eq(&self, other: &i256) -> bool {
self.hi == other.hi && self.lo == other.lo
}
}PartialEq, #[automatically_derived]
#[allow(non_camel_case_types)]
impl ::core::cmp::PartialOrd for i256 {
#[inline]
fn partial_cmp(&self, other: &i256)
-> ::core::option::Option<::core::cmp::Ordering> {
match ::core::cmp::PartialOrd::partial_cmp(&self.hi, &other.hi) {
::core::option::Option::Some(::core::cmp::Ordering::Equal) =>
::core::cmp::PartialOrd::partial_cmp(&self.lo, &other.lo),
cmp => cmp,
}
}
}PartialOrd, #[automatically_derived]
#[allow(non_camel_case_types)]
impl ::core::cmp::Eq for i256 {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<i128>;
let _: ::core::cmp::AssertParamIsEq<u128>;
}
}Eq, #[automatically_derived]
#[allow(non_camel_case_types)]
impl ::core::cmp::Ord for i256 {
#[inline]
fn cmp(&self, other: &i256) -> ::core::cmp::Ordering {
match ::core::cmp::Ord::cmp(&self.hi, &other.hi) {
::core::cmp::Ordering::Equal =>
::core::cmp::Ord::cmp(&self.lo, &other.lo),
cmp => cmp,
}
}
}Ord)]
39pub struct i256 {
40 pub hi: i128,
41 pub lo: u128,
42}
43
44impl i256 {
45 #[cfg(any(test, feature = "unstable-public-internals"))]
47 pub fn unsigned(self) -> u256 {
48 u256 {
49 lo: self.lo,
50 hi: self.hi as u128,
51 }
52 }
53}
54
55impl MinInt for u256 {
56 type OtherSign = i256;
57
58 type Unsigned = u256;
59
60 const SIGNED: bool = false;
61 const BITS: u32 = 256;
62 const ZERO: Self = Self { lo: 0, hi: 0 };
63 const ONE: Self = Self { lo: 1, hi: 0 };
64 const MIN: Self = Self { lo: 0, hi: 0 };
65 const MAX: Self = Self {
66 lo: u128::MAX,
67 hi: u128::MAX,
68 };
69}
70
71impl MinInt for i256 {
72 type OtherSign = u256;
73
74 type Unsigned = u256;
75
76 const SIGNED: bool = true;
77 const BITS: u32 = 256;
78 const ZERO: Self = Self { lo: 0, hi: 0 };
79 const ONE: Self = Self { lo: 1, hi: 0 };
80 const MIN: Self = Self {
81 lo: u128::MIN,
82 hi: i128::MIN,
83 };
84 const MAX: Self = Self {
85 lo: u128::MAX,
86 hi: i128::MAX,
87 };
88}
89
90macro_rules! impl_common {
91 ($ty:ty) => {
92 impl ops::BitOr for $ty {
93 type Output = Self;
94
95 fn bitor(mut self, rhs: Self) -> Self::Output {
96 self.lo |= rhs.lo;
97 self.hi |= rhs.hi;
98 self
99 }
100 }
101
102 impl ops::Not for $ty {
103 type Output = Self;
104
105 fn not(mut self) -> Self::Output {
106 self.lo = !self.lo;
107 self.hi = !self.hi;
108 self
109 }
110 }
111
112 impl ops::Add<Self> for $ty {
113 type Output = Self;
114
115 fn add(self, rhs: Self) -> Self::Output {
116 let (lo, carry) = self.lo.overflowing_add(rhs.lo);
117 let (hi, of) = Int::carrying_add(self.hi, rhs.hi, carry);
118 debug_assert!(!of, "attempt to add with overflow");
119 Self { lo, hi }
120 }
121 }
122
123 impl ops::Sub<Self> for $ty {
124 type Output = Self;
125
126 fn sub(self, rhs: Self) -> Self::Output {
127 let (lo, borrow) = self.lo.overflowing_sub(rhs.lo);
128 let (hi, of) = Int::borrowing_sub(self.hi, rhs.hi, borrow);
129 debug_assert!(!of, "attempt to subtract with overflow");
130 Self { lo, hi }
131 }
132 }
133
134 impl ops::Shl<u32> for $ty {
135 type Output = Self;
136
137 fn shl(mut self, rhs: u32) -> Self::Output {
138 debug_assert!(rhs < Self::BITS, "attempt to shift left with overflow");
139
140 let half_bits = Self::BITS / 2;
141 let low_mask = half_bits - 1;
142 let s = rhs & low_mask;
143
144 let lo = self.lo;
145 let hi = self.hi;
146
147 self.lo = lo << s;
148
149 if rhs & half_bits == 0 {
150 self.hi = (lo >> (low_mask ^ s) >> 1) as _;
151 self.hi |= hi << s;
152 } else {
153 self.hi = self.lo as _;
154 self.lo = 0;
155 }
156 self
157 }
158 }
159
160 impl ops::Shr<u32> for $ty {
161 type Output = Self;
162
163 fn shr(mut self, rhs: u32) -> Self::Output {
164 debug_assert!(rhs < Self::BITS, "attempt to shift right with overflow");
165
166 let half_bits = Self::BITS / 2;
167 let low_mask = half_bits - 1;
168 let s = rhs & low_mask;
169
170 let lo = self.lo;
171 let hi = self.hi;
172
173 self.hi = hi >> s;
174
175 #[allow(unused_comparisons)]
176 if rhs & half_bits == 0 {
177 self.lo = (hi << (low_mask ^ s) << 1) as _;
178 self.lo |= lo >> s;
179 } else {
180 self.lo = self.hi as _;
181 self.hi = if hi < 0 { !0 } else { 0 };
182 }
183 self
184 }
185 }
186 };
187}
188
189impl ops::BitOr for i256 {
type Output = Self;
fn bitor(mut self, rhs: Self) -> Self::Output {
self.lo |= rhs.lo;
self.hi |= rhs.hi;
self
}
}
impl ops::Not for i256 {
type Output = Self;
fn not(mut self) -> Self::Output {
self.lo = !self.lo;
self.hi = !self.hi;
self
}
}
impl ops::Add<Self> for i256 {
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);
if true {
if !!of {
{
::core::panicking::panic_fmt(format_args!("attempt to add with overflow"));
}
};
};
Self { lo, hi }
}
}
impl ops::Sub<Self> for i256 {
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);
if true {
if !!of {
{
::core::panicking::panic_fmt(format_args!("attempt to subtract with overflow"));
}
};
};
Self { lo, hi }
}
}
impl ops::Shl<u32> for i256 {
type Output = Self;
fn shl(mut self, rhs: u32) -> Self::Output {
if true {
if !(rhs < Self::BITS) {
{
::core::panicking::panic_fmt(format_args!("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 i256 {
type Output = Self;
fn shr(mut self, rhs: u32) -> Self::Output {
if true {
if !(rhs < Self::BITS) {
{
::core::panicking::panic_fmt(format_args!("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);
190impl ops::BitOr for u256 {
type Output = Self;
fn bitor(mut self, rhs: Self) -> Self::Output {
self.lo |= rhs.lo;
self.hi |= rhs.hi;
self
}
}
impl ops::Not for u256 {
type Output = Self;
fn not(mut self) -> Self::Output {
self.lo = !self.lo;
self.hi = !self.hi;
self
}
}
impl ops::Add<Self> for u256 {
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);
if true {
if !!of {
{
::core::panicking::panic_fmt(format_args!("attempt to add with overflow"));
}
};
};
Self { lo, hi }
}
}
impl ops::Sub<Self> for u256 {
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);
if true {
if !!of {
{
::core::panicking::panic_fmt(format_args!("attempt to subtract with overflow"));
}
};
};
Self { lo, hi }
}
}
impl ops::Shl<u32> for u256 {
type Output = Self;
fn shl(mut self, rhs: u32) -> Self::Output {
if true {
if !(rhs < Self::BITS) {
{
::core::panicking::panic_fmt(format_args!("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 u256 {
type Output = Self;
fn shr(mut self, rhs: u32) -> Self::Output {
if true {
if !(rhs < Self::BITS) {
{
::core::panicking::panic_fmt(format_args!("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!(u256);
191
192impl HInt for u128 {
193 type D = u256;
194
195 fn widen(self) -> Self::D {
196 u256 { lo: self, hi: 0 }
197 }
198
199 fn zero_widen(self) -> Self::D {
200 self.widen()
201 }
202
203 fn zero_widen_mul(self, rhs: Self) -> Self::D {
204 let l0 = self & U128_LO_MASK;
205 let l1 = rhs & U128_LO_MASK;
206 let h0 = self >> 64;
207 let h1 = rhs >> 64;
208
209 let p_ll: u128 = l0.overflowing_mul(l1).0;
210 let p_lh: u128 = l0.overflowing_mul(h1).0;
211 let p_hl: u128 = h0.overflowing_mul(l1).0;
212 let p_hh: u128 = h0.overflowing_mul(h1).0;
213
214 let s0 = p_hl + (p_ll >> 64);
215 let s1 = (p_ll & U128_LO_MASK) + (s0 << 64);
216 let s2 = p_lh + (s1 >> 64);
217
218 let lo = (p_ll & U128_LO_MASK) + (s2 << 64);
219 let hi = p_hh + (s0 >> 64) + (s2 >> 64);
220
221 u256 { lo, hi }
222 }
223
224 fn widen_mul(self, rhs: Self) -> Self::D {
225 self.zero_widen_mul(rhs)
226 }
227
228 fn widen_hi(self) -> Self::D {
229 u256 { lo: 0, hi: self }
230 }
231}
232
233impl HInt for i128 {
234 type D = i256;
235
236 fn widen(self) -> Self::D {
237 i256 {
238 lo: self as u128,
239 hi: if self < 0 { -1 } else { 0 },
240 }
241 }
242
243 fn zero_widen(self) -> Self::D {
244 self.unsigned().zero_widen().signed()
245 }
246
247 fn zero_widen_mul(self, rhs: Self) -> Self::D {
248 self.unsigned().zero_widen_mul(rhs.unsigned()).signed()
249 }
250
251 fn widen_mul(self, _rhs: Self) -> Self::D {
252 {
::core::panicking::panic_fmt(format_args!("not implemented: {0}",
format_args!("signed i128 widening multiply is not used")));
}unimplemented!("signed i128 widening multiply is not used")
253 }
254
255 fn widen_hi(self) -> Self::D {
256 i256 { lo: 0, hi: self }
257 }
258}
259
260impl DInt for u256 {
261 type H = u128;
262
263 fn lo(self) -> Self::H {
264 self.lo
265 }
266
267 fn hi(self) -> Self::H {
268 self.hi
269 }
270}
271
272impl DInt for i256 {
273 type H = i128;
274
275 fn lo(self) -> Self::H {
276 self.lo as i128
277 }
278
279 fn hi(self) -> Self::H {
280 self.hi
281 }
282}