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}