compiler_builtins/int/
big.rs1#![allow(unused)]
4
5use core::{fmt, ops};
6
7use crate::int::{DInt, HInt, Int, MinInt};
8
9const WORD_LO_MASK: u64 = 0x00000000ffffffff;
10const WORD_HI_MASK: u64 = 0xffffffff00000000;
11const WORD_FULL_MASK: u64 = 0xffffffffffffffff;
12const U128_LO_MASK: u128 = u64::MAX as u128;
13const U128_HI_MASK: u128 = (u64::MAX as u128) << 64;
14
15#[allow(non_camel_case_types)]
19#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
20pub struct u256(pub [u64; 4]);
21
22impl u256 {
23 pub const MAX: Self = Self([u64::MAX, u64::MAX, u64::MAX, u64::MAX]);
24
25 pub fn signed(self) -> i256 {
27 i256(self.0)
28 }
29}
30
31#[allow(non_camel_case_types)]
35#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
36pub struct i256(pub [u64; 4]);
37
38impl i256 {
39 pub fn unsigned(self) -> u256 {
41 u256(self.0)
42 }
43}
44
45impl MinInt for u256 {
46 type OtherSign = i256;
47
48 type UnsignedInt = u256;
49
50 const SIGNED: bool = false;
51 const BITS: u32 = 256;
52 const ZERO: Self = Self([0u64; 4]);
53 const ONE: Self = Self([1, 0, 0, 0]);
54 const MIN: Self = Self([0u64; 4]);
55 const MAX: Self = Self([u64::MAX; 4]);
56}
57
58impl MinInt for i256 {
59 type OtherSign = u256;
60
61 type UnsignedInt = u256;
62
63 const SIGNED: bool = false;
64 const BITS: u32 = 256;
65 const ZERO: Self = Self([0u64; 4]);
66 const ONE: Self = Self([1, 0, 0, 0]);
67 const MIN: Self = Self([0, 0, 0, 1 << 63]);
68 const MAX: Self = Self([u64::MAX, u64::MAX, u64::MAX, u64::MAX << 1]);
69}
70
71macro_rules! impl_common {
72 ($ty:ty) => {
73 impl ops::BitOr for $ty {
74 type Output = Self;
75
76 fn bitor(mut self, rhs: Self) -> Self::Output {
77 self.0[0] |= rhs.0[0];
78 self.0[1] |= rhs.0[1];
79 self.0[2] |= rhs.0[2];
80 self.0[3] |= rhs.0[3];
81 self
82 }
83 }
84
85 impl ops::Not for $ty {
86 type Output = Self;
87
88 fn not(self) -> Self::Output {
89 Self([!self.0[0], !self.0[1], !self.0[2], !self.0[3]])
90 }
91 }
92
93 impl ops::Shl<u32> for $ty {
94 type Output = Self;
95
96 fn shl(self, rhs: u32) -> Self::Output {
97 unimplemented!("only used to meet trait bounds")
98 }
99 }
100 };
101}
102
103impl_common!(i256);
104impl_common!(u256);
105
106impl ops::Shr<u32> for u256 {
107 type Output = Self;
108
109 fn shr(self, rhs: u32) -> Self::Output {
110 assert!(rhs < Self::BITS, "attempted to shift right with overflow");
111
112 if rhs == 0 {
113 return self;
114 }
115
116 let mut ret = self;
117 let byte_shift = rhs / 64;
118 let bit_shift = rhs % 64;
119
120 for idx in 0..4 {
121 let base_idx = idx + byte_shift as usize;
122
123 let Some(base) = ret.0.get(base_idx) else {
124 ret.0[idx] = 0;
125 continue;
126 };
127
128 let mut new_val = base >> bit_shift;
129
130 if let Some(new) = ret.0.get(base_idx + 1) {
131 new_val |= new.overflowing_shl(64 - bit_shift).0;
132 }
133
134 ret.0[idx] = new_val;
135 }
136
137 ret
138 }
139}
140
141macro_rules! word {
142 (1, $val:expr) => {
143 (($val >> (32 * 3)) & Self::from(WORD_LO_MASK)) as u64
144 };
145 (2, $val:expr) => {
146 (($val >> (32 * 2)) & Self::from(WORD_LO_MASK)) as u64
147 };
148 (3, $val:expr) => {
149 (($val >> (32 * 1)) & Self::from(WORD_LO_MASK)) as u64
150 };
151 (4, $val:expr) => {
152 (($val >> (32 * 0)) & Self::from(WORD_LO_MASK)) as u64
153 };
154}
155
156impl HInt for u128 {
157 type D = u256;
158
159 fn widen(self) -> Self::D {
160 let w0 = self & u128::from(u64::MAX);
161 let w1 = (self >> u64::BITS) & u128::from(u64::MAX);
162 u256([w0 as u64, w1 as u64, 0, 0])
163 }
164
165 fn zero_widen(self) -> Self::D {
166 self.widen()
167 }
168
169 fn zero_widen_mul(self, rhs: Self) -> Self::D {
170 let product11: u64 = word!(1, self) * word!(1, rhs);
171 let product12: u64 = word!(1, self) * word!(2, rhs);
172 let product13: u64 = word!(1, self) * word!(3, rhs);
173 let product14: u64 = word!(1, self) * word!(4, rhs);
174 let product21: u64 = word!(2, self) * word!(1, rhs);
175 let product22: u64 = word!(2, self) * word!(2, rhs);
176 let product23: u64 = word!(2, self) * word!(3, rhs);
177 let product24: u64 = word!(2, self) * word!(4, rhs);
178 let product31: u64 = word!(3, self) * word!(1, rhs);
179 let product32: u64 = word!(3, self) * word!(2, rhs);
180 let product33: u64 = word!(3, self) * word!(3, rhs);
181 let product34: u64 = word!(3, self) * word!(4, rhs);
182 let product41: u64 = word!(4, self) * word!(1, rhs);
183 let product42: u64 = word!(4, self) * word!(2, rhs);
184 let product43: u64 = word!(4, self) * word!(3, rhs);
185 let product44: u64 = word!(4, self) * word!(4, rhs);
186
187 let sum0: u128 = u128::from(product44);
188 let sum1: u128 = u128::from(product34) + u128::from(product43);
189 let sum2: u128 = u128::from(product24) + u128::from(product33) + u128::from(product42);
190 let sum3: u128 = u128::from(product14)
191 + u128::from(product23)
192 + u128::from(product32)
193 + u128::from(product41);
194 let sum4: u128 = u128::from(product13) + u128::from(product22) + u128::from(product31);
195 let sum5: u128 = u128::from(product12) + u128::from(product21);
196 let sum6: u128 = u128::from(product11);
197
198 let r0: u128 =
199 (sum0 & u128::from(WORD_FULL_MASK)) + ((sum1 & u128::from(WORD_LO_MASK)) << 32);
200 let r1: u128 = (sum0 >> 64)
201 + ((sum1 >> 32) & u128::from(WORD_FULL_MASK))
202 + (sum2 & u128::from(WORD_FULL_MASK))
203 + ((sum3 << 32) & u128::from(WORD_HI_MASK));
204
205 let (lo, carry) = r0.overflowing_add(r1 << 64);
206 let hi = (r1 >> 64)
207 + (sum1 >> 96)
208 + (sum2 >> 64)
209 + (sum3 >> 32)
210 + sum4
211 + (sum5 << 32)
212 + (sum6 << 64)
213 + u128::from(carry);
214
215 u256([
216 (lo & U128_LO_MASK) as u64,
217 ((lo >> 64) & U128_LO_MASK) as u64,
218 (hi & U128_LO_MASK) as u64,
219 ((hi >> 64) & U128_LO_MASK) as u64,
220 ])
221 }
222
223 fn widen_mul(self, rhs: Self) -> Self::D {
224 self.zero_widen_mul(rhs)
225 }
226
227 fn widen_hi(self) -> Self::D {
228 self.widen() << <Self as MinInt>::BITS
229 }
230}
231
232impl HInt for i128 {
233 type D = i256;
234
235 fn widen(self) -> Self::D {
236 let mut ret = self.unsigned().zero_widen().signed();
237 if self.is_negative() {
238 ret.0[2] = u64::MAX;
239 ret.0[3] = u64::MAX;
240 }
241 ret
242 }
243
244 fn zero_widen(self) -> Self::D {
245 self.unsigned().zero_widen().signed()
246 }
247
248 fn zero_widen_mul(self, rhs: Self) -> Self::D {
249 self.unsigned().zero_widen_mul(rhs.unsigned()).signed()
250 }
251
252 fn widen_mul(self, rhs: Self) -> Self::D {
253 unimplemented!("signed i128 widening multiply is not used")
254 }
255
256 fn widen_hi(self) -> Self::D {
257 self.widen() << <Self as MinInt>::BITS
258 }
259}
260
261impl DInt for u256 {
262 type H = u128;
263
264 fn lo(self) -> Self::H {
265 let mut tmp = [0u8; 16];
266 tmp[..8].copy_from_slice(&self.0[0].to_le_bytes());
267 tmp[8..].copy_from_slice(&self.0[1].to_le_bytes());
268 u128::from_le_bytes(tmp)
269 }
270
271 fn hi(self) -> Self::H {
272 let mut tmp = [0u8; 16];
273 tmp[..8].copy_from_slice(&self.0[2].to_le_bytes());
274 tmp[8..].copy_from_slice(&self.0[3].to_le_bytes());
275 u128::from_le_bytes(tmp)
276 }
277}
278
279impl DInt for i256 {
280 type H = i128;
281
282 fn lo(self) -> Self::H {
283 let mut tmp = [0u8; 16];
284 tmp[..8].copy_from_slice(&self.0[0].to_le_bytes());
285 tmp[8..].copy_from_slice(&self.0[1].to_le_bytes());
286 i128::from_le_bytes(tmp)
287 }
288
289 fn hi(self) -> Self::H {
290 let mut tmp = [0u8; 16];
291 tmp[..8].copy_from_slice(&self.0[2].to_le_bytes());
292 tmp[8..].copy_from_slice(&self.0[3].to_le_bytes());
293 i128::from_le_bytes(tmp)
294 }
295}