ethnum/uint.rs
1//! Root module for 256-bit unsigned integer type.
2
3mod api;
4mod cmp;
5mod convert;
6mod fmt;
7mod iter;
8mod ops;
9mod parse;
10
11pub use self::convert::AsU256;
12use crate::I256;
13use core::{mem::MaybeUninit, num::ParseIntError};
14
15/// A 256-bit unsigned integer type.
16#[derive(Clone, Copy, Default, Eq, Hash, PartialEq)]
17#[repr(transparent)]
18pub struct U256(pub [u128; 2]);
19
20impl U256 {
21 /// The additive identity for this integer type, i.e. `0`.
22 pub const ZERO: Self = U256([0; 2]);
23
24 /// The multiplicative identity for this integer type, i.e. `1`.
25 pub const ONE: Self = U256::new(1);
26
27 /// Creates a new 256-bit integer value from a primitive `u128` integer.
28 #[inline]
29 pub const fn new(value: u128) -> Self {
30 U256::from_words(0, value)
31 }
32
33 /// Creates a new 256-bit integer value from high and low words.
34 #[inline]
35 pub const fn from_words(hi: u128, lo: u128) -> Self {
36 #[cfg(target_endian = "little")]
37 {
38 U256([lo, hi])
39 }
40 #[cfg(target_endian = "big")]
41 {
42 U256([hi, lo])
43 }
44 }
45
46 /// Splits a 256-bit integer into high and low words.
47 #[inline]
48 pub const fn into_words(self) -> (u128, u128) {
49 #[cfg(target_endian = "little")]
50 {
51 let U256([lo, hi]) = self;
52 (hi, lo)
53 }
54 #[cfg(target_endian = "big")]
55 {
56 let U256([hi, lo]) = self;
57 (hi, lo)
58 }
59 }
60
61 /// Get the low 128-bit word for this unsigned integer.
62 #[inline]
63 pub fn low(&self) -> &u128 {
64 #[cfg(target_endian = "little")]
65 {
66 &self.0[0]
67 }
68 #[cfg(target_endian = "big")]
69 {
70 &self.0[1]
71 }
72 }
73
74 /// Get the low 128-bit word for this unsigned integer as a mutable
75 /// reference.
76 #[inline]
77 pub fn low_mut(&mut self) -> &mut u128 {
78 #[cfg(target_endian = "little")]
79 {
80 &mut self.0[0]
81 }
82 #[cfg(target_endian = "big")]
83 {
84 &mut self.0[1]
85 }
86 }
87
88 /// Get the high 128-bit word for this unsigned integer.
89 #[inline]
90 pub fn high(&self) -> &u128 {
91 #[cfg(target_endian = "little")]
92 {
93 &self.0[1]
94 }
95 #[cfg(target_endian = "big")]
96 {
97 &self.0[0]
98 }
99 }
100
101 /// Get the high 128-bit word for this unsigned integer as a mutable
102 /// reference.
103 #[inline]
104 pub fn high_mut(&mut self) -> &mut u128 {
105 #[cfg(target_endian = "little")]
106 {
107 &mut self.0[1]
108 }
109 #[cfg(target_endian = "big")]
110 {
111 &mut self.0[0]
112 }
113 }
114
115 /// Converts a prefixed string slice in base 16 to an integer.
116 ///
117 /// The string is expected to be an optional `+` sign followed by the `0x`
118 /// prefix and finally the digits. Leading and trailing whitespace represent
119 /// an error.
120 ///
121 /// # Examples
122 ///
123 /// Basic usage:
124 ///
125 /// ```
126 /// # use ethnum::U256;
127 /// assert_eq!(U256::from_str_hex("0x2A"), Ok(U256::new(42)));
128 /// ```
129 pub fn from_str_hex(src: &str) -> Result<Self, ParseIntError> {
130 crate::parse::from_str_radix(src, 16, Some("0x"))
131 }
132
133 /// Converts a prefixed string slice in a base determined by the prefix to
134 /// an integer.
135 ///
136 /// The string is expected to be an optional `+` sign followed by the one of
137 /// the supported prefixes and finally the digits. Leading and trailing
138 /// whitespace represent an error. The base is determined based on the
139 /// prefix:
140 ///
141 /// * `0b`: base `2`
142 /// * `0o`: base `8`
143 /// * `0x`: base `16`
144 /// * no prefix: base `10`
145 ///
146 /// # Examples
147 ///
148 /// Basic usage:
149 ///
150 /// ```
151 /// # use ethnum::U256;
152 /// assert_eq!(U256::from_str_prefixed("0b101"), Ok(U256::new(0b101)));
153 /// assert_eq!(U256::from_str_prefixed("0o17"), Ok(U256::new(0o17)));
154 /// assert_eq!(U256::from_str_prefixed("0xa"), Ok(U256::new(0xa)));
155 /// assert_eq!(U256::from_str_prefixed("42"), Ok(U256::new(42)));
156 /// ```
157 pub fn from_str_prefixed(src: &str) -> Result<Self, ParseIntError> {
158 crate::parse::from_str_prefixed(src)
159 }
160
161 /// Same as [`U256::from_str_prefixed`] but as a `const fn`. This method is
162 /// not intended to be used directly but rather through the [`crate::uint`]
163 /// macro.
164 #[doc(hidden)]
165 pub const fn const_from_str_prefixed(src: &str) -> Self {
166 parse::const_from_str_prefixed(src)
167 }
168
169 /// Cast to a primitive `i8`.
170 #[inline]
171 pub const fn as_i8(self) -> i8 {
172 let (_, lo) = self.into_words();
173 lo as _
174 }
175
176 /// Cast to a primitive `i16`.
177 #[inline]
178 pub const fn as_i16(self) -> i16 {
179 let (_, lo) = self.into_words();
180 lo as _
181 }
182
183 /// Cast to a primitive `i32`.
184 #[inline]
185 pub const fn as_i32(self) -> i32 {
186 let (_, lo) = self.into_words();
187 lo as _
188 }
189
190 /// Cast to a primitive `i64`.
191 #[inline]
192 pub const fn as_i64(self) -> i64 {
193 let (_, lo) = self.into_words();
194 lo as _
195 }
196
197 /// Cast to a primitive `i128`.
198 #[inline]
199 pub const fn as_i128(self) -> i128 {
200 let (_, lo) = self.into_words();
201 lo as _
202 }
203
204 /// Cast to a `I256`.
205 #[inline]
206 pub const fn as_i256(self) -> I256 {
207 let Self([a, b]) = self;
208 I256([a as _, b as _])
209 }
210
211 /// Cast to a primitive `u8`.
212 #[inline]
213 pub const fn as_u8(self) -> u8 {
214 let (_, lo) = self.into_words();
215 lo as _
216 }
217
218 /// Cast to a primitive `u16`.
219 #[inline]
220 pub const fn as_u16(self) -> u16 {
221 let (_, lo) = self.into_words();
222 lo as _
223 }
224
225 /// Cast to a primitive `u32`.
226 #[inline]
227 pub const fn as_u32(self) -> u32 {
228 let (_, lo) = self.into_words();
229 lo as _
230 }
231
232 /// Cast to a primitive `u64`.
233 #[inline]
234 pub const fn as_u64(self) -> u64 {
235 let (_, lo) = self.into_words();
236 lo as _
237 }
238
239 /// Cast to a primitive `u128`.
240 #[inline]
241 pub const fn as_u128(self) -> u128 {
242 let (_, lo) = self.into_words();
243 lo
244 }
245
246 /// Cast to a primitive `isize`.
247 #[inline]
248 pub const fn as_isize(self) -> isize {
249 let (_, lo) = self.into_words();
250 lo as _
251 }
252
253 /// Cast to a primitive `usize`.
254 #[inline]
255 pub const fn as_usize(self) -> usize {
256 let (_, lo) = self.into_words();
257 lo as _
258 }
259
260 /// Cast to a primitive `f32`.
261 #[inline]
262 pub fn as_f32(self) -> f32 {
263 match self.into_words() {
264 (0, lo) => lo as _,
265 _ => f32::INFINITY,
266 }
267 }
268
269 /// Cast to a primitive `f64`.
270 #[inline]
271 pub fn as_f64(self) -> f64 {
272 // NOTE: Binary representation of 2**128. This is used because `powi` is
273 // neither `const` nor `no_std`.
274 const HI: u64 = 0x47f0000000000000;
275 let (hi, lo) = self.into_words();
276 (hi as f64) * f64::from_bits(HI) + (lo as f64)
277 }
278
279 /// Performs integer and division and returns the quotient and the remainder as a tuple. This is faster than computing the quotient and remainder separately.
280 ///
281 /// # Panics
282 ///
283 /// This function will panic if `rhs` is 0.
284 ///
285 /// # Examples
286 ///
287 /// Basic usage:
288 ///
289 /// ```
290 /// # use ethnum::U256;
291 /// assert_eq!(U256::new(7).div_rem(U256::new(4)), (U256::new(1), U256::new(3)));
292 /// ```
293 #[inline]
294 #[must_use = "this returns the result of the operation, \
295 without modifying the original"]
296 #[track_caller]
297 pub fn div_rem(self, rhs: Self) -> (Self, Self) {
298 if rhs == 0 {
299 if rhs > 0 {
300 // The optimizer understands inequalities better
301 unsafe { core::hint::unreachable_unchecked() }
302 }
303 panic!("attempt to divide by zero");
304 }
305 if rhs <= 0 {
306 // The optimizer understands inequalities better
307 unsafe { core::hint::unreachable_unchecked() }
308 }
309
310 let mut res: MaybeUninit<Self> = MaybeUninit::uninit();
311 let mut rem: MaybeUninit<Self> = MaybeUninit::uninit();
312 crate::intrinsics::udivmod4(&mut res, &self, &rhs, Some(&mut rem));
313 let ret = unsafe { ((res.assume_init()), (rem.assume_init())) };
314
315 // This helps the optimizer figure out when it can use smaller
316 // operands for later functions.
317 // SAFETY: Relies on the fact that rhs is at least 1.
318 if ret.1 >= rhs {
319 unsafe { core::hint::unreachable_unchecked() }
320 }
321 if ret.1 > self {
322 unsafe { core::hint::unreachable_unchecked() }
323 }
324 if ret.0 > self {
325 unsafe { core::hint::unreachable_unchecked() }
326 }
327
328 ret
329 }
330
331 /// Performs Euclidean division.
332 ///
333 /// Since, for the positive integers, all common definitions of division are
334 /// equal, this is exactly equal to `self.div_rem(rhs)`.
335 ///
336 /// # Panics
337 ///
338 /// This function will panic if `rhs` is 0.
339 ///
340 /// # Examples
341 ///
342 /// Basic usage:
343 ///
344 /// ```
345 /// # use ethnum::U256;
346 /// assert_eq!(U256::new(7).div_rem_euclid(U256::new(4)), (U256::new(1), U256::new(3)));
347 /// ```
348 #[inline(always)]
349 #[must_use = "this returns the result of the operation, \
350 without modifying the original"]
351 #[track_caller]
352 pub fn div_rem_euclid(self, rhs: Self) -> (Self, Self) {
353 self.div_rem(rhs)
354 }
355
356 /// Checked integer division. Computes `self.div_rem(rhs)`, returning `None` if
357 /// `rhs == 0`.
358 ///
359 /// # Examples
360 ///
361 /// Basic usage:
362 ///
363 /// ```
364 /// # use ethnum::U256;
365 /// assert_eq!(U256::new(128).checked_div_rem(U256::new(2)), Some((U256::new(64), U256::new(0))));
366 /// assert_eq!(U256::new(1).checked_div_rem(U256::new(0)), None);
367 /// ```
368 #[inline]
369 #[must_use = "this returns the result of the operation, \
370 without modifying the original"]
371 pub fn checked_div_rem(self, rhs: Self) -> Option<(Self, Self)> {
372 if rhs == Self::ZERO {
373 if rhs > 0 {
374 // The optimizer understands inequalities better
375 unsafe { core::hint::unreachable_unchecked() }
376 }
377
378 None
379 } else {
380 if rhs <= 0 {
381 // The optimizer understands inequalities better
382 unsafe { core::hint::unreachable_unchecked() }
383 }
384
385 Some(self.div_rem(rhs))
386 }
387 }
388
389 /// Checked Euclidean division. Computes `self.div_rem_euclid(rhs)`, returning `None` if
390 /// `rhs == 0`.
391 ///
392 /// # Examples
393 ///
394 /// Basic usage:
395 ///
396 /// ```
397 /// # use ethnum::U256;
398 /// assert_eq!(U256::new(128).checked_div_rem_euclid(U256::new(2)), Some((U256::new(64), U256::new(0))));
399 /// assert_eq!(U256::new(1).checked_div_rem_euclid(U256::new(0)), None);
400 /// ```
401 #[inline(always)]
402 #[must_use = "this returns the result of the operation, \
403 without modifying the original"]
404 pub fn checked_div_rem_euclid(self, rhs: Self) -> Option<(Self, Self)> {
405 self.checked_div_rem(rhs)
406 }
407
408 /// Saturating integer division. Computes `self.div_rem(rhs)`, saturating at the
409 /// numeric bounds instead of overflowing.
410 ///
411 /// # Examples
412 ///
413 /// Basic usage:
414 ///
415 /// ```
416 /// # use ethnum::U256;
417 /// assert_eq!(U256::new(5).saturating_div_rem(U256::new(2)), (U256::new(2), U256::new(1)));
418 /// ```
419 ///
420 /// ```should_panic (expected = "attempt to divide by zero")
421 /// # use ethnum::U256;
422 /// let _ = U256::new(1).saturating_div_rem(U256::ZERO);
423 /// ```
424 #[inline(always)]
425 #[must_use = "this returns the result of the operation, \
426 without modifying the original"]
427 #[track_caller]
428 pub fn saturating_div_rem(self, rhs: Self) -> (Self, Self) {
429 self.div_rem(rhs)
430 }
431
432 /// Saturating integer division. Computes `self.div_rem_euclid(rhs)`, saturating at the
433 /// numeric bounds instead of overflowing.
434 ///
435 /// # Examples
436 ///
437 /// Basic usage:
438 ///
439 /// ```
440 /// # use ethnum::U256;
441 /// assert_eq!(U256::new(5).saturating_div_rem_euclid(U256::new(2)), (U256::new(2), U256::new(1)));
442 /// ```
443 ///
444 /// ```should_panic (expected = "attempt to divide by zero")
445 /// # use ethnum::U256;
446 /// let _ = U256::new(1).saturating_div_rem_euclid(U256::ZERO);
447 /// ```
448 #[inline(always)]
449 #[must_use = "this returns the result of the operation, \
450 without modifying the original"]
451 #[track_caller]
452 pub fn saturating_div_rem_euclid(self, rhs: Self) -> (Self, Self) {
453 self.div_rem(rhs)
454 }
455
456 /// Wrapping (modular) division. Computes `self.div_rem(rhs)`. Wrapped division on
457 /// unsigned types is just normal division. There's no way wrapping could
458 /// ever happen. This function exists, so that all operations are accounted
459 /// for in the wrapping operations.
460 ///
461 /// # Panics
462 ///
463 /// This function will panic if `rhs` is 0.
464 ///
465 /// # Examples
466 ///
467 /// Basic usage:
468 ///
469 /// ```
470 /// # use ethnum::U256;
471 /// assert_eq!(U256::new(100).wrapping_div_rem(U256::new(10)), (U256::new(10), U256::new(0)));
472 /// ```
473 #[inline(always)]
474 #[must_use = "this returns the result of the operation, \
475 without modifying the original"]
476 #[track_caller]
477 pub fn wrapping_div_rem(self, rhs: Self) -> (Self, Self) {
478 self.div_rem(rhs)
479 }
480
481 /// Wrapping Euclidean division. Computes `self.div_rem_euclid(rhs)`. Wrapped division on
482 /// unsigned types is just normal division. There's no way wrapping could
483 /// ever happen. This function exists, so that all operations are accounted
484 /// for in the wrapping operations. Since, for the positive integers, all common
485 /// definitions of division are equal, this is exactly equal to `self.div_rem(rhs)`.
486 ///
487 /// # Panics
488 ///
489 /// This function will panic if `rhs` is 0.
490 ///
491 /// # Examples
492 ///
493 /// Basic usage:
494 ///
495 /// ```
496 /// # use ethnum::U256;
497 /// assert_eq!(U256::new(100).wrapping_div_rem_euclid(U256::new(10)), (U256::new(10), U256::new(0)));
498 /// ```
499 #[inline(always)]
500 #[must_use = "this returns the result of the operation, \
501 without modifying the original"]
502 #[track_caller]
503 pub fn wrapping_div_rem_euclid(self, rhs: Self) -> (Self, Self) {
504 self.div_rem(rhs)
505 }
506
507 /// Calculates the quotient and the remainder when `self` is divided by `rhs`.
508 ///
509 /// Returns a tuple of the divisor and the remainder along with a boolean indicating whether
510 /// an arithmetic overflow would occur. Note that for unsigned integers
511 /// overflow never occurs, so the second value is always `false`.
512 ///
513 /// # Panics
514 ///
515 /// This function will panic if `rhs` is 0.
516 ///
517 /// # Examples
518 ///
519 /// Basic usage
520 ///
521 /// ```
522 /// # use ethnum::U256;
523 /// assert_eq!(U256::new(5).overflowing_div_rem(U256::new(2)), (U256::new(2), U256::new(1), false));
524 /// ```
525 #[inline(always)]
526 #[must_use = "this returns the result of the operation, \
527 without modifying the original"]
528 #[track_caller]
529 pub fn overflowing_div_rem(self, rhs: Self) -> (Self, Self, bool) {
530 let (q, r) = self.div_rem(rhs);
531 (q, r, false)
532 }
533
534 /// Calculates the quotient of Euclidean division `self.div_rem_euclid(rhs)`.
535 ///
536 /// Returns a tuple of the divisor along with a boolean indicating whether
537 /// an arithmetic overflow would occur. Note that for unsigned integers
538 /// overflow never occurs, so the second value is always `false`. Since,
539 /// for the positive integers, all common definitions of division are equal,
540 /// this is exactly equal to `self.div_rem(rhs)`.
541 ///
542 /// # Panics
543 ///
544 /// This function will panic if `rhs` is 0.
545 ///
546 /// # Examples
547 ///
548 /// Basic usage
549 ///
550 /// ```
551 /// # use ethnum::U256;
552 /// assert_eq!(U256::new(5).overflowing_div_rem_euclid(U256::new(2)), (U256::new(2), U256::new(1), false));
553 /// ```
554 #[inline(always)]
555 #[must_use = "this returns the result of the operation, \
556 without modifying the original"]
557 #[track_caller]
558 pub fn overflowing_div_rem_euclid(self, rhs: Self) -> (Self, Self, bool) {
559 let (q, r) = self.div_rem(rhs);
560 (q, r, false)
561 }
562}
563
564#[cfg(test)]
565mod tests {
566 use crate::uint::U256;
567
568 #[test]
569 #[allow(clippy::float_cmp)]
570 fn converts_to_f64() {
571 assert_eq!(U256::from_words(1, 0).as_f64(), 2.0f64.powi(128))
572 }
573}