diff --git a/Backend/README.md b/Backend/README.md index 9a060c2..14c5442 100644 --- a/Backend/README.md +++ b/Backend/README.md @@ -15,7 +15,7 @@ The backend is responsible for: * Savings vault management * Transaction processing * Nigerian bank integrations -* Fiat-to-USDC conversion workflows +* Fiat-to-USDT conversion workflows * Lending and borrowing services * Investment management * Reward and streak calculations @@ -384,7 +384,7 @@ Responsibilities: * Receive NGN deposits * Verify payments -* Convert NGN to USDC +* Convert NGN to USDT * Transfer assets to Stellar wallets * Process withdrawals back to bank accounts diff --git a/Contract/Cargo.toml b/Contract/Cargo.toml index b13cc05..b9ebc36 100644 --- a/Contract/Cargo.toml +++ b/Contract/Cargo.toml @@ -16,6 +16,3 @@ edition = "2021" [workspace.dependencies] soroban-sdk = "20.5.0" shared = { path = "shared" } - -[patch.crates-io] -ethnum = { path = "./ethnum-patch" } diff --git a/Contract/README.md b/Contract/README.md index 37cc7a5..8f7685f 100644 --- a/Contract/README.md +++ b/Contract/README.md @@ -235,7 +235,7 @@ User Create Vault │ ▼ -Deposit USDC +Deposit USDT │ ▼ Vault Contract diff --git a/Contract/ethnum-patch/Cargo.toml b/Contract/ethnum-patch/Cargo.toml deleted file mode 100644 index 8fd0596..0000000 --- a/Contract/ethnum-patch/Cargo.toml +++ /dev/null @@ -1,31 +0,0 @@ -[package] -name = "ethnum" -version = "1.5.0" -authors = ["Nicholas Rodrigues Lordello "] -edition = "2021" -description = "256-bit integer implementation" -documentation = "https://docs.rs/ethnum" -readme = "README.md" -homepage = "https://github.com/nlordell/ethnum-rs" -repository = "https://github.com/nlordell/ethnum-rs" -license = "MIT OR Apache-2.0" -keywords = ["integer", "u256", "ethereum"] -categories = ["cryptography::cryptocurrencies", "mathematics", "no-std"] - -[package.metadata.docs.rs] -features = ["serde"] - -[workspace] -members = [ - "bench", - "fuzz", - "intrinsics", -] - -[features] -llvm-intrinsics = ["ethnum-intrinsics"] -macros = [] # deprecated - -[dependencies] -ethnum-intrinsics = { version = "=1.2.0", path = "intrinsics", optional = true } -serde = { version = "1", default-features = false, optional = true } diff --git a/Contract/ethnum-patch/src/error.rs b/Contract/ethnum-patch/src/error.rs deleted file mode 100644 index 117dd5a..0000000 --- a/Contract/ethnum-patch/src/error.rs +++ /dev/null @@ -1,65 +0,0 @@ -//! Module with safe helpers for creating error variants for standard library -//! errors without public constructors. - -use core::num::{IntErrorKind, ParseIntError, TryFromIntError}; - -/// Returns a `ParseIntError` with the specified `IntErrorKind`. -pub const fn pie(kind: IntErrorKind) -> ParseIntError { - match kind { - IntErrorKind::Empty => u8_parse_error(""), - IntErrorKind::InvalidDigit => u8_parse_error("?"), - IntErrorKind::PosOverflow => u8_parse_error("256"), - IntErrorKind::NegOverflow => i8_parse_error("-129"), - _ => unreachable!(), - } -} - -const fn u8_parse_error(s: &str) -> ParseIntError { - let Err(err) = u8::from_str_radix(s, 10) else { - panic!("not a parse error!"); - }; - err -} - -const fn i8_parse_error(s: &str) -> ParseIntError { - let Err(err) = i8::from_str_radix(s, 10) else { - panic!("not a parse error!"); - }; - err -} - -/// Returns a `TryFromIntError`. -pub fn tfie() -> TryFromIntError { - u8::try_from(-1i8).unwrap_err() -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - #[allow(clippy::from_str_radix_10)] - fn parse_int_error() { - assert_eq!( - pie(IntErrorKind::Empty), - u8::from_str_radix("", 2).unwrap_err(), - ); - assert_eq!( - pie(IntErrorKind::InvalidDigit), - u8::from_str_radix("?", 2).unwrap_err(), - ); - assert_eq!( - pie(IntErrorKind::PosOverflow), - u8::from_str_radix("zzz", 36).unwrap_err(), - ); - assert_eq!( - pie(IntErrorKind::NegOverflow), - i8::from_str_radix("-1337", 10).unwrap_err(), - ); - } - - #[test] - fn try_from_int_error() { - assert_eq!(tfie(), u8::try_from(-1).unwrap_err()); - } -} diff --git a/Contract/ethnum-patch/src/fmt.rs b/Contract/ethnum-patch/src/fmt.rs deleted file mode 100644 index 730e159..0000000 --- a/Contract/ethnum-patch/src/fmt.rs +++ /dev/null @@ -1,153 +0,0 @@ -//! Module with common integer formatting logic for implementing the standard -//! library `core::fmt` traits. -//! -//! Most of these implementations were ported from the Rust standard library's -//! implementation for primitive integer types: -//! - -use crate::uint::U256; -use core::{fmt, mem::MaybeUninit, ptr, slice, str}; - -pub(crate) trait GenericRadix: Sized { - const BASE: u8; - const PREFIX: &'static str; - fn digit(x: u8) -> u8; - fn fmt_u256(&self, mut x: U256, is_nonnegative: bool, f: &mut fmt::Formatter) -> fmt::Result { - // The radix can be as low as 2, so we need a buffer of at least 256 - // characters for a base 2 number. - let zero = U256::ZERO; - let mut buf = [MaybeUninit::::uninit(); 256]; - let mut curr = buf.len(); - let base = U256::from(Self::BASE); - // Accumulate each digit of the number from the least significant - // to the most significant figure. - for byte in buf.iter_mut().rev() { - let n = x % base; // Get the current place value. - x /= base; // Deaccumulate the number. - byte.write(Self::digit(n.as_u8())); // Store the digit in the buffer. - curr -= 1; - if x == zero { - // No more digits left to accumulate. - break; - }; - } - let buf = &buf[curr..]; - // SAFETY: The only chars in `buf` are created by `Self::digit` which are assumed to be - // valid UTF-8 - let buf = unsafe { - str::from_utf8_unchecked(slice::from_raw_parts( - &buf[0] as *const _ as *const u8, - buf.len(), - )) - }; - f.pad_integral(is_nonnegative, Self::PREFIX, buf) - } -} - -/// A binary (base 2) radix -#[derive(Clone, PartialEq)] -pub(crate) struct Binary; - -/// An octal (base 8) radix -#[derive(Clone, PartialEq)] -pub(crate) struct Octal; - -/// A hexadecimal (base 16) radix, formatted with lower-case characters -#[derive(Clone, PartialEq)] -pub(crate) struct LowerHex; - -/// A hexadecimal (base 16) radix, formatted with upper-case characters -#[derive(Clone, PartialEq)] -pub(crate) struct UpperHex; - -macro_rules! radix { - ($T:ident, $base:expr, $prefix:expr, $($x:pat => $conv:expr),+) => { - impl GenericRadix for $T { - const BASE: u8 = $base; - const PREFIX: &'static str = $prefix; - fn digit(x: u8) -> u8 { - match x { - $($x => $conv,)+ - x => panic!("number not in the range 0..={}: {}", Self::BASE - 1, x), - } - } - } - } -} - -radix! { Binary, 2, "0b", x @ 0 ..= 1 => b'0' + x } -radix! { Octal, 8, "0o", x @ 0 ..= 7 => b'0' + x } -radix! { LowerHex, 16, "0x", x @ 0 ..= 9 => b'0' + x, x @ 10 ..= 15 => b'a' + (x - 10) } -radix! { UpperHex, 16, "0x", x @ 0 ..= 9 => b'0' + x, x @ 10 ..= 15 => b'A' + (x - 10) } - -const DEC_DIGITS_LUT: &[u8; 200] = b"\ - 0001020304050607080910111213141516171819\ - 2021222324252627282930313233343536373839\ - 4041424344454647484950515253545556575859\ - 6061626364656667686970717273747576777879\ - 8081828384858687888990919293949596979899"; - -pub(crate) fn fmt_u256(mut n: U256, is_nonnegative: bool, f: &mut fmt::Formatter) -> fmt::Result { - // 2^256 is about 1*10^78, so 79 gives an extra byte of space - let mut buf = [MaybeUninit::::uninit(); 79]; - let mut curr = buf.len() as isize; - let buf_ptr = &mut buf[0] as *mut _ as *mut u8; - let lut_ptr = DEC_DIGITS_LUT.as_ptr(); - - // SAFETY: Since `d1` and `d2` are always less than or equal to `198`, we - // can copy from `lut_ptr[d1..d1 + 1]` and `lut_ptr[d2..d2 + 1]`. To show - // that it's OK to copy into `buf_ptr`, notice that at the beginning - // `curr == buf.len() == 39 > log(n)` since `n < 2^128 < 10^39`, and at - // each step this is kept the same as `n` is divided. Since `n` is always - // non-negative, this means that `curr > 0` so `buf_ptr[curr..curr + 1]` - // is safe to access. - unsafe { - // eagerly decode 4 characters at a time - while n >= 10000 { - let (q, r) = n.div_rem(U256::new(10000)); - n = q; - let rem = r.as_isize(); - - let d1 = (rem / 100) << 1; - let d2 = (rem % 100) << 1; - curr -= 4; - - // We are allowed to copy to `buf_ptr[curr..curr + 3]` here since - // otherwise `curr < 0`. But then `n` was originally at least `10000^10` - // which is `10^40 > 2^128 > n`. - ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2); - ptr::copy_nonoverlapping(lut_ptr.offset(d2), buf_ptr.offset(curr + 2), 2); - } - - // if we reach here numbers are <= 9999, so at most 4 chars long - let mut n = n.as_isize(); // possibly reduce 64bit math - - // decode 2 more chars, if > 2 chars - if n >= 100 { - let d1 = (n % 100) << 1; - n /= 100; - curr -= 2; - ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2); - } - - // decode last 1 or 2 chars - if n < 10 { - curr -= 1; - *buf_ptr.offset(curr) = (n as u8) + b'0'; - } else { - let d1 = n << 1; - curr -= 2; - ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2); - } - } - - // SAFETY: `curr` > 0 (since we made `buf` large enough), and all the chars are valid - // UTF-8 since `DEC_DIGITS_LUT` is - let buf_slice = unsafe { - str::from_utf8_unchecked(slice::from_raw_parts( - buf_ptr.offset(curr), - buf.len() - curr as usize, - )) - }; - f.pad_integral(is_nonnegative, "", buf_slice) -} diff --git a/Contract/ethnum-patch/src/int.rs b/Contract/ethnum-patch/src/int.rs deleted file mode 100644 index 4339890..0000000 --- a/Contract/ethnum-patch/src/int.rs +++ /dev/null @@ -1,638 +0,0 @@ -//! Root module for 256-bit signed integer type. - -mod api; -mod cmp; -mod convert; -mod fmt; -mod iter; -mod ops; -mod parse; - -pub use self::convert::AsI256; -use crate::uint::U256; -use core::{mem::MaybeUninit, num::ParseIntError}; - -/// A 256-bit signed integer type. -#[derive(Clone, Copy, Default, Eq, Hash, PartialEq)] -#[repr(transparent)] -pub struct I256(pub [i128; 2]); - -impl I256 { - /// The additive identity for this integer type, i.e. `0`. - pub const ZERO: Self = I256([0; 2]); - - /// The multiplicative identity for this integer type, i.e. `1`. - pub const ONE: Self = I256::new(1); - - /// The multiplicative inverse for this integer type, i.e. `-1`. - pub const MINUS_ONE: Self = I256::new(-1); - - /// Creates a new 256-bit integer value from a primitive `i128` integer. - #[inline] - pub const fn new(value: i128) -> Self { - I256::from_words(value >> 127, value) - } - - /// Creates a new 256-bit integer value from high and low words. - #[inline] - pub const fn from_words(hi: i128, lo: i128) -> Self { - #[cfg(target_endian = "little")] - { - I256([lo, hi]) - } - #[cfg(target_endian = "big")] - { - I256([hi, lo]) - } - } - - /// Splits a 256-bit integer into high and low words. - #[inline] - pub const fn into_words(self) -> (i128, i128) { - #[cfg(target_endian = "little")] - { - let I256([lo, hi]) = self; - (hi, lo) - } - #[cfg(target_endian = "big")] - { - let I256([hi, lo]) = self; - (hi, lo) - } - } - - /// Get the low 128-bit word for this signed integer. - #[inline] - pub fn low(&self) -> &i128 { - #[cfg(target_endian = "little")] - { - &self.0[0] - } - #[cfg(target_endian = "big")] - { - &self.0[1] - } - } - - /// Get the low 128-bit word for this signed integer as a mutable reference. - #[inline] - pub fn low_mut(&mut self) -> &mut i128 { - #[cfg(target_endian = "little")] - { - &mut self.0[0] - } - #[cfg(target_endian = "big")] - { - &mut self.0[1] - } - } - - /// Get the high 128-bit word for this signed integer. - #[inline] - pub fn high(&self) -> &i128 { - #[cfg(target_endian = "little")] - { - &self.0[1] - } - #[cfg(target_endian = "big")] - { - &self.0[0] - } - } - - /// Get the high 128-bit word for this signed integer as a mutable - /// reference. - #[inline] - pub fn high_mut(&mut self) -> &mut i128 { - #[cfg(target_endian = "little")] - { - &mut self.0[1] - } - #[cfg(target_endian = "big")] - { - &mut self.0[0] - } - } - - /// Converts a prefixed string slice in base 16 to an integer. - /// - /// The string is expected to be an optional `+` or `-` sign followed by - /// the `0x` prefix and finally the digits. Leading and trailing whitespace - /// represent an error. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// assert_eq!(I256::from_str_hex("0x2A"), Ok(I256::new(42))); - /// assert_eq!(I256::from_str_hex("-0xa"), Ok(I256::new(-10))); - /// ``` - pub fn from_str_hex(src: &str) -> Result { - crate::parse::from_str_radix(src, 16, Some("0x")) - } - - /// Converts a prefixed string slice in a base determined by the prefix to - /// an integer. - /// - /// The string is expected to be an optional `+` or `-` sign followed by - /// the one of the supported prefixes and finally the digits. Leading and - /// trailing whitespace represent an error. The base is determined based - /// on the prefix: - /// - /// * `0b`: base `2` - /// * `0o`: base `8` - /// * `0x`: base `16` - /// * no prefix: base `10` - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// assert_eq!(I256::from_str_prefixed("-0b101"), Ok(I256::new(-0b101))); - /// assert_eq!(I256::from_str_prefixed("0o17"), Ok(I256::new(0o17))); - /// assert_eq!(I256::from_str_prefixed("-0xa"), Ok(I256::new(-0xa))); - /// assert_eq!(I256::from_str_prefixed("42"), Ok(I256::new(42))); - /// ``` - pub fn from_str_prefixed(src: &str) -> Result { - crate::parse::from_str_prefixed(src) - } - - /// Same as [`I256::from_str_prefixed`] but as a `const fn`. This method is - /// not intended to be used directly but rather through the [`crate::int`] - /// macro. - #[doc(hidden)] - pub const fn const_from_str_prefixed(src: &str) -> Self { - parse::const_from_str_prefixed(src) - } - - /// Cast to a primitive `i8`. - #[inline] - pub const fn as_i8(self) -> i8 { - let (_, lo) = self.into_words(); - lo as _ - } - - /// Cast to a primitive `i16`. - #[inline] - pub const fn as_i16(self) -> i16 { - let (_, lo) = self.into_words(); - lo as _ - } - - /// Cast to a primitive `i32`. - #[inline] - pub const fn as_i32(self) -> i32 { - let (_, lo) = self.into_words(); - lo as _ - } - - /// Cast to a primitive `i64`. - #[inline] - pub const fn as_i64(self) -> i64 { - let (_, lo) = self.into_words(); - lo as _ - } - - /// Cast to a primitive `i128`. - #[inline] - pub const fn as_i128(self) -> i128 { - let (_, lo) = self.into_words(); - lo as _ - } - - /// Cast to a primitive `u8`. - #[inline] - pub const fn as_u8(self) -> u8 { - let (_, lo) = self.into_words(); - lo as _ - } - - /// Cast to a primitive `u16`. - #[inline] - pub const fn as_u16(self) -> u16 { - let (_, lo) = self.into_words(); - lo as _ - } - - /// Cast to a primitive `u32`. - #[inline] - pub const fn as_u32(self) -> u32 { - let (_, lo) = self.into_words(); - lo as _ - } - - /// Cast to a primitive `u64`. - #[inline] - pub const fn as_u64(self) -> u64 { - let (_, lo) = self.into_words(); - lo as _ - } - - /// Cast to a primitive `u128`. - #[inline] - pub const fn as_u128(self) -> u128 { - let (_, lo) = self.into_words(); - lo as _ - } - - /// Cast to a `U256`. - #[inline] - pub const fn as_u256(self) -> U256 { - let Self([a, b]) = self; - U256([a as _, b as _]) - } - - /// Cast to a primitive `isize`. - #[inline] - pub const fn as_isize(self) -> isize { - let (_, lo) = self.into_words(); - lo as _ - } - - /// Cast to a primitive `usize`. - #[inline] - pub const fn as_usize(self) -> usize { - let (_, lo) = self.into_words(); - lo as _ - } - - /// Cast to a primitive `f32`. - #[inline] - pub fn as_f32(self) -> f32 { - self.as_f64() as _ - } - - /// Cast to a primitive `f64`. - #[inline] - pub fn as_f64(self) -> f64 { - let sign = self.signum128() as f64; - self.unsigned_abs().as_f64() * sign - } - - /// Performs integer and division and returns the quotient and the remainder as a tuple. This is equivelent to `(self / rhs, self % rhs)`, but more effecient. - /// - /// # Panics - /// - /// This function will panic if `rhs` is 0, and will panic on overflow iff debug assertions are enabled. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// assert_eq!(I256::new(22).div_rem(I256::new(5)), (I256::new(4), I256::new(2))); - /// assert_eq!(I256::new(-22).div_rem(I256::new(5)), (I256::new(-4), I256::new(-2))); - /// assert_eq!(I256::new(22).div_rem(I256::new(-5)), (I256::new(-4), I256::new(2))); - /// assert_eq!(I256::new(-22).div_rem(I256::new(-5)), (I256::new(4), I256::new(-2))); - /// ``` - #[inline] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[track_caller] - pub fn div_rem(self, rhs: Self) -> (Self, Self) { - if self == Self::MIN && rhs == -1 { - panic!("attempt to divide with overflow") - } - self.wrapping_div_rem(rhs) - } - - /// Performs euclidean division and returns the quotient and the remainder as a tuple. - /// - /// This computes the integers `q` and `r` such that self = q * rhs + r, with `q = self.div_euclid` and `r = self.rem_euclid(rhs)`. - /// - /// # Panics - /// - /// This function will panic if `rhs` is 0, and will panic on overflow iff debug assertions are enabled. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// assert_eq!(I256::new(22).div_rem_euclid(I256::new(5)), (I256::new(4), I256::new(2))); - /// assert_eq!(I256::new(-22).div_rem_euclid(I256::new(5)), (I256::new(-5), I256::new(3))); - /// assert_eq!(I256::new(22).div_rem_euclid(I256::new(-5)), (I256::new(-4), I256::new(2))); - /// assert_eq!(I256::new(-22).div_rem_euclid(I256::new(-5)), (I256::new(5), I256::new(3))); - /// - /// # assert_eq!(I256::new(20).div_rem_euclid(I256::new(5)), (I256::new(4), I256::new(0))); - /// # assert_eq!(I256::new(-20).div_rem_euclid(I256::new(5)), (I256::new(-4), I256::new(0))); - /// # assert_eq!(I256::new(20).div_rem_euclid(I256::new(-5)), (I256::new(-4), I256::new(0))); - /// # assert_eq!(I256::new(-20).div_rem_euclid(I256::new(-5)), (I256::new(4), I256::new(0))); - /// ``` - #[inline] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[track_caller] - pub fn div_rem_euclid(self, rhs: Self) -> (Self, Self) { - if self == Self::MIN && rhs == -1 { - panic!("attempt to divide with overflow") - } - self.wrapping_div_rem_euclid(rhs) - } - - /// Checked division. Computes `self.div_rem(rhs)`, - /// returning `None` if `rhs == 0` or the division results in overflow. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// assert_eq!((I256::MIN + 1).checked_div_rem(I256::new(-1)), Some((I256::MAX, I256::new(0)))); - /// assert_eq!(I256::MIN.checked_div_rem(I256::new(-1)), None); - /// assert_eq!(I256::new(1).checked_div_rem(I256::new(0)), None); - /// ``` - #[inline] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[track_caller] - pub fn checked_div_rem(self, rhs: Self) -> Option<(Self, Self)> { - if rhs == 0 || (self == Self::MIN && rhs == -1) { - None - } else { - if rhs.cmp(&I256::ZERO) == core::cmp::Ordering::Equal { - // The optimizer understands inequalities better - unsafe { core::hint::unreachable_unchecked() } - } - - let mut res: MaybeUninit = MaybeUninit::uninit(); - let mut rem: MaybeUninit = MaybeUninit::uninit(); - crate::intrinsics::idivmod4(&mut res, &self, &rhs, Some(&mut rem)); - unsafe { Some(((res.assume_init()), (rem.assume_init()))) } - } - } - - /// Checked Euclidean division. Computes `self.div_rem_euclid(rhs)`, - /// returning `None` if `rhs == 0` or the division results in overflow. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// assert_eq!((I256::MIN + 1).checked_div_rem_euclid(I256::new(-1)), Some((I256::MAX, I256::new(0)))); - /// assert_eq!(I256::MIN.checked_div_rem_euclid(I256::new(-1)), None); - /// assert_eq!(I256::new(1).checked_div_rem_euclid(I256::new(0)), None); - /// ``` - #[inline] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[track_caller] - pub fn checked_div_rem_euclid(self, rhs: Self) -> Option<(Self, Self)> { - if rhs == 0 || (self == Self::MIN && rhs == -1) { - None - } else { - if rhs.cmp(&I256::ZERO) == core::cmp::Ordering::Equal { - // The optimizer understands inequalities better - unsafe { core::hint::unreachable_unchecked() } - } - - Some(self.wrapping_div_rem_euclid(rhs)) - } - } - - /// Saturating integer division. Computes `self.div_rem(rhs)`, saturating at the - /// numeric bounds instead of overflowing. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// assert_eq!(I256::new(5).saturating_div_rem(I256::new(2)), (I256::new(2), I256::new(1))); - /// assert_eq!(I256::MAX.saturating_div_rem(I256::new(-1)), (I256::MIN + 1, I256::new(0))); - /// assert_eq!(I256::MIN.saturating_div_rem(I256::new(-1)), (I256::MAX, I256::new(0))); - /// ``` - /// ```should_panic (expected = "attempt to divide by zero") - /// # use ethnum::I256; - /// let _ = I256::new(1).saturating_div_rem(I256::ZERO); - /// ``` - #[inline] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[track_caller] - pub fn saturating_div_rem(self, rhs: Self) -> (Self, Self) { - match self.overflowing_div_rem(rhs) { - (q, r, false) => (q, r), - (_q, r, true) => (Self::MAX, r), // MIN / -1 is the only possible saturating overflow - } - } - - /// Saturating integer division. Computes `self.div_rem_euclid(rhs)`, saturating at the - /// numeric bounds instead of overflowing. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// assert_eq!(I256::new(5).saturating_div_rem_euclid(I256::new(2)), (I256::new(2), I256::new(1))); - /// assert_eq!(I256::MAX.saturating_div_rem_euclid(I256::new(-1)), (I256::MIN + 1, I256::new(0))); - /// assert_eq!(I256::MIN.saturating_div_rem_euclid(I256::new(-1)), (I256::MAX, I256::new(0))); - /// ``` - /// ```should_panic (expected = "attempt to divide by zero") - /// # use ethnum::I256; - /// let _ = I256::new(1).saturating_div_rem_euclid(I256::ZERO); - /// ``` - #[inline] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[track_caller] - pub fn saturating_div_rem_euclid(self, rhs: Self) -> (Self, Self) { - match self.overflowing_div_rem_euclid(rhs) { - (q, r, false) => (q, r), - (_q, r, true) => (Self::MAX, r), - } - } - - /// Performs integer and division and returns the quotient and the remainder as a tuple. This is equivelent to `(self.wrapping_div(rhs), self.wrapping_rem(rhs))`, but more effecient. - /// - /// # Panics - /// - /// This function will panic if `rhs` is 0. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// assert_eq!(I256::new(22).wrapping_div_rem(I256::new(5)), (I256::new(4), I256::new(2))); - /// assert_eq!(I256::new(-22).wrapping_div_rem(I256::new(5)), (I256::new(-4), I256::new(-2))); - /// assert_eq!(I256::new(22).wrapping_div_rem(I256::new(-5)), (I256::new(-4), I256::new(2))); - /// assert_eq!(I256::new(-22).wrapping_div_rem(I256::new(-5)), (I256::new(4), I256::new(-2))); - /// - /// assert_eq!(I256::MIN.wrapping_div_rem(I256::MINUS_ONE), (I256::MIN, I256::ZERO)); - /// ``` - #[inline] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[track_caller] - pub fn wrapping_div_rem(self, rhs: Self) -> (Self, Self) { - if rhs == 0 { - if rhs.cmp(&I256::ZERO) != core::cmp::Ordering::Equal { - // The optimizer understands inequalities better - unsafe { core::hint::unreachable_unchecked() } - } - panic!("attempt to divide by zero"); - } - if rhs.cmp(&I256::ZERO) == core::cmp::Ordering::Equal { - // The optimizer understands inequalities better - unsafe { core::hint::unreachable_unchecked() } - } - - let mut res: MaybeUninit = MaybeUninit::uninit(); - let mut rem: MaybeUninit = MaybeUninit::uninit(); - crate::intrinsics::idivmod4(&mut res, &self, &rhs, Some(&mut rem)); - unsafe { ((res.assume_init()), (rem.assume_init())) } - } - - /// Performs euclidean division and returns the quotient and the remainder as a tuple. - /// - /// This computes the integers `q` and `r` such that self = q * rhs + r, with `q = self.wrapping_div_euclid` and `r = self.wrapping_rem_euclid(rhs)`. - /// - /// # Panics - /// - /// This function will panic if `rhs` is 0. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// assert_eq!(I256::new(22).wrapping_div_rem_euclid(I256::new(5)), (I256::new(4), I256::new(2))); - /// assert_eq!(I256::new(-22).wrapping_div_rem_euclid(I256::new(5)), (I256::new(-5), I256::new(3))); - /// assert_eq!(I256::new(22).wrapping_div_rem_euclid(I256::new(-5)), (I256::new(-4), I256::new(2))); - /// assert_eq!(I256::new(-22).wrapping_div_rem_euclid(I256::new(-5)), (I256::new(5), I256::new(3))); - /// - /// assert_eq!(I256::MIN.wrapping_div_rem(I256::MINUS_ONE), (I256::MIN, I256::ZERO)); - /// # assert_eq!(I256::new(20).wrapping_div_rem_euclid(I256::new(5)), (I256::new(4), I256::new(0))); - /// # assert_eq!(I256::new(-20).wrapping_div_rem_euclid(I256::new(5)), (I256::new(-4), I256::new(0))); - /// # assert_eq!(I256::new(20).wrapping_div_rem_euclid(I256::new(-5)), (I256::new(-4), I256::new(0))); - /// # assert_eq!(I256::new(-20).wrapping_div_rem_euclid(I256::new(-5)), (I256::new(4), I256::new(0))); - /// ``` - #[inline] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[track_caller] - pub fn wrapping_div_rem_euclid(self, rhs: Self) -> (Self, Self) { - let dividend_sign = self.is_negative(); - let quotient_sign = dividend_sign ^ rhs.is_negative(); - let abs_dividend = self.unsigned_abs(); - let abs_divisor = rhs.unsigned_abs(); - - let (q, r) = abs_dividend.div_rem(abs_divisor); - let mut quotient = q.as_i256(); - let mut remainder = r.as_i256(); - - let adjust_remainder = dividend_sign && remainder != 0; - if adjust_remainder { - remainder = abs_divisor.as_i256() - remainder; - // cannot overflow - } - if remainder.is_negative() || remainder.as_u256() >= abs_divisor { - debug_assert!(false); - unsafe { core::hint::unreachable_unchecked() } - } - - if adjust_remainder { - if quotient_sign { - quotient = !quotient; - // quotient = -quotient - 1 - } else { - quotient += 1; - // cannot overflow - } - } else if quotient_sign { - quotient = quotient.wrapping_neg(); - } - - (quotient, remainder) - } - - /// Calculates the quotient and the remainder when `self` is divided by `rhs`. - /// - /// Returns a tuple of the quotient and the remainder along with a boolean indicating whether - /// an arithmetic overflow would occur. If an overflow would occur then - /// `self` is returned. - /// - /// # Panics - /// - /// This function will panic if `rhs` is 0. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// assert_eq!(I256::new(5).overflowing_div_rem(I256::new(2)), (I256::new(2), I256::new(1), false)); - /// assert_eq!(I256::MIN.overflowing_div_rem(I256::new(-1)), (I256::MIN, I256::new(0), true)); - /// ``` - #[inline] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[track_caller] - pub fn overflowing_div_rem(self, rhs: Self) -> (Self, Self, bool) { - if self == Self::MIN && rhs == -1 { - (self, Self::ZERO, true) - } else { - let (q, r) = self.wrapping_div_rem(rhs); - (q, r, false) - } - } - - /// Calculates the quotient and remainder of Euclidean division `self.div_rem_euclid(rhs)`. - /// - /// Returns a tuple of the quotient and the remainder along with a boolean indicating whether - /// an arithmetic overflow would occur. If an overflow would occur then - /// `self` is returned. - /// - /// # Panics - /// - /// This function will panic if `rhs` is 0. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// assert_eq!(I256::new(5).overflowing_div_rem_euclid(I256::new(2)), (I256::new(2), I256::new(1), false)); - /// assert_eq!(I256::MIN.overflowing_div_rem_euclid(I256::new(-1)), (I256::MIN, I256::new(0), true)); - /// ``` - #[inline] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[track_caller] - pub fn overflowing_div_rem_euclid(self, rhs: Self) -> (Self, Self, bool) { - if self == Self::MIN && rhs == -1 { - (self, Self::ZERO, true) - } else { - let (q, r) = self.wrapping_div_rem_euclid(rhs); - (q, r, false) - } - } -} - -#[cfg(test)] -mod tests { - use crate::I256; - - #[test] - #[allow(clippy::float_cmp)] - fn converts_to_f64() { - assert_eq!((-I256::from_words(1, 0)).as_f64(), -(2.0f64.powi(128))) - } -} diff --git a/Contract/ethnum-patch/src/int/api.rs b/Contract/ethnum-patch/src/int/api.rs deleted file mode 100644 index 593af39..0000000 --- a/Contract/ethnum-patch/src/int/api.rs +++ /dev/null @@ -1,2261 +0,0 @@ -//! Module containing integer aritimetic methods closely following the Rust -//! standard library API for `iN` types. - -use crate::{intrinsics, I256, U256}; -use core::{ - mem::{self, MaybeUninit}, - num::ParseIntError, -}; - -impl I256 { - /// The smallest value that can be represented by this integer type, - /// -2255. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// assert_eq!( - /// I256::MIN.to_string(), - /// "-57896044618658097711785492504343953926634992332820282019728792003956564819968", - /// ); - /// ``` - pub const MIN: Self = Self::from_words(i128::MIN, 0); - - /// The largest value that can be represented by this integer type, - /// 2255 - 1. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// assert_eq!( - /// I256::MAX.to_string(), - /// "57896044618658097711785492504343953926634992332820282019728792003956564819967", - /// ); - /// ``` - pub const MAX: Self = Self::from_words(i128::MAX, -1); - - /// The size of this integer type in bits. - /// - /// # Examples - /// - /// ``` - /// # use ethnum::I256; - /// assert_eq!(I256::BITS, 256); - /// ``` - pub const BITS: u32 = 256; - - /// Converts a string slice in a given base to an integer. - /// - /// The string is expected to be an optional `+` or `-` sign followed by - /// digits. Leading and trailing whitespace represent an error. Digits are a - /// subset of these characters, depending on `radix`: - /// - /// * `0-9` - /// * `a-z` - /// * `A-Z` - /// - /// # Panics - /// - /// This function panics if `radix` is not in the range from 2 to 36. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// assert_eq!(I256::from_str_radix("A", 16), Ok(I256::new(10))); - /// ``` - pub fn from_str_radix(src: &str, radix: u32) -> Result { - crate::parse::from_str_radix(src, radix, None) - } - - /// Returns the number of ones in the binary representation of `self`. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// let n = I256::new(0b100_0000); - /// - /// assert_eq!(n.count_ones(), 1); - /// ``` - /// - #[doc(alias = "popcount")] - #[doc(alias = "popcnt")] - #[inline] - pub const fn count_ones(self) -> u32 { - let Self([a, b]) = self; - a.count_ones() + b.count_ones() - } - - /// Returns the number of zeros in the binary representation of `self`. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// assert_eq!(I256::MAX.count_zeros(), 1); - /// ``` - #[inline] - pub const fn count_zeros(self) -> u32 { - let Self([a, b]) = self; - a.count_zeros() + b.count_zeros() - } - - /// Returns the number of leading zeros in the binary representation of - /// `self`. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// let n = I256::new(-1); - /// - /// assert_eq!(n.leading_zeros(), 0); - /// ``` - #[inline(always)] - pub fn leading_zeros(self) -> u32 { - intrinsics::signed::ictlz(&self) - } - - /// Returns the number of trailing zeros in the binary representation of - /// `self`. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// let n = I256::new(-4); - /// - /// assert_eq!(n.trailing_zeros(), 2); - /// ``` - #[inline(always)] - pub fn trailing_zeros(self) -> u32 { - intrinsics::signed::icttz(&self) - } - - /// Returns the number of leading ones in the binary representation of - /// `self`. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// let n = I256::new(-1); - /// - /// assert_eq!(n.leading_ones(), 256); - /// ``` - #[inline] - pub fn leading_ones(self) -> u32 { - (!self).leading_zeros() - } - - /// Returns the number of trailing ones in the binary representation of - /// `self`. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// let n = I256::new(3); - /// - /// assert_eq!(n.trailing_ones(), 2); - /// ``` - #[inline] - pub fn trailing_ones(self) -> u32 { - (!self).trailing_zeros() - } - - /// Shifts the bits to the left by a specified amount, `n`, - /// wrapping the truncated bits to the end of the resulting integer. - /// - /// Please note this isn't the same operation as the `<<` shifting operator! - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// let n = I256::from_words( - /// 0x13f40000000000000000000000000000, - /// 0x00000000000000000000000000004f76, - /// ); - /// let m = I256::new(0x4f7613f4); - /// - /// assert_eq!(n.rotate_left(16), m); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline(always)] - pub fn rotate_left(self, n: u32) -> Self { - let mut r = MaybeUninit::uninit(); - intrinsics::signed::irol3(&mut r, &self, n); - unsafe { r.assume_init() } - } - - /// Shifts the bits to the right by a specified amount, `n`, - /// wrapping the truncated bits to the beginning of the resulting - /// integer. - /// - /// Please note this isn't the same operation as the `>>` shifting operator! - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// let n = I256::new(0x4f7613f4); - /// let m = I256::from_words( - /// 0x13f40000000000000000000000000000, - /// 0x00000000000000000000000000004f76, - /// ); - /// - /// assert_eq!(n.rotate_right(16), m); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline(always)] - pub fn rotate_right(self, n: u32) -> Self { - let mut r = MaybeUninit::uninit(); - intrinsics::signed::iror3(&mut r, &self, n); - unsafe { r.assume_init() } - } - - /// Reverses the byte order of the integer. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// let n = I256::from_words( - /// 0x00010203_04050607_08090a0b_0c0d0e0f, - /// 0x10111213_14151617_18191a1b_1c1d1e1f, - /// ); - /// - /// assert_eq!( - /// n.swap_bytes(), - /// I256::from_words( - /// 0x1f1e1d1c_1b1a1918_17161514_13121110, - /// 0x0f0e0d0c_0b0a0908_07060504_03020100, - /// ), - /// ); - /// ``` - #[inline] - pub const fn swap_bytes(self) -> Self { - let Self([a, b]) = self; - Self([b.swap_bytes(), a.swap_bytes()]) - } - - /// Reverses the order of bits in the integer. The least significant bit - /// becomes the most significant bit, second least-significant bit becomes - /// second most-significant bit, etc. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// let n = I256::from_words( - /// 0x00010203_04050607_08090a0b_0c0d0e0f, - /// 0x10111213_14151617_18191a1b_1c1d1e1f, - /// ); - /// - /// assert_eq!( - /// n.reverse_bits(), - /// I256::from_words( - /// 0xf878b838_d8589818_e868a828_c8488808_u128 as _, - /// 0xf070b030_d0509010_e060a020_c0408000_u128 as _, - /// ), - /// ); - /// ``` - #[inline] - #[must_use] - pub const fn reverse_bits(self) -> Self { - let Self([a, b]) = self; - Self([b.reverse_bits(), a.reverse_bits()]) - } - - /// Converts an integer from big endian to the target's endianness. - /// - /// On big endian this is a no-op. On little endian the bytes are swapped. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// let n = I256::new(0x1A); - /// - /// if cfg!(target_endian = "big") { - /// assert_eq!(I256::from_be(n), n) - /// } else { - /// assert_eq!(I256::from_be(n), n.swap_bytes()) - /// } - /// ``` - #[inline(always)] - pub const fn from_be(x: Self) -> Self { - #[cfg(target_endian = "big")] - { - x - } - #[cfg(not(target_endian = "big"))] - { - x.swap_bytes() - } - } - - /// Converts an integer from little endian to the target's endianness. - /// - /// On little endian this is a no-op. On big endian the bytes are swapped. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// let n = I256::new(0x1A); - /// - /// if cfg!(target_endian = "little") { - /// assert_eq!(I256::from_le(n), n) - /// } else { - /// assert_eq!(I256::from_le(n), n.swap_bytes()) - /// } - /// ``` - #[inline(always)] - pub const fn from_le(x: Self) -> Self { - #[cfg(target_endian = "little")] - { - x - } - #[cfg(not(target_endian = "little"))] - { - x.swap_bytes() - } - } - - /// Converts `self` to big endian from the target's endianness. - /// - /// On big endian this is a no-op. On little endian the bytes are swapped. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// let n = I256::new(0x1A); - /// - /// if cfg!(target_endian = "big") { - /// assert_eq!(n.to_be(), n) - /// } else { - /// assert_eq!(n.to_be(), n.swap_bytes()) - /// } - /// ``` - #[inline(always)] - pub const fn to_be(self) -> Self { - // or not to be? - #[cfg(target_endian = "big")] - { - self - } - #[cfg(not(target_endian = "big"))] - { - self.swap_bytes() - } - } - - /// Converts `self` to little endian from the target's endianness. - /// - /// On little endian this is a no-op. On big endian the bytes are swapped. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// let n = I256::new(0x1A); - /// - /// if cfg!(target_endian = "little") { - /// assert_eq!(n.to_le(), n) - /// } else { - /// assert_eq!(n.to_le(), n.swap_bytes()) - /// } - /// ``` - #[inline(always)] - pub const fn to_le(self) -> Self { - #[cfg(target_endian = "little")] - { - self - } - #[cfg(not(target_endian = "little"))] - { - self.swap_bytes() - } - } - - /// Checked integer addition. Computes `self + rhs`, returning `None` - /// if overflow occurred. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// assert_eq!((I256::MAX - 2).checked_add(I256::new(1)), Some(I256::MAX - 1)); - /// assert_eq!((I256::MAX - 2).checked_add(I256::new(3)), None); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub fn checked_add(self, rhs: Self) -> Option { - let (a, b) = self.overflowing_add(rhs); - if b { - None - } else { - Some(a) - } - } - - /// Checked addition with an unsigned integer. Computes `self + rhs`, - /// returning `None` if overflow occurred. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::{I256, U256}; - /// assert_eq!(I256::new(1).checked_add_unsigned(U256::new(2)), Some(I256::new(3))); - /// assert_eq!((I256::MAX - 2).checked_add_unsigned(U256::new(3)), None); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub fn checked_add_unsigned(self, rhs: U256) -> Option { - let (a, b) = self.overflowing_add_unsigned(rhs); - if b { - None - } else { - Some(a) - } - } - - /// Checked integer subtraction. Computes `self - rhs`, returning `None` if - /// overflow occurred. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// assert_eq!((I256::MIN + 2).checked_sub(I256::new(1)), Some(I256::MIN + 1)); - /// assert_eq!((I256::MIN + 2).checked_sub(I256::new(3)), None); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub fn checked_sub(self, rhs: Self) -> Option { - let (a, b) = self.overflowing_sub(rhs); - if b { - None - } else { - Some(a) - } - } - - /// Checked subtraction with an unsigned integer. Computes `self - rhs`, - /// returning `None` if overflow occurred. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::{I256, U256}; - /// assert_eq!(I256::new(1).checked_sub_unsigned(U256::new(2)), Some(I256::new(-1))); - /// assert_eq!((I256::MIN + 2).checked_sub_unsigned(U256::new(3)), None); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub fn checked_sub_unsigned(self, rhs: U256) -> Option { - let (a, b) = self.overflowing_sub_unsigned(rhs); - if b { - None - } else { - Some(a) - } - } - - /// Checked integer multiplication. Computes `self * rhs`, returning `None` - /// if overflow occurred. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// assert_eq!(I256::MAX.checked_mul(I256::new(1)), Some(I256::MAX)); - /// assert_eq!(I256::MAX.checked_mul(I256::new(2)), None); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub fn checked_mul(self, rhs: Self) -> Option { - let (a, b) = self.overflowing_mul(rhs); - if b { - None - } else { - Some(a) - } - } - - /// Checked integer division. Computes `self / rhs`, returning `None` if - /// `rhs == 0` or the division results in overflow. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// assert_eq!((I256::MIN + 1).checked_div(I256::new(-1)), Some(I256::MAX)); - /// assert_eq!(I256::MIN.checked_div(I256::new(-1)), None); - /// assert_eq!(I256::new(1).checked_div(I256::new(0)), None); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub fn checked_div(self, rhs: Self) -> Option { - if rhs == 0 || (self == Self::MIN && rhs == -1) { - None - } else { - let mut result = MaybeUninit::uninit(); - intrinsics::signed::idiv3(&mut result, &self, &rhs); - Some(unsafe { result.assume_init() }) - } - } - - /// Checked Euclidean division. Computes `self.div_euclid(rhs)`, - /// returning `None` if `rhs == 0` or the division results in overflow. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// assert_eq!((I256::MIN + 1).checked_div_euclid(I256::new(-1)), Some(I256::MAX)); - /// assert_eq!(I256::MIN.checked_div_euclid(I256::new(-1)), None); - /// assert_eq!(I256::new(1).checked_div_euclid(I256::new(0)), None); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub fn checked_div_euclid(self, rhs: Self) -> Option { - if rhs == 0 || (self == Self::MIN && rhs == -1) { - None - } else { - Some(self.div_euclid(rhs)) - } - } - - /// Checked integer remainder. Computes `self % rhs`, returning `None` if - /// `rhs == 0` or the division results in overflow. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// assert_eq!(I256::new(5).checked_rem(I256::new(2)), Some(I256::new(1))); - /// assert_eq!(I256::new(5).checked_rem(I256::new(0)), None); - /// assert_eq!(I256::MIN.checked_rem(I256::new(-1)), None); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub fn checked_rem(self, rhs: Self) -> Option { - if rhs == 0 || (self == Self::MIN && rhs == -1) { - None - } else { - let mut result = MaybeUninit::uninit(); - intrinsics::signed::irem3(&mut result, &self, &rhs); - Some(unsafe { result.assume_init() }) - } - } - - /// Checked Euclidean remainder. Computes `self.rem_euclid(rhs)`, returning - /// `None` if `rhs == 0` or the division results in overflow. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// assert_eq!(I256::new(5).checked_rem_euclid(I256::new(2)), Some(I256::new(1))); - /// assert_eq!(I256::new(5).checked_rem_euclid(I256::new(0)), None); - /// assert_eq!(I256::MIN.checked_rem_euclid(I256::new(-1)), None); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub fn checked_rem_euclid(self, rhs: Self) -> Option { - if rhs == 0 || (self == Self::MIN && rhs == -1) { - None - } else { - Some(self.rem_euclid(rhs)) - } - } - - /// Checked negation. Computes `-self`, returning `None` if `self == MIN`. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// assert_eq!(I256::new(5).checked_neg(), Some(I256::new(-5))); - /// assert_eq!(I256::MIN.checked_neg(), None); - /// ``` - #[inline] - pub fn checked_neg(self) -> Option { - let (a, b) = self.overflowing_neg(); - if b { - None - } else { - Some(a) - } - } - - /// Checked shift left. Computes `self << rhs`, returning `None` if `rhs` - /// is larger than or equal to the number of bits in `self`. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// assert_eq!(I256::new(0x1).checked_shl(4), Some(I256::new(0x10))); - /// assert_eq!(I256::new(0x1).checked_shl(257), None); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub fn checked_shl(self, rhs: u32) -> Option { - let (a, b) = self.overflowing_shl(rhs); - if b { - None - } else { - Some(a) - } - } - - /// Checked shift right. Computes `self >> rhs`, returning `None` if `rhs` - /// is larger than or equal to the number of bits in `self`. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// assert_eq!(I256::new(0x10).checked_shr(4), Some(I256::new(0x1))); - /// assert_eq!(I256::new(0x10).checked_shr(256), None); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub fn checked_shr(self, rhs: u32) -> Option { - let (a, b) = self.overflowing_shr(rhs); - if b { - None - } else { - Some(a) - } - } - - /// Checked absolute value. Computes `self.abs()`, returning `None` if - /// `self == MIN`. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// assert_eq!(I256::new(-5).checked_abs(), Some(I256::new(5))); - /// assert_eq!(I256::MIN.checked_abs(), None); - /// ``` - #[inline] - pub fn checked_abs(self) -> Option { - if self.is_negative() { - self.checked_neg() - } else { - Some(self) - } - } - - /// Checked exponentiation. Computes `self.pow(exp)`, returning `None` if - /// overflow occurred. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// assert_eq!(I256::new(8).checked_pow(2), Some(I256::new(64))); - /// assert_eq!(I256::MAX.checked_pow(2), None); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub fn checked_pow(self, mut exp: u32) -> Option { - if exp == 0 { - return Some(Self::ONE); - } - let mut base = self; - let mut acc = Self::ONE; - - while exp > 1 { - if (exp & 1) == 1 { - acc = acc.checked_mul(base)?; - } - exp /= 2; - base = base.checked_mul(base)?; - } - // since exp!=0, finally the exp must be 1. - // Deal with the final bit of the exponent separately, since - // squaring the base afterwards is not necessary and may cause a - // needless overflow. - acc.checked_mul(base) - } - - /// Saturating integer addition. Computes `self + rhs`, saturating at the - /// numeric bounds instead of overflowing. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// assert_eq!(I256::new(100).saturating_add(I256::new(1)), 101); - /// assert_eq!(I256::MAX.saturating_add(I256::new(100)), I256::MAX); - /// assert_eq!(I256::MIN.saturating_add(I256::new(-1)), I256::MIN); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub fn saturating_add(self, rhs: Self) -> Self { - match self.checked_add(rhs) { - Some(x) => x, - None => { - if rhs > 0 { - Self::MAX - } else { - Self::MIN - } - } - } - } - - /// Saturating addition with an unsigned integer. Computes `self + rhs`, - /// saturating at the numeric bounds instead of overflowing. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::{I256, U256}; - /// assert_eq!(I256::new(1).saturating_add_unsigned(U256::new(2)), 3); - /// assert_eq!(I256::MAX.saturating_add_unsigned(U256::new(100)), I256::MAX); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub fn saturating_add_unsigned(self, rhs: U256) -> Self { - // Overflow can only happen at the upper bound - match self.checked_add_unsigned(rhs) { - Some(x) => x, - None => Self::MAX, - } - } - - /// Saturating integer subtraction. Computes `self - rhs`, saturating at the - /// numeric bounds instead of overflowing. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// assert_eq!(I256::new(100).saturating_sub(I256::new(127)), -27); - /// assert_eq!(I256::MIN.saturating_sub(I256::new(100)), I256::MIN); - /// assert_eq!(I256::MAX.saturating_sub(I256::new(-1)), I256::MAX); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub fn saturating_sub(self, rhs: Self) -> Self { - match self.checked_sub(rhs) { - Some(x) => x, - None => { - if rhs > 0 { - Self::MIN - } else { - Self::MAX - } - } - } - } - - /// Saturating subtraction with an unsigned integer. Computes `self - rhs`, - /// saturating at the numeric bounds instead of overflowing. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::{I256, U256}; - /// assert_eq!(I256::new(100).saturating_sub_unsigned(U256::new(127)), -27); - /// assert_eq!(I256::MIN.saturating_sub_unsigned(U256::new(100)), I256::MIN); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub fn saturating_sub_unsigned(self, rhs: U256) -> Self { - // Overflow can only happen at the lower bound - match self.checked_sub_unsigned(rhs) { - Some(x) => x, - None => Self::MIN, - } - } - - /// Saturating integer negation. Computes `-self`, returning `MAX` if - /// `self == MIN` instead of overflowing. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// assert_eq!(I256::new(100).saturating_neg(), -100); - /// assert_eq!(I256::new(-100).saturating_neg(), 100); - /// assert_eq!(I256::MIN.saturating_neg(), I256::MAX); - /// assert_eq!(I256::MAX.saturating_neg(), I256::MIN + 1); - /// ``` - #[inline(always)] - pub fn saturating_neg(self) -> Self { - I256::ZERO.saturating_sub(self) - } - - /// Saturating absolute value. Computes `self.abs()`, returning `MAX` if - /// `self == MIN` instead of overflowing. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// assert_eq!(I256::new(100).saturating_abs(), 100); - /// assert_eq!(I256::new(-100).saturating_abs(), 100); - /// assert_eq!(I256::MIN.saturating_abs(), I256::MAX); - /// assert_eq!((I256::MIN + 1).saturating_abs(), I256::MAX); - /// ``` - #[inline] - pub fn saturating_abs(self) -> Self { - if self.is_negative() { - self.saturating_neg() - } else { - self - } - } - - /// Saturating integer multiplication. Computes `self * rhs`, saturating at - /// the numeric bounds instead of overflowing. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// assert_eq!(I256::new(10).saturating_mul(I256::new(12)), 120); - /// assert_eq!(I256::MAX.saturating_mul(I256::new(10)), I256::MAX); - /// assert_eq!(I256::MIN.saturating_mul(I256::new(10)), I256::MIN); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub fn saturating_mul(self, rhs: Self) -> Self { - match self.checked_mul(rhs) { - Some(x) => x, - None => { - if (self < 0) == (rhs < 0) { - Self::MAX - } else { - Self::MIN - } - } - } - } - - /// Saturating integer division. Computes `self / rhs`, saturating at the - /// numeric bounds instead of overflowing. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// assert_eq!(I256::new(5).saturating_div(I256::new(2)), 2); - /// assert_eq!(I256::MAX.saturating_div(I256::new(-1)), I256::MIN + 1); - /// assert_eq!(I256::MIN.saturating_div(I256::new(-1)), I256::MAX); - /// ``` - /// - /// ```should_panic - /// # use ethnum::I256;; - /// let _ = I256::new(1).saturating_div(I256::new(0)); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub fn saturating_div(self, rhs: Self) -> Self { - match self.overflowing_div(rhs) { - (result, false) => result, - (_result, true) => Self::MAX, // MIN / -1 is the only possible saturating overflow - } - } - - /// Saturating integer exponentiation. Computes `self.pow(exp)`, - /// saturating at the numeric bounds instead of overflowing. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// assert_eq!(I256::new(-4).saturating_pow(3), -64); - /// assert_eq!(I256::MIN.saturating_pow(2), I256::MAX); - /// assert_eq!(I256::MIN.saturating_pow(3), I256::MIN); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub fn saturating_pow(self, exp: u32) -> Self { - match self.checked_pow(exp) { - Some(x) => x, - None if self < 0 && exp % 2 == 1 => Self::MIN, - None => Self::MAX, - } - } - - /// Wrapping (modular) addition. Computes `self + rhs`, wrapping around at - /// the boundary of the type. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// assert_eq!(I256::new(100).wrapping_add(I256::new(27)), 127); - /// assert_eq!(I256::MAX.wrapping_add(I256::new(2)), I256::MIN + 1); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline(always)] - pub fn wrapping_add(self, rhs: Self) -> Self { - let mut result = MaybeUninit::uninit(); - intrinsics::signed::iadd3(&mut result, &self, &rhs); - unsafe { result.assume_init() } - } - - /// Wrapping (modular) addition with an unsigned integer. Computes - /// `self + rhs`, wrapping around at the boundary of the type. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::{I256, U256}; - /// assert_eq!(I256::new(100).wrapping_add_unsigned(U256::new(27)), 127); - /// assert_eq!(I256::MAX.wrapping_add_unsigned(U256::new(2)), I256::MIN + 1); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline(always)] - pub fn wrapping_add_unsigned(self, rhs: U256) -> Self { - self.wrapping_add(rhs.as_i256()) - } - - /// Wrapping (modular) subtraction. Computes `self - rhs`, wrapping around - /// at the boundary of the type. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// assert_eq!(I256::new(0).wrapping_sub(I256::new(127)), -127); - /// assert_eq!(I256::new(-2).wrapping_sub(I256::MAX), I256::MAX); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline(always)] - pub fn wrapping_sub(self, rhs: Self) -> Self { - let mut result = MaybeUninit::uninit(); - intrinsics::signed::isub3(&mut result, &self, &rhs); - unsafe { result.assume_init() } - } - - /// Wrapping (modular) subtraction with an unsigned integer. Computes - /// `self - rhs`, wrapping around at the boundary of the type. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::{I256, U256}; - /// assert_eq!(I256::new(0).wrapping_sub_unsigned(U256::new(127)), -127); - /// assert_eq!(I256::new(-2).wrapping_sub_unsigned(U256::MAX), -1); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline(always)] - pub fn wrapping_sub_unsigned(self, rhs: U256) -> Self { - self.wrapping_sub(rhs.as_i256()) - } - - /// Wrapping (modular) multiplication. Computes `self * rhs`, wrapping - /// around at the boundary of the type. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// assert_eq!(I256::new(10).wrapping_mul(I256::new(12)), 120); - /// assert_eq!(I256::MAX.wrapping_mul(I256::new(2)), -2); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline(always)] - pub fn wrapping_mul(self, rhs: Self) -> Self { - let mut result = MaybeUninit::uninit(); - intrinsics::signed::imul3(&mut result, &self, &rhs); - unsafe { result.assume_init() } - } - - /// Wrapping (modular) division. Computes `self / rhs`, wrapping around at - /// the boundary of the type. - /// - /// The only case where such wrapping can occur is when one divides - /// `MIN / -1` on a signed type (where `MIN` is the negative minimal value - /// for the type); this is equivalent to `-MIN`, a positive value that is - /// too large to represent in the type. In such a case, this function - /// returns `MIN` itself. - /// - /// # Panics - /// - /// This function will panic if `rhs` is 0. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// assert_eq!(I256::new(100).wrapping_div(I256::new(10)), 10); - /// assert_eq!(I256::MIN.wrapping_div(I256::new(-1)), I256::MIN); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub fn wrapping_div(self, rhs: Self) -> Self { - self.overflowing_div(rhs).0 - } - - /// Wrapping Euclidean division. Computes `self.div_euclid(rhs)`, - /// wrapping around at the boundary of the type. - /// - /// Wrapping will only occur in `MIN / -1` on a signed type (where `MIN` is - /// the negative minimal value for the type). This is equivalent to `-MIN`, - /// a positive value that is too large to represent in the type. In this - /// case, this method returns `MIN` itself. - /// - /// # Panics - /// - /// This function will panic if `rhs` is 0. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// assert_eq!(I256::new(100).wrapping_div_euclid(I256::new(10)), 10); - /// assert_eq!(I256::MIN.wrapping_div_euclid(I256::new(-1)), I256::MIN); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub fn wrapping_div_euclid(self, rhs: Self) -> Self { - self.overflowing_div_euclid(rhs).0 - } - - /// Wrapping (modular) remainder. Computes `self % rhs`, wrapping around at - /// the boundary of the type. - /// - /// Such wrap-around never actually occurs mathematically; implementation - /// artifacts make `x % y` invalid for `MIN / -1` on a signed type (where - /// MIN` is the negative minimal value). In such a case, this function - /// returns `0`. - /// - /// # Panics - /// - /// This function will panic if `rhs` is 0. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// assert_eq!(I256::new(100).wrapping_rem(I256::new(10)), 0); - /// assert_eq!(I256::MIN.wrapping_rem(I256::new(-1)), 0); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub fn wrapping_rem(self, rhs: Self) -> Self { - self.overflowing_rem(rhs).0 - } - - /// Wrapping Euclidean remainder. Computes `self.rem_euclid(rhs)`, wrapping - /// around at the boundary of the type. - /// - /// Wrapping will only occur in `MIN % -1` on a signed type (where `MIN` is - /// the negative minimal value for the type). In this case, this method - /// returns 0. - /// - /// # Panics - /// - /// This function will panic if `rhs` is 0. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// assert_eq!(I256::new(100).wrapping_rem_euclid(I256::new(10)), 0); - /// assert_eq!(I256::MIN.wrapping_rem_euclid(I256::new(-1)), 0); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub fn wrapping_rem_euclid(self, rhs: Self) -> Self { - self.overflowing_rem_euclid(rhs).0 - } - - /// Wrapping (modular) negation. Computes `-self`, wrapping around at the - /// boundary of the type. - /// - /// The only case where such wrapping can occur is when one negates `MIN` on - /// a signed type (where `MIN` is the negative minimal value for the type); - /// this is a positive value that is too large to represent in the type. In - /// such a case, this function returns `MIN` itself. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// assert_eq!(I256::new(100).wrapping_neg(), -100); - /// assert_eq!(I256::MIN.wrapping_neg(), I256::MIN); - /// ``` - #[inline(always)] - pub fn wrapping_neg(self) -> Self { - Self::ZERO.wrapping_sub(self) - } - - /// Panic-free bitwise shift-left; yields `self << mask(rhs)`, where `mask` - /// removes any high-order bits of `rhs` that would cause the shift to - /// exceed the bitwidth of the type. - /// - /// Note that this is *not* the same as a rotate-left; the RHS of a wrapping - /// shift-left is restricted to the range of the type, rather than the bits - /// shifted out of the LHS being returned to the other end. The primitive - /// integer types all implement a [`rotate_left`](Self::rotate_left) - /// function, which may be what you want instead. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// assert_eq!(I256::new(-1).wrapping_shl(7), -128); - /// assert_eq!(I256::new(-1).wrapping_shl(128), I256::from_words(-1, 0)); - /// assert_eq!(I256::new(-1).wrapping_shl(256), -1); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline(always)] - pub fn wrapping_shl(self, rhs: u32) -> Self { - let mut result = MaybeUninit::uninit(); - intrinsics::signed::ishl3(&mut result, &self, rhs & 0xff); - unsafe { result.assume_init() } - } - - /// Panic-free bitwise shift-right; yields `self >> mask(rhs)`, where `mask` - /// removes any high-order bits of `rhs` that would cause the shift to - /// exceed the bitwidth of the type. - /// - /// Note that this is *not* the same as a rotate-right; the RHS of a - /// wrapping shift-right is restricted to the range of the type, rather than - /// the bits shifted out of the LHS being returned to the other end. The - /// primitive integer types all implement a - /// [`rotate_right`](Self::rotate_right) function, which may be what you - /// want instead. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// assert_eq!(I256::new(-128).wrapping_shr(7), -1); - /// assert_eq!((-128i16).wrapping_shr(64), -128); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline(always)] - pub fn wrapping_shr(self, rhs: u32) -> Self { - let mut result = MaybeUninit::uninit(); - intrinsics::signed::isar3(&mut result, &self, rhs & 0xff); - unsafe { result.assume_init() } - } - - /// Wrapping (modular) absolute value. Computes `self.abs()`, wrapping - /// around at the boundary of the type. - /// - /// The only case where such wrapping can occur is when one takes the - /// absolute value of the negative minimal value for the type; this is a - /// positive value that is too large to represent in the type. In such a - /// case, this function returns `MIN` itself. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::{I256, U256}; - /// assert_eq!(I256::new(100).wrapping_abs(), 100); - /// assert_eq!(I256::new(-100).wrapping_abs(), 100); - /// assert_eq!(I256::MIN.wrapping_abs(), I256::MIN); - /// assert_eq!( - /// I256::MIN.wrapping_abs().as_u256(), - /// U256::from_words( - /// 0x80000000000000000000000000000000, - /// 0x00000000000000000000000000000000, - /// ), - /// ); - /// ``` - #[allow(unused_attributes)] - #[inline] - pub fn wrapping_abs(self) -> Self { - if self.is_negative() { - self.wrapping_neg() - } else { - self - } - } - - /// Computes the absolute value of `self` without any wrapping - /// or panicking. - /// - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::{I256, U256}; - /// assert_eq!(I256::new(100).unsigned_abs(), 100); - /// assert_eq!(I256::new(-100).unsigned_abs(), 100); - /// assert_eq!( - /// I256::MIN.unsigned_abs(), - /// U256::from_words( - /// 0x80000000000000000000000000000000, - /// 0x00000000000000000000000000000000, - /// ), - /// ); - /// ``` - #[inline(always)] - pub fn unsigned_abs(self) -> U256 { - self.wrapping_abs().as_u256() - } - - /// Wrapping (modular) exponentiation. Computes `self.pow(exp)`, - /// wrapping around at the boundary of the type. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// assert_eq!(I256::new(3).wrapping_pow(4), 81); - /// assert_eq!(3i8.wrapping_pow(5), -13); - /// assert_eq!(3i8.wrapping_pow(6), -39); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub fn wrapping_pow(self, mut exp: u32) -> Self { - if exp == 0 { - return Self::ONE; - } - let mut base = self; - let mut acc = Self::ONE; - - while exp > 1 { - if (exp & 1) == 1 { - acc = acc.wrapping_mul(base); - } - exp /= 2; - base = base.wrapping_mul(base); - } - - // since exp!=0, finally the exp must be 1. - // Deal with the final bit of the exponent separately, since - // squaring the base afterwards is not necessary and may cause a - // needless overflow. - acc.wrapping_mul(base) - } - - /// Calculates `self` + `rhs` - /// - /// Returns a tuple of the addition along with a boolean indicating whether - /// an arithmetic overflow would occur. If an overflow would have occurred - /// then the wrapped value is returned. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// assert_eq!(I256::new(5).overflowing_add(I256::new(2)), (I256::new(7), false)); - /// assert_eq!(I256::MAX.overflowing_add(I256::new(1)), (I256::MIN, true)); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline(always)] - pub fn overflowing_add(self, rhs: Self) -> (Self, bool) { - let mut result = MaybeUninit::uninit(); - let overflow = intrinsics::signed::iaddc(&mut result, &self, &rhs); - (unsafe { result.assume_init() }, overflow) - } - - /// Calculates `self` + `rhs` with an unsigned `rhs` - /// - /// Returns a tuple of the addition along with a boolean indicating - /// whether an arithmetic overflow would occur. If an overflow would - /// have occurred then the wrapped value is returned. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::{I256, U256}; - /// assert_eq!(I256::new(1).overflowing_add_unsigned(U256::new(2)), (I256::new(3), false)); - /// assert_eq!((I256::MIN).overflowing_add_unsigned(U256::MAX), (I256::MAX, false)); - /// assert_eq!((I256::MAX - 2).overflowing_add_unsigned(U256::new(3)), (I256::MIN, true)); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub fn overflowing_add_unsigned(self, rhs: U256) -> (Self, bool) { - let rhs = rhs.as_i256(); - let (res, overflowed) = self.overflowing_add(rhs); - (res, overflowed ^ (rhs < 0)) - } - - /// Calculates `self` - `rhs` - /// - /// Returns a tuple of the subtraction along with a boolean indicating - /// whether an arithmetic overflow would occur. If an overflow would have - /// occurred then the wrapped value is returned. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// assert_eq!(I256::new(5).overflowing_sub(I256::new(2)), (I256::new(3), false)); - /// assert_eq!(I256::MIN.overflowing_sub(I256::new(1)), (I256::MAX, true)); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline(always)] - pub fn overflowing_sub(self, rhs: Self) -> (Self, bool) { - let mut result = MaybeUninit::uninit(); - let overflow = intrinsics::signed::isubc(&mut result, &self, &rhs); - (unsafe { result.assume_init() }, overflow) - } - - /// Calculates `self` - `rhs` with an unsigned `rhs` - /// - /// Returns a tuple of the subtraction along with a boolean indicating - /// whether an arithmetic overflow would occur. If an overflow would - /// have occurred then the wrapped value is returned. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::{I256, U256}; - /// assert_eq!(I256::new(1).overflowing_sub_unsigned(U256::new(2)), (I256::new(-1), false)); - /// assert_eq!((I256::MAX).overflowing_sub_unsigned(U256::MAX), (I256::MIN, false)); - /// assert_eq!((I256::MIN + 2).overflowing_sub_unsigned(U256::new(3)), (I256::MAX, true)); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub fn overflowing_sub_unsigned(self, rhs: U256) -> (Self, bool) { - let rhs = rhs.as_i256(); - let (res, overflowed) = self.overflowing_sub(rhs); - (res, overflowed ^ (rhs < 0)) - } - - /// Computes the absolute difference between `self` and `other`. - /// - /// This function always returns the correct answer without overflow or - /// panics by returning an unsigned integer. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::{I256, U256}; - /// assert_eq!(I256::new(100).abs_diff(I256::new(80)), 20); - /// assert_eq!(I256::new(100).abs_diff(I256::new(110)), 10); - /// assert_eq!(I256::new(-100).abs_diff(I256::new(80)), 180); - /// assert_eq!(I256::new(-100).abs_diff(I256::new(-120)), 20); - /// assert_eq!(I256::MIN.abs_diff(I256::MAX), U256::MAX); - /// assert_eq!(I256::MAX.abs_diff(I256::MIN), U256::MAX); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub fn abs_diff(self, other: Self) -> U256 { - if self < other { - // Converting a non-negative x from signed to unsigned by using - // `x as U` is left unchanged, but a negative x is converted - // to value x + 2^N. Thus if `s` and `o` are binary variables - // respectively indicating whether `self` and `other` are - // negative, we are computing the mathematical value: - // - // (other + o*2^N) - (self + s*2^N) mod 2^N - // other - self + (o-s)*2^N mod 2^N - // other - self mod 2^N - // - // Finally, taking the mod 2^N of the mathematical value of - // `other - self` does not change it as it already is - // in the range [0, 2^N). - other.as_u256().wrapping_sub(self.as_u256()) - } else { - self.as_u256().wrapping_sub(other.as_u256()) - } - } - - /// Calculates the multiplication of `self` and `rhs`. - /// - /// Returns a tuple of the multiplication along with a boolean indicating - /// whether an arithmetic overflow would occur. If an overflow would have - /// occurred then the wrapped value is returned. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// assert_eq!(I256::new(5).overflowing_mul(I256::new(2)), (I256::new(10), false)); - /// assert_eq!(I256::MAX.overflowing_mul(I256::new(2)), (I256::new(-2), true)); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline(always)] - pub fn overflowing_mul(self, rhs: Self) -> (Self, bool) { - let mut result = MaybeUninit::uninit(); - let overflow = intrinsics::signed::imulc(&mut result, &self, &rhs); - (unsafe { result.assume_init() }, overflow) - } - - /// Calculates the divisor when `self` is divided by `rhs`. - /// - /// Returns a tuple of the divisor along with a boolean indicating whether - /// an arithmetic overflow would occur. If an overflow would occur then self - /// is returned. - /// - /// # Panics - /// - /// This function will panic if `rhs` is 0. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// assert_eq!(I256::new(5).overflowing_div(I256::new(2)), (I256::new(2), false)); - /// assert_eq!(I256::MIN.overflowing_div(I256::new(-1)), (I256::MIN, true)); - /// ``` - #[inline] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - pub fn overflowing_div(self, rhs: Self) -> (Self, bool) { - if self == Self::MIN && rhs == -1 { - (self, true) - } else { - (self / rhs, false) - } - } - - /// Calculates the quotient of Euclidean division `self.div_euclid(rhs)`. - /// - /// Returns a tuple of the divisor along with a boolean indicating whether - /// an arithmetic overflow would occur. If an overflow would occur then - /// `self` is returned. - /// - /// # Panics - /// - /// This function will panic if `rhs` is 0. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// assert_eq!(I256::new(5).overflowing_div_euclid(I256::new(2)), (I256::new(2), false)); - /// assert_eq!(I256::MIN.overflowing_div_euclid(I256::new(-1)), (I256::MIN, true)); - /// ``` - #[inline] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - pub fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) { - if self == Self::MIN && rhs == -1 { - (self, true) - } else { - (self.div_euclid(rhs), false) - } - } - - /// Calculates the remainder when `self` is divided by `rhs`. - /// - /// Returns a tuple of the remainder after dividing along with a boolean - /// indicating whether an arithmetic overflow would occur. If an overflow - /// would occur then 0 is returned. - /// - /// # Panics - /// - /// This function will panic if `rhs` is 0. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// assert_eq!(I256::new(5).overflowing_rem(I256::new(2)), (I256::new(1), false)); - /// assert_eq!(I256::MIN.overflowing_rem(I256::new(-1)), (I256::new(0), true)); - /// ``` - #[inline] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - pub fn overflowing_rem(self, rhs: Self) -> (Self, bool) { - if self == Self::MIN && rhs == -1 { - (Self::ZERO, true) - } else { - (self % rhs, false) - } - } - - /// Overflowing Euclidean remainder. Calculates `self.rem_euclid(rhs)`. - /// - /// Returns a tuple of the remainder after dividing along with a boolean - /// indicating whether an arithmetic overflow would occur. If an overflow - /// would occur then 0 is returned. - /// - /// # Panics - /// - /// This function will panic if `rhs` is 0. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// assert_eq!(I256::new(5).overflowing_rem_euclid(I256::new(2)), (I256::new(1), false)); - /// assert_eq!(I256::MIN.overflowing_rem_euclid(I256::new(-1)), (I256::new(0), true)); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) { - if self == Self::MIN && rhs == -1 { - (Self::ZERO, true) - } else { - (self.rem_euclid(rhs), false) - } - } - - /// Negates self, overflowing if this is equal to the minimum value. - /// - /// Returns a tuple of the negated version of self along with a boolean - /// indicating whether an overflow happened. If `self` is the minimum value - /// (e.g., `i32::MIN` for values of type `i32`), then the minimum value will - /// be returned again and `true` will be returned for an overflow happening. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// assert_eq!(I256::new(2).overflowing_neg(), (I256::new(-2), false)); - /// assert_eq!(I256::MIN.overflowing_neg(), (I256::MIN, true)); - /// ``` - #[inline] - pub fn overflowing_neg(self) -> (Self, bool) { - if self == Self::MIN { - (Self::MIN, true) - } else { - (-self, false) - } - } - - /// Shifts self left by `rhs` bits. - /// - /// Returns a tuple of the shifted version of self along with a boolean - /// indicating whether the shift value was larger than or equal to the - /// number of bits. If the shift value is too large, then value is masked - /// (N-1) where N is the number of bits, and this value is then used to - /// perform the shift. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// assert_eq!(I256::new(1).overflowing_shl(4), (I256::new(0x10), false)); - /// assert_eq!(I256::new(1).overflowing_shl(260), (I256::new(0x10), true)); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub fn overflowing_shl(self, rhs: u32) -> (Self, bool) { - (self.wrapping_shl(rhs), (rhs > 255)) - } - - /// Shifts self right by `rhs` bits. - /// - /// Returns a tuple of the shifted version of self along with a boolean - /// indicating whether the shift value was larger than or equal to the - /// number of bits. If the shift value is too large, then value is masked - /// (N-1) where N is the number of bits, and this value is then used to - /// perform the shift. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// assert_eq!(I256::new(0x10).overflowing_shr(4), (I256::new(0x1), false)); - /// assert_eq!(I256::new(0x10).overflowing_shr(260), (I256::new(0x1), true)); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub fn overflowing_shr(self, rhs: u32) -> (Self, bool) { - (self.wrapping_shr(rhs), (rhs > 255)) - } - - /// Computes the absolute value of `self`. - /// - /// Returns a tuple of the absolute version of self along with a boolean - /// indicating whether an overflow happened. If self is the minimum value - /// (e.g., I256::MIN for values of type I256), then the minimum value will - /// be returned again and true will be returned for an overflow happening. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// assert_eq!(I256::new(10).overflowing_abs(), (I256::new(10), false)); - /// assert_eq!(I256::new(-10).overflowing_abs(), (I256::new(10), false)); - /// assert_eq!(I256::MIN.overflowing_abs(), (I256::MIN, true)); - /// ``` - #[inline] - pub fn overflowing_abs(self) -> (Self, bool) { - (self.wrapping_abs(), self == Self::MIN) - } - - /// Raises self to the power of `exp`, using exponentiation by squaring. - /// - /// Returns a tuple of the exponentiation along with a bool indicating - /// whether an overflow happened. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// assert_eq!(I256::new(3).overflowing_pow(4), (I256::new(81), false)); - /// assert_eq!( - /// I256::new(10).overflowing_pow(77), - /// ( - /// I256::from_words( - /// -46408779215366586471190473126206792002, - /// -113521875028918879454725857041952276480, - /// ), - /// true, - /// ) - /// ); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub fn overflowing_pow(self, mut exp: u32) -> (Self, bool) { - if exp == 0 { - return (Self::ONE, false); - } - let mut base = self; - let mut acc = Self::ONE; - let mut overflown = false; - // Scratch space for storing results of overflowing_mul. - let mut r; - - while exp > 1 { - if (exp & 1) == 1 { - r = acc.overflowing_mul(base); - acc = r.0; - overflown |= r.1; - } - exp /= 2; - r = base.overflowing_mul(base); - base = r.0; - overflown |= r.1; - } - - // since exp!=0, finally the exp must be 1. - // Deal with the final bit of the exponent separately, since - // squaring the base afterwards is not necessary and may cause a - // needless overflow. - r = acc.overflowing_mul(base); - r.1 |= overflown; - r - } - - /// Raises self to the power of `exp`, using exponentiation by squaring. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// - /// assert_eq!(I256::new(2).pow(5), 32); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub fn pow(self, mut exp: u32) -> Self { - if exp == 0 { - return Self::ONE; - } - let mut base = self; - let mut acc = Self::ONE; - - while exp > 1 { - if (exp & 1) == 1 { - acc *= base; - } - exp /= 2; - base = base * base; - } - - // since exp!=0, finally the exp must be 1. - // Deal with the final bit of the exponent separately, since - // squaring the base afterwards is not necessary and may cause a - // needless overflow. - acc * base - } - - /// Calculates the quotient of Euclidean division of `self` by `rhs`. - /// - /// This computes the integer `q` such that `self = q * rhs + r`, with - /// `r = self.rem_euclid(rhs)` and `0 <= r < abs(rhs)`. - /// - /// In other words, the result is `self / rhs` rounded to the integer `q` - /// such that `self >= q * rhs`. - /// If `self > 0`, this is equal to round towards zero (the default in - /// Rust); if `self < 0`, this is equal to round towards +/- infinity. - /// - /// # Panics - /// - /// This function will panic if `rhs` is 0 or the division results in - /// overflow. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// let a = I256::new(7); - /// let b = I256::new(4); - /// - /// assert_eq!(a.div_euclid(b), 1); // 7 >= 4 * 1 - /// assert_eq!(a.div_euclid(-b), -1); // 7 >= -4 * -1 - /// assert_eq!((-a).div_euclid(b), -2); // -7 >= 4 * -2 - /// assert_eq!((-a).div_euclid(-b), 2); // -7 >= -4 * 2 - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub fn div_euclid(self, rhs: Self) -> Self { - let q = self / rhs; - if self % rhs < 0 { - return if rhs > 0 { q - 1 } else { q + 1 }; - } - q - } - - /// Calculates the least nonnegative remainder of `self (mod rhs)`. - /// - /// This is done as if by the Euclidean division algorithm -- given - /// `r = self.rem_euclid(rhs)`, `self = rhs * self.div_euclid(rhs) + r`, and - /// `0 <= r < abs(rhs)`. - /// - /// # Panics - /// - /// This function will panic if `rhs` is 0 or the division results in - /// overflow. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// let a = I256::new(7); - /// let b = I256::new(4); - /// - /// assert_eq!(a.rem_euclid(b), 3); - /// assert_eq!((-a).rem_euclid(b), 1); - /// assert_eq!(a.rem_euclid(-b), 3); - /// assert_eq!((-a).rem_euclid(-b), 1); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub fn rem_euclid(self, rhs: Self) -> Self { - let r = self % rhs; - if r < 0 { - if rhs < 0 { - r - rhs - } else { - r + rhs - } - } else { - r - } - } - - /// Computes the absolute value of `self`. - /// - /// # Overflow behavior - /// - /// The absolute value of - /// `I256::MIN` - /// cannot be represented as an - /// `I256`, - /// and attempting to calculate it will cause an overflow. This means - /// that code in debug mode will trigger a panic on this case and - /// optimized code will return - /// `I256::MIN` - /// without a panic. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// assert_eq!(I256::new(10).abs(), 10); - /// assert_eq!(I256::new(-10).abs(), 10); - /// ``` - #[allow(unused_attributes)] - #[inline] - pub fn abs(self) -> Self { - if self.is_negative() { - -self - } else { - self - } - } - - /// Returns a number representing sign of `self`. - /// - /// - `0` if the number is zero - /// - `1` if the number is positive - /// - `-1` if the number is negative - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// assert_eq!(I256::new(10).signum(), 1); - /// assert_eq!(I256::new(0).signum(), 0); - /// assert_eq!(I256::new(-10).signum(), -1); - /// ``` - #[inline(always)] - pub const fn signum(self) -> Self { - I256::new(self.signum128()) - } - - /// Returns a number representing sign of `self` as a 128 bit signed integer. - /// - /// - `0` if the number is zero - /// - `1` if the number is positive - /// - `-1` if the number is negative - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// assert_eq!(I256::new(10).signum128(), 1i128); - /// assert_eq!(I256::new(0).signum128(), 0i128); - /// assert_eq!(I256::new(-10).signum128(), -1i128); - /// ``` - #[inline] - pub const fn signum128(self) -> i128 { - let (hi, lo) = self.into_words(); - hi.signum() | (lo != 0) as i128 - } - - /// Returns `true` if `self` is positive and `false` if the number is zero - /// or negative. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// assert!(I256::new(10).is_positive()); - /// assert!(!I256::new(-10).is_positive()); - /// ``` - #[inline] - pub const fn is_positive(self) -> bool { - self.signum128() > 0 - } - - /// Returns `true` if `self` is negative and `false` if the number is zero - /// or positive. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::I256; - /// assert!(I256::new(-10).is_negative()); - /// assert!(!I256::new(10).is_negative()); - /// ``` - #[inline(always)] - pub const fn is_negative(self) -> bool { - let (a, _) = self.into_words(); - a < 0 - } - - /// Return the memory representation of this integer as a byte array in - /// big-endian (network) byte order. - /// - /// # Examples - /// - /// ``` - /// # use ethnum::I256; - /// let bytes = I256::from_words( - /// 0x00010203_04050607_08090a0b_0c0d0e0f, - /// 0x10111213_14151617_18191a1b_1c1d1e1f, - /// ); - /// assert_eq!( - /// bytes.to_be_bytes(), - /// [ - /// 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - /// 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - /// ], - /// ); - /// ``` - #[inline] - pub const fn to_be_bytes(self) -> [u8; mem::size_of::()] { - self.to_be().to_ne_bytes() - } - - /// Return the memory representation of this integer as a byte array in - /// little-endian byte order. - /// - /// # Examples - /// - /// ``` - /// # use ethnum::I256; - /// let bytes = I256::from_words( - /// 0x00010203_04050607_08090a0b_0c0d0e0f, - /// 0x10111213_14151617_18191a1b_1c1d1e1f, - /// ); - /// assert_eq!( - /// bytes.to_le_bytes(), - /// [ - /// 0x1f, 0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, - /// 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, - /// ], - /// ); - /// ``` - #[inline] - pub const fn to_le_bytes(self) -> [u8; mem::size_of::()] { - self.to_le().to_ne_bytes() - } - - /// Return the memory representation of this integer as a byte array in - /// native byte order. - /// - /// As the target platform's native endianness is used, portable code - /// should use [`to_be_bytes`] or [`to_le_bytes`], as appropriate, - /// instead. - /// - /// [`to_be_bytes`]: Self::to_be_bytes - /// [`to_le_bytes`]: Self::to_le_bytes - /// - /// # Examples - /// - /// ``` - /// # use ethnum::I256; - /// let bytes = I256::from_words( - /// 0x00010203_04050607_08090a0b_0c0d0e0f, - /// 0x10111213_14151617_18191a1b_1c1d1e1f, - /// ); - /// assert_eq!( - /// bytes.to_ne_bytes(), - /// if cfg!(target_endian = "big") { - /// [ - /// 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - /// 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - /// ] - /// } else { - /// [ - /// 0x1f, 0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, - /// 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, - /// ] - /// } - /// ); - /// ``` - #[inline] - pub const fn to_ne_bytes(self) -> [u8; mem::size_of::()] { - // SAFETY: integers are plain old datatypes so we can always transmute them to - // arrays of bytes - unsafe { mem::transmute(self) } - } - - /// Create an integer value from its representation as a byte array in - /// big endian. - /// - /// # Examples - /// - /// ``` - /// # use ethnum::I256; - /// let value = I256::from_be_bytes([ - /// 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - /// 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - /// ]); - /// assert_eq!( - /// value, - /// I256::from_words( - /// 0x00010203_04050607_08090a0b_0c0d0e0f, - /// 0x10111213_14151617_18191a1b_1c1d1e1f, - /// ), - /// ); - /// ``` - /// - /// When starting from a slice rather than an array, fallible conversion - /// APIs can be used: - /// - /// ``` - /// # use ethnum::I256; - /// fn read_be_i256(input: &mut &[u8]) -> I256 { - /// let (int_bytes, rest) = input.split_at(std::mem::size_of::()); - /// *input = rest; - /// I256::from_be_bytes(int_bytes.try_into().unwrap()) - /// } - /// ``` - #[inline] - pub const fn from_be_bytes(bytes: [u8; mem::size_of::()]) -> Self { - Self::from_be(Self::from_ne_bytes(bytes)) - } - - /// Create an integer value from its representation as a byte array in - /// little endian. - /// - /// # Examples - /// - /// ``` - /// # use ethnum::I256; - /// let value = I256::from_le_bytes([ - /// 0x1f, 0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, - /// 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, - /// ]); - /// assert_eq!( - /// value, - /// I256::from_words( - /// 0x00010203_04050607_08090a0b_0c0d0e0f, - /// 0x10111213_14151617_18191a1b_1c1d1e1f, - /// ), - /// ); - /// ``` - /// - /// When starting from a slice rather than an array, fallible conversion - /// APIs can be used: - /// - /// ``` - /// # use ethnum::I256; - /// fn read_le_i256(input: &mut &[u8]) -> I256 { - /// let (int_bytes, rest) = input.split_at(std::mem::size_of::()); - /// *input = rest; - /// I256::from_le_bytes(int_bytes.try_into().unwrap()) - /// } - /// ``` - #[inline] - pub const fn from_le_bytes(bytes: [u8; mem::size_of::()]) -> Self { - Self::from_le(Self::from_ne_bytes(bytes)) - } - - /// Create an integer value from its memory representation as a byte - /// array in native endianness. - /// - /// As the target platform's native endianness is used, portable code - /// likely wants to use [`from_be_bytes`] or [`from_le_bytes`], as - /// appropriate instead. - /// - /// [`from_be_bytes`]: Self::from_be_bytes - /// [`from_le_bytes`]: Self::from_le_bytes - /// - /// # Examples - /// - /// ``` - /// # use ethnum::I256; - /// let value = I256::from_ne_bytes(if cfg!(target_endian = "big") { - /// [ - /// 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - /// 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - /// ] - /// } else { - /// [ - /// 0x1f, 0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, - /// 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, - /// ] - /// }); - /// assert_eq!( - /// value, - /// I256::from_words( - /// 0x00010203_04050607_08090a0b_0c0d0e0f, - /// 0x10111213_14151617_18191a1b_1c1d1e1f, - /// ), - /// ); - /// ``` - /// - /// When starting from a slice rather than an array, fallible conversion - /// APIs can be used: - /// - /// ``` - /// # use ethnum::I256; - /// fn read_ne_i256(input: &mut &[u8]) -> I256 { - /// let (int_bytes, rest) = input.split_at(std::mem::size_of::()); - /// *input = rest; - /// I256::from_ne_bytes(int_bytes.try_into().unwrap()) - /// } - /// ``` - #[inline] - pub const fn from_ne_bytes(bytes: [u8; mem::size_of::()]) -> Self { - // SAFETY: integers are plain old datatypes so we can always transmute to them - unsafe { mem::transmute(bytes) } - } -} diff --git a/Contract/ethnum-patch/src/int/cmp.rs b/Contract/ethnum-patch/src/int/cmp.rs deleted file mode 100644 index d9c8097..0000000 --- a/Contract/ethnum-patch/src/int/cmp.rs +++ /dev/null @@ -1,71 +0,0 @@ -//! Module with comparison implementations for `I256`. -//! -//! `PartialEq` is derived and not implemented, which is important for ensuring -//! that `match` can be used with `I256`. -//! -//! ``` -//! # use ethnum::I256; -//! # let value = I256::new(42); -//! -//! match (value) { -//! I256::ZERO => println!("I am zero"), -//! I256::ONE => println!("I am one"), -//! _ => println!("I am something else"), -//! } -//! ``` -//! -//! `PartialEq` and `PartialOrd` implementations for `i128` are also provided -//! to allow notation such as: -//! -//! ``` -//! # use ethnum::I256; -//! assert_eq!(I256::new(42), 42); -//! assert_eq!(42, I256::new(42)); -//! assert!(I256::ONE > 0 && I256::ZERO == 0); -//! assert!(0 < I256::ONE && 0 == I256::ZERO); -//! ``` - -use super::I256; -use core::cmp::Ordering; - -impl Ord for I256 { - #[inline] - fn cmp(&self, other: &Self) -> Ordering { - let (ahi, alo) = self.into_words(); - let (bhi, blo) = other.into_words(); - (ahi, alo as u128).cmp(&(bhi, blo as u128)) - } -} - -impl_cmp! { - impl Cmp for I256 (i128); -} - -#[cfg(test)] -mod tests { - use super::*; - use core::cmp::Ordering; - - #[test] - fn cmp() { - // 1e38 - let x = I256::from_words(0, 100000000000000000000000000000000000000); - // 1e48 - let y = I256::from_words(2938735877, 18960114910927365649471927446130393088); - assert!(x < y); - assert_eq!(x.cmp(&y), Ordering::Less); - assert!(y > x); - assert_eq!(y.cmp(&x), Ordering::Greater); - - let x = I256::new(100); - let y = I256::new(100); - assert!(x <= y); - assert_eq!(x.cmp(&y), Ordering::Equal); - - assert!(I256::ZERO > I256::MIN); - assert!(I256::ZERO < I256::MAX); - - assert!(I256::MAX > I256::MIN); - assert!(I256::MIN < I256::MAX); - } -} diff --git a/Contract/ethnum-patch/src/int/convert.rs b/Contract/ethnum-patch/src/int/convert.rs deleted file mode 100644 index a013240..0000000 --- a/Contract/ethnum-patch/src/int/convert.rs +++ /dev/null @@ -1,230 +0,0 @@ -//! Module contains conversions for [`I256`] to and from primimitive types. - -use super::I256; -use crate::{error::tfie, uint::U256}; -use core::num::TryFromIntError; - -macro_rules! impl_from { - ($($t:ty),* $(,)?) => {$( - impl From<$t> for I256 { - #[inline] - fn from(value: $t) -> Self { - value.as_i256() - } - } - )*}; -} - -impl_from! { - bool, - i8, i16, i32, i64, i128, - u8, u16, u32, u64, u128, -} - -impl TryFrom for I256 { - type Error = TryFromIntError; - - fn try_from(value: U256) -> Result { - if value > I256::MAX.as_u256() { - return Err(tfie()); - } - Ok(value.as_i256()) - } -} - -/// This trait defines `as` conversions (casting) from primitive types to -/// [`I256`]. -/// -/// [`I256`]: struct.I256.html -/// -/// # Examples -/// -/// Casting a floating point value to an integer is a saturating operation, -/// with `NaN` converting to `0`. So: -/// -/// ``` -/// # use ethnum::{I256, AsI256}; -/// assert_eq!((-1i32).as_i256(), -I256::ONE); -/// assert_eq!(u32::MAX.as_i256(), 0xffffffff); -/// -/// assert_eq!(-13.37f64.as_i256(), -13); -/// assert_eq!(42.0f64.as_i256(), 42); -/// assert_eq!( -/// f32::MAX.as_i256(), -/// 0xffffff00000000000000000000000000u128.as_i256(), -/// ); -/// assert_eq!( -/// f32::MIN.as_i256(), -/// -0xffffff00000000000000000000000000u128.as_i256(), -/// ); -/// -/// assert_eq!(f64::NEG_INFINITY.as_i256(), I256::MIN); -/// assert_eq!((-2.0f64.powi(256)).as_i256(), I256::MIN); -/// assert_eq!(f64::INFINITY.as_i256(), I256::MAX); -/// assert_eq!(2.0f64.powi(256).as_i256(), I256::MAX); -/// assert_eq!(f64::NAN.as_i256(), 0); -/// ``` -pub trait AsI256 { - /// Perform an `as` conversion to a [`I256`]. - /// - /// [`I256`]: struct.I256.html - #[allow(clippy::wrong_self_convention)] - fn as_i256(self) -> I256; -} - -impl AsI256 for I256 { - #[inline] - fn as_i256(self) -> I256 { - self - } -} - -impl AsI256 for U256 { - #[inline] - fn as_i256(self) -> I256 { - U256::as_i256(self) - } -} - -macro_rules! impl_as_i256 { - ($($t:ty),* $(,)?) => {$( - impl AsI256 for $t { - #[inline] - fn as_i256(self) -> I256 { - #[allow(unused_comparisons)] - let hi = if self >= 0 { 0 } else { !0 }; - I256::from_words(hi, self as _) - } - } - )*}; -} - -impl_as_i256! { - i8, i16, i32, i64, i128, - u8, u16, u32, u64, u128, - isize, usize, -} - -impl AsI256 for bool { - #[inline] - fn as_i256(self) -> I256 { - I256::new(self as _) - } -} - -macro_rules! impl_as_i256_float { - ($($t:ty [$b:ty]),* $(,)?) => {$( - impl AsI256 for $t { - #[inline] - fn as_i256(self) -> I256 { - // The conversion follows roughly the same rules as converting - // `f64` to other primitive integer types: - // - `NaN` => `0` - // - `(-∞, I256::MIN]` => `I256::MIN` - // - `(I256::MIN, I256::MAX]` => `value as I256` - // - `(I256::MAX, +∞)` => `I256::MAX` - - const M: $b = (<$t>::MANTISSA_DIGITS - 1) as _; - const MAN_MASK: $b = !(!0 << M); - const MAN_ONE: $b = 1 << M; - const EXP_MASK: $b = !0 >> <$t>::MANTISSA_DIGITS; - const EXP_OFFSET: $b = EXP_MASK / 2; - const ABS_MASK: $b = !0 >> 1; - const SIG_MASK: $b = !ABS_MASK; - - let abs = <$t>::from_bits(self.to_bits() & ABS_MASK); - let sign = -(((self.to_bits() & SIG_MASK) >> (<$b>::BITS - 2)) as i128) - .wrapping_sub(1); // if self >= 0. { 1 } else { -1 } - if abs >= 1.0 { - let bits = abs.to_bits(); - let exponent = ((bits >> M) & EXP_MASK) - EXP_OFFSET; - let mantissa = (bits & MAN_MASK) | MAN_ONE; - if exponent <= M { - (I256::from(mantissa >> (M - exponent))) * sign - } else if exponent < 255 { - (I256::from(mantissa) << (exponent - M)) * sign - } else if sign > 0 { - I256::MAX - } else { - I256::MIN - } - } else { - I256::ZERO - } - } - } - )*}; -} - -impl_as_i256_float! { - f32[u32], f64[u64], -} - -macro_rules! impl_try_into { - ($($t:ty),* $(,)?) => {$( - impl TryFrom for $t { - type Error = TryFromIntError; - - #[inline] - fn try_from(x: I256) -> Result { - if x >= <$t>::MIN.as_i256() && x <= <$t>::MAX.as_i256() { - Ok(*x.low() as _) - } else { - Err(tfie()) - } - } - } - )*}; -} - -impl_try_into! { - i8, i16, i32, i64, i128, - u8, u16, u32, u64, u128, - isize, usize, -} - -macro_rules! impl_into_float { - ($($t:ty => $f:ident),* $(,)?) => {$( - impl From for $t { - #[inline] - fn from(x: I256) -> $t { - x.$f() - } - } - )*}; -} - -impl_into_float! { - f32 => as_f32, f64 => as_f64, -} - -#[cfg(test)] -mod tests { - use crate::I256; - use core::str::FromStr as _; - - #[test] - fn checked_conversion() { - assert_eq!(i32::try_from(I256::new(-10)).unwrap(), -10); - assert_eq!(i32::try_from(I256::new(10)).unwrap(), 10); - assert!(i32::try_from(I256::MIN).is_err()); - assert!(i32::try_from(I256::MAX).is_err()); - } - - #[test] - fn github_issue_44() { - // A big number. - let lhs_i256 = I256::from(i128::MAX); - - // Adding 19 zeros. - let scaled_lhs = lhs_i256 * I256::from_str("10000000000000000000").unwrap(); - - // One and 18 zeros. - let rhs_i256 = I256::from_str("-1000000000000000000").unwrap(); - - // So result is basically -i128::MAX and one zero. - let result = scaled_lhs.checked_div(rhs_i256).unwrap(); - - assert!(i128::try_from(result).is_err()); - } -} diff --git a/Contract/ethnum-patch/src/int/fmt.rs b/Contract/ethnum-patch/src/int/fmt.rs deleted file mode 100644 index 4c88305..0000000 --- a/Contract/ethnum-patch/src/int/fmt.rs +++ /dev/null @@ -1,69 +0,0 @@ -//! Module implementing formatting for `I256` type. - -use crate::int::I256; - -impl_fmt! { - impl Fmt for I256; -} - -#[cfg(test)] -mod tests { - use super::*; - use alloc::format; - - #[test] - fn from_str() { - assert_eq!("42".parse::().unwrap(), 42); - } - - #[test] - fn debug() { - assert_eq!( - format!("{:?}", I256::MAX), - "57896044618658097711785492504343953926634992332820282019728792003956564819967", - ); - assert_eq!( - format!("{:x?}", I256::MIN), - "8000000000000000000000000000000000000000000000000000000000000000", - ); - assert_eq!( - format!("{:#X?}", I256::MAX), - "0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", - ); - } - - #[test] - fn display() { - assert_eq!( - format!("{}", I256::MIN), - "-57896044618658097711785492504343953926634992332820282019728792003956564819968", - ); - assert_eq!( - format!( - "{}", - I256::from_words(0, -1329227995784915854529085396220968961) - ), - "338953138925153547608845522035547242495", - ); - } - - #[test] - fn radix() { - assert_eq!(format!("{:b}", I256::new(42)), "101010"); - assert_eq!(format!("{:o}", I256::new(42)), "52"); - assert_eq!(format!("{:x}", I256::new(42)), "2a"); - - // Note that there is no '-' sign for binary, octal or hex formatting! - // This is the same behaviour for the standard iN types. - assert_eq!(format!("{:b}", I256::MINUS_ONE), "1".repeat(256)); - assert_eq!(format!("{:o}", I256::MINUS_ONE), format!("{:7<86}", "1")); - assert_eq!(format!("{:x}", I256::MINUS_ONE), "f".repeat(64)); - } - - #[test] - fn exp() { - assert_eq!(format!("{:e}", I256::new(42)), "4.2e1"); - assert_eq!(format!("{:e}", I256::new(10).pow(76)), "1e76"); - assert_eq!(format!("{:E}", -I256::new(10).pow(39) * 1337), "-1.337E42"); - } -} diff --git a/Contract/ethnum-patch/src/int/iter.rs b/Contract/ethnum-patch/src/int/iter.rs deleted file mode 100644 index a228a42..0000000 --- a/Contract/ethnum-patch/src/int/iter.rs +++ /dev/null @@ -1,13 +0,0 @@ -//! Module contains iterator specific trait implementations. -//! -//! ``` -//! # use ethnum::I256; -//! assert_eq!((1..=3).map(I256::new).sum::(), 6); -//! assert_eq!([I256::new(6), I256::new(7)].iter().product::(), 42); -//! ``` - -use super::I256; - -impl_iter! { - impl Iter for I256; -} diff --git a/Contract/ethnum-patch/src/int/ops.rs b/Contract/ethnum-patch/src/int/ops.rs deleted file mode 100644 index b9c7ba6..0000000 --- a/Contract/ethnum-patch/src/int/ops.rs +++ /dev/null @@ -1,326 +0,0 @@ -//! Module `core::ops` trait implementations. -//! -//! Trait implementations for `i128` are also provided to allow notation such -//! as: -//! -//! ``` -//! # use ethnum::I256; -//! -//! let a = 1 + I256::ONE; -//! let b = I256::ONE + 1; -//! dbg!(a, b); -//! ``` - -use super::I256; -use crate::intrinsics::signed::*; - -impl_ops! { - for I256 | i128 { - add => iadd2, iadd3, iaddc; - mul => imul2, imul3, imulc; - sub => isub2, isub3, isubc; - - div => idiv2, idiv3; - rem => irem2, irem3; - - shl => ishl2, ishl3; - shr => isar2, isar3; - } -} - -impl_ops_neg! { - for I256 { - add => iadd2; - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::uint::U256; - use core::ops::*; - - #[test] - fn trait_implementations() { - trait Implements {} - impl Implements for I256 {} - impl Implements for &'_ I256 {} - - fn assert_ops() - where - for<'a> T: Implements - + Add<&'a i128> - + Add<&'a I256> - + Add - + Add - + AddAssign<&'a i128> - + AddAssign<&'a I256> - + AddAssign - + AddAssign - + BitAnd<&'a i128> - + BitAnd<&'a I256> - + BitAnd - + BitAnd - + BitAndAssign<&'a i128> - + BitAndAssign<&'a I256> - + BitAndAssign - + BitAndAssign - + BitOr<&'a i128> - + BitOr<&'a I256> - + BitOr - + BitOr - + BitOrAssign<&'a i128> - + BitOrAssign<&'a I256> - + BitOrAssign - + BitOrAssign - + BitXor<&'a i128> - + BitXor<&'a I256> - + BitXor - + BitXor - + BitXorAssign<&'a i128> - + BitXorAssign<&'a I256> - + BitXorAssign - + BitXorAssign - + Div<&'a i128> - + Div<&'a I256> - + Div - + Div - + DivAssign<&'a i128> - + DivAssign<&'a I256> - + DivAssign - + DivAssign - + Mul<&'a i128> - + Mul<&'a I256> - + Mul - + Mul - + MulAssign<&'a i128> - + MulAssign<&'a I256> - + MulAssign - + MulAssign - + Neg - + Not - + Rem<&'a i128> - + Rem<&'a I256> - + Rem - + Rem - + RemAssign<&'a i128> - + RemAssign<&'a I256> - + RemAssign - + RemAssign - + Shl<&'a i128> - + Shl<&'a i16> - + Shl<&'a I256> - + Shl<&'a i32> - + Shl<&'a i64> - + Shl<&'a i8> - + Shl<&'a isize> - + Shl<&'a u128> - + Shl<&'a u16> - + Shl<&'a U256> - + Shl<&'a u32> - + Shl<&'a u64> - + Shl<&'a u8> - + Shl<&'a usize> - + Shl - + Shl - + Shl - + Shl - + Shl - + Shl - + Shl - + Shl - + Shl - + Shl - + Shl - + Shl - + Shl - + Shl - + ShlAssign<&'a i128> - + ShlAssign<&'a i16> - + ShlAssign<&'a I256> - + ShlAssign<&'a i32> - + ShlAssign<&'a i64> - + ShlAssign<&'a i8> - + ShlAssign<&'a isize> - + ShlAssign<&'a u128> - + ShlAssign<&'a u16> - + ShlAssign<&'a U256> - + ShlAssign<&'a u32> - + ShlAssign<&'a u64> - + ShlAssign<&'a u8> - + ShlAssign<&'a usize> - + ShlAssign - + ShlAssign - + ShlAssign - + ShlAssign - + ShlAssign - + ShlAssign - + ShlAssign - + ShlAssign - + ShlAssign - + ShlAssign - + ShlAssign - + ShlAssign - + ShlAssign - + ShlAssign - + Shr<&'a i128> - + Shr<&'a i16> - + Shr<&'a I256> - + Shr<&'a i32> - + Shr<&'a i64> - + Shr<&'a i8> - + Shr<&'a isize> - + Shr<&'a u128> - + Shr<&'a u16> - + Shr<&'a U256> - + Shr<&'a u32> - + Shr<&'a u64> - + Shr<&'a u8> - + Shr<&'a usize> - + Shr - + Shr - + Shr - + Shr - + Shr - + Shr - + Shr - + Shr - + Shr - + Shr - + Shr - + Shr - + Shr - + Shr - + ShrAssign<&'a i128> - + ShrAssign<&'a i16> - + ShrAssign<&'a I256> - + ShrAssign<&'a i32> - + ShrAssign<&'a i64> - + ShrAssign<&'a i8> - + ShrAssign<&'a isize> - + ShrAssign<&'a u128> - + ShrAssign<&'a u16> - + ShrAssign<&'a U256> - + ShrAssign<&'a u32> - + ShrAssign<&'a u64> - + ShrAssign<&'a u8> - + ShrAssign<&'a usize> - + ShrAssign - + ShrAssign - + ShrAssign - + ShrAssign - + ShrAssign - + ShrAssign - + ShrAssign - + ShrAssign - + ShrAssign - + ShrAssign - + ShrAssign - + ShrAssign - + ShrAssign - + ShrAssign - + Sub<&'a i128> - + Sub<&'a I256> - + Sub - + Sub - + SubAssign<&'a i128> - + SubAssign<&'a I256> - + SubAssign - + SubAssign, - for<'a> &'a T: Implements - + Add<&'a i128> - + Add<&'a I256> - + Add - + Add - + BitAnd<&'a i128> - + BitAnd<&'a I256> - + BitAnd - + BitAnd - + BitOr<&'a i128> - + BitOr<&'a I256> - + BitOr - + BitOr - + BitXor<&'a i128> - + BitXor<&'a I256> - + BitXor - + BitXor - + Div<&'a i128> - + Div<&'a I256> - + Div - + Div - + Mul<&'a i128> - + Mul<&'a I256> - + Mul - + Mul - + Neg - + Not - + Rem<&'a i128> - + Rem<&'a I256> - + Rem - + Rem - + Shl<&'a i128> - + Shl<&'a i16> - + Shl<&'a I256> - + Shl<&'a i32> - + Shl<&'a i64> - + Shl<&'a i8> - + Shl<&'a isize> - + Shl<&'a u128> - + Shl<&'a u16> - + Shl<&'a U256> - + Shl<&'a u32> - + Shl<&'a u64> - + Shl<&'a u8> - + Shl<&'a usize> - + Shl - + Shl - + Shl - + Shl - + Shl - + Shl - + Shl - + Shl - + Shl - + Shl - + Shl - + Shl - + Shl - + Shl - + Shr<&'a i128> - + Shr<&'a i16> - + Shr<&'a I256> - + Shr<&'a i32> - + Shr<&'a i64> - + Shr<&'a i8> - + Shr<&'a isize> - + Shr<&'a u128> - + Shr<&'a u16> - + Shr<&'a U256> - + Shr<&'a u32> - + Shr<&'a u64> - + Shr<&'a u8> - + Shr<&'a usize> - + Shr - + Shr - + Shr - + Shr - + Shr - + Shr - + Shr - + Shr - + Shr - + Shr - + Shr - + Shr - + Shr - + Shr - + Sub<&'a i128> - + Sub<&'a I256> - + Sub - + Sub, - { - } - - assert_ops::(); - } -} diff --git a/Contract/ethnum-patch/src/int/parse.rs b/Contract/ethnum-patch/src/int/parse.rs deleted file mode 100644 index d8ddecc..0000000 --- a/Contract/ethnum-patch/src/int/parse.rs +++ /dev/null @@ -1,151 +0,0 @@ -//! Module implementing parsing for `I256` type. - -use crate::int::I256; - -impl_from_str! { - impl FromStr for I256; -} - -pub const fn const_from_str_prefixed(src: &str) -> I256 { - assert!(!src.is_empty(), "empty string"); - - let bytes = src.as_bytes(); - let (negate, start) = match bytes[0] { - b'+' => (false, 1), - b'-' => (true, 1), - _ => (false, 0), - }; - let uint = crate::parse::const_from_str_prefixed(bytes, start as _); - - let int = { - let (hi, lo) = if negate { - let (hi, lo) = uint.into_words(); - let (lo, carry) = (!lo).overflowing_add(1); - let hi = (!hi).wrapping_add(carry as _); - (hi, lo) - } else { - uint.into_words() - }; - I256::from_words(hi as _, lo as _) - }; - - if matches!((negate, int.signum128()), (false, -1) | (true, 1)) { - panic!("overflows integer type"); - } - - int -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::parse::from_str_radix; - use core::num::IntErrorKind; - - #[test] - fn from_str() { - assert_eq!("42".parse::().unwrap(), 42); - } - - #[test] - fn from_str_prefixed() { - assert_eq!(from_str_radix::("0b101", 2, Some("0b")).unwrap(), 5); - assert_eq!(from_str_radix::("-0xf", 16, Some("0x")).unwrap(), -15); - } - - #[test] - fn from_str_errors() { - assert_eq!( - from_str_radix::("", 2, None).unwrap_err().kind(), - &IntErrorKind::Empty, - ); - assert_eq!( - from_str_radix::("?", 2, None).unwrap_err().kind(), - &IntErrorKind::InvalidDigit, - ); - assert_eq!( - from_str_radix::("1", 16, Some("0x")) - .unwrap_err() - .kind(), - &IntErrorKind::InvalidDigit, - ); - assert_eq!( - from_str_radix::( - "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz", - 36, - None - ) - .unwrap_err() - .kind(), - &IntErrorKind::PosOverflow, - ); - assert_eq!( - from_str_radix::( - "-zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz", - 36, - None - ) - .unwrap_err() - .kind(), - &IntErrorKind::NegOverflow, - ); - } - - #[test] - fn const_parse() { - assert_eq!(const_from_str_prefixed("-0b1101"), -0b1101); - assert_eq!(const_from_str_prefixed("0o777"), 0o777); - assert_eq!(const_from_str_prefixed("-0x1f"), -0x1f); - assert_eq!(const_from_str_prefixed("+42"), 42); - - assert_eq!( - const_from_str_prefixed( - "0x7fff_ffff_ffff_ffff_ffff_ffff_ffff_fffe\ - baae_dce6_af48_a03b_bfd2_5e8c_d036_4141" - ), - I256::from_words( - 0x7fff_ffff_ffff_ffff_ffff_ffff_ffff_fffe, - 0xbaae_dce6_af48_a03b_bfd2_5e8c_d036_4141_u128 as _, - ), - ); - - assert_eq!( - const_from_str_prefixed( - "-0x8000_0000_0000_0000_0000_0000_0000_0000\ - 0000_0000_0000_0000_0000_0000_0000_0000" - ), - I256::MIN, - ); - assert_eq!( - const_from_str_prefixed( - "+0x7fff_ffff_ffff_ffff_ffff_ffff_ffff_ffff\ - ffff_ffff_ffff_ffff_ffff_ffff_ffff_ffff" - ), - I256::MAX, - ); - } - - #[test] - #[should_panic] - fn const_parse_overflow() { - const_from_str_prefixed( - "0x8000_0000_0000_0000_0000_0000_0000_0000\ - 0000_0000_0000_0000_0000_0000_0000_0000", - ); - } - - #[test] - #[should_panic] - fn const_parse_negative_overflow() { - const_from_str_prefixed( - "-0x8000_0000_0000_0000_0000_0000_0000_0000\ - 0000_0000_0000_0000_0000_0000_0000_0001", - ); - } - - #[test] - #[should_panic] - fn const_parse_invalid() { - const_from_str_prefixed("invalid"); - } -} diff --git a/Contract/ethnum-patch/src/intrinsics.rs b/Contract/ethnum-patch/src/intrinsics.rs deleted file mode 100644 index 5eb172a..0000000 --- a/Contract/ethnum-patch/src/intrinsics.rs +++ /dev/null @@ -1,37 +0,0 @@ -//! This module contains intrinsics used by the [`I256`](struct@crate::I256) and -//! [`U256`](struct@crate::U256) implementations. -//! -//! # Stability -//! -//! Be careful when using these intrinsics directly. Semantic versioning API -//! compatibility is **not guaranteed** for any of these intrinsics. - -#![allow(missing_docs)] - -#[macro_use] -mod cast; - -#[cfg(feature = "llvm-intrinsics")] -mod llvm; -#[cfg(not(feature = "llvm-intrinsics"))] -mod native; -pub mod signed; - -#[cfg(feature = "llvm-intrinsics")] -pub use self::llvm::*; -#[cfg(not(feature = "llvm-intrinsics"))] -pub use self::native::*; - -#[cfg(test)] -mod tests { - use super::*; - use crate::uint::U256; - use core::mem::MaybeUninit; - - #[test] - fn unchecked_addition() { - let mut res = MaybeUninit::uninit(); - add3(&mut res, &U256([1, 2]), &U256([3, 0])); - assert_eq!(unsafe { res.assume_init() }, U256([4, 2])); - } -} diff --git a/Contract/ethnum-patch/src/intrinsics/cast.rs b/Contract/ethnum-patch/src/intrinsics/cast.rs deleted file mode 100644 index fc536d6..0000000 --- a/Contract/ethnum-patch/src/intrinsics/cast.rs +++ /dev/null @@ -1,17 +0,0 @@ -//! Module with casting helpers. - -/// Cast references of `U256` to `I256` for intrinsic implementations. -macro_rules! cast { - (mut: $x:expr) => { - unsafe { &mut *($x as *mut $crate::int::I256).cast::<$crate::uint::U256>() } - }; - (ref: $x:expr) => { - unsafe { &*($x as *const $crate::int::I256).cast::<$crate::uint::U256>() } - }; - (uninit: $x:expr) => { - unsafe { &mut *($x).as_mut_ptr().cast::<::core::mem::MaybeUninit<$crate::uint::U256>>() } - }; - (optuninit: $x:expr) => { - ($x).as_mut().map(|x| cast!(uninit: *x)) - }; -} diff --git a/Contract/ethnum-patch/src/intrinsics/llvm.rs b/Contract/ethnum-patch/src/intrinsics/llvm.rs deleted file mode 100644 index b5a158f..0000000 --- a/Contract/ethnum-patch/src/intrinsics/llvm.rs +++ /dev/null @@ -1,96 +0,0 @@ -//! This module contains definitions for LLVM IR generated intrinsics. - -// NOTE: LLVM IR generated intrinsics for `{i,u}div i256`, `{i,u}rem i256`, and -// `imul i256` produce an error when compiling. Use the native implementations -// even when generated intrinsics are enabled. -#[path = "native/divmod.rs"] -mod divmod; -#[path = "native/mul.rs"] -#[allow(dead_code)] -mod mul; - -pub use self::{divmod::*, mul::imulc}; -use crate::{int::I256, uint::U256}; -use core::mem::{self, MaybeUninit}; - -macro_rules! def { - ($( - $(#[$a:meta])* - pub fn $name:ident( - $($p:ident : $t:ty),* - ) $(-> $ret:ty)?; - )*) => {$( - $(#[$a])* - pub fn $name( - $($p: $t,)* - ) $(-> $ret)? { - unsafe { - ethnum_intrinsics::$name($( - #[allow( - clippy::missing_transmute_annotations, - clippy::transmute_ptr_to_ptr, - clippy::useless_transmute, - )] - mem::transmute::<_, _>($p) - ),*) - } - } - )*}; -} - -def! { - pub fn add2(r: &mut U256, a: &U256); - pub fn add3(r: &mut MaybeUninit, a: &U256, b: &U256); - pub fn uaddc(r: &mut MaybeUninit, a: &U256, b: &U256) -> bool; - pub fn iaddc(r: &mut MaybeUninit, a: &I256, b: &I256) -> bool; - - pub fn sub2(r: &mut U256, a: &U256); - pub fn sub3(r: &mut MaybeUninit, a: &U256, b: &U256); - pub fn usubc(r: &mut MaybeUninit, a: &U256, b: &U256) -> bool; - pub fn isubc(r: &mut MaybeUninit, a: &I256, b: &I256) -> bool; - - pub fn mul2(r: &mut U256, a: &U256); - pub fn mul3(r: &mut MaybeUninit, a: &U256, b: &U256); - pub fn umulc(r: &mut MaybeUninit, a: &U256, b: &U256) -> bool; - - pub fn shl2(r: &mut U256, a: u32); - pub fn shl3(r: &mut MaybeUninit, a: &U256, b: u32); - - pub fn sar2(r: &mut I256, a: u32); - pub fn sar3(r: &mut MaybeUninit, a: &I256, b: u32); - pub fn shr2(r: &mut U256, a: u32); - pub fn shr3(r: &mut MaybeUninit, a: &U256, b: u32); - - pub fn rol3(r: &mut MaybeUninit, a: &U256, b: u32); - pub fn ror3(r: &mut MaybeUninit, a: &U256, b: u32); - - pub fn ctlz(a: &U256) -> u32; - pub fn cttz(a: &U256) -> u32; -} - -#[cfg(test)] -mod tests { - use super::*; - use core::{alloc::Layout, mem}; - - #[test] - fn layout() { - // Small note on alignment: Since we pass in pointers to our wide - // integer types we need only to make sure that the alignment of - // `ethnum::{I256, U256}` types are larger than the FFI-safe type (i.e. - // the alignment is compatible with the FFI type). - - assert_eq!( - Layout::new::(), - Layout::new::() - .align_to(mem::align_of::()) - .unwrap(), - ); - assert_eq!( - Layout::new::(), - Layout::new::() - .align_to(mem::align_of::()) - .unwrap(), - ); - } -} diff --git a/Contract/ethnum-patch/src/intrinsics/native.rs b/Contract/ethnum-patch/src/intrinsics/native.rs deleted file mode 100644 index 04abe09..0000000 --- a/Contract/ethnum-patch/src/intrinsics/native.rs +++ /dev/null @@ -1,13 +0,0 @@ -//! This module contains native implementations for intrinsics. These are used -//! when generated IR intrinsics are disabled. - -mod add; -mod ctz; -mod divmod; -mod mul; -mod rot; -mod shl; -mod shr; -mod sub; - -pub use self::{add::*, ctz::*, divmod::*, mul::*, rot::*, shl::*, shr::*, sub::*}; diff --git a/Contract/ethnum-patch/src/intrinsics/native/add.rs b/Contract/ethnum-patch/src/intrinsics/native/add.rs deleted file mode 100644 index dc65058..0000000 --- a/Contract/ethnum-patch/src/intrinsics/native/add.rs +++ /dev/null @@ -1,36 +0,0 @@ -//! Module implementing addition intrinsics. - -use crate::{int::I256, uint::U256}; -use core::mem::MaybeUninit; - -#[inline] -pub fn add2(r: &mut U256, a: &U256) { - let (lo, carry) = r.low().overflowing_add(*a.low()); - *r.low_mut() = lo; - *r.high_mut() = r.high().wrapping_add(carry as _).wrapping_add(*a.high()); -} - -#[inline] -pub fn add3(r: &mut MaybeUninit, a: &U256, b: &U256) { - let (lo, carry) = a.low().overflowing_add(*b.low()); - let hi = a.high().wrapping_add(carry as _).wrapping_add(*b.high()); - - r.write(U256::from_words(hi, lo)); -} - -#[inline] -pub fn uaddc(r: &mut MaybeUninit, a: &U256, b: &U256) -> bool { - let (lo, carry_lo) = a.low().overflowing_add(*b.low()); - let (hi, carry_c) = a.high().overflowing_add(carry_lo as _); - let (hi, carry_hi) = hi.overflowing_add(*b.high()); - - r.write(U256::from_words(hi, lo)); - carry_c || carry_hi -} - -#[inline] -pub fn iaddc(r: &mut MaybeUninit, a: &I256, b: &I256) -> bool { - add3(cast!(uninit: r), cast!(ref: a), cast!(ref: b)); - let s = unsafe { r.assume_init_ref() }; - (*b >= 0 && s < a) || (*b < 0 && s >= a) -} diff --git a/Contract/ethnum-patch/src/intrinsics/native/ctz.rs b/Contract/ethnum-patch/src/intrinsics/native/ctz.rs deleted file mode 100644 index f830e13..0000000 --- a/Contract/ethnum-patch/src/intrinsics/native/ctz.rs +++ /dev/null @@ -1,16 +0,0 @@ -//! This module implements intrinsics for counting trailing and leading zeros -//! for 256-bit integers. - -use crate::uint::U256; - -#[inline] -pub fn ctlz(a: &U256) -> u32 { - let f = -((*a.high() == 0) as i128) as u128; - ((a.high() & !f) | (a.low() & f)).leading_zeros() + ((f as u32) & 128) -} - -#[inline] -pub fn cttz(a: &U256) -> u32 { - let f = -((*a.low() == 0) as i128) as u128; - ((a.high() & f) | (a.low() & !f)).trailing_zeros() + ((f as u32) & 128) -} diff --git a/Contract/ethnum-patch/src/intrinsics/native/divmod.rs b/Contract/ethnum-patch/src/intrinsics/native/divmod.rs deleted file mode 100644 index 9ed16ff..0000000 --- a/Contract/ethnum-patch/src/intrinsics/native/divmod.rs +++ /dev/null @@ -1,615 +0,0 @@ -//! This module contains a Rust port of the `__u?divmodti4` compiler builtins -//! that are typically used for implementing 64-bit signed and unsigned division -//! on 32-bit platforms. -//! -//! This port is adapted to use 128-bit high and low words in order to implement -//! 256-bit division. -//! -//! This source is ported from LLVM project from C: -//! - signed division: -//! - unsigned division: - -use crate::{int::I256, uint::U256}; -use core::{mem::MaybeUninit, num::NonZeroU128}; - -#[inline(always)] -fn udiv256_by_128_to_128(u1: u128, u0: u128, mut v: NonZeroU128, r: &mut u128) -> u128 { - const N_UDWORD_BITS: u32 = 128; - - #[inline] - unsafe fn shl_nz(x: NonZeroU128, n: u32) -> NonZeroU128 { - debug_assert!(n < N_UDWORD_BITS); - let res: u128 = x.get() << n; - debug_assert_ne!(res, 0); - NonZeroU128::new_unchecked(res) - } - - #[inline] - unsafe fn shr_nz(x: NonZeroU128, n: u32) -> NonZeroU128 { - debug_assert!(n < N_UDWORD_BITS); - let res: u128 = x.get() >> n; - debug_assert_ne!(res, 0); - NonZeroU128::new_unchecked(res) - } - - const B: u128 = 1 << (N_UDWORD_BITS / 2); // Number base (128 bits) - let (un1, un0): (u128, u128); // Norm. dividend LSD's - let (vn1, vn0): (NonZeroU128, u128); // Norm. divisor digits - let (mut q1, mut q0): (u128, u128); // Quotient digits - let (un128, un21, un10): (u128, u128, u128); // Dividend digit pairs - - debug_assert!(v.get() > u1); - - let s = v.leading_zeros(); - debug_assert_ne!(s, N_UDWORD_BITS); - if s > 0 { - // Normalize the divisor. - v = unsafe { shl_nz(v, s) }; - un128 = (u1 << s) | (u0 >> (N_UDWORD_BITS - s)); - un10 = u0 << s; // Shift dividend left - } else { - // Avoid undefined behavior of (u0 >> 128). - un128 = u1; - un10 = u0; - } - - // Break divisor up into two 64-bit digits. - vn1 = unsafe { shr_nz(v, N_UDWORD_BITS / 2) }; - vn0 = v.get() & 0xFFFF_FFFF_FFFF_FFFF; - - // Break right half of dividend into two digits. - un1 = un10 >> (N_UDWORD_BITS / 2); - un0 = un10 & 0xFFFF_FFFF_FFFF_FFFF; - - // Compute the first quotient digit, q1. - q1 = un128 / vn1; - let mut rhat = un128 - q1 * vn1.get(); - - // q1 has at most error 2. No more than 2 iterations. - while q1 >= B || q1 * vn0 > B * rhat + un1 { - q1 -= 1; - rhat += vn1.get(); - if rhat >= B { - break; - } - } - - un21 = un128 - .wrapping_mul(B) - .wrapping_add(un1) - .wrapping_sub(q1.wrapping_mul(v.get())); - - // Compute the second quotient digit. - q0 = un21 / vn1; - rhat = un21 - q0 * vn1.get(); - - // q0 has at most error 2. No more than 2 iterations. - while q0 >= B || q0 * vn0 > B * rhat + un0 { - q0 -= 1; - rhat += vn1.get(); - if rhat >= B { - break; - } - } - - *r = (un21 - .wrapping_mul(B) - .wrapping_add(un0) - .wrapping_sub(q0.wrapping_mul(v.get()))) - >> s; - q1 * B + q0 -} - -#[allow(clippy::many_single_char_names)] -pub fn udivmod4( - res: &mut MaybeUninit, - a: &U256, - b: &U256, - rem: Option<&mut MaybeUninit>, -) { - // In the LLVM version on the x86_64 platform, `udiv256_by_128_to_128` would - // defer to `divq` instruction, which divides a 128-bit value by a 64-bit - // one returning a 64-bit value, making it very performant when dividing - // small values: - // ``` - // du_int result; - // __asm__("divq %[v]" - // : "=a"(result), "=d"(*r) - // : [ v ] "r"(v), "a"(u0), "d"(u1)); - // return result; - // ``` - // Unfortunately, there is no 256-bit equivalent on x86_64, but we can still - // shortcut if the high and low values of the operands are 0: - if a.high() | b.high() == 0 { - res.write(U256::from_words(0, a.low() / b.low())); - if let Some(rem) = rem { - rem.write(U256::from_words(0, a.low() % b.low())); - } - return; - } - - let dividend = *a; - let divisor = *b; - let quotient: U256; - let mut remainder: U256; - - if divisor > dividend { - if let Some(rem) = rem { - rem.write(dividend); - } - res.write(U256::ZERO); - return; - } - // When the divisor fits in 128 bits, we can use an optimized path. - if *divisor.high() == 0 { - remainder = U256::ZERO; - if dividend.high() < divisor.low() { - // The result fits in 128 bits. - quotient = U256::from_words( - 0, - udiv256_by_128_to_128( - *dividend.high(), - *dividend.low(), - // SAFETY: dividend.high() < divisor.low() - unsafe { NonZeroU128::new_unchecked(*divisor.low()) }, - remainder.low_mut(), - ), - ); - } else { - // First, divide with the high part to get the remainder in dividend.s.high. - // After that dividend.s.high < divisor.s.low. - quotient = U256::from_words( - dividend.high() / divisor.low(), - udiv256_by_128_to_128( - dividend.high() % divisor.low(), - *dividend.low(), - // SAFETY: dividend.high() / divisor.low() - unsafe { NonZeroU128::new_unchecked(*divisor.low()) }, - remainder.low_mut(), - ), - ); - } - if let Some(rem) = rem { - rem.write(remainder); - } - res.write(quotient); - return; - } - - // SAFETY: `*divisor.high() != 0` - (quotient, remainder) = unsafe { div_mod_knuth(÷nd, &divisor) }; - - if let Some(rem) = rem { - rem.write(remainder); - } - res.write(quotient); -} - -// See Knuth, TAOCP, Volume 2, section 4.3.1, Algorithm D. -// https://skanthak.homepage.t-online.de/division.html -// SAFETY: The high word of v (the divisor) must be non-zero. -#[inline] -unsafe fn div_mod_knuth(u: &U256, v: &U256) -> (U256, U256) { - const N_UDWORD_BITS: u32 = 128; - debug_assert_ne!( - *u.high(), - 0, - "The second operand must be greater than u128::MAX" - ); - if *u.high() == 0 { - unsafe { core::hint::unreachable_unchecked() } - } - - #[inline] - fn full_shl(a: &U256, shift: u32) -> [u128; 3] { - debug_assert!(shift < N_UDWORD_BITS); - let mut u = [0_u128; 3]; - let u_lo = a.low() << shift; - let u_hi = a >> (N_UDWORD_BITS - shift); - u[0] = u_lo; - u[1] = *u_hi.low(); - u[2] = *u_hi.high(); - - u - } - - #[inline] - fn full_shr(u: &[u128; 3], shift: u32) -> U256 { - debug_assert!(shift < N_UDWORD_BITS); - let mut res = U256::ZERO; - *res.low_mut() = u[0] >> shift; - *res.high_mut() = u[1] >> shift; - // carry - if shift > 0 { - let sh = N_UDWORD_BITS - shift; - *res.low_mut() |= u[1] << sh; - *res.high_mut() |= u[2] << sh; - } - - res - } - - // returns (lo, hi) - #[inline] - const fn split_u128_to_u128(a: u128) -> (u128, u128) { - (a & 0xFFFFFFFFFFFFFFFF, a >> (N_UDWORD_BITS / 2)) - } - - // returns (lo, hi) - #[inline] - const fn fullmul_u128(a: u128, b: u128) -> (u128, u128) { - let (a0, a1) = split_u128_to_u128(a); - let (b0, b1) = split_u128_to_u128(b); - - let mut t = a0 * b0; - let mut k: u128; - let w3: u128; - (w3, k) = split_u128_to_u128(t); - - t = a1 * b0 + k; - let (w1, w2) = split_u128_to_u128(t); - t = a0 * b1 + w1; - k = t >> 64; - - let w_hi = a1 * b1 + w2 + k; - let w_lo = (t << 64) + w3; - - (w_lo, w_hi) - } - - #[inline] - fn fullmul_u256_u128(a: &U256, b: u128) -> [u128; 3] { - let mut acc = [0_u128; 3]; - let mut lo: u128; - let mut carry: u128; - let c: bool; - if b != 0 { - (lo, carry) = fullmul_u128(*a.low(), b); - acc[0] = lo; - acc[1] = carry; - (lo, carry) = fullmul_u128(*a.high(), b); - (acc[1], c) = acc[1].overflowing_add(lo); - acc[2] = carry + c as u128; - } - - acc - } - - #[inline] - const fn add_carry(a: u128, b: u128, c: bool) -> (u128, bool) { - let (res1, overflow1) = b.overflowing_add(c as u128); - let (res2, overflow2) = u128::overflowing_add(a, res1); - - (res2, overflow1 || overflow2) - } - - #[inline] - const fn sub_carry(a: u128, b: u128, c: bool) -> (u128, bool) { - let (res1, overflow1) = b.overflowing_add(c as u128); - let (res2, overflow2) = u128::overflowing_sub(a, res1); - - (res2, overflow1 || overflow2) - } - - // D1. - // Make sure 128th bit in v's highest word is set. - // If we shift both u and v, it won't affect the quotient - // and the remainder will only need to be shifted back. - let shift = v.high().leading_zeros(); - debug_assert!(shift < N_UDWORD_BITS); - let v = v << shift; - // u will store the remainder (shifted) - let mut u = full_shl(u, shift); - - // quotient - let mut q = U256::ZERO; - let v_n_1 = *v.high(); - let v_n_2 = *v.low(); - - if v_n_1 >> (N_UDWORD_BITS - 1) != 1 { - debug_assert!(false); - - // SAFETY: `v_n_1` must be normalized because input `v` has - // been checked to be non-zero. - unsafe { core::hint::unreachable_unchecked() } - } - - // D2. D7. - unrolled loop j == 0, n == 2, m == 0 (only one possible iteration) - let mut r_hat: u128 = 0; - let u_jn = u[2]; - - // D3. - // q_hat is our guess for the j-th quotient digit - // q_hat = min(b - 1, (u_{j+n} * b + u_{j+n-1}) / v_{n-1}) - // b = 1 << WORD_BITS - // Theorem B: q_hat >= q_j >= q_hat - 2 - let mut q_hat = if u_jn < v_n_1 { - //let (mut q_hat, mut r_hat) = _div_mod_u128(u_jn, u[j + n - 1], v_n_1); - let mut q_hat = udiv256_by_128_to_128( - u_jn, - u[1], - unsafe { NonZeroU128::new_unchecked(v_n_1) }, - &mut r_hat, - ); - let mut overflow: bool; - // this loop takes at most 2 iterations - loop { - let another_iteration = { - // check if q_hat * v_{n-2} > b * r_hat + u_{j+n-2} - let (lo, hi) = fullmul_u128(q_hat, v_n_2); - hi > r_hat || (hi == r_hat && lo > u[0]) - }; - if !another_iteration { - break; - } - q_hat -= 1; - (r_hat, overflow) = r_hat.overflowing_add(v_n_1); - // if r_hat overflowed, we're done - if overflow { - break; - } - } - q_hat - } else { - // here q_hat >= q_j >= q_hat - 1 - u128::MAX - }; - - // ex. 20: - // since q_hat * v_{n-2} <= b * r_hat + u_{j+n-2}, - // either q_hat == q_j, or q_hat == q_j + 1 - - // D4. - // let's assume optimistically q_hat == q_j - // subtract (q_hat * v) from u[j..] - let q_hat_v = fullmul_u256_u128(&v, q_hat); - // u[j..] -= q_hat_v; - let mut c = false; - (u[0], c) = sub_carry(u[0], q_hat_v[0], c); - (u[1], c) = sub_carry(u[1], q_hat_v[1], c); - (u[2], c) = sub_carry(u[2], q_hat_v[2], c); - - // D6. - // actually, q_hat == q_j + 1 and u[j..] has overflowed - // highly unlikely ~ (1 / 2^127) - if c { - q_hat -= 1; - // add v to u[j..] - c = false; - (u[0], c) = add_carry(u[0], *v.low(), c); - (u[1], c) = add_carry(u[1], *v.high(), c); - u[2] = u[2].wrapping_add(c as u128); - } - - // D5. - *q.low_mut() = q_hat; - - // D8. - let remainder = full_shr(&u, shift); - - (q, remainder) -} - -#[inline] -pub fn udiv2(r: &mut U256, a: &U256) { - let (a, b) = (*r, a); - // SAFETY: `udivmod4` does not write `MaybeUninit::uninit()` to `res` and - // `U256` does not implement `Drop`. - let res = unsafe { &mut *(r as *mut U256).cast() }; - udivmod4(res, &a, b, None); -} - -#[inline] -pub fn udiv3(r: &mut MaybeUninit, a: &U256, b: &U256) { - udivmod4(r, a, b, None); -} - -#[inline] -pub fn urem2(r: &mut U256, a: &U256) { - let mut res = MaybeUninit::uninit(); - let (a, b) = (*r, a); - // SAFETY: `udivmod4` does not write `MaybeUninit::uninit()` to `rem` and - // `U256` does not implement `Drop`. - let r = unsafe { &mut *(r as *mut U256).cast() }; - udivmod4(&mut res, &a, b, Some(r)); -} - -#[inline] -pub fn urem3(r: &mut MaybeUninit, a: &U256, b: &U256) { - let mut res = MaybeUninit::uninit(); - udivmod4(&mut res, a, b, Some(r)); -} - -pub fn idivmod4( - res: &mut MaybeUninit, - a: &I256, - b: &I256, - mut rem: Option<&mut MaybeUninit>, -) { - const BITS_IN_TWORD_M1: u32 = 255; - let s_a = a >> BITS_IN_TWORD_M1; // s_a = a < 0 ? -1 : 0 - let mut s_b = b >> BITS_IN_TWORD_M1; // s_b = b < 0 ? -1 : 0 - let a = (a ^ s_a).wrapping_sub(s_a); // negate if s_a == -1 - let b = (b ^ s_b).wrapping_sub(s_b); // negate if s_b == -1 - s_b ^= s_a; // sign of quotient - udivmod4( - cast!(uninit: res), - cast!(ref: &a), - cast!(ref: &b), - cast!(optuninit: rem), - ); - let q = unsafe { res.assume_init_ref() }; - let q = (q ^ s_b).wrapping_sub(s_b); // negate if s_b == -1 - res.write(q); - if let Some(rem) = rem { - let r = unsafe { rem.assume_init_ref() }; - let r = (r ^ s_a).wrapping_sub(s_a); - rem.write(r); - } -} - -#[inline] -pub fn idiv2(r: &mut I256, a: &I256) { - let (a, b) = (*r, a); - // SAFETY: `udivmod4` does not write `MaybeUninit::uninit()` to `res` and - // `U256` does not implement `Drop`. - let res = unsafe { &mut *(r as *mut I256).cast() }; - idivmod4(res, &a, b, None); -} - -#[inline] -pub fn idiv3(r: &mut MaybeUninit, a: &I256, b: &I256) { - idivmod4(r, a, b, None); -} - -#[inline] -pub fn irem2(r: &mut I256, a: &I256) { - let mut res = MaybeUninit::uninit(); - let (a, b) = (*r, a); - // SAFETY: `udivmod4` does not write `MaybeUninit::uninit()` to `rem` and - // `U256` does not implement `Drop`. - let r = unsafe { &mut *(r as *mut I256).cast() }; - idivmod4(&mut res, &a, b, Some(r)); -} - -#[inline] -pub fn irem3(r: &mut MaybeUninit, a: &I256, b: &I256) { - let mut res = MaybeUninit::uninit(); - idivmod4(&mut res, a, b, Some(r)); -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::AsU256; - - fn udiv(a: impl AsU256, b: impl AsU256) -> U256 { - let mut r = MaybeUninit::uninit(); - udiv3(&mut r, &a.as_u256(), &b.as_u256()); - unsafe { r.assume_init() } - } - - fn urem(a: impl AsU256, b: impl AsU256) -> U256 { - let mut r = MaybeUninit::uninit(); - urem3(&mut r, &a.as_u256(), &b.as_u256()); - unsafe { r.assume_init() } - } - - #[test] - fn division() { - // 0 X - // --- - // 0 X - assert_eq!(udiv(100, 9), 11); - - // 0 X - // --- - // K X - assert_eq!(udiv(!0u128, U256::ONE << 128u32), 0); - - // K 0 - // --- - // K 0 - assert_eq!(udiv(U256::from_words(100, 0), U256::from_words(10, 0)), 10); - - // K K - // --- - // K 0 - assert_eq!(udiv(U256::from_words(100, 1337), U256::ONE << 130u32), 25); - assert_eq!( - udiv(U256::from_words(1337, !0), U256::from_words(63, 0)), - 21 - ); - - // K X - // --- - // 0 K - assert_eq!( - udiv(U256::from_words(42, 0), U256::ONE), - U256::from_words(42, 0), - ); - assert_eq!( - udiv(U256::from_words(42, 42), U256::ONE << 42), - 42u128 << (128 - 42), - ); - assert_eq!( - udiv(U256::from_words(1337, !0), 0xc0ffee), - 35996389033280467545299711090127855, - ); - assert_eq!( - udiv(U256::from_words(42, 0), 99), - 144362216269489045105674075880144089708, - ); - - // K X - // --- - // K K - assert_eq!( - udiv(U256::from_words(100, 100), U256::from_words(1000, 1000)), - 0, - ); - assert_eq!( - udiv(U256::from_words(1337, !0), U256::from_words(43, !0)), - 30, - ); - } - - #[test] - #[should_panic] - fn division_by_zero() { - udiv(1, 0); - } - - #[test] - fn remainder() { - // 0 X - // --- - // 0 X - assert_eq!(urem(100, 9), 1); - - // 0 X - // --- - // K X - assert_eq!(urem(!0u128, U256::ONE << 128u32), !0u128); - - // K 0 - // --- - // K 0 - assert_eq!(urem(U256::from_words(100, 0), U256::from_words(10, 0)), 0); - - // K K - // --- - // K 0 - assert_eq!(urem(U256::from_words(100, 1337), U256::ONE << 130u32), 1337); - assert_eq!( - urem(U256::from_words(1337, !0), U256::from_words(63, 0)), - U256::from_words(14, !0), - ); - - // K X - // --- - // 0 K - assert_eq!(urem(U256::from_words(42, 0), U256::ONE), 0); - assert_eq!(urem(U256::from_words(42, 42), U256::ONE << 42), 42); - assert_eq!(urem(U256::from_words(1337, !0), 0xc0ffee), 1910477); - assert_eq!(urem(U256::from_words(42, 0), 99), 60); - - // K X - // --- - // K K - assert_eq!( - urem(U256::from_words(100, 100), U256::from_words(1000, 1000)), - U256::from_words(100, 100), - ); - assert_eq!( - urem(U256::from_words(1337, !0), U256::from_words(43, !0)), - U256::from_words(18, 29), - ); - } - - #[test] - #[should_panic] - fn remainder_by_zero() { - urem(1, 0); - } -} diff --git a/Contract/ethnum-patch/src/intrinsics/native/mul.rs b/Contract/ethnum-patch/src/intrinsics/native/mul.rs deleted file mode 100644 index 27fa064..0000000 --- a/Contract/ethnum-patch/src/intrinsics/native/mul.rs +++ /dev/null @@ -1,119 +0,0 @@ -//! This module contains a Rust port of the `__multi3` compiler builtin that is -//! typically used for implementing 64-bit multiplication on 32-bit platforms. -//! -//! This port is adapted to use 128-bit high and low words and return carry -//! information in order to implement 256-bit overflowing multiplication. -//! -//! This source is ported from LLVM project from C: -//! - -use crate::{int::I256, uint::U256}; -use core::mem::MaybeUninit; - -#[inline] -pub fn umulddi3(a: &u128, b: &u128) -> U256 { - const BITS_IN_DWORD_2: u32 = 64; - const LOWER_MASK: u128 = u128::MAX >> BITS_IN_DWORD_2; - - let mut low = (a & LOWER_MASK) * (b & LOWER_MASK); - let mut t = low >> BITS_IN_DWORD_2; - low &= LOWER_MASK; - t += (a >> BITS_IN_DWORD_2) * (b & LOWER_MASK); - low += (t & LOWER_MASK) << BITS_IN_DWORD_2; - let mut high = t >> BITS_IN_DWORD_2; - t = low >> BITS_IN_DWORD_2; - low &= LOWER_MASK; - t += (b >> BITS_IN_DWORD_2) * (a & LOWER_MASK); - low += (t & LOWER_MASK) << BITS_IN_DWORD_2; - high += t >> BITS_IN_DWORD_2; - high += (a >> BITS_IN_DWORD_2) * (b >> BITS_IN_DWORD_2); - - U256::from_words(high, low) -} - -#[inline] -pub fn mul2(r: &mut U256, a: &U256) { - let (a, b) = (*r, a); - // SAFETY: `multi3` does not write `MaybeUninit::uninit()` to `res` and - // `U256` does not implement `Drop`. - let res = unsafe { &mut *(r as *mut U256).cast() }; - mul3(res, &a, b); -} - -#[inline] -pub fn mul3(res: &mut MaybeUninit, a: &U256, b: &U256) { - let mut r = umulddi3(a.low(), b.low()); - - let hi_lo = a.high().wrapping_mul(*b.low()); - let lo_hi = a.low().wrapping_mul(*b.high()); - *r.high_mut() = r.high().wrapping_add(hi_lo.wrapping_add(lo_hi)); - - res.write(r); -} - -#[inline] -pub fn umulc(r: &mut MaybeUninit, a: &U256, b: &U256) -> bool { - let mut res = umulddi3(a.low(), b.low()); - - let (hi_lo, overflow_hi_lo) = a.high().overflowing_mul(*b.low()); - let (lo_hi, overflow_lo_hi) = a.low().overflowing_mul(*b.high()); - let (hi, overflow_hi) = hi_lo.overflowing_add(lo_hi); - let (high, overflow_high) = res.high().overflowing_add(hi); - *res.high_mut() = high; - - let overflow_hi_hi = (*a.high() != 0) & (*b.high() != 0); - - r.write(res); - overflow_hi_lo | overflow_lo_hi | overflow_hi | overflow_high | overflow_hi_hi -} - -#[inline] -pub fn imulc(res: &mut MaybeUninit, a: &I256, b: &I256) -> bool { - mul3(cast!(uninit: res), cast!(ref: a), cast!(ref: b)); - if *a == I256::MIN { - return *b != 0 && *b != 1; - } - if *b == I256::MIN { - return *a != 0 && *a != 1; - } - let sa = a >> (I256::BITS - 1); - let abs_a = (a ^ sa).wrapping_sub(sa); - let sb = b >> (I256::BITS - 1); - let abs_b = (b ^ sb).wrapping_sub(sb); - if abs_a < 2 || abs_b < 2 { - return false; - } - if sa == sb { - abs_a > I256::MAX / abs_b - } else { - abs_a > I256::MIN / -abs_b - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::AsU256; - - fn umul(a: impl AsU256, b: impl AsU256) -> (U256, bool) { - let mut r = MaybeUninit::uninit(); - let overflow = umulc(&mut r, &a.as_u256(), &b.as_u256()); - (unsafe { r.assume_init() }, overflow) - } - - #[test] - fn multiplication() { - assert_eq!(umul(6, 7), (42.as_u256(), false)); - - assert_eq!(umul(U256::MAX, 1), (U256::MAX, false)); - assert_eq!(umul(1, U256::MAX), (U256::MAX, false)); - assert_eq!(umul(U256::MAX, 0), (U256::ZERO, false)); - assert_eq!(umul(0, U256::MAX), (U256::ZERO, false)); - - assert_eq!(umul(U256::MAX, 5), (U256::MAX ^ 4, true)); - assert_eq!( - umul(u128::MAX, u128::MAX), - (U256::from_words(!0 << 1, 1), false), - ); - } -} diff --git a/Contract/ethnum-patch/src/intrinsics/native/rot.rs b/Contract/ethnum-patch/src/intrinsics/native/rot.rs deleted file mode 100644 index 8a584bc..0000000 --- a/Contract/ethnum-patch/src/intrinsics/native/rot.rs +++ /dev/null @@ -1,15 +0,0 @@ -//! This module implements right and left rotation (**not** shifting) intrinsics -//! for 256-bit integers. - -use crate::uint::U256; -use core::mem::MaybeUninit; - -#[inline] -pub fn rol3(r: &mut MaybeUninit, a: &U256, b: u32) { - r.write((a << (b & 0xff)) | (a >> ((256 - b) & 0xff))); -} - -#[inline] -pub fn ror3(r: &mut MaybeUninit, a: &U256, b: u32) { - r.write((a >> (b & 0xff)) | (a << ((256 - b) & 0xff))); -} diff --git a/Contract/ethnum-patch/src/intrinsics/native/shl.rs b/Contract/ethnum-patch/src/intrinsics/native/shl.rs deleted file mode 100644 index f4f291d..0000000 --- a/Contract/ethnum-patch/src/intrinsics/native/shl.rs +++ /dev/null @@ -1,34 +0,0 @@ -//! Module containing arithmetic left shift intrinsic. - -use crate::uint::U256; -use core::mem::MaybeUninit; - -#[inline] -pub fn shl2(r: &mut U256, a: u32) { - debug_assert!(a < 256, "shl intrinsic called with overflowing shift"); - - let (hi, lo) = if a == 0 { - return; - } else if a < 128 { - ((r.high() << a) | (r.low() >> (128 - a)), r.low() << a) - } else { - (r.low() << (a & 0x7f), 0) - }; - - *r = U256::from_words(hi, lo); -} - -#[inline] -pub fn shl3(r: &mut MaybeUninit, a: &U256, b: u32) { - debug_assert!(b < 256, "shl intrinsic called with overflowing shift"); - - let (hi, lo) = if b == 0 { - (*a.high(), *a.low()) - } else if b < 128 { - ((a.high() << b) | (a.low() >> (128 - b)), a.low() << b) - } else { - (a.low() << (b & 0x7f), 0) - }; - - r.write(U256::from_words(hi, lo)); -} diff --git a/Contract/ethnum-patch/src/intrinsics/native/shr.rs b/Contract/ethnum-patch/src/intrinsics/native/shr.rs deleted file mode 100644 index 38b4f7a..0000000 --- a/Contract/ethnum-patch/src/intrinsics/native/shr.rs +++ /dev/null @@ -1,70 +0,0 @@ -//! Module containing logical right shift intrinsic. - -use crate::{int::I256, uint::U256}; -use core::mem::MaybeUninit; - -#[inline] -pub fn sar2(r: &mut I256, a: u32) { - debug_assert!(a < 256, "shr intrinsic called with overflowing shift"); - - let (hi, lo) = if a == 0 { - return; - } else if a < 128 { - ( - r.high() >> a, - ((*r.low() as u128) >> a | ((*r.high() as u128) << (128 - a))) as i128, - ) - } else { - (r.high() >> 127, (r.high() >> (a & 0x7f))) - }; - - *r = I256::from_words(hi, lo); -} - -#[inline] -pub fn sar3(r: &mut MaybeUninit, a: &I256, b: u32) { - debug_assert!(b < 256, "shr intrinsic called with overflowing shift"); - - let (hi, lo) = if b == 0 { - (*a.high(), *a.low()) - } else if b < 128 { - ( - a.high() >> b, - ((*a.low() as u128) >> b | ((*a.high() as u128) << (128 - b))) as i128, - ) - } else { - (a.high() >> 127, a.high() >> (b & 0x7f)) - }; - - r.write(I256::from_words(hi, lo)); -} - -#[inline] -pub fn shr2(r: &mut U256, a: u32) { - debug_assert!(a < 256, "shr intrinsic called with overflowing shift"); - - let (hi, lo) = if a == 0 { - return; - } else if a < 128 { - (r.high() >> a, r.low() >> a | (r.high() << (128 - a))) - } else { - (0, r.high() >> (a & 0x7f)) - }; - - *r = U256::from_words(hi, lo); -} - -#[inline] -pub fn shr3(r: &mut MaybeUninit, a: &U256, b: u32) { - debug_assert!(b < 256, "shr intrinsic called with overflowing shift"); - - let (hi, lo) = if b == 0 { - (*a.high(), *a.low()) - } else if b < 128 { - (a.high() >> b, a.low() >> b | (a.high() << (128 - b))) - } else { - (0, a.high() >> (b & 0x7f)) - }; - - r.write(U256::from_words(hi, lo)); -} diff --git a/Contract/ethnum-patch/src/intrinsics/native/sub.rs b/Contract/ethnum-patch/src/intrinsics/native/sub.rs deleted file mode 100644 index 2fbce20..0000000 --- a/Contract/ethnum-patch/src/intrinsics/native/sub.rs +++ /dev/null @@ -1,36 +0,0 @@ -//! Module implementing subtraction intrinsics. - -use crate::{int::I256, uint::U256}; -use core::mem::MaybeUninit; - -#[inline] -pub fn sub2(r: &mut U256, a: &U256) { - let (lo, carry) = r.low().overflowing_sub(*a.low()); - *r.low_mut() = lo; - *r.high_mut() = r.high().wrapping_sub(carry as _).wrapping_sub(*a.high()); -} - -#[inline] -pub fn sub3(r: &mut MaybeUninit, a: &U256, b: &U256) { - let (lo, carry) = a.low().overflowing_sub(*b.low()); - let hi = a.high().wrapping_sub(carry as _).wrapping_sub(*b.high()); - - r.write(U256::from_words(hi, lo)); -} - -#[inline] -pub fn usubc(r: &mut MaybeUninit, a: &U256, b: &U256) -> bool { - let (lo, carry_lo) = a.low().overflowing_sub(*b.low()); - let (hi, carry_c) = a.high().overflowing_sub(carry_lo as _); - let (hi, carry_hi) = hi.overflowing_sub(*b.high()); - - r.write(U256::from_words(hi, lo)); - carry_c || carry_hi -} - -#[inline] -pub fn isubc(r: &mut MaybeUninit, a: &I256, b: &I256) -> bool { - sub3(cast!(uninit: r), cast!(ref: a), cast!(ref: b)); - let s = unsafe { r.assume_init_ref() }; - (*b >= 0 && s > a) || (*b < 0 && s <= a) -} diff --git a/Contract/ethnum-patch/src/intrinsics/signed.rs b/Contract/ethnum-patch/src/intrinsics/signed.rs deleted file mode 100644 index a28b94d..0000000 --- a/Contract/ethnum-patch/src/intrinsics/signed.rs +++ /dev/null @@ -1,85 +0,0 @@ -//! Module containing signed wrapping functions around various intrinsics that -//! are agnostic to sign. -//! -//! This module can be helpful when using intrinsics directly. - -pub use super::{ - add2 as uadd2, add3 as uadd3, ctlz as uctlz, cttz as ucttz, iaddc, idiv2, idiv3, imulc, irem2, - irem3, isubc, mul2 as umul2, mul3 as umul3, rol3 as urol3, ror3 as uror3, sar2 as isar2, - sar3 as isar3, shl2 as ushl2, shl3 as ushl3, shr2 as ushr2, shr3 as ushr3, sub2 as usub2, - sub3 as usub3, uaddc, udiv2, udiv3, umulc, urem2, urem3, usubc, -}; -use crate::int::I256; -use core::mem::MaybeUninit; - -#[inline] -pub fn iadd2(r: &mut I256, a: &I256) { - super::add2(cast!(mut: r), cast!(ref: a)); -} - -#[inline] -pub fn iadd3(r: &mut MaybeUninit, a: &I256, b: &I256) { - super::add3(cast!(uninit: r), cast!(ref: a), cast!(ref: b)); -} - -#[inline] -pub fn isub2(r: &mut I256, a: &I256) { - super::sub2(cast!(mut: r), cast!(ref: a)); -} - -#[inline] -pub fn isub3(r: &mut MaybeUninit, a: &I256, b: &I256) { - super::sub3(cast!(uninit: r), cast!(ref: a), cast!(ref: b)); -} - -#[inline] -pub fn imul2(r: &mut I256, a: &I256) { - super::mul2(cast!(mut: r), cast!(ref: a)); -} - -#[inline] -pub fn imul3(r: &mut MaybeUninit, a: &I256, b: &I256) { - super::mul3(cast!(uninit: r), cast!(ref: a), cast!(ref: b)); -} - -#[inline] -pub fn ishl2(r: &mut I256, a: u32) { - super::shl2(cast!(mut: r), a); -} - -#[inline] -pub fn ishl3(r: &mut MaybeUninit, a: &I256, b: u32) { - super::shl3(cast!(uninit: r), cast!(ref: a), b); -} - -#[inline] -pub fn irol3(r: &mut MaybeUninit, a: &I256, b: u32) { - super::rol3(cast!(uninit: r), cast!(ref: a), b); -} - -#[inline] -pub fn iror3(r: &mut MaybeUninit, a: &I256, b: u32) { - super::ror3(cast!(uninit: r), cast!(ref: a), b); -} - -#[inline] -pub fn ictlz(a: &I256) -> u32 { - super::ctlz(cast!(ref: a)) -} - -#[inline] -pub fn icttz(a: &I256) -> u32 { - super::cttz(cast!(ref: a)) -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::uint::U256; - use core::alloc::Layout; - - #[test] - fn layout() { - assert_eq!(Layout::new::(), Layout::new::()); - } -} diff --git a/Contract/ethnum-patch/src/lib.rs b/Contract/ethnum-patch/src/lib.rs deleted file mode 100644 index ccc53ef..0000000 --- a/Contract/ethnum-patch/src/lib.rs +++ /dev/null @@ -1,133 +0,0 @@ -//! This crate implements 256-bit integer types. -//! -//! The implementation tries to follow as closely as possible to primitive -//! integer types, and should implement all the common methods and traits as the -//! primitive integer types. - -#![deny(missing_docs)] -#![no_std] - -#[cfg(test)] -extern crate alloc; - -#[macro_use] -mod macros { - #[macro_use] - pub mod cmp; - #[macro_use] - pub mod fmt; - #[macro_use] - pub mod iter; - #[macro_use] - pub mod ops; - #[macro_use] - pub mod parse; -} - -mod error; -mod fmt; -mod int; -pub mod intrinsics; -mod parse; -#[cfg(feature = "serde")] -pub mod serde; -mod uint; - -/// Macro for 256-bit signed integer literal. -/// -/// # Examples -/// -/// Basic usage: -/// -/// ``` -/// # use ethnum::{int, I256}; -/// assert_eq!( -/// int!( -/// "-57896044618658097711785492504343953926634992332820282019728792003956564819968" -/// ), -/// I256::MIN, -/// ); -/// ``` -/// -/// Additionally, this macro accepts `0b` for binary, `0o` for octal, and `0x` -/// for hexadecimal literals. Using `_` for spacing is also permitted. -/// -/// ``` -/// # use ethnum::{int, I256}; -/// assert_eq!( -/// int!( -/// "0x7fff_ffff_ffff_ffff_ffff_ffff_ffff_ffff -/// ffff_ffff_ffff_ffff_ffff_ffff_ffff_ffff" -/// ), -/// I256::MAX, -/// ); -/// assert_eq!(int!("0b101010"), 42); -/// assert_eq!(int!("-0o52"), -42); -/// ``` -#[macro_export] -macro_rules! int { - ($integer:literal) => {{ - const VALUE: $crate::I256 = $crate::I256::const_from_str_prefixed($integer); - VALUE - }}; -} - -/// Macro for 256-bit unsigned integer literal. -/// -/// # Examples -/// -/// Basic usage: -/// -/// ``` -/// # use ethnum::{uint, U256}; -/// assert_eq!( -/// uint!( -/// "115792089237316195423570985008687907852837564279074904382605163141518161494337" -/// ), -/// U256::from_words( -/// 0xfffffffffffffffffffffffffffffffe, -/// 0xbaaedce6af48a03bbfd25e8cd0364141, -/// ), -/// ); -/// ``` -/// -/// Additionally, this macro accepts `0b` for binary, `0o` for octal, and `0x` -/// for hexadecimal literals. Using `_` for spacing is also permitted. -/// -/// ``` -/// # use ethnum::{uint, U256}; -/// assert_eq!( -/// uint!( -/// "0xffff_ffff_ffff_ffff_ffff_ffff_ffff_ffff -/// ffff_ffff_ffff_ffff_ffff_ffff_ffff_ffff" -/// ), -/// U256::MAX, -/// ); -/// assert_eq!(uint!("0b101010"), 42); -/// assert_eq!(uint!("0o52"), 42); -/// ``` -#[macro_export] -macro_rules! uint { - ($integer:literal) => {{ - const VALUE: $crate::U256 = $crate::U256::const_from_str_prefixed($integer); - VALUE - }}; -} - -/// Convenience re-export of 256-integer types and as- conversion traits. -pub mod prelude { - pub use crate::{AsI256, AsU256, I256, U256}; -} - -pub use crate::{ - int::{AsI256, I256}, - uint::{AsU256, U256}, -}; - -/// A 256-bit signed integer type. -#[allow(non_camel_case_types)] -pub type i256 = I256; - -/// A 256-bit unsigned integer type. -#[allow(non_camel_case_types)] -pub type u256 = U256; diff --git a/Contract/ethnum-patch/src/macros/cmp.rs b/Contract/ethnum-patch/src/macros/cmp.rs deleted file mode 100644 index a3a7192..0000000 --- a/Contract/ethnum-patch/src/macros/cmp.rs +++ /dev/null @@ -1,42 +0,0 @@ -//! Module containing macros for implementing `core::ops` traits. - -macro_rules! impl_cmp { - ( - impl Cmp for $int:ident ($prim:ident); - ) => { - impl PartialEq<$prim> for $int { - #[inline] - fn eq(&self, other: &$prim) -> bool { - *self == $int::new(*other) - } - } - - impl PartialEq<$int> for $prim { - #[inline] - fn eq(&self, other: &$int) -> bool { - $int::new(*self) == *other - } - } - - impl PartialOrd for $int { - #[inline] - fn partial_cmp(&self, other: &Self) -> Option<::core::cmp::Ordering> { - Some(self.cmp(other)) - } - } - - impl PartialOrd<$prim> for $int { - #[inline] - fn partial_cmp(&self, rhs: &$prim) -> Option<::core::cmp::Ordering> { - Some(self.cmp(&$int::new(*rhs))) - } - } - - impl PartialOrd<$int> for $prim { - #[inline] - fn partial_cmp(&self, rhs: &$int) -> Option<::core::cmp::Ordering> { - Some($int::new(*self).cmp(rhs)) - } - } - }; -} diff --git a/Contract/ethnum-patch/src/macros/fmt.rs b/Contract/ethnum-patch/src/macros/fmt.rs deleted file mode 100644 index d9d4290..0000000 --- a/Contract/ethnum-patch/src/macros/fmt.rs +++ /dev/null @@ -1,86 +0,0 @@ -//! Module containing macros for implementing `core::fmt` traits. - -macro_rules! impl_fmt { - (impl Fmt for $int:ident;) => { - __impl_fmt_base! { Binary for $int } - __impl_fmt_base! { Octal for $int } - __impl_fmt_base! { LowerHex for $int } - __impl_fmt_base! { UpperHex for $int } - - impl ::core::fmt::Debug for $int { - #[inline] - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - // NOTE: Work around `Formatter::debug_{lower,upper}_hex` being private - // and not stabilized. - #[allow(deprecated)] - let flags = f.flags(); - const DEBUG_LOWER_HEX: u32 = 1 << 4; - const DEBUG_UPPER_HEX: u32 = 1 << 5; - - if flags & DEBUG_LOWER_HEX != 0 { - ::core::fmt::LowerHex::fmt(self, f) - } else if flags & DEBUG_UPPER_HEX != 0 { - ::core::fmt::UpperHex::fmt(self, f) - } else { - ::core::fmt::Display::fmt(self, f) - } - } - } - - impl ::core::fmt::Display for $int { - #[allow(unused_comparisons, unused_imports)] - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use $crate::uint::AsU256; - - let is_nonnegative = *self >= 0; - let n = if is_nonnegative { - self.as_u256() - } else { - // convert the negative num to positive by summing 1 to it's 2 complement - (!self.as_u256()).wrapping_add($crate::uint::U256::ONE) - }; - $crate::fmt::fmt_u256(n, is_nonnegative, f) - } - } - - impl ::core::fmt::LowerExp for $int { - fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { - // TODO(nlordell): Ideally this should be implemented similarly - // to the primitive integer types as seen here: - // https://doc.rust-lang.org/src/core/fmt/num.rs.html#274 - // Unfortunately, just porting this implementation is not - // possible as it requires private standard library items. For - // now, just convert to a `f64` as an approximation. - ::core::fmt::LowerExp::fmt(&self.as_f64(), f) - } - } - - impl ::core::fmt::UpperExp for $int { - fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { - ::core::fmt::UpperExp::fmt(&self.as_f64(), f) - } - } - }; -} - -macro_rules! __impl_fmt_base { - ($base:ident for $int:ident) => { - impl ::core::fmt::$base for $int { - #[allow(unused_imports)] - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use $crate::{fmt::GenericRadix, uint::AsU256}; - let (abs, is_nonnegative) = if *self < 0 && f.sign_minus() { - // NOTE(nlordell): This is non-standard break from the Rust - // standard integer types, but allows `format!("{val:-#x")` - // notation for formating a number as `-0x...` (and in - // in general prefix with a `-` sign for negative numbers - // with radix formatting. - (self.wrapping_neg(), false) - } else { - (*self, true) - }; - $crate::fmt::$base.fmt_u256(abs.as_u256(), is_nonnegative, f) - } - } - }; -} diff --git a/Contract/ethnum-patch/src/macros/iter.rs b/Contract/ethnum-patch/src/macros/iter.rs deleted file mode 100644 index 496cccf..0000000 --- a/Contract/ethnum-patch/src/macros/iter.rs +++ /dev/null @@ -1,31 +0,0 @@ -//! Module containing macros for implementing iterator specific traits. - -macro_rules! impl_iter { - ( - impl Iter for $int:ident; - ) => { - impl ::core::iter::Sum for $int { - fn sum>(iter: I) -> Self { - iter.fold($int::ZERO, ::core::ops::Add::add) - } - } - - impl ::core::iter::Product for $int { - fn product>(iter: I) -> Self { - iter.fold($int::ONE, ::core::ops::Mul::mul) - } - } - - impl<'a> ::core::iter::Sum<&'a $int> for $int { - fn sum>(iter: I) -> Self { - iter.fold($int::ZERO, ::core::ops::Add::add) - } - } - - impl<'a> ::core::iter::Product<&'a $int> for $int { - fn product>(iter: I) -> Self { - iter.fold($int::ONE, ::core::ops::Mul::mul) - } - } - }; -} diff --git a/Contract/ethnum-patch/src/macros/ops.rs b/Contract/ethnum-patch/src/macros/ops.rs deleted file mode 100644 index e735359..0000000 --- a/Contract/ethnum-patch/src/macros/ops.rs +++ /dev/null @@ -1,542 +0,0 @@ -//! Module containing macros for implementing `core::ops` traits. - -macro_rules! impl_ops { - ( - for $int:ident | $prim:ident { - add => $add2:ident, $add3:ident, $addc:ident; - mul => $mul2:ident, $mul3:ident, $mulc:ident; - sub => $sub2:ident, $sub3:ident, $subc:ident; - div => $div2:ident, $div3:ident; - rem => $rem2:ident, $rem3:ident; - shl => $shl2:ident, $shl3:ident; - shr => $shr2:ident, $shr3:ident; - } - ) => { - __impl_ops_binop! { - for $int | $prim - - impl Add { - + add => $add3, $addc; "add with overflow" - } - impl Mul { - * mul => $mul3, $mulc; "multiply with overflow" - } - impl Sub { - - sub => $sub3, $subc; "subtract with overflow" - } - } - - __impl_ops_divmod! { - for $int | $prim - - impl Div { - / div => $div3; "divide by zero" - } - impl Rem { - % rem => $rem3; "calculate the remainder with a divisor of zero" - } - } - - __impl_ops_shift! { - for $int - - impl Shl { - << shl => $shl3; "shift left with overflow" - } - impl Shr { - >> shr => $shr3; "shift right with overflow" - } - } - - __impl_ops_unop! { - impl Not for $int { - not(x) { - let $int([a, b]) = x; - $int([!a, !b]) - } - } - } - - __impl_ops_bitwise! { - for $int | $prim - - impl BitAnd { - & bitand; - } - impl BitOr { - | bitor; - } - impl BitXor { - ^ bitxor; - } - } - - __impl_ops_binop_assign! { - for $int | $prim - - impl AddAssign { - += add_assign => $add2, +; - } - impl DivAssign { - /= div_assign => $div2, /; - } - impl MulAssign { - *= mul_assign => $mul2, *; - } - impl RemAssign { - %= rem_assign => $rem2, %; - } - impl SubAssign { - -= sub_assign => $sub2, -; - } - } - - __impl_ops_shift_assign! { - for $int - - impl ShlAssign { - <<= shl_assign => $shl2, <<; - } - impl ShrAssign { - >>= shr_assign => $shr2, >>; - } - } - - __impl_ops_bitwise_assign! { - for $int | $prim - - impl BitAndAssign { - &= bitand_assign; - } - impl BitOrAssign { - |= bitor_assign; - } - impl BitXorAssign { - ^= bitxor_assign; - } - } - }; -} - -macro_rules! impl_ops_neg { - ( - for $int:ident { - add => $add2:ident; - } - ) => { - __impl_ops_unop! { - impl Neg for $int { - neg(x) { - #[cfg(debug_assertions)] - { - if x.eq(&I256::MIN) { - panic!("attempt to negate with overflow"); - } - } - let mut result = !x; - $add2(&mut result, &$int::ONE); - result - } - } - } - }; -} - -macro_rules! __impl_ops_binop { - ( - for $int:ident | $prim:ident - $( - impl $op:ident { - $x:tt $method:ident => $op3:path, $opc:path; $msg:expr - } - )* - ) => {$( - impl ::core::ops::$op for &'_ $int { - type Output = $int; - - #[inline] - fn $method(self, rhs: Self) -> Self::Output { - let mut result = ::core::mem::MaybeUninit::uninit(); - #[cfg(not(debug_assertions))] - { - $op3(&mut result, self, rhs); - } - #[cfg(debug_assertions)] - { - if $opc(&mut result, self, rhs) { - panic!(concat!("attempt to ", $msg)); - } - } - unsafe { result.assume_init() } - } - } - - __impl_ops_binop_extra_variants! { - impl $op for $int | $prim { $method = $x } - } - )*}; -} - -macro_rules! __impl_ops_binop_extra_variants { - ( - impl $op:ident for $int:ident | $prim:ident { $method:ident = $x:tt } - ) => { - __impl_ops_binop_ref! { - impl $op for $int { - $method(a: &'_ $int, b: $int) { a $x &b }; - $method(a: $int, b: &'_ $int) { &a $x b }; - $method(a: $int, b: $int) { &a $x &b }; - - $method(a: &'_ $int, b: $prim) { a $x $int::new(b) }; - $method(a: &'_ $int, b: &'_ $prim) { a $x *b }; - $method(a: $int, b: &'_ $prim) { &a $x *b }; - $method(a: $int, b: $prim) { &a $x b }; - - $method(a: $prim, b: &'_ $int) { $int::new(a) $x b }; - $method(a: &'_ $prim, b: &'_ $int) { *a $x b }; - $method(a: &'_ $prim, b: $int) { *a $x &b }; - $method(a: $prim, b: $int) { a $x &b }; - } - } - }; -} - -macro_rules! __impl_ops_binop_ref { - ( - impl $op:ident for $int:ident {$( - $method:ident($lhs:ident: $lhst:ty, $rhs:ident: $rhst:ty) $impl:block; - )*} - ) => {$( - impl ::core::ops::$op<$rhst> for $lhst { - type Output = $int; - - #[inline] - fn $method(self, rhs: $rhst) -> Self::Output { - let ($lhs, $rhs) = (self, rhs); - $impl - } - } - )*} -} - -macro_rules! __impl_ops_divmod { - ( - for $int:ident | $prim:ident - $( - impl $op:ident { - $x:tt $method:ident => $op3:path; $msg:expr - } - )* - ) => {$( - impl ::core::ops::$op for &'_ $int { - type Output = $int; - - #[inline] - fn $method(self, rhs: Self) -> Self::Output { - if *rhs == 0 { - panic!(concat!("attempt to ", $msg)); - } - - let mut result = ::core::mem::MaybeUninit::uninit(); - $op3(&mut result, self, rhs); - unsafe { result.assume_init() } - } - } - - __impl_ops_binop_extra_variants! { - impl $op for $int | $prim { $method = $x } - } - )*}; -} - -macro_rules! __impl_ops_shift { - ( - for $int:ident - $( - impl $op:ident { - $x:tt $method:ident => $op3:path; $msg:expr - } - )* - ) => {$( - impl ::core::ops::$op for &'_ $int { - type Output = $int; - - #[inline] - fn $method(self, rhs: u32) -> Self::Output { - #[cfg(debug_assertions)] - if rhs > 0xff { - panic!(concat!("attempt to ", $msg)); - } - - let mut result = ::core::mem::MaybeUninit::uninit(); - $op3(&mut result, self, rhs); - - unsafe { result.assume_init() } - } - } - - __impl_ops_shift_extra_variants! { - impl $op for $int { $method = $x } - } - )*}; -} - -macro_rules! __impl_ops_shift_extra_variants { - ( - impl $op:ident for $int:ident { $method:ident = $x:tt } - ) => { - __impl_ops_binop_ref! { - impl $op for $int { - $method(a: &'_ $int, b: &'_ u32) { a $x *b }; - $method(a: $int, b: &'_ u32) { &a $x *b }; - $method(a: $int, b: u32) { &a $x b }; - } - } - - __impl_ops_shift_extra_variants! { __inner: - impl $op<$crate::int::I256, $crate::uint::U256> for $int { - $method = $x - |b| { b.as_u32() } - } - } - - __impl_ops_shift_extra_variants! { __inner: - impl $op for $int { - $method = $x - |b| { b as u32 } - } - } - }; - - (__inner: - impl $op:ident <$($lhst:ty),*> for $int:ident - { $method:ident = $x:tt |$lhs:ident| $conv:block } - ) => {$( - __impl_ops_binop_ref! { - impl $op for $int { - $method(a: &'_ $int, $lhs: $lhst) { - #[cfg(not(debug_assertions))] - let b = $conv; - #[cfg(debug_assertions)] - let b = u32::try_from($lhs).unwrap_or(u32::MAX); - a $x b - }; - $method(a: &'_ $int, b: &'_ $lhst) { a $x *b }; - $method(a: $int, b: &'_ $lhst) { &a $x *b }; - $method(a: $int, b: $lhst) { &a $x b }; - } - } - )*}; -} - -macro_rules! __impl_ops_unop { - ( - impl $op:ident for $int:ident { - $method:ident($self:ident) $impl:block - } - ) => { - impl ::core::ops::$op for $int { - type Output = $int; - - #[inline] - fn $method(self) -> Self::Output { - let $self = self; - $impl - } - } - - impl ::core::ops::$op for &'_ $int { - type Output = $int; - - #[inline] - fn $method(self) -> Self::Output { - let $self = self; - $impl - } - } - }; -} - -macro_rules! __impl_ops_bitwise { - ( - for $int:ident | $prim:ident - $( - impl $op:ident { - $x:tt $method:ident; - } - )* - ) => {$( - impl ::core::ops::$op<&'_ $int> for &'_ $int { - type Output = $int; - - #[inline] - fn $method(self, rhs: &'_ $int) -> Self::Output { - let $int([a0, a1]) = self; - let $int([b0, b1]) = rhs; - $int([a0 $x b0, a1 $x b1]) - } - } - - __impl_ops_binop_extra_variants! { - impl $op for $int | $prim { $method = $x } - } - )*}; -} - -macro_rules! __impl_ops_binop_assign { - ( - for $int:ident | $prim:ident - $( - impl $op:ident { - $x:tt $method:ident => $op2:path, $y:tt; - } - )* - ) => {$( - impl ::core::ops::$op<&'_ $int> for $int { - #[inline] - fn $method(&mut self, rhs: &'_ $int) { - #[cfg(not(debug_assertions))] - { - $op2(self, rhs); - } - #[cfg(debug_assertions)] - { - *self = &*self $y rhs; - } - } - } - - __impl_ops_binop_assign_extra_variants! { - impl $op for $int | $prim { $method = $x } - } - )*}; -} - -macro_rules! __impl_ops_binop_assign_extra_variants { - ( - impl $op:ident for $int:ident | $prim:ident { $method:ident = $x:tt } - ) => { - __impl_ops_binop_assign_ref! { - impl $op for $int { - $method(a, b: $int) { *a $x &b }; - - $method(a, b: $prim) { *a $x $int::new(b) }; - $method(a, b: &'_ $prim) { *a $x *b }; - } - } - }; -} - -macro_rules! __impl_ops_binop_assign_ref { - ( - impl $op:ident for $int:ident {$( - $method:ident($self:ident, $rhs:ident: $rhst:ty) $impl:block; - )*} - ) => {$( - impl ::core::ops::$op<$rhst> for $int { - #[inline] - fn $method(&mut self, rhs: $rhst) { - let ($self, $rhs) = (self, rhs); - $impl - } - } - )*} -} - -macro_rules! __impl_ops_shift_assign { - ( - for $int:ident - $( - impl $op:ident { - $x:tt $method:ident => $op2:path, $y:tt; - } - )* - ) => {$( - impl ::core::ops::$op for $int { - #[inline] - fn $method(&mut self, rhs: u32) { - #[cfg(not(debug_assertions))] - { - $op2(self, rhs); - } - #[cfg(debug_assertions)] - { - *self = &*self $y rhs; - } - } - } - - __impl_ops_shift_assign_extra_variants! { - impl $op for $int { $method = $x } - } - )*}; -} - -macro_rules! __impl_ops_shift_assign_extra_variants { - ( - impl $op:ident for $int:ident { $method:ident = $x:tt } - ) => { - __impl_ops_binop_assign_ref! { - impl $op for $int { - $method(a, b: &'_ u32) { *a $x *b }; - } - } - - __impl_ops_shift_assign_extra_variants! { __inner: - impl $op<$crate::int::I256, $crate::uint::U256> for $int { - $method = $x - |b| { b.as_u32() } - } - } - - __impl_ops_shift_assign_extra_variants! { __inner: - impl $op for $int { - $method = $x - |b| { b as u32 } - } - } - }; - - (__inner: - impl $op:ident <$($lhst:ty),*> for $int:ident - { $method:ident = $x:tt |$lhs:ident| $conv:block } - ) => {$( - __impl_ops_binop_assign_ref! { - impl $op for $int { - $method(a, $lhs: $lhst) { - #[cfg(not(debug_assertions))] - let b = $conv; - #[cfg(debug_assertions)] - let b = u32::try_from($lhs).unwrap_or(u32::MAX); - *a $x b - }; - $method(a, b: &'_ $lhst) { *a $x *b }; - } - } - )*}; -} - -macro_rules! __impl_ops_bitwise_assign { - ( - for $int:ident | $prim:ident - $( - impl $op:ident { - $x:tt $method:ident; - } - )* - ) => {$( - impl ::core::ops::$op<&'_ $int> for $int { - #[inline] - fn $method(&mut self, rhs: &'_ $int) { - let $int([a0, a1]) = self; - let $int([b0, b1]) = rhs; - *a0 $x b0; - *a1 $x b1; - } - } - - __impl_ops_binop_assign_extra_variants! { - impl $op for $int | $prim { $method = $x } - } - )*}; -} diff --git a/Contract/ethnum-patch/src/macros/parse.rs b/Contract/ethnum-patch/src/macros/parse.rs deleted file mode 100644 index b2ee93c..0000000 --- a/Contract/ethnum-patch/src/macros/parse.rs +++ /dev/null @@ -1,34 +0,0 @@ -//! Module containing macros for implementing string to integer parsing. - -macro_rules! impl_from_str { - (impl FromStr for $int:ident;) => { - impl $crate::parse::FromStrRadixHelper for $int { - const MIN: Self = Self::MIN; - #[inline] - fn from_u32(u: u32) -> Self { - Self::from(u) - } - #[inline] - fn checked_mul(&self, other: u32) -> Option { - Self::checked_mul(*self, Self::from(other)) - } - #[inline] - fn checked_sub(&self, other: u32) -> Option { - Self::checked_sub(*self, Self::from(other)) - } - #[inline] - fn checked_add(&self, other: u32) -> Option { - Self::checked_add(*self, Self::from(other)) - } - } - - impl ::core::str::FromStr for $int { - type Err = ::core::num::ParseIntError; - - #[inline] - fn from_str(s: &str) -> Result { - $crate::parse::from_str_radix(s, 10, None) - } - } - }; -} diff --git a/Contract/ethnum-patch/src/parse.rs b/Contract/ethnum-patch/src/parse.rs deleted file mode 100644 index dca813c..0000000 --- a/Contract/ethnum-patch/src/parse.rs +++ /dev/null @@ -1,205 +0,0 @@ -//! Module with common integer parsing logic. -//! -//! Most of these implementations were ported from the Rust standard library's -//! implementation for primitive integer types: -//! - -use crate::U256; -use core::{ - mem, - num::{IntErrorKind, ParseIntError}, - ops::{Add, Mul, Sub}, -}; - -#[doc(hidden)] -pub(crate) trait FromStrRadixHelper: - PartialOrd + Copy + Add + Sub + Mul -{ - const MIN: Self; - fn from_u32(u: u32) -> Self; - fn checked_mul(&self, other: u32) -> Option; - fn checked_sub(&self, other: u32) -> Option; - fn checked_add(&self, other: u32) -> Option; -} - -#[inline(always)] -fn can_not_overflow(radix: u32, is_signed_ty: bool, digits: &[u8]) -> bool { - radix <= 16 && digits.len() <= mem::size_of::() * 2 - is_signed_ty as usize -} - -pub(crate) fn from_str_radix( - src: &str, - radix: u32, - prefix: Option<&str>, -) -> Result { - use self::IntErrorKind::*; - use crate::error::pie; - - assert!( - (2..=36).contains(&radix), - "from_str_radix_int: must lie in the range `[2, 36]` - found {}", - radix - ); - - if src.is_empty() { - return Err(pie(Empty)); - } - - let is_signed_ty = T::from_u32(0) > T::MIN; - - // all valid digits are ascii, so we will just iterate over the utf8 bytes - // and cast them to chars. .to_digit() will safely return None for anything - // other than a valid ascii digit for the given radix, including the first-byte - // of multi-byte sequences - let src = src.as_bytes(); - - let (is_positive, prefixed_digits) = match src[0] { - b'+' | b'-' if src[1..].is_empty() => { - return Err(pie(InvalidDigit)); - } - b'+' => (true, &src[1..]), - b'-' if is_signed_ty => (false, &src[1..]), - _ => (true, src), - }; - - let digits = match prefix { - Some(prefix) => prefixed_digits - .strip_prefix(prefix.as_bytes()) - .ok_or(pie(InvalidDigit))?, - None => prefixed_digits, - }; - if digits.is_empty() { - return Err(pie(InvalidDigit)); - } - - let mut result = T::from_u32(0); - - if can_not_overflow::(radix, is_signed_ty, digits) { - // If the len of the str is short compared to the range of the type - // we are parsing into, then we can be certain that an overflow will not occur. - // This bound is when `radix.pow(digits.len()) - 1 <= T::MAX` but the condition - // above is a faster (conservative) approximation of this. - // - // Consider radix 16 as it has the highest information density per digit and will thus overflow the earliest: - // `u8::MAX` is `ff` - any str of len 2 is guaranteed to not overflow. - // `i8::MAX` is `7f` - only a str of len 1 is guaranteed to not overflow. - macro_rules! run_unchecked_loop { - ($unchecked_additive_op:expr) => { - for &c in digits { - result = result * T::from_u32(radix); - let x = (c as char).to_digit(radix).ok_or(pie(InvalidDigit))?; - result = $unchecked_additive_op(result, T::from_u32(x)); - } - }; - } - if is_positive { - run_unchecked_loop!(::add) - } else { - run_unchecked_loop!(::sub) - }; - } else { - macro_rules! run_checked_loop { - ($checked_additive_op:ident, $overflow_err:expr) => { - for &c in digits { - // When `radix` is passed in as a literal, rather than doing a slow `imul` - // the compiler can use shifts if `radix` can be expressed as a - // sum of powers of 2 (x*10 can be written as x*8 + x*2). - // When the compiler can't use these optimisations, - // the latency of the multiplication can be hidden by issuing it - // before the result is needed to improve performance on - // modern out-of-order CPU as multiplication here is slower - // than the other instructions, we can get the end result faster - // doing multiplication first and let the CPU spends other cycles - // doing other computation and get multiplication result later. - let mul = result.checked_mul(radix); - let x = (c as char).to_digit(radix).ok_or(pie(InvalidDigit))?; - result = mul.ok_or_else($overflow_err)?; - result = T::$checked_additive_op(&result, x).ok_or_else($overflow_err)?; - } - }; - } - if is_positive { - run_checked_loop!(checked_add, || pie(PosOverflow)) - } else { - run_checked_loop!(checked_sub, || pie(NegOverflow)) - }; - } - Ok(result) -} - -pub(crate) fn from_str_prefixed(src: &str) -> Result { - from_str_radix(src, 2, Some("0b")) - .or_else(|_| from_str_radix(src, 8, Some("0o"))) - .or_else(|_| from_str_radix(src, 16, Some("0x"))) - .or_else(|_| from_str_radix(src, 10, None)) -} - -pub(crate) const fn const_from_str_prefixed(bytes: &[u8], start: usize) -> U256 { - const fn check(overflow: bool) { - assert!(!overflow, "overflows integer type"); - } - - const fn add(a: U256, b: u8) -> U256 { - let (hi, lo) = a.into_words(); - - let (lo, carry) = lo.overflowing_add(b as _); - let (hi, overflow) = hi.overflowing_add(carry as _); - check(overflow); - - U256::from_words(hi, lo) - } - - const fn mul(a: U256, r: u128) -> U256 { - let (hi, lo) = a.into_words(); - let (lh, ll) = (lo >> 64, lo & u64::MAX as u128); - - let ll = ll * r; - let lh = lh * r; - let (hi, overflow) = hi.overflowing_mul(r); - check(overflow); - - let (lo, overflow) = ll.overflowing_add(lh << 64); - check(overflow); - let (hi, overflow) = hi.overflowing_add(lh >> 64); - check(overflow); - - U256::from_words(hi, lo) - } - - assert!(bytes.len() > start, "missing number"); - - let (radix, mut i) = if bytes.len() - start > 2 { - match (bytes[start], bytes[start + 1]) { - (b'0', b'b') => (2, start + 2), - (b'0', b'o') => (8, start + 2), - (b'0', b'x') => (16, start + 2), - _ => (10, start), - } - } else { - (10, start) - }; - - let mut value = U256::ZERO; - - while i < bytes.len() { - let byte = bytes[i]; - i += 1; - - if byte == b'_' || byte.is_ascii_whitespace() { - continue; - } - - let next = match (byte, radix) { - (b'0'..=b'1', 2 | 8 | 10 | 16) => byte - b'0', - (b'2'..=b'7', 8 | 10 | 16) => byte - b'0', - (b'8'..=b'9', 10 | 16) => byte - b'0', - (b'a'..=b'f', 16) => byte - b'a' + 0xa, - (b'A'..=b'F', 16) => byte - b'A' + 0xa, - (b'_', _) => continue, - _ => panic!("invalid digit"), - }; - value = add(mul(value, radix), next); - } - - value -} diff --git a/Contract/ethnum-patch/src/serde.rs b/Contract/ethnum-patch/src/serde.rs deleted file mode 100644 index 2df9aff..0000000 --- a/Contract/ethnum-patch/src/serde.rs +++ /dev/null @@ -1,1579 +0,0 @@ -//! Serde serialization implementation for 256-bit integer types. -//! -//! This implementation is very JSON-centric in that it serializes the integer -//! types as `QUANTITIES` as specified in the Ethereum RPC. That is, integers -//! are encoded as `"0x"` prefixed strings without extrenuous leading `0`s. For -//! negative signed integers, the string is prefixed with a `"-"` sign. -//! -//! Note that this module contains alternative serialization schemes that can -//! be used with `#[serde(with = "...")]`. -//! -//! # Examples -//! -//! Basic usage: -//! -//! ```text -//! #[derive(Deserialize, Serialize)] -//! struct Example { -//! a: U256, // "0x2a" -//! #[serde(with = "ethnum::serde::decimal")] -//! b: I256, // "-42" -//! #[serde(with = "ethnum::serde::prefixed")] -//! c: U256, // "0x2a" or "42" -//! #[serde(with = "ethnum::serde::permissive")] -//! d: I256, // "-0x2a" or "-42" or -42 -//! #[serde(with = "ethnum::serde::bytes::be")] -//! e: U256, // [0x2a, 0x00, ..., 0x00] -//! #[serde(with = "ethnum::serde::bytes::le")] -//! f: I256, // [0xd6, 0xff, ..., 0xff] -//! #[serde(with = "ethnum::serde::compressed_bytes::be")] -//! g: U256, // [0x2a] -//! #[serde(with = "ethnum::serde::compressed_bytes::le")] -//! h: I256, // [0xd6] -//! } -//! ``` - -use crate::{int::I256, uint::U256}; -use core::{ - fmt::{self, Display, Formatter, Write}, - mem::MaybeUninit, - ptr, slice, str, -}; -use serde::{ - de::{self, Visitor}, - Deserialize, Deserializer, Serialize, Serializer, -}; - -impl Serialize for I256 { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - let mut f = FormatBuffer::hex(); - write!(f, "{self:-#x}").expect("unexpected formatting failure"); - serializer.serialize_str(f.as_str()) - } -} - -impl Serialize for U256 { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - let mut f = FormatBuffer::hex(); - write!(f, "{self:#x}").expect("unexpected formatting failure"); - serializer.serialize_str(f.as_str()) - } -} - -impl<'de> Deserialize<'de> for I256 { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - deserializer.deserialize_str(FormatVisitor(Self::from_str_hex)) - } -} - -impl<'de> Deserialize<'de> for U256 { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - deserializer.deserialize_str(FormatVisitor(Self::from_str_hex)) - } -} - -/// Module for use with `#[serde(with = "ethnum::serde::decimal")]` to specify -/// decimal string serialization for 256-bit integer types. -pub mod decimal { - use super::*; - use core::num::ParseIntError; - - #[doc(hidden)] - pub trait Decimal: Sized { - fn from_str_decimal(src: &str) -> Result; - fn write_decimal(&self, f: &mut impl Write); - } - - impl Decimal for I256 { - fn from_str_decimal(src: &str) -> Result { - Self::from_str_radix(src, 10) - } - fn write_decimal(&self, f: &mut impl Write) { - write!(f, "{self}").expect("unexpected formatting error") - } - } - - impl Decimal for U256 { - fn from_str_decimal(src: &str) -> Result { - Self::from_str_radix(src, 10) - } - fn write_decimal(&self, f: &mut impl Write) { - write!(f, "{self}").expect("unexpected formatting error") - } - } - - #[doc(hidden)] - pub fn serialize(value: &T, serializer: S) -> Result - where - T: Decimal, - S: Serializer, - { - let mut f = FormatBuffer::decimal(); - value.write_decimal(&mut f); - serializer.serialize_str(f.as_str()) - } - - #[doc(hidden)] - pub fn deserialize<'de, T, D>(deserializer: D) -> Result - where - T: Decimal, - D: Deserializer<'de>, - { - deserializer.deserialize_str(FormatVisitor(T::from_str_decimal)) - } -} - -/// Module for use with `#[serde(with = "ethnum::serde::prefixed")]` to specify -/// prefixed string serialization for 256-bit integer types. -/// -/// This allows serialization to look for an optional `0x` prefix to determine -/// if it is a hexadecimal string or decimal string. -pub mod prefixed { - use super::*; - use core::num::ParseIntError; - - #[doc(hidden)] - pub trait Prefixed: Serialize + Sized { - fn from_str_prefixed(src: &str) -> Result; - } - - impl Prefixed for I256 { - fn from_str_prefixed(src: &str) -> Result { - Self::from_str_prefixed(src) - } - } - - impl Prefixed for U256 { - fn from_str_prefixed(src: &str) -> Result { - Self::from_str_prefixed(src) - } - } - - #[doc(hidden)] - pub fn serialize(value: &T, serializer: S) -> Result - where - T: Prefixed, - S: Serializer, - { - value.serialize(serializer) - } - - #[doc(hidden)] - pub fn deserialize<'de, T, D>(deserializer: D) -> Result - where - T: Prefixed, - D: Deserializer<'de>, - { - deserializer.deserialize_str(FormatVisitor(T::from_str_prefixed)) - } -} - -/// Module for use with `#[serde(with = "ethnum::serde::permissive")]` to -/// specify extremely permissive serialization for 256-bit integer types. -/// -/// This allows serialization to also accept standard numerical types as values -/// in addition to prefixed strings. -pub mod permissive { - use super::{prefixed::Prefixed, FormatVisitor}; - use crate::{AsI256 as _, I256, U256}; - use core::fmt::{self, Formatter}; - use core::marker::PhantomData; - use serde::{ - de::{self, Deserializer, Visitor}, - Serializer, - }; - - #[doc(hidden)] - pub trait Permissive: Prefixed { - fn cast(value: I256) -> Self; - } - - impl Permissive for I256 { - fn cast(value: I256) -> Self { - value - } - } - - impl Permissive for U256 { - fn cast(value: I256) -> Self { - value.as_u256() - } - } - - #[doc(hidden)] - pub fn serialize(value: &T, serializer: S) -> Result - where - T: Permissive, - S: Serializer, - { - value.serialize(serializer) - } - - struct PermissiveVisitor(PhantomData); - - impl Visitor<'_> for PermissiveVisitor - where - T: Permissive, - { - type Value = T; - - fn expecting(&self, f: &mut Formatter) -> fmt::Result { - f.write_str("number, decimal string or '0x-' prefixed hexadecimal string") - } - - fn visit_i64(self, v: i64) -> Result - where - E: de::Error, - { - Ok(T::cast(v.as_i256())) - } - - fn visit_u64(self, v: u64) -> Result - where - E: de::Error, - { - Ok(T::cast(v.as_i256())) - } - - fn visit_i128(self, v: i128) -> Result - where - E: de::Error, - { - Ok(T::cast(v.as_i256())) - } - - fn visit_u128(self, v: u128) -> Result - where - E: de::Error, - { - Ok(T::cast(v.as_i256())) - } - - fn visit_f32(self, v: f32) -> Result - where - E: de::Error, - { - const N: f32 = (1_u64 << 24) as _; - if !(-N..N).contains(&v) { - return Err(de::Error::custom( - "invalid conversion from single precision floating point \ - number outside of valid integer range (-2^24, 2^24)", - )); - } - - self.visit_f64(v as _) - } - - fn visit_f64(self, v: f64) -> Result - where - E: de::Error, - { - const N: f64 = (1_u64 << 53) as _; - if !(-N..N).contains(&v) { - return Err(de::Error::custom( - "invalid conversion from double precision floating point \ - number outside of valid integer range (-2^53, 2^53)", - )); - } - - // SOUNDNESS: `#[no_std]` does not have `f64::fract`, so work around - // it by casting to and from an integer type. This is sound because - // we already verified that the `f64` is within a "safe" range. - let i = v as i64; - if i as f64 != v { - return Err(de::Error::custom( - "invalid conversion from floating point number \ - with fractional part to 256-bit integer", - )); - } - - Ok(T::cast(i.as_i256())) - } - - fn visit_str(self, v: &str) -> Result - where - E: de::Error, - { - FormatVisitor(T::from_str_prefixed).visit_str(v) - } - } - - #[doc(hidden)] - pub fn deserialize<'de, T, D>(deserializer: D) -> Result - where - T: Permissive, - D: Deserializer<'de>, - { - deserializer.deserialize_any(PermissiveVisitor(PhantomData)) - } -} - -/// Serde byte serialization for 256-bit integer types. -pub mod bytes { - macro_rules! endianness { - ($name:literal; $to:ident, $from:ident) => { - use crate::{I256, U256}; - use core::{ - fmt::{self, Formatter}, - marker::PhantomData, - mem::{self, MaybeUninit}, - }; - use serde::{ - de::{self, Deserializer, Visitor}, - Serializer, - }; - - #[doc(hidden)] - pub trait Bytes: Sized + Copy { - fn to_bytes(self) -> [u8; 32]; - fn from_bytes(bytes: [u8; 32]) -> Self; - } - - impl Bytes for I256 { - fn to_bytes(self) -> [u8; 32] { - self.$to() - } - - fn from_bytes(bytes: [u8; 32]) -> Self { - I256::$from(bytes) - } - } - - impl Bytes for U256 { - fn to_bytes(self) -> [u8; 32] { - self.$to() - } - - fn from_bytes(bytes: [u8; 32]) -> Self { - U256::$from(bytes) - } - } - - #[doc(hidden)] - pub fn serialize(value: &T, serializer: S) -> Result - where - T: Bytes, - S: Serializer, - { - let bytes = value.to_bytes(); - serializer.serialize_bytes(&bytes) - } - - struct BytesVisitor(PhantomData); - - impl<'de, T> Visitor<'de> for BytesVisitor - where - T: Bytes, - { - type Value = T; - - fn expecting(&self, f: &mut Formatter) -> fmt::Result { - f.write_str(concat!("32 bytes in ", $name, " endian")) - } - - fn visit_bytes(self, v: &[u8]) -> Result - where - E: de::Error, - { - let bytes = v - .try_into() - .map_err(|_| E::invalid_length(v.len(), &self))?; - - Ok(T::from_bytes(bytes)) - } - - fn visit_seq(self, mut seq: S) -> Result - where - S: de::SeqAccess<'de>, - { - match seq.size_hint() { - Some(len) if len != 32 => { - return Err(de::Error::invalid_length(len, &self)) - } - _ => {} - } - - let mut bytes = [MaybeUninit::::uninit(); 32]; - for i in 0..32 { - bytes[i].write( - seq.next_element()? - .ok_or(de::Error::invalid_length(i, &self))?, - ); - } - if seq.next_element::()?.is_some() { - return Err(de::Error::invalid_length(33, &self)); - } - - // SAFETY: all bytes have been initialized in for loop. - let bytes = unsafe { mem::transmute::<[MaybeUninit; 32], [u8; 32]>(bytes) }; - - Ok(T::from_bytes(bytes)) - } - } - - #[doc(hidden)] - pub fn deserialize<'de, T, D>(deserializer: D) -> Result - where - T: Bytes, - D: Deserializer<'de>, - { - deserializer.deserialize_bytes(BytesVisitor(PhantomData)) - } - }; - } - - /// Module for use with `#[serde(with = "ethnum::serde::bytes::le")]` to - /// specify little endian byte serialization for 256-bit integer types. - pub mod le { - endianness!("little"; to_le_bytes, from_le_bytes); - } - - /// Module for use with `#[serde(with = "ethnum::serde::bytes::be")]` to - /// specify big endian byte serialization for 256-bit integer types. - pub mod be { - endianness!("big"; to_be_bytes, from_be_bytes); - } - - /// Module for use with `#[serde(with = "ethnum::serde::bytes::ne")]` to - /// specify native endian byte serialization for 256-bit integer types. - pub mod ne { - #[cfg(target_endian = "little")] - #[doc(hidden)] - pub use super::le::{deserialize, serialize}; - - #[cfg(target_endian = "big")] - #[doc(hidden)] - pub use super::be::{deserialize, serialize}; - } -} - -/// Serde compressed byte serialization for 256-bit integer types. -pub mod compressed_bytes { - use crate::{I256, U256}; - - #[doc(hidden)] - pub trait CompressedBytes { - fn leading_bits(&self) -> u32; - fn extend(msb: u8) -> u8; - } - - impl CompressedBytes for I256 { - fn leading_bits(&self) -> u32 { - match self.is_negative() { - true => self.leading_ones() - 1, - false => self.leading_zeros(), - } - } - - fn extend(msb: u8) -> u8 { - ((msb as i8) >> 7) as _ - } - } - - impl CompressedBytes for U256 { - fn leading_bits(&self) -> u32 { - self.leading_zeros() - } - - fn extend(_: u8) -> u8 { - 0 - } - } - - macro_rules! endianness { - ($name:literal; $parent:ident, |$tb:ident| $to:block, |$fb:ident| $from:block) => { - use super::CompressedBytes; - use crate::serde::bytes::$parent::Bytes; - use core::{ - fmt::{self, Formatter}, - marker::PhantomData, - mem::MaybeUninit, - }; - use serde::{ - de::{self, Deserializer, Visitor}, - Serializer, - }; - - #[doc(hidden)] - pub fn serialize(value: &T, serializer: S) -> Result - where - T: Bytes + CompressedBytes, - S: Serializer, - { - let bytes = value.to_bytes(); - let $tb = (value.leading_bits() as usize) / 8; - let index = { $to }; - serializer.serialize_bytes(&bytes[index]) - } - - struct CompressedBytesVisitor(PhantomData); - - impl<'de, T> Visitor<'de> for CompressedBytesVisitor - where - T: Bytes + CompressedBytes, - { - type Value = T; - - fn expecting(&self, f: &mut Formatter) -> fmt::Result { - f.write_str(concat!("bytes in ", $name, " endian")) - } - - fn visit_bytes(self, v: &[u8]) -> Result - where - E: de::Error, - { - if v.len() > 32 { - return Err(E::invalid_length(v.len(), &self)); - } - - let extend = T::extend(v.last().copied().unwrap_or_default()); - let mut bytes = [extend; 32]; - let $fb = v.len(); - let index = { $from }; - bytes[index].copy_from_slice(v); - - Ok(T::from_bytes(bytes)) - } - - fn visit_seq(self, mut seq: S) -> Result - where - S: de::SeqAccess<'de>, - { - match seq.size_hint() { - Some(len) if len > 32 => return Err(de::Error::invalid_length(len, &self)), - _ => {} - } - - let mut bytes = [MaybeUninit::::uninit(); 32]; - let mut i = 0; - while i < 32 { - let b = match seq.next_element()? { - Some(b) => b, - None => break, - }; - bytes[i].write(b); - i += 1; - } - if i == 32 && seq.next_element::()?.is_some() { - return Err(de::Error::invalid_length(33, &self)); - } - - // SAFETY: bytes up to `i` have been initialized in while - // loop. - let bytes = unsafe { &*(&bytes[..i] as *const _ as *const _) }; - - self.visit_bytes(bytes) - } - } - - #[doc(hidden)] - pub fn deserialize<'de, T, D>(deserializer: D) -> Result - where - T: Bytes + CompressedBytes, - D: Deserializer<'de>, - { - deserializer.deserialize_bytes(CompressedBytesVisitor(PhantomData)) - } - }; - } - - /// Module for `#[serde(with = "ethnum::serde::compressed_bytes::le")]` - /// to specify compressed little endian byte serialization for 256-bit - /// integer types. This will serialize integer types with as few bytes as - /// possible. - pub mod le { - endianness!("little"; le, |l| { ..32 - l }, |l| { ..l }); - } - - /// Module for `#[serde(with = "ethnum::serde::compressed_bytes::be")]` - /// to specify compressed big endian byte serialization for 256-bit - /// integer types. This will serialize integer types with as few bytes as - /// possible. - pub mod be { - endianness!("big"; be, |l| { l.. }, |l| { 32 - l.. }); - } - - /// Module for `#[serde(with = "ethnum::serde::compressed_bytes::ne")]` - /// to specify compressed native endian byte serialization for 256-bit - /// integer types. This will serialize integer types with as few bytes as - /// possible. - pub mod ne { - #[cfg(target_endian = "little")] - #[doc(hidden)] - pub use super::le::{deserialize, serialize}; - - #[cfg(target_endian = "big")] - #[doc(hidden)] - pub use super::be::{deserialize, serialize}; - } -} - -/// Internal visitor struct implementation to facilitate implementing different -/// serialization formats. -struct FormatVisitor(F); - -impl Visitor<'_> for FormatVisitor -where - E: Display, - F: FnOnce(&str) -> Result, -{ - type Value = T; - - fn expecting(&self, f: &mut Formatter) -> fmt::Result { - f.write_str("a formatted 256-bit integer") - } - - fn visit_str(self, v: &str) -> Result - where - E_: de::Error, - { - self.0(v).map_err(de::Error::custom) - } - - fn visit_bytes(self, v: &[u8]) -> Result - where - E_: de::Error, - { - let string = str::from_utf8(v) - .map_err(|_| de::Error::invalid_value(de::Unexpected::Bytes(v), &self))?; - self.visit_str(string) - } -} - -/// A stack-allocated buffer that can be used for writing formatted strings. -/// -/// This allows us to leverage existing `fmt` implementations on integer types -/// without requiring heap allocations (i.e. writing to a `String` buffer). -struct FormatBuffer { - offset: usize, - buffer: [MaybeUninit; N], -} - -impl FormatBuffer { - /// Creates a new formatting buffer. - fn new() -> Self { - Self { - offset: 0, - buffer: [MaybeUninit::uninit(); N], - } - } - - /// Returns a `str` to the currently written data. - fn as_str(&self) -> &str { - // SAFETY: We only ever write valid UTF-8 strings to the buffer, so the - // resulting string will always be valid. - unsafe { - let buffer = slice::from_raw_parts(self.buffer[0].as_ptr(), self.offset); - str::from_utf8_unchecked(buffer) - } - } -} - -impl FormatBuffer<78> { - /// Allocates a formatting buffer large enough to hold any possible decimal - /// encoded 256-bit value. - fn decimal() -> Self { - Self::new() - } -} - -impl FormatBuffer<67> { - /// Allocates a formatting buffer large enough to hold any possible - /// hexadecimal encoded 256-bit value. - fn hex() -> Self { - Self::new() - } -} - -impl Write for FormatBuffer { - fn write_str(&mut self, s: &str) -> fmt::Result { - let end = self.offset.checked_add(s.len()).ok_or(fmt::Error)?; - - // Make sure there is enough space in the buffer. - if end > N { - return Err(fmt::Error); - } - - // SAFETY: We checked that there is enough space in the buffer to fit - // the string `s` starting from `offset`, and the pointers cannot be - // overlapping because of Rust ownership semantics (i.e. `s` cannot - // overlap with `buffer` because we have a mutable reference to `self` - // and by extension `buffer`). - unsafe { - let buffer = self.buffer[0].as_mut_ptr().add(self.offset); - ptr::copy_nonoverlapping(s.as_ptr(), buffer, s.len()); - } - self.offset = end; - - Ok(()) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use alloc::{ - boxed::Box, - fmt::{Display, LowerHex}, - format, - string::String, - vec, - vec::Vec, - }; - use serde::{ - de::{value, IntoDeserializer}, - ser::Impossible, - }; - - #[test] - fn serialize_integers() { - macro_rules! ser { - ($method:expr, $value:expr) => {{ - let value = $value; - ($method)(&value, StringSerializer).unwrap() - }}; - } - - macro_rules! bin_ser { - ($method:expr, $value:expr) => {{ - let value = $value; - ($method)(&value, BytesSerializer).unwrap() - }}; - } - - assert_eq!( - ser!(I256::serialize, I256::MIN), - "-0x8000000000000000000000000000000000000000000000000000000000000000", - ); - assert_eq!(ser!(I256::serialize, I256::new(-1)), "-0x1"); - assert_eq!(ser!(I256::serialize, I256::new(0)), "0x0"); - assert_eq!(ser!(I256::serialize, I256::new(42)), "0x2a"); - - assert_eq!(ser!(U256::serialize, U256::new(0)), "0x0"); - assert_eq!(ser!(U256::serialize, U256::new(4919)), "0x1337"); - assert_eq!( - ser!(U256::serialize, U256::MAX), - "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - ); - - assert_eq!( - ser!(decimal::serialize, I256::MIN), - "-57896044618658097711785492504343953926634992332820282019728792003956564819968", - ); - assert_eq!(ser!(decimal::serialize, I256::new(-1)), "-1"); - assert_eq!(ser!(decimal::serialize, I256::new(0)), "0"); - assert_eq!(ser!(decimal::serialize, I256::new(42)), "42"); - - assert_eq!(ser!(decimal::serialize, U256::new(0)), "0"); - assert_eq!(ser!(decimal::serialize, U256::new(4919)), "4919"); - assert_eq!( - ser!(decimal::serialize, U256::MAX), - "115792089237316195423570985008687907853269984665640564039457584007913129639935", - ); - - assert_eq!(ser!(prefixed::serialize, I256::new(42)), "0x2a"); - assert_eq!(ser!(permissive::serialize, I256::new(42)), "0x2a"); - - assert_eq!(bin_ser!(bytes::le::serialize, U256::ZERO), vec![0x00; 32]); - assert_eq!(bin_ser!(bytes::le::serialize, U256::MAX), vec![0xff; 32]); - assert_eq!(bin_ser!(bytes::le::serialize, U256::new(0x4215)), { - let mut v = vec![0x15, 0x42]; - v.resize(32, 0x00); - v - }); - - assert_eq!( - bin_ser!(bytes::le::serialize, I256::new(-1)), - vec![0xff; 32] - ); - assert_eq!(bin_ser!(bytes::le::serialize, I256::new(-424242)), { - let mut v = vec![0xce, 0x86, 0xf9]; - v.resize(32, 0xff); - v - }); - - assert_eq!(bin_ser!(bytes::be::serialize, U256::ZERO), vec![0x00; 32]); - assert_eq!(bin_ser!(bytes::be::serialize, U256::MAX), vec![0xff; 32]); - assert_eq!(bin_ser!(bytes::be::serialize, U256::new(0x4215)), { - let mut v = vec![0x00; 32]; - v[30..].copy_from_slice(&[0x42, 0x15]); - v - }); - - assert_eq!( - bin_ser!(bytes::be::serialize, I256::new(-1)), - vec![0xff; 32] - ); - assert_eq!(bin_ser!(bytes::be::serialize, I256::new(-424242)), { - let mut v = vec![0xff; 32]; - v[29..].copy_from_slice(&[0xf9, 0x86, 0xce]); - v - }); - - assert_eq!( - bin_ser!(compressed_bytes::le::serialize, U256::ZERO), - vec![] - ); - assert_eq!( - bin_ser!(compressed_bytes::le::serialize, U256::MAX), - vec![0xff; 32], - ); - assert_eq!( - bin_ser!(compressed_bytes::le::serialize, U256::new(0x4215)), - vec![0x15, 0x42], - ); - - assert_eq!(bin_ser!(compressed_bytes::le::serialize, I256::MIN), { - let mut v = vec![0; 32]; - v[31] = 0x80; - v - }); - assert_eq!( - bin_ser!(compressed_bytes::le::serialize, I256::ZERO), - vec![] - ); - assert_eq!( - bin_ser!(compressed_bytes::le::serialize, I256::new(-1)), - vec![0xff], - ); - assert_eq!( - bin_ser!(compressed_bytes::le::serialize, I256::new(-0x8000)), - vec![0x00, 0x80], - ); - assert_eq!( - bin_ser!(compressed_bytes::le::serialize, I256::new(-424242)), - vec![0xce, 0x86, 0xf9], - ); - - assert_eq!( - bin_ser!(compressed_bytes::be::serialize, U256::ZERO), - vec![] - ); - assert_eq!( - bin_ser!(compressed_bytes::be::serialize, U256::MAX), - vec![0xff; 32], - ); - assert_eq!( - bin_ser!(compressed_bytes::be::serialize, U256::new(0x4215)), - vec![0x42, 0x15], - ); - - assert_eq!(bin_ser!(compressed_bytes::be::serialize, I256::MIN), { - let mut v = vec![0; 32]; - v[0] = 0x80; - v - }); - assert_eq!( - bin_ser!(compressed_bytes::be::serialize, I256::ZERO), - vec![] - ); - assert_eq!( - bin_ser!(compressed_bytes::be::serialize, I256::new(-1)), - vec![0xff], - ); - assert_eq!( - bin_ser!(compressed_bytes::be::serialize, I256::new(-0x8000)), - vec![0x80, 0x00], - ); - assert_eq!( - bin_ser!(compressed_bytes::be::serialize, I256::new(-424242)), - vec![0xf9, 0x86, 0xce], - ); - } - - #[test] - fn deserialize_integers() { - macro_rules! de { - ($method:expr, $src:expr) => {{ - let deserializer = IntoDeserializer::::into_deserializer($src); - ($method)(deserializer).unwrap() - }}; - (err; $method:expr, $src:expr) => {{ - let deserializer = IntoDeserializer::::into_deserializer($src); - ($method)(deserializer).is_err() - }}; - } - - macro_rules! assert_de_bytes { - ($method:expr, $src:expr; eq: $exp:expr) => {{ - let src = $src; - let exp = $exp; - - assert_eq!(de!($method, src.as_slice()), exp); - - let seq = - value::SeqDeserializer::<_, value::Error>::new(src.into_iter()); - assert_eq!(($method)(seq).unwrap(), exp); - }}; - ($method:expr, $src:expr; err) => {{ - let src = $src; - assert!(de!(err; $method, src.as_slice())); - let seq = - value::SeqDeserializer::<_, value::Error>::new(src.into_iter()); - assert!(($method)(seq).is_err()); - }}; - } - - assert_eq!( - de!( - I256::deserialize, - "-0x8000000000000000000000000000000000000000000000000000000000000000" - ), - I256::MIN - ); - assert_eq!(de!(I256::deserialize, "-0x1337"), I256::new(-4919)); - assert_eq!(de!(I256::deserialize, "0x0"), I256::new(0)); - assert_eq!(de!(I256::deserialize, "0x2a"), I256::new(42)); - assert_eq!(de!(I256::deserialize, "0x2A"), I256::new(42)); - - assert_eq!(de!(U256::deserialize, "0x0"), U256::new(0)); - assert_eq!(de!(U256::deserialize, "0x2a"), U256::new(42)); - assert_eq!(de!(U256::deserialize, "0x2A"), U256::new(42)); - assert_eq!( - de!( - U256::deserialize, - "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - ), - U256::MAX - ); - - assert_eq!( - de!( - decimal::deserialize::, - "-57896044618658097711785492504343953926634992332820282019728792003956564819968" - ), - I256::MIN - ); - assert_eq!(de!(decimal::deserialize::, "-1"), I256::new(-1)); - assert_eq!(de!(decimal::deserialize::, "0"), I256::new(0)); - assert_eq!(de!(decimal::deserialize::, "42"), I256::new(42)); - - assert_eq!(de!(decimal::deserialize::, "0"), U256::new(0)); - assert_eq!(de!(decimal::deserialize::, "42"), U256::new(42)); - assert_eq!( - de!( - decimal::deserialize::, - "115792089237316195423570985008687907853269984665640564039457584007913129639935" - ), - U256::MAX - ); - - assert_eq!(de!(prefixed::deserialize::, "-1"), I256::new(-1)); - assert_eq!(de!(prefixed::deserialize::, "-0x1"), I256::new(-1)); - assert_eq!(de!(prefixed::deserialize::, "42"), I256::new(42)); - assert_eq!(de!(prefixed::deserialize::, "0x2a"), I256::new(42)); - assert_eq!(de!(prefixed::deserialize::, "0x2A"), I256::new(42)); - - assert_eq!(de!(prefixed::deserialize::, "42"), U256::new(42)); - assert_eq!(de!(prefixed::deserialize::, "0x2a"), U256::new(42)); - assert_eq!(de!(prefixed::deserialize::, "0x2A"), U256::new(42)); - - assert_eq!( - de!(permissive::deserialize::, -42_i64), - I256::new(-42) - ); - assert_eq!( - de!(permissive::deserialize::, 42_u64), - I256::new(42) - ); - assert_eq!( - de!(permissive::deserialize::, -1337_i128), - I256::new(-1337) - ); - assert_eq!( - de!(permissive::deserialize::, 1337_u128), - I256::new(1337) - ); - assert_eq!( - de!(permissive::deserialize::, 100.0_f32), - I256::new(100) - ); - assert_eq!( - de!(permissive::deserialize::, -100.0_f64), - I256::new(-100) - ); - assert_eq!(de!(permissive::deserialize::, "-1"), I256::new(-1)); - assert_eq!( - de!(permissive::deserialize::, "1000"), - I256::new(1000) - ); - assert_eq!( - de!(permissive::deserialize::, "0x42"), - I256::new(0x42) - ); - assert_eq!( - de!(permissive::deserialize::, "-0x2a"), - I256::new(-42) - ); - assert_eq!( - de!( - permissive::deserialize::, - "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - ), - I256::MAX - ); - assert_eq!( - de!( - permissive::deserialize::, - "-0x8000000000000000000000000000000000000000000000000000000000000000" - ), - I256::MIN - ); - - assert_eq!( - de!(permissive::deserialize::, 42_u64), - U256::new(42) - ); - assert_eq!( - de!(permissive::deserialize::, 1337_u128), - U256::new(1337) - ); - assert_eq!( - de!(permissive::deserialize::, 100.0_f32), - U256::new(100) - ); - assert_eq!( - de!(permissive::deserialize::, 100.0_f64), - U256::new(100) - ); - assert_eq!( - de!(permissive::deserialize::, "1000"), - U256::new(1000) - ); - assert_eq!( - de!(permissive::deserialize::, "0x42"), - U256::new(0x42) - ); - assert_eq!( - de!( - permissive::deserialize::, - "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - ), - U256::MAX - ); - - assert!(de!(err; permissive::deserialize::, 4.2_f32)); - assert!(de!(err; permissive::deserialize::, 16777216.0_f32)); - assert!(de!(err; permissive::deserialize::, -13.37_f64)); - assert!(de!(err; permissive::deserialize::, 9007199254740992.0_f32)); - assert!( - de!(err; permissive::deserialize::, "0x8000000000000000000000000000000000000000000000000000000000000000") - ); - assert!( - de!(err; permissive::deserialize::, "-0x8000000000000000000000000000000000000000000000000000000000000001" - ) - ); - - assert!(de!(err; permissive::deserialize::, 4.2_f32)); - assert!(de!(err; permissive::deserialize::, 16777216.0_f32)); - assert!(de!(err; permissive::deserialize::, 13.37_f64)); - assert!(de!(err; permissive::deserialize::, 9007199254740992.0_f32)); - assert!( - de!(err; permissive::deserialize::, "0x10000000000000000000000000000000000000000000000000000000000000000") - ); - - assert_de_bytes!( - bytes::le::deserialize::, [0x00; 32]; - eq: U256::ZERO - ); - assert_de_bytes!( - bytes::le::deserialize::, [0xff; 32]; - eq: U256::MAX - ); - - assert_de_bytes!( - bytes::le::deserialize::, [0x00; 32]; - eq: I256::ZERO - ); - assert_de_bytes!( - bytes::le::deserialize::, [0xff; 32]; - eq: I256::new(-1) - ); - - let forty_two = { - let mut v = [0x00; 32]; - v[0] = 0x2a; - v - }; - assert_de_bytes!( - bytes::le::deserialize::, forty_two; - eq: U256::new(42) - ); - assert_de_bytes!( - bytes::le::deserialize::, forty_two; - eq: I256::new(42) - ); - - assert_de_bytes!( - bytes::le::deserialize::, [0xff; 31]; - err - ); - assert_de_bytes!( - bytes::le::deserialize::, [0xff; 33]; - err - ); - assert_de_bytes!( - bytes::le::deserialize::, [0xff; 31]; - err - ); - assert_de_bytes!( - bytes::le::deserialize::, [0xff; 33]; - err - ); - - assert_de_bytes!( - bytes::be::deserialize::, [0x00; 32]; - eq: U256::ZERO - ); - assert_de_bytes!( - bytes::be::deserialize::, [0xff; 32]; - eq: U256::MAX - ); - - assert_de_bytes!( - bytes::be::deserialize::, [0x00; 32]; - eq: I256::ZERO - ); - assert_de_bytes!( - bytes::be::deserialize::, [0xff; 32]; - eq: I256::new(-1) - ); - - let forty_two = { - let mut v = [0x00; 32]; - v[31] = 0x2a; - v - }; - assert_de_bytes!( - bytes::be::deserialize::, forty_two; - eq: U256::new(42) - ); - assert_de_bytes!( - bytes::be::deserialize::, forty_two; - eq: I256::new(42) - ); - - assert_de_bytes!( - bytes::be::deserialize::, [0xff; 31]; - err - ); - assert_de_bytes!( - bytes::be::deserialize::, [0xff; 33]; - err - ); - assert_de_bytes!( - bytes::be::deserialize::, [0xff; 31]; - err - ); - assert_de_bytes!( - bytes::be::deserialize::, [0xff; 33]; - err - ); - - assert_de_bytes!( - compressed_bytes::le::deserialize::, []; - eq: U256::ZERO - ); - assert_de_bytes!( - compressed_bytes::le::deserialize::, [0xff; 32]; - eq: U256::MAX - ); - - assert_de_bytes!( - compressed_bytes::le::deserialize::, [0x2a]; - eq: U256::new(42) - ); - assert_de_bytes!( - compressed_bytes::le::deserialize::, [0xee, 0xff]; - eq: U256::new(0xffee) - ); - assert_de_bytes!( - compressed_bytes::le::deserialize::, []; - eq: I256::ZERO - ); - assert_de_bytes!( - compressed_bytes::le::deserialize::, [0xff]; - eq: I256::new(-1) - ); - - assert_de_bytes!( - compressed_bytes::le::deserialize::, [0xff; 33]; - err - ); - assert_de_bytes!( - compressed_bytes::le::deserialize::, [0xff; 33]; - err - ); - - assert_de_bytes!( - compressed_bytes::be::deserialize::, []; - eq: U256::ZERO - ); - assert_de_bytes!( - compressed_bytes::be::deserialize::, [0xff; 32]; - eq: U256::MAX - ); - - assert_de_bytes!( - compressed_bytes::be::deserialize::, [0x2a]; - eq: U256::new(42) - ); - assert_de_bytes!( - compressed_bytes::be::deserialize::, [0xff, 0xee]; - eq: U256::new(0xffee) - ); - assert_de_bytes!( - compressed_bytes::be::deserialize::, []; - eq: I256::ZERO - ); - assert_de_bytes!( - compressed_bytes::be::deserialize::, [0xfe]; - eq: I256::new(-2) - ); - - assert_de_bytes!( - compressed_bytes::be::deserialize::, [0xff; 33]; - err - ); - assert_de_bytes!( - compressed_bytes::be::deserialize::, [0xff; 33]; - err - ); - } - - #[test] - fn formatting_buffer() { - for value in [ - Box::new(I256::MIN) as Box, - Box::new(I256::MAX), - Box::new(U256::MIN), - Box::new(U256::MAX), - ] { - let mut f = FormatBuffer::decimal(); - write!(f, "{value}").unwrap(); - assert_eq!(f.as_str(), format!("{value}")); - } - - for value in [ - Box::new(I256::MIN) as Box, - Box::new(I256::MAX), - Box::new(U256::MIN), - Box::new(U256::MAX), - ] { - let mut f = FormatBuffer::hex(); - let value = &*value; - write!(f, "{value:-#x}").unwrap(); - assert_eq!(f.as_str(), format!("{value:-#x}")); - } - } - - /// A string serializer used for testing. - struct StringSerializer; - - impl Serializer for StringSerializer { - type Ok = String; - type Error = fmt::Error; - type SerializeSeq = Impossible; - type SerializeTuple = Impossible; - type SerializeTupleStruct = Impossible; - type SerializeTupleVariant = Impossible; - type SerializeMap = Impossible; - type SerializeStruct = Impossible; - type SerializeStructVariant = Impossible; - fn serialize_bool(self, _: bool) -> Result { - unimplemented!() - } - fn serialize_i8(self, _: i8) -> Result { - unimplemented!() - } - fn serialize_i16(self, _: i16) -> Result { - unimplemented!() - } - fn serialize_i32(self, _: i32) -> Result { - unimplemented!() - } - fn serialize_i64(self, _: i64) -> Result { - unimplemented!() - } - fn serialize_u8(self, _: u8) -> Result { - unimplemented!() - } - fn serialize_u16(self, _: u16) -> Result { - unimplemented!() - } - fn serialize_u32(self, _: u32) -> Result { - unimplemented!() - } - fn serialize_u64(self, _: u64) -> Result { - unimplemented!() - } - fn serialize_f32(self, _: f32) -> Result { - unimplemented!() - } - fn serialize_f64(self, _: f64) -> Result { - unimplemented!() - } - fn serialize_char(self, _: char) -> Result { - unimplemented!() - } - fn serialize_str(self, v: &str) -> Result { - Ok(v.into()) - } - fn serialize_bytes(self, _: &[u8]) -> Result { - unimplemented!() - } - fn serialize_none(self) -> Result { - unimplemented!() - } - fn serialize_some(self, _: &T) -> Result - where - T: Serialize + ?Sized, - { - unimplemented!() - } - fn serialize_unit(self) -> Result { - unimplemented!() - } - fn serialize_unit_struct(self, _: &'static str) -> Result { - unimplemented!() - } - fn serialize_unit_variant( - self, - _: &'static str, - _: u32, - _: &'static str, - ) -> Result { - unimplemented!() - } - fn serialize_newtype_struct( - self, - _: &'static str, - _: &T, - ) -> Result - where - T: Serialize + ?Sized, - { - unimplemented!() - } - fn serialize_newtype_variant( - self, - _: &'static str, - _: u32, - _: &'static str, - _: &T, - ) -> Result - where - T: Serialize + ?Sized, - { - unimplemented!() - } - fn serialize_seq(self, _: Option) -> Result { - unimplemented!() - } - fn serialize_tuple(self, _: usize) -> Result { - unimplemented!() - } - fn serialize_tuple_struct( - self, - _: &'static str, - _: usize, - ) -> Result { - unimplemented!() - } - fn serialize_tuple_variant( - self, - _: &'static str, - _: u32, - _: &'static str, - _: usize, - ) -> Result { - unimplemented!() - } - fn serialize_map(self, _: Option) -> Result { - unimplemented!() - } - fn serialize_struct( - self, - _: &'static str, - _: usize, - ) -> Result { - unimplemented!() - } - fn serialize_struct_variant( - self, - _: &'static str, - _: u32, - _: &'static str, - _: usize, - ) -> Result { - unimplemented!() - } - fn collect_str(self, _: &T) -> Result - where - T: Display + ?Sized, - { - unimplemented!() - } - } - - /// A string serializer used for testing. - struct BytesSerializer; - - impl Serializer for BytesSerializer { - type Ok = Vec; - type Error = fmt::Error; - type SerializeSeq = Impossible, fmt::Error>; - type SerializeTuple = Impossible, fmt::Error>; - type SerializeTupleStruct = Impossible, fmt::Error>; - type SerializeTupleVariant = Impossible, fmt::Error>; - type SerializeMap = Impossible, fmt::Error>; - type SerializeStruct = Impossible, fmt::Error>; - type SerializeStructVariant = Impossible, fmt::Error>; - fn serialize_bool(self, _: bool) -> Result { - unimplemented!() - } - fn serialize_i8(self, _: i8) -> Result { - unimplemented!() - } - fn serialize_i16(self, _: i16) -> Result { - unimplemented!() - } - fn serialize_i32(self, _: i32) -> Result { - unimplemented!() - } - fn serialize_i64(self, _: i64) -> Result { - unimplemented!() - } - fn serialize_u8(self, _: u8) -> Result { - unimplemented!() - } - fn serialize_u16(self, _: u16) -> Result { - unimplemented!() - } - fn serialize_u32(self, _: u32) -> Result { - unimplemented!() - } - fn serialize_u64(self, _: u64) -> Result { - unimplemented!() - } - fn serialize_f32(self, _: f32) -> Result { - unimplemented!() - } - fn serialize_f64(self, _: f64) -> Result { - unimplemented!() - } - fn serialize_char(self, _: char) -> Result { - unimplemented!() - } - fn serialize_str(self, _: &str) -> Result { - unimplemented!() - } - fn serialize_bytes(self, v: &[u8]) -> Result { - Ok(v.to_vec()) - } - fn serialize_none(self) -> Result { - unimplemented!() - } - fn serialize_some(self, _: &T) -> Result - where - T: Serialize + ?Sized, - { - unimplemented!() - } - fn serialize_unit(self) -> Result { - unimplemented!() - } - fn serialize_unit_struct(self, _: &'static str) -> Result { - unimplemented!() - } - fn serialize_unit_variant( - self, - _: &'static str, - _: u32, - _: &'static str, - ) -> Result { - unimplemented!() - } - fn serialize_newtype_struct( - self, - _: &'static str, - _: &T, - ) -> Result - where - T: Serialize + ?Sized, - { - unimplemented!() - } - fn serialize_newtype_variant( - self, - _: &'static str, - _: u32, - _: &'static str, - _: &T, - ) -> Result - where - T: Serialize + ?Sized, - { - unimplemented!() - } - fn serialize_seq(self, _: Option) -> Result { - unimplemented!() - } - fn serialize_tuple(self, _: usize) -> Result { - unimplemented!() - } - fn serialize_tuple_struct( - self, - _: &'static str, - _: usize, - ) -> Result { - unimplemented!() - } - fn serialize_tuple_variant( - self, - _: &'static str, - _: u32, - _: &'static str, - _: usize, - ) -> Result { - unimplemented!() - } - fn serialize_map(self, _: Option) -> Result { - unimplemented!() - } - fn serialize_struct( - self, - _: &'static str, - _: usize, - ) -> Result { - unimplemented!() - } - fn serialize_struct_variant( - self, - _: &'static str, - _: u32, - _: &'static str, - _: usize, - ) -> Result { - unimplemented!() - } - fn collect_str(self, _: &T) -> Result - where - T: Display + ?Sized, - { - unimplemented!() - } - } -} diff --git a/Contract/ethnum-patch/src/uint.rs b/Contract/ethnum-patch/src/uint.rs deleted file mode 100644 index 5b0b7b3..0000000 --- a/Contract/ethnum-patch/src/uint.rs +++ /dev/null @@ -1,573 +0,0 @@ -//! Root module for 256-bit unsigned integer type. - -mod api; -mod cmp; -mod convert; -mod fmt; -mod iter; -mod ops; -mod parse; - -pub use self::convert::AsU256; -use crate::I256; -use core::{mem::MaybeUninit, num::ParseIntError}; - -/// A 256-bit unsigned integer type. -#[derive(Clone, Copy, Default, Eq, Hash, PartialEq)] -#[repr(transparent)] -pub struct U256(pub [u128; 2]); - -impl U256 { - /// The additive identity for this integer type, i.e. `0`. - pub const ZERO: Self = U256([0; 2]); - - /// The multiplicative identity for this integer type, i.e. `1`. - pub const ONE: Self = U256::new(1); - - /// Creates a new 256-bit integer value from a primitive `u128` integer. - #[inline] - pub const fn new(value: u128) -> Self { - U256::from_words(0, value) - } - - /// Creates a new 256-bit integer value from high and low words. - #[inline] - pub const fn from_words(hi: u128, lo: u128) -> Self { - #[cfg(target_endian = "little")] - { - U256([lo, hi]) - } - #[cfg(target_endian = "big")] - { - U256([hi, lo]) - } - } - - /// Splits a 256-bit integer into high and low words. - #[inline] - pub const fn into_words(self) -> (u128, u128) { - #[cfg(target_endian = "little")] - { - let U256([lo, hi]) = self; - (hi, lo) - } - #[cfg(target_endian = "big")] - { - let U256([hi, lo]) = self; - (hi, lo) - } - } - - /// Get the low 128-bit word for this unsigned integer. - #[inline] - pub fn low(&self) -> &u128 { - #[cfg(target_endian = "little")] - { - &self.0[0] - } - #[cfg(target_endian = "big")] - { - &self.0[1] - } - } - - /// Get the low 128-bit word for this unsigned integer as a mutable - /// reference. - #[inline] - pub fn low_mut(&mut self) -> &mut u128 { - #[cfg(target_endian = "little")] - { - &mut self.0[0] - } - #[cfg(target_endian = "big")] - { - &mut self.0[1] - } - } - - /// Get the high 128-bit word for this unsigned integer. - #[inline] - pub fn high(&self) -> &u128 { - #[cfg(target_endian = "little")] - { - &self.0[1] - } - #[cfg(target_endian = "big")] - { - &self.0[0] - } - } - - /// Get the high 128-bit word for this unsigned integer as a mutable - /// reference. - #[inline] - pub fn high_mut(&mut self) -> &mut u128 { - #[cfg(target_endian = "little")] - { - &mut self.0[1] - } - #[cfg(target_endian = "big")] - { - &mut self.0[0] - } - } - - /// Converts a prefixed string slice in base 16 to an integer. - /// - /// The string is expected to be an optional `+` sign followed by the `0x` - /// prefix and finally the digits. Leading and trailing whitespace represent - /// an error. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::U256; - /// assert_eq!(U256::from_str_hex("0x2A"), Ok(U256::new(42))); - /// ``` - pub fn from_str_hex(src: &str) -> Result { - crate::parse::from_str_radix(src, 16, Some("0x")) - } - - /// Converts a prefixed string slice in a base determined by the prefix to - /// an integer. - /// - /// The string is expected to be an optional `+` sign followed by the one of - /// the supported prefixes and finally the digits. Leading and trailing - /// whitespace represent an error. The base is determined based on the - /// prefix: - /// - /// * `0b`: base `2` - /// * `0o`: base `8` - /// * `0x`: base `16` - /// * no prefix: base `10` - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::U256; - /// assert_eq!(U256::from_str_prefixed("0b101"), Ok(U256::new(0b101))); - /// assert_eq!(U256::from_str_prefixed("0o17"), Ok(U256::new(0o17))); - /// assert_eq!(U256::from_str_prefixed("0xa"), Ok(U256::new(0xa))); - /// assert_eq!(U256::from_str_prefixed("42"), Ok(U256::new(42))); - /// ``` - pub fn from_str_prefixed(src: &str) -> Result { - crate::parse::from_str_prefixed(src) - } - - /// Same as [`U256::from_str_prefixed`] but as a `const fn`. This method is - /// not intended to be used directly but rather through the [`crate::uint`] - /// macro. - #[doc(hidden)] - pub const fn const_from_str_prefixed(src: &str) -> Self { - parse::const_from_str_prefixed(src) - } - - /// Cast to a primitive `i8`. - #[inline] - pub const fn as_i8(self) -> i8 { - let (_, lo) = self.into_words(); - lo as _ - } - - /// Cast to a primitive `i16`. - #[inline] - pub const fn as_i16(self) -> i16 { - let (_, lo) = self.into_words(); - lo as _ - } - - /// Cast to a primitive `i32`. - #[inline] - pub const fn as_i32(self) -> i32 { - let (_, lo) = self.into_words(); - lo as _ - } - - /// Cast to a primitive `i64`. - #[inline] - pub const fn as_i64(self) -> i64 { - let (_, lo) = self.into_words(); - lo as _ - } - - /// Cast to a primitive `i128`. - #[inline] - pub const fn as_i128(self) -> i128 { - let (_, lo) = self.into_words(); - lo as _ - } - - /// Cast to a `I256`. - #[inline] - pub const fn as_i256(self) -> I256 { - let Self([a, b]) = self; - I256([a as _, b as _]) - } - - /// Cast to a primitive `u8`. - #[inline] - pub const fn as_u8(self) -> u8 { - let (_, lo) = self.into_words(); - lo as _ - } - - /// Cast to a primitive `u16`. - #[inline] - pub const fn as_u16(self) -> u16 { - let (_, lo) = self.into_words(); - lo as _ - } - - /// Cast to a primitive `u32`. - #[inline] - pub const fn as_u32(self) -> u32 { - let (_, lo) = self.into_words(); - lo as _ - } - - /// Cast to a primitive `u64`. - #[inline] - pub const fn as_u64(self) -> u64 { - let (_, lo) = self.into_words(); - lo as _ - } - - /// Cast to a primitive `u128`. - #[inline] - pub const fn as_u128(self) -> u128 { - let (_, lo) = self.into_words(); - lo - } - - /// Cast to a primitive `isize`. - #[inline] - pub const fn as_isize(self) -> isize { - let (_, lo) = self.into_words(); - lo as _ - } - - /// Cast to a primitive `usize`. - #[inline] - pub const fn as_usize(self) -> usize { - let (_, lo) = self.into_words(); - lo as _ - } - - /// Cast to a primitive `f32`. - #[inline] - pub fn as_f32(self) -> f32 { - match self.into_words() { - (0, lo) => lo as _, - _ => f32::INFINITY, - } - } - - /// Cast to a primitive `f64`. - #[inline] - pub fn as_f64(self) -> f64 { - // NOTE: Binary representation of 2**128. This is used because `powi` is - // neither `const` nor `no_std`. - const HI: u64 = 0x47f0000000000000; - let (hi, lo) = self.into_words(); - (hi as f64) * f64::from_bits(HI) + (lo as f64) - } - - /// Performs integer and division and returns the quotient and the remainder as a tuple. This is faster than computing the quotient and remainder separately. - /// - /// # Panics - /// - /// This function will panic if `rhs` is 0. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::U256; - /// assert_eq!(U256::new(7).div_rem(U256::new(4)), (U256::new(1), U256::new(3))); - /// ``` - #[inline] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[track_caller] - pub fn div_rem(self, rhs: Self) -> (Self, Self) { - if rhs == 0 { - if rhs > 0 { - // The optimizer understands inequalities better - unsafe { core::hint::unreachable_unchecked() } - } - panic!("attempt to divide by zero"); - } - if rhs <= 0 { - // The optimizer understands inequalities better - unsafe { core::hint::unreachable_unchecked() } - } - - let mut res: MaybeUninit = MaybeUninit::uninit(); - let mut rem: MaybeUninit = MaybeUninit::uninit(); - crate::intrinsics::udivmod4(&mut res, &self, &rhs, Some(&mut rem)); - let ret = unsafe { ((res.assume_init()), (rem.assume_init())) }; - - // This helps the optimizer figure out when it can use smaller - // operands for later functions. - // SAFETY: Relies on the fact that rhs is at least 1. - if ret.1 >= rhs { - unsafe { core::hint::unreachable_unchecked() } - } - if ret.1 > self { - unsafe { core::hint::unreachable_unchecked() } - } - if ret.0 > self { - unsafe { core::hint::unreachable_unchecked() } - } - - ret - } - - /// Performs Euclidean division. - /// - /// Since, for the positive integers, all common definitions of division are - /// equal, this is exactly equal to `self.div_rem(rhs)`. - /// - /// # Panics - /// - /// This function will panic if `rhs` is 0. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::U256; - /// assert_eq!(U256::new(7).div_rem_euclid(U256::new(4)), (U256::new(1), U256::new(3))); - /// ``` - #[inline(always)] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[track_caller] - pub fn div_rem_euclid(self, rhs: Self) -> (Self, Self) { - self.div_rem(rhs) - } - - /// Checked integer division. Computes `self.div_rem(rhs)`, returning `None` if - /// `rhs == 0`. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::U256; - /// assert_eq!(U256::new(128).checked_div_rem(U256::new(2)), Some((U256::new(64), U256::new(0)))); - /// assert_eq!(U256::new(1).checked_div_rem(U256::new(0)), None); - /// ``` - #[inline] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - pub fn checked_div_rem(self, rhs: Self) -> Option<(Self, Self)> { - if rhs == Self::ZERO { - if rhs > 0 { - // The optimizer understands inequalities better - unsafe { core::hint::unreachable_unchecked() } - } - - None - } else { - if rhs <= 0 { - // The optimizer understands inequalities better - unsafe { core::hint::unreachable_unchecked() } - } - - Some(self.div_rem(rhs)) - } - } - - /// Checked Euclidean division. Computes `self.div_rem_euclid(rhs)`, returning `None` if - /// `rhs == 0`. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::U256; - /// assert_eq!(U256::new(128).checked_div_rem_euclid(U256::new(2)), Some((U256::new(64), U256::new(0)))); - /// assert_eq!(U256::new(1).checked_div_rem_euclid(U256::new(0)), None); - /// ``` - #[inline(always)] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - pub fn checked_div_rem_euclid(self, rhs: Self) -> Option<(Self, Self)> { - self.checked_div_rem(rhs) - } - - /// Saturating integer division. Computes `self.div_rem(rhs)`, saturating at the - /// numeric bounds instead of overflowing. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::U256; - /// assert_eq!(U256::new(5).saturating_div_rem(U256::new(2)), (U256::new(2), U256::new(1))); - /// ``` - /// - /// ```should_panic (expected = "attempt to divide by zero") - /// # use ethnum::U256; - /// let _ = U256::new(1).saturating_div_rem(U256::ZERO); - /// ``` - #[inline(always)] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[track_caller] - pub fn saturating_div_rem(self, rhs: Self) -> (Self, Self) { - self.div_rem(rhs) - } - - /// Saturating integer division. Computes `self.div_rem_euclid(rhs)`, saturating at the - /// numeric bounds instead of overflowing. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::U256; - /// assert_eq!(U256::new(5).saturating_div_rem_euclid(U256::new(2)), (U256::new(2), U256::new(1))); - /// ``` - /// - /// ```should_panic (expected = "attempt to divide by zero") - /// # use ethnum::U256; - /// let _ = U256::new(1).saturating_div_rem_euclid(U256::ZERO); - /// ``` - #[inline(always)] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[track_caller] - pub fn saturating_div_rem_euclid(self, rhs: Self) -> (Self, Self) { - self.div_rem(rhs) - } - - /// Wrapping (modular) division. Computes `self.div_rem(rhs)`. Wrapped division on - /// unsigned types is just normal division. There's no way wrapping could - /// ever happen. This function exists, so that all operations are accounted - /// for in the wrapping operations. - /// - /// # Panics - /// - /// This function will panic if `rhs` is 0. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::U256; - /// assert_eq!(U256::new(100).wrapping_div_rem(U256::new(10)), (U256::new(10), U256::new(0))); - /// ``` - #[inline(always)] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[track_caller] - pub fn wrapping_div_rem(self, rhs: Self) -> (Self, Self) { - self.div_rem(rhs) - } - - /// Wrapping Euclidean division. Computes `self.div_rem_euclid(rhs)`. Wrapped division on - /// unsigned types is just normal division. There's no way wrapping could - /// ever happen. This function exists, so that all operations are accounted - /// for in the wrapping operations. Since, for the positive integers, all common - /// definitions of division are equal, this is exactly equal to `self.div_rem(rhs)`. - /// - /// # Panics - /// - /// This function will panic if `rhs` is 0. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::U256; - /// assert_eq!(U256::new(100).wrapping_div_rem_euclid(U256::new(10)), (U256::new(10), U256::new(0))); - /// ``` - #[inline(always)] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[track_caller] - pub fn wrapping_div_rem_euclid(self, rhs: Self) -> (Self, Self) { - self.div_rem(rhs) - } - - /// Calculates the quotient and the remainder when `self` is divided by `rhs`. - /// - /// Returns a tuple of the divisor and the remainder along with a boolean indicating whether - /// an arithmetic overflow would occur. Note that for unsigned integers - /// overflow never occurs, so the second value is always `false`. - /// - /// # Panics - /// - /// This function will panic if `rhs` is 0. - /// - /// # Examples - /// - /// Basic usage - /// - /// ``` - /// # use ethnum::U256; - /// assert_eq!(U256::new(5).overflowing_div_rem(U256::new(2)), (U256::new(2), U256::new(1), false)); - /// ``` - #[inline(always)] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[track_caller] - pub fn overflowing_div_rem(self, rhs: Self) -> (Self, Self, bool) { - let (q, r) = self.div_rem(rhs); - (q, r, false) - } - - /// Calculates the quotient of Euclidean division `self.div_rem_euclid(rhs)`. - /// - /// Returns a tuple of the divisor along with a boolean indicating whether - /// an arithmetic overflow would occur. Note that for unsigned integers - /// overflow never occurs, so the second value is always `false`. Since, - /// for the positive integers, all common definitions of division are equal, - /// this is exactly equal to `self.div_rem(rhs)`. - /// - /// # Panics - /// - /// This function will panic if `rhs` is 0. - /// - /// # Examples - /// - /// Basic usage - /// - /// ``` - /// # use ethnum::U256; - /// assert_eq!(U256::new(5).overflowing_div_rem_euclid(U256::new(2)), (U256::new(2), U256::new(1), false)); - /// ``` - #[inline(always)] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[track_caller] - pub fn overflowing_div_rem_euclid(self, rhs: Self) -> (Self, Self, bool) { - let (q, r) = self.div_rem(rhs); - (q, r, false) - } -} - -#[cfg(test)] -mod tests { - use crate::uint::U256; - - #[test] - #[allow(clippy::float_cmp)] - fn converts_to_f64() { - assert_eq!(U256::from_words(1, 0).as_f64(), 2.0f64.powi(128)) - } -} diff --git a/Contract/ethnum-patch/src/uint/api.rs b/Contract/ethnum-patch/src/uint/api.rs deleted file mode 100644 index 002908c..0000000 --- a/Contract/ethnum-patch/src/uint/api.rs +++ /dev/null @@ -1,1865 +0,0 @@ -//! Module containing integer aritimetic methods closely following the Rust -//! standard library API for `uN` types. - -use super::U256; -use crate::{intrinsics, I256}; -use core::{ - mem::{self, MaybeUninit}, - num::ParseIntError, -}; - -impl U256 { - /// The smallest value that can be represented by this integer type. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::U256; - /// assert_eq!(U256::MIN, U256::new(0)); - /// ``` - pub const MIN: Self = Self([0; 2]); - - /// The largest value that can be represented by this integer type. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::U256; - /// assert_eq!( - /// U256::MAX.to_string(), - /// "115792089237316195423570985008687907853269984665640564039457584007913129639935", - /// ); - /// ``` - pub const MAX: Self = Self([!0; 2]); - - /// The size of this integer type in bits. - /// - /// # Examples - /// - /// ``` - /// # use ethnum::U256; - /// assert_eq!(U256::BITS, 256); - /// ``` - pub const BITS: u32 = 256; - - /// Converts a string slice in a given base to an integer. - /// - /// The string is expected to be an optional `+` sign followed by digits. - /// Leading and trailing whitespace represent an error. Digits are a subset - /// of these characters, depending on `radix`: - /// - /// * `0-9` - /// * `a-z` - /// * `A-Z` - /// - /// # Panics - /// - /// This function panics if `radix` is not in the range from 2 to 36. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::U256; - /// assert_eq!(U256::from_str_radix("A", 16), Ok(U256::new(10))); - /// ``` - #[inline] - pub fn from_str_radix(src: &str, radix: u32) -> Result { - crate::parse::from_str_radix(src, radix, None) - } - - /// Returns the number of ones in the binary representation of `self`. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::U256; - /// let n = U256::new(0b01001100); - /// assert_eq!(n.count_ones(), 3); - /// ``` - #[inline] - pub const fn count_ones(self) -> u32 { - let Self([a, b]) = self; - a.count_ones() + b.count_ones() - } - - /// Returns the number of zeros in the binary representation of `self`. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::U256; - /// assert_eq!(U256::MIN.count_zeros(), 256); - /// assert_eq!(U256::MAX.count_zeros(), 0); - /// ``` - #[inline] - pub const fn count_zeros(self) -> u32 { - let Self([a, b]) = self; - a.count_zeros() + b.count_zeros() - } - - /// Returns the number of leading zeros in the binary representation of - /// `self`. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::U256; - /// let n = U256::MAX >> 2u32; - /// assert_eq!(n.leading_zeros(), 2); - /// ``` - #[inline(always)] - pub fn leading_zeros(self) -> u32 { - intrinsics::signed::uctlz(&self) - } - - /// Returns the number of trailing zeros in the binary representation of - /// `self`. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::U256; - /// let n = U256::new(0b0101000); - /// assert_eq!(n.trailing_zeros(), 3); - /// ``` - #[inline(always)] - pub fn trailing_zeros(self) -> u32 { - intrinsics::signed::ucttz(&self) - } - - /// Returns the number of leading ones in the binary representation of - /// `self`. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::U256; - /// let n = !(U256::MAX >> 2u32); - /// assert_eq!(n.leading_ones(), 2); - /// ``` - #[inline] - pub fn leading_ones(self) -> u32 { - (!self).leading_zeros() - } - - /// Returns the number of trailing ones in the binary representation of - /// `self`. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::U256; - /// let n = U256::new(0b1010111); - /// assert_eq!(n.trailing_ones(), 3); - /// ``` - #[inline] - pub fn trailing_ones(self) -> u32 { - (!self).trailing_zeros() - } - - /// Shifts the bits to the left by a specified amount, `n`, wrapping the - /// truncated bits to the end of the resulting integer. - /// - /// Please note this isn't the same operation as the `<<` shifting - /// operator! - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::U256; - /// let n = U256::from_words( - /// 0x13f40000000000000000000000000000, - /// 0x00000000000000000000000000004f76, - /// ); - /// let m = U256::new(0x4f7613f4); - /// assert_eq!(n.rotate_left(16), m); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline(always)] - pub fn rotate_left(self, n: u32) -> Self { - let mut r = MaybeUninit::uninit(); - intrinsics::signed::urol3(&mut r, &self, n); - unsafe { r.assume_init() } - } - - /// Shifts the bits to the right by a specified amount, `n`, wrapping the - /// truncated bits to the beginning of the resulting integer. - /// - /// Please note this isn't the same operation as the `>>` shifting operator! - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::U256; - /// let n = U256::new(0x4f7613f4); - /// let m = U256::from_words( - /// 0x13f40000000000000000000000000000, - /// 0x00000000000000000000000000004f76, - /// ); - /// - /// assert_eq!(n.rotate_right(16), m); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline(always)] - pub fn rotate_right(self, n: u32) -> Self { - let mut r = MaybeUninit::uninit(); - intrinsics::signed::uror3(&mut r, &self, n); - unsafe { r.assume_init() } - } - - /// Reverses the byte order of the integer. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::U256; - /// let n = U256::from_words( - /// 0x00010203_04050607_08090a0b_0c0d0e0f, - /// 0x10111213_14151617_18191a1b_1c1d1e1f, - /// ); - /// assert_eq!( - /// n.swap_bytes(), - /// U256::from_words( - /// 0x1f1e1d1c_1b1a1918_17161514_13121110, - /// 0x0f0e0d0c_0b0a0908_07060504_03020100, - /// ), - /// ); - /// ``` - #[inline] - pub const fn swap_bytes(self) -> Self { - let Self([a, b]) = self; - Self([b.swap_bytes(), a.swap_bytes()]) - } - - /// Reverses the bit pattern of the integer. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::U256; - /// let n = U256::from_words( - /// 0x00010203_04050607_08090a0b_0c0d0e0f, - /// 0x10111213_14151617_18191a1b_1c1d1e1f, - /// ); - /// assert_eq!( - /// n.reverse_bits(), - /// U256::from_words( - /// 0xf878b838_d8589818_e868a828_c8488808, - /// 0xf070b030_d0509010_e060a020_c0408000, - /// ), - /// ); - /// ``` - #[inline] - pub const fn reverse_bits(self) -> Self { - let Self([a, b]) = self; - Self([b.reverse_bits(), a.reverse_bits()]) - } - - /// Converts an integer from big endian to the target's endianness. - /// - /// On big endian this is a no-op. On little endian the bytes are swapped. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::U256; - /// let n = U256::new(0x1A); - /// if cfg!(target_endian = "big") { - /// assert_eq!(U256::from_be(n), n); - /// } else { - /// assert_eq!(U256::from_be(n), n.swap_bytes()); - /// } - /// ``` - #[inline(always)] - #[allow(clippy::wrong_self_convention)] - pub const fn from_be(x: Self) -> Self { - #[cfg(target_endian = "big")] - { - x - } - #[cfg(not(target_endian = "big"))] - { - x.swap_bytes() - } - } - - /// Converts an integer from little endian to the target's endianness. - /// - /// On little endian this is a no-op. On big endian the bytes are swapped. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::U256; - /// let n = U256::new(0x1A); - /// if cfg!(target_endian = "little") { - /// assert_eq!(U256::from_le(n), n) - /// } else { - /// assert_eq!(U256::from_le(n), n.swap_bytes()) - /// } - /// ``` - #[inline(always)] - #[allow(clippy::wrong_self_convention)] - pub const fn from_le(x: Self) -> Self { - #[cfg(target_endian = "little")] - { - x - } - #[cfg(not(target_endian = "little"))] - { - x.swap_bytes() - } - } - - /// Converts `self` to big endian from the target's endianness. - /// - /// On big endian this is a no-op. On little endian the bytes are swapped. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::U256; - /// let n = U256::new(0x1A); - /// if cfg!(target_endian = "big") { - /// assert_eq!(n.to_be(), n) - /// } else { - /// assert_eq!(n.to_be(), n.swap_bytes()) - /// } - /// ``` - #[inline(always)] - pub const fn to_be(self) -> Self { - #[cfg(target_endian = "big")] - { - self - } - #[cfg(not(target_endian = "big"))] - { - self.swap_bytes() - } - } - - /// Converts `self` to little endian from the target's endianness. - /// - /// On little endian this is a no-op. On big endian the bytes are swapped. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::U256; - /// let n = U256::new(0x1A); - /// if cfg!(target_endian = "little") { - /// assert_eq!(n.to_le(), n) - /// } else { - /// assert_eq!(n.to_le(), n.swap_bytes()) - /// } - /// ``` - #[inline(always)] - pub const fn to_le(self) -> Self { - #[cfg(target_endian = "little")] - { - self - } - #[cfg(not(target_endian = "little"))] - { - self.swap_bytes() - } - } - - /// Checked integer addition. Computes `self + rhs`, returning `None` if - /// overflow occurred. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::U256; - /// assert_eq!((U256::MAX - 2).checked_add(U256::new(1)), Some(U256::MAX - 1)); - /// assert_eq!((U256::MAX - 2).checked_add(U256::new(3)), None); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub fn checked_add(self, rhs: Self) -> Option { - let (a, b) = self.overflowing_add(rhs); - if b { - None - } else { - Some(a) - } - } - - /// Checked addition with a signed integer. Computes `self + rhs`, - /// returning `None` if overflow occurred. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::{I256, U256}; - /// assert_eq!(U256::new(1).checked_add_signed(I256::new(2)), Some(U256::new(3))); - /// assert_eq!(U256::new(1).checked_add_signed(I256::new(-2)), None); - /// assert_eq!((U256::MAX - 2).checked_add_signed(I256::new(3)), None); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub fn checked_add_signed(self, rhs: I256) -> Option { - let (a, b) = self.overflowing_add_signed(rhs); - if b { - None - } else { - Some(a) - } - } - - /// Checked integer subtraction. Computes `self - rhs`, returning `None` if - /// overflow occurred. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::U256; - /// assert_eq!(U256::new(1).checked_sub(U256::new(1)), Some(U256::ZERO)); - /// assert_eq!(U256::new(0).checked_sub(U256::new(1)), None); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub fn checked_sub(self, rhs: Self) -> Option { - let (a, b) = self.overflowing_sub(rhs); - if b { - None - } else { - Some(a) - } - } - - /// Checked integer multiplication. Computes `self * rhs`, returning `None` - /// if overflow occurred. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::U256; - /// assert_eq!(U256::new(5).checked_mul(U256::new(1)), Some(U256::new(5))); - /// assert_eq!(U256::MAX.checked_mul(U256::new(2)), None); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub fn checked_mul(self, rhs: Self) -> Option { - let (a, b) = self.overflowing_mul(rhs); - if b { - None - } else { - Some(a) - } - } - - /// Checked integer division. Computes `self / rhs`, returning `None` if - /// `rhs == 0`. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::U256; - /// assert_eq!(U256::new(128).checked_div(U256::new(2)), Some(U256::new(64))); - /// assert_eq!(U256::new(1).checked_div(U256::new(0)), None); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub fn checked_div(self, rhs: Self) -> Option { - if rhs == U256::ZERO { - None - } else { - Some(self / rhs) - } - } - - /// Checked Euclidean division. Computes `self.div_euclid(rhs)`, returning - /// `None` if `rhs == 0`. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::U256; - /// assert_eq!(U256::new(128).checked_div_euclid(U256::new(2)), Some(U256::new(64))); - /// assert_eq!(U256::new(1).checked_div_euclid(U256::new(0)), None); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub fn checked_div_euclid(self, rhs: Self) -> Option { - if rhs == U256::ZERO { - None - } else { - Some(self.div_euclid(rhs)) - } - } - - /// Checked integer remainder. Computes `self % rhs`, returning `None` if - /// `rhs == 0`. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::U256; - /// assert_eq!(U256::new(5).checked_rem(U256::new(2)), Some(U256::new(1))); - /// assert_eq!(U256::new(5).checked_rem(U256::new(0)), None); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub fn checked_rem(self, rhs: Self) -> Option { - if rhs == U256::ZERO { - None - } else { - Some(self % rhs) - } - } - - /// Checked Euclidean modulo. Computes `self.rem_euclid(rhs)`, returning - /// `None` if `rhs == 0`. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::U256; - /// assert_eq!(U256::new(5).checked_rem_euclid(U256::new(2)), Some(U256::new(1))); - /// assert_eq!(U256::new(5).checked_rem_euclid(U256::new(0)), None); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub fn checked_rem_euclid(self, rhs: Self) -> Option { - if rhs == U256::ZERO { - None - } else { - Some(self.rem_euclid(rhs)) - } - } - - /// Checked negation. Computes `-self`, returning `None` unless `self == 0`. - /// - /// Note that negating any positive integer will overflow. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::U256; - /// assert_eq!(U256::ZERO.checked_neg(), Some(U256::ZERO)); - /// assert_eq!(U256::new(1).checked_neg(), None); - /// ``` - #[inline] - pub fn checked_neg(self) -> Option { - let (a, b) = self.overflowing_neg(); - if b { - None - } else { - Some(a) - } - } - - /// Checked shift left. Computes `self << rhs`, returning `None` if `rhs` is - /// larger than or equal to the number of bits in `self`. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::U256; - /// assert_eq!(U256::new(0x1).checked_shl(4), Some(U256::new(0x10))); - /// assert_eq!(U256::new(0x10).checked_shl(257), None); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub fn checked_shl(self, rhs: u32) -> Option { - let (a, b) = self.overflowing_shl(rhs); - if b { - None - } else { - Some(a) - } - } - - /// Checked shift right. Computes `self >> rhs`, returning `None` if `rhs` - /// is larger than or equal to the number of bits in `self`. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::U256; - /// assert_eq!(U256::new(0x10).checked_shr(4), Some(U256::new(0x1))); - /// assert_eq!(U256::new(0x10).checked_shr(257), None); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub fn checked_shr(self, rhs: u32) -> Option { - let (a, b) = self.overflowing_shr(rhs); - if b { - None - } else { - Some(a) - } - } - - /// Checked exponentiation. Computes `self.pow(exp)`, returning `None` if - /// overflow occurred. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::U256; - /// assert_eq!(U256::new(2).checked_pow(5), Some(U256::new(32))); - /// assert_eq!(U256::MAX.checked_pow(2), None); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub fn checked_pow(self, mut exp: u32) -> Option { - let mut base = self; - let mut acc = U256::ONE; - - while exp > 1 { - if (exp & 1) == 1 { - acc = acc.checked_mul(base)?; - } - exp /= 2; - base = base.checked_mul(base)?; - } - - // Deal with the final bit of the exponent separately, since - // squaring the base afterwards is not necessary and may cause a - // needless overflow. - if exp == 1 { - acc = acc.checked_mul(base)?; - } - - Some(acc) - } - - /// Saturating integer addition. Computes `self + rhs`, saturating at the - /// numeric bounds instead of overflowing. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::U256; - /// assert_eq!(U256::new(100).saturating_add(U256::new(1)), U256::new(101)); - /// assert_eq!(U256::MAX.saturating_add(U256::new(127)), U256::MAX); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub fn saturating_add(self, rhs: Self) -> Self { - self.checked_add(rhs).unwrap_or(U256::MAX) - } - - /// Saturating addition with a signed integer. Computes `self + rhs`, - /// saturating at the numeric bounds instead of overflowing. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::{I256, U256}; - /// assert_eq!(U256::new(1).saturating_add_signed(I256::new(2)), U256::new(3)); - /// assert_eq!(U256::new(1).saturating_add_signed(I256::new(-2)), U256::new(0)); - /// assert_eq!((U256::MAX - 2).saturating_add_signed(I256::new(4)), U256::MAX); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub fn saturating_add_signed(self, rhs: I256) -> Self { - let (res, overflow) = self.overflowing_add(rhs.as_u256()); - if overflow == (rhs < 0) { - res - } else if overflow { - Self::MAX - } else { - Self::ZERO - } - } - - /// Saturating integer subtraction. Computes `self - rhs`, saturating at the - /// numeric bounds instead of overflowing. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::U256; - /// assert_eq!(U256::new(100).saturating_sub(U256::new(27)), U256::new(73)); - /// assert_eq!(U256::new(13).saturating_sub(U256::new(127)), U256::new(0)); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub fn saturating_sub(self, rhs: Self) -> Self { - self.checked_sub(rhs).unwrap_or(U256::MIN) - } - - /// Saturating integer multiplication. Computes `self * rhs`, saturating at - /// the numeric bounds instead of overflowing. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::U256; - /// assert_eq!(U256::new(2).saturating_mul(U256::new(10)), U256::new(20)); - /// assert_eq!((U256::MAX).saturating_mul(U256::new(10)), U256::MAX); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub fn saturating_mul(self, rhs: Self) -> Self { - match self.checked_mul(rhs) { - Some(x) => x, - None => Self::MAX, - } - } - - /// Saturating integer division. Computes `self / rhs`, saturating at the - /// numeric bounds instead of overflowing. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::U256; - /// assert_eq!(U256::new(5).saturating_div(U256::new(2)), U256::new(2)); - /// ``` - /// - /// ```should_panic - /// # use ethnum::U256; - /// let _ = U256::new(1).saturating_div(U256::ZERO); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline(always)] - pub fn saturating_div(self, rhs: Self) -> Self { - // on unsigned types, there is no overflow in integer division - self.wrapping_div(rhs) - } - - /// Saturating integer exponentiation. Computes `self.pow(exp)`, saturating - /// at the numeric bounds instead of overflowing. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::U256; - /// assert_eq!(U256::new(4).saturating_pow(3), U256::new(64)); - /// assert_eq!(U256::MAX.saturating_pow(2), U256::MAX); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub fn saturating_pow(self, exp: u32) -> Self { - match self.checked_pow(exp) { - Some(x) => x, - None => Self::MAX, - } - } - - /// Wrapping (modular) addition. Computes `self + rhs`, wrapping around at - /// the boundary of the type. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::U256; - /// assert_eq!(U256::new(200).wrapping_add(U256::new(55)), U256::new(255)); - /// assert_eq!(U256::new(200).wrapping_add(U256::MAX), U256::new(199)); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline(always)] - pub fn wrapping_add(self, rhs: Self) -> Self { - let mut result = MaybeUninit::uninit(); - intrinsics::signed::uadd3(&mut result, &self, &rhs); - unsafe { result.assume_init() } - } - - /// Wrapping (modular) addition with a signed integer. Computes - /// `self + rhs`, wrapping around at the boundary of the type. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::{I256, U256}; - /// assert_eq!(U256::new(1).wrapping_add_signed(I256::new(2)), U256::new(3)); - /// assert_eq!(U256::new(1).wrapping_add_signed(I256::new(-2)), U256::MAX); - /// assert_eq!((U256::MAX - 2).wrapping_add_signed(I256::new(4)), U256::new(1)); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub fn wrapping_add_signed(self, rhs: I256) -> Self { - self.wrapping_add(rhs.as_u256()) - } - - /// Wrapping (modular) subtraction. Computes `self - rhs`, wrapping around - /// at the boundary of the type. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::U256; - /// assert_eq!(U256::new(100).wrapping_sub(U256::new(100)), U256::new(0)); - /// assert_eq!(U256::new(100).wrapping_sub(U256::MAX), U256::new(101)); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline(always)] - pub fn wrapping_sub(self, rhs: Self) -> Self { - let mut result = MaybeUninit::uninit(); - intrinsics::signed::usub3(&mut result, &self, &rhs); - unsafe { result.assume_init() } - } - - /// Wrapping (modular) multiplication. Computes `self * rhs`, wrapping - /// around at the boundary of the type. - /// - /// # Examples - /// - /// Basic usage: - /// - /// Please note that this example is shared between integer types. - /// Which explains why `u8` is used here. - /// - /// ``` - /// # use ethnum::U256; - /// assert_eq!(U256::new(10).wrapping_mul(U256::new(12)), U256::new(120)); - /// assert_eq!(U256::MAX.wrapping_mul(U256::new(2)), U256::MAX - 1); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline(always)] - pub fn wrapping_mul(self, rhs: Self) -> Self { - let mut result = MaybeUninit::uninit(); - intrinsics::signed::umul3(&mut result, &self, &rhs); - unsafe { result.assume_init() } - } - - /// Wrapping (modular) division. Computes `self / rhs`. Wrapped division on - /// unsigned types is just normal division. There's no way wrapping could - /// ever happen. This function exists, so that all operations are accounted - /// for in the wrapping operations. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::U256; - /// assert_eq!(U256::new(100).wrapping_div(U256::new(10)), U256::new(10)); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline(always)] - pub fn wrapping_div(self, rhs: Self) -> Self { - self / rhs - } - - /// Wrapping Euclidean division. Computes `self.div_euclid(rhs)`. Wrapped - /// division on unsigned types is just normal division. There's no way - /// wrapping could ever happen. This function exists, so that all operations - /// are accounted for in the wrapping operations. Since, for the positive - /// integers, all common definitions of division are equal, this is exactly - /// equal to `self.wrapping_div(rhs)`. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::U256; - /// assert_eq!(U256::new(100).wrapping_div_euclid(U256::new(10)), U256::new(10)); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline(always)] - pub fn wrapping_div_euclid(self, rhs: Self) -> Self { - self / rhs - } - - /// Wrapping (modular) remainder. Computes `self % rhs`. Wrapped remainder - /// calculation on unsigned types is just the regular remainder calculation. - /// There's no way wrapping could ever happen. This function exists, so that - /// all operations are accounted for in the wrapping operations. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::U256; - /// assert_eq!(U256::new(100).wrapping_rem(U256::new(10)), U256::new(0)); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline(always)] - pub fn wrapping_rem(self, rhs: Self) -> Self { - self % rhs - } - - /// Wrapping Euclidean modulo. Computes `self.rem_euclid(rhs)`. Wrapped - /// modulo calculation on unsigned types is just the regular remainder - /// calculation. There's no way wrapping could ever happen. This function - /// exists, so that all operations are accounted for in the wrapping - /// operations. Since, for the positive integers, all common definitions of - /// division are equal, this is exactly equal to `self.wrapping_rem(rhs)`. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::U256; - /// assert_eq!(U256::new(100).wrapping_rem_euclid(U256::new(10)), U256::new(0)); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline(always)] - pub fn wrapping_rem_euclid(self, rhs: Self) -> Self { - self % rhs - } - - /// Wrapping (modular) negation. Computes `-self`, wrapping around at the - /// boundary of the type. - /// - /// Since unsigned types do not have negative equivalents all applications - /// of this function will wrap (except for `-0`). For values smaller than - /// the corresponding signed type's maximum the result is the same as - /// casting the corresponding signed value. Any larger values are equivalent - /// to `MAX + 1 - (val - MAX - 1)` where `MAX` is the corresponding signed - /// type's maximum. - /// - /// # Examples - /// - /// Basic usage: - /// - /// Please note that this example is shared between integer types. - /// Which explains why `i8` is used here. - /// - /// ``` - /// # use ethnum::{U256, AsU256}; - /// assert_eq!(U256::new(100).wrapping_neg(), (-100i128).as_u256()); - /// assert_eq!( - /// U256::from_words(i128::MIN as _, 0).wrapping_neg(), - /// U256::from_words(i128::MIN as _, 0), - /// ); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub fn wrapping_neg(self) -> Self { - self.overflowing_neg().0 - } - - /// Panic-free bitwise shift-left; yields `self << mask(rhs)`, where `mask` - /// removes any high-order bits of `rhs` that would cause the shift to - /// exceed the bitwidth of the type. - /// - /// Note that this is *not* the same as a rotate-left; the RHS of a wrapping - /// shift-left is restricted to the range of the type, rather than the bits - /// shifted out of the LHS being returned to the other end. The primitive - /// integer types all implement a `rotate_left` function, which maybe what - /// you want instead. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::U256; - /// assert_eq!(U256::new(1).wrapping_shl(7), U256::new(128)); - /// assert_eq!(U256::new(1).wrapping_shl(128), U256::from_words(1, 0)); - /// assert_eq!(U256::new(1).wrapping_shl(256), U256::new(1)); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline(always)] - pub fn wrapping_shl(self, rhs: u32) -> Self { - let mut result = MaybeUninit::uninit(); - intrinsics::signed::ushl3(&mut result, &self, rhs & 0xff); - unsafe { result.assume_init() } - } - - /// Panic-free bitwise shift-right; yields `self >> mask(rhs)`, where `mask` - /// removes any high-order bits of `rhs` that would cause the shift to - /// exceed the bitwidth of the type. - /// - /// Note that this is *not* the same as a rotate-right; the RHS of a - /// wrapping shift-right is restricted to the range of the type, rather than - /// the bits shifted out of the LHS being returned to the other end. The - /// primitive integer types all implement a `rotate_right` function, which - /// may be what you want instead. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::U256; - /// assert_eq!(U256::new(128).wrapping_shr(7), U256::new(1)); - /// assert_eq!(U256::from_words(128, 0).wrapping_shr(128), U256::new(128)); - /// assert_eq!(U256::new(128).wrapping_shr(256), U256::new(128)); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline(always)] - pub fn wrapping_shr(self, rhs: u32) -> Self { - let mut result = MaybeUninit::uninit(); - intrinsics::signed::ushr3(&mut result, &self, rhs & 0xff); - unsafe { result.assume_init() } - } - - /// Wrapping (modular) exponentiation. Computes `self.pow(exp)`, wrapping - /// around at the boundary of the type. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::U256; - /// assert_eq!(U256::new(3).wrapping_pow(5), U256::new(243)); - /// assert_eq!( - /// U256::new(1337).wrapping_pow(42), - /// U256::from_words( - /// 45367329835866155830012179193722278514, - /// 159264946433345088039815329994094210673, - /// ), - /// ); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub fn wrapping_pow(self, mut exp: u32) -> Self { - let mut base = self; - let mut acc = U256::ONE; - - while exp > 1 { - if (exp & 1) == 1 { - acc = acc.wrapping_mul(base); - } - exp /= 2; - base = base.wrapping_mul(base); - } - - // Deal with the final bit of the exponent separately, since - // squaring the base afterwards is not necessary and may cause a - // needless overflow. - if exp == 1 { - acc = acc.wrapping_mul(base); - } - - acc - } - - /// Calculates `self` + `rhs` - /// - /// Returns a tuple of the addition along with a boolean indicating whether - /// an arithmetic overflow would occur. If an overflow would have occurred - /// then the wrapped value is returned. - /// - /// # Examples - /// - /// Basic usage - /// - /// ``` - /// # use ethnum::U256; - /// assert_eq!(U256::new(5).overflowing_add(U256::new(2)), (U256::new(7), false)); - /// assert_eq!(U256::MAX.overflowing_add(U256::new(1)), (U256::new(0), true)); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline(always)] - pub fn overflowing_add(self, rhs: Self) -> (Self, bool) { - let mut result = MaybeUninit::uninit(); - let overflow = intrinsics::signed::uaddc(&mut result, &self, &rhs); - (unsafe { result.assume_init() }, overflow) - } - - /// Calculates `self` + `rhs` with a signed `rhs` - /// - /// Returns a tuple of the addition along with a boolean indicating - /// whether an arithmetic overflow would occur. If an overflow would - /// have occurred then the wrapped value is returned. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::{I256, U256}; - /// assert_eq!(U256::new(1).overflowing_add_signed(I256::new(2)), (U256::new(3), false)); - /// assert_eq!(U256::new(1).overflowing_add_signed(I256::new(-2)), (U256::MAX, true)); - /// assert_eq!((U256::MAX - 2).overflowing_add_signed(I256::new(4)), (U256::new(1), true)); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub fn overflowing_add_signed(self, rhs: I256) -> (Self, bool) { - let (res, overflowed) = self.overflowing_add(rhs.as_u256()); - (res, overflowed ^ (rhs < 0)) - } - - /// Calculates `self` - `rhs` - /// - /// Returns a tuple of the subtraction along with a boolean indicating - /// whether an arithmetic overflow would occur. If an overflow would have - /// occurred then the wrapped value is returned. - /// - /// # Examples - /// - /// Basic usage - /// - /// ``` - /// # use ethnum::U256; - /// assert_eq!(U256::new(5).overflowing_sub(U256::new(2)), (U256::new(3), false)); - /// assert_eq!(U256::new(0).overflowing_sub(U256::new(1)), (U256::MAX, true)); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline(always)] - pub fn overflowing_sub(self, rhs: Self) -> (Self, bool) { - let mut result = MaybeUninit::uninit(); - let overflow = intrinsics::signed::usubc(&mut result, &self, &rhs); - (unsafe { result.assume_init() }, overflow) - } - - /// Computes the absolute difference between `self` and `other`. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::U256; - /// assert_eq!(U256::new(100).abs_diff(U256::new(80)), 20); - /// assert_eq!(U256::new(100).abs_diff(U256::new(110)), 10); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub fn abs_diff(self, other: Self) -> Self { - if self < other { - other - self - } else { - self - other - } - } - - /// Calculates the multiplication of `self` and `rhs`. - /// - /// Returns a tuple of the multiplication along with a boolean indicating - /// whether an arithmetic overflow would occur. If an overflow would have - /// occurred then the wrapped value is returned. - /// - /// # Examples - /// - /// Basic usage: - /// - /// Please note that this example is shared between integer types. - /// Which explains why `u32` is used here. - /// - /// ``` - /// # use ethnum::U256; - /// assert_eq!(U256::new(5).overflowing_mul(U256::new(2)), (U256::new(10), false)); - /// assert_eq!( - /// U256::MAX.overflowing_mul(U256::new(2)), - /// (U256::MAX - 1, true), - /// ); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline(always)] - pub fn overflowing_mul(self, rhs: Self) -> (Self, bool) { - let mut result = MaybeUninit::uninit(); - let overflow = intrinsics::signed::umulc(&mut result, &self, &rhs); - (unsafe { result.assume_init() }, overflow) - } - - /// Calculates the divisor when `self` is divided by `rhs`. - /// - /// Returns a tuple of the divisor along with a boolean indicating whether - /// an arithmetic overflow would occur. Note that for unsigned integers - /// overflow never occurs, so the second value is always `false`. - /// - /// # Panics - /// - /// This function will panic if `rhs` is 0. - /// - /// # Examples - /// - /// Basic usage - /// - /// ``` - /// # use ethnum::U256; - /// assert_eq!(U256::new(5).overflowing_div(U256::new(2)), (U256::new(2), false)); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline(always)] - pub fn overflowing_div(self, rhs: Self) -> (Self, bool) { - (self / rhs, false) - } - - /// Calculates the quotient of Euclidean division `self.div_euclid(rhs)`. - /// - /// Returns a tuple of the divisor along with a boolean indicating whether - /// an arithmetic overflow would occur. Note that for unsigned integers - /// overflow never occurs, so the second value is always `false`. Since, - /// for the positive integers, all common definitions of division are equal, - /// this is exactly equal to `self.overflowing_div(rhs)`. - /// - /// # Panics - /// - /// This function will panic if `rhs` is 0. - /// - /// # Examples - /// - /// Basic usage - /// - /// ``` - /// # use ethnum::U256; - /// assert_eq!(U256::new(5).overflowing_div_euclid(U256::new(2)), (U256::new(2), false)); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline(always)] - pub fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) { - (self / rhs, false) - } - - /// Calculates the remainder when `self` is divided by `rhs`. - /// - /// Returns a tuple of the remainder after dividing along with a boolean - /// indicating whether an arithmetic overflow would occur. Note that for - /// unsigned integers overflow never occurs, so the second value is always - /// `false`. - /// - /// # Panics - /// - /// This function will panic if `rhs` is 0. - /// - /// # Examples - /// - /// Basic usage - /// - /// ``` - /// # use ethnum::U256; - /// assert_eq!(U256::new(5).overflowing_rem(U256::new(2)), (U256::new(1), false)); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline(always)] - pub fn overflowing_rem(self, rhs: Self) -> (Self, bool) { - (self % rhs, false) - } - - /// Calculates the remainder `self.rem_euclid(rhs)` as if by Euclidean - /// division. - /// - /// Returns a tuple of the modulo after dividing along with a boolean - /// indicating whether an arithmetic overflow would occur. Note that for - /// unsigned integers overflow never occurs, so the second value is always - /// `false`. Since, for the positive integers, all common definitions of - /// division are equal, this operation is exactly equal to - /// `self.overflowing_rem(rhs)`. - /// - /// # Panics - /// - /// This function will panic if `rhs` is 0. - /// - /// # Examples - /// - /// Basic usage - /// - /// ``` - /// # use ethnum::U256; - /// assert_eq!(U256::new(5).overflowing_rem_euclid(U256::new(2)), (U256::new(1), false)); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline(always)] - pub fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) { - (self % rhs, false) - } - - /// Negates self in an overflowing fashion. - /// - /// Returns `!self + 1` using wrapping operations to return the value that - /// represents the negation of this unsigned value. Note that for positive - /// unsigned values overflow always occurs, but negating 0 does not - /// overflow. - /// - /// # Examples - /// - /// Basic usage - /// - /// ``` - /// # use ethnum::{U256, AsU256}; - /// assert_eq!(U256::new(0).overflowing_neg(), (U256::new(0), false)); - /// assert_eq!(U256::new(2).overflowing_neg(), ((-2i32).as_u256(), true)); - /// ``` - #[inline] - pub fn overflowing_neg(self) -> (Self, bool) { - ((!self).wrapping_add(U256::ONE), self != U256::ZERO) - } - - /// Shifts self left by `rhs` bits. - /// - /// Returns a tuple of the shifted version of self along with a boolean - /// indicating whether the shift value was larger than or equal to the - /// number of bits. If the shift value is too large, then value is masked - /// (N-1) where N is the number of bits, and this value is then used to - /// perform the shift. - /// - /// # Examples - /// - /// Basic usage - /// - /// ``` - /// # use ethnum::U256; - /// assert_eq!(U256::new(0x1).overflowing_shl(4), (U256::new(0x10), false)); - /// assert_eq!(U256::new(0x1).overflowing_shl(260), (U256::new(0x10), true)); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline(always)] - pub fn overflowing_shl(self, rhs: u32) -> (Self, bool) { - (self.wrapping_shl(rhs), rhs > 255) - } - - /// Shifts self right by `rhs` bits. - /// - /// Returns a tuple of the shifted version of self along with a boolean - /// indicating whether the shift value was larger than or equal to the - /// number of bits. If the shift value is too large, then value is masked - /// (N-1) where N is the number of bits, and this value is then used to - /// perform the shift. - /// - /// # Examples - /// - /// Basic usage - /// - /// ``` - /// # use ethnum::U256; - /// assert_eq!(U256::new(0x10).overflowing_shr(4), (U256::new(0x1), false)); - /// assert_eq!(U256::new(0x10).overflowing_shr(260), (U256::new(0x1), true)); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline(always)] - pub fn overflowing_shr(self, rhs: u32) -> (Self, bool) { - (self.wrapping_shr(rhs), rhs > 255) - } - - /// Raises self to the power of `exp`, using exponentiation by squaring. - /// - /// Returns a tuple of the exponentiation along with a bool indicating - /// whether an overflow happened. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::U256; - /// assert_eq!(U256::new(3).overflowing_pow(5), (U256::new(243), false)); - /// assert_eq!( - /// U256::new(1337).overflowing_pow(42), - /// ( - /// U256::from_words( - /// 45367329835866155830012179193722278514, - /// 159264946433345088039815329994094210673, - /// ), - /// true, - /// ) - /// ); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub fn overflowing_pow(self, mut exp: u32) -> (Self, bool) { - let mut base = self; - let mut acc = U256::ONE; - let mut overflown = false; - // Scratch space for storing results of overflowing_mul. - let mut r; - - while exp > 1 { - if (exp & 1) == 1 { - r = acc.overflowing_mul(base); - acc = r.0; - overflown |= r.1; - } - exp /= 2; - r = base.overflowing_mul(base); - base = r.0; - overflown |= r.1; - } - - // Deal with the final bit of the exponent separately, since - // squaring the base afterwards is not necessary and may cause a - // needless overflow. - if exp == 1 { - r = acc.overflowing_mul(base); - acc = r.0; - overflown |= r.1; - } - - (acc, overflown) - } - - /// Raises self to the power of `exp`, using exponentiation by squaring. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::U256; - /// assert_eq!(U256::new(2).pow(5), U256::new(32)); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub fn pow(self, mut exp: u32) -> Self { - let mut base = self; - let mut acc = U256::ONE; - - while exp > 1 { - if (exp & 1) == 1 { - acc *= base; - } - exp /= 2; - base = base * base; - } - - // Deal with the final bit of the exponent separately, since - // squaring the base afterwards is not necessary and may cause a - // needless overflow. - if exp == 1 { - acc *= base; - } - - acc - } - - /// Performs Euclidean division. - /// - /// Since, for the positive integers, all common definitions of division are - /// equal, this is exactly equal to `self / rhs`. - /// - /// # Panics - /// - /// This function will panic if `rhs` is 0. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::U256; - /// assert_eq!(U256::new(7).div_euclid(U256::new(4)), U256::new(1)); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline(always)] - pub fn div_euclid(self, rhs: Self) -> Self { - self / rhs - } - - /// Calculates the least remainder of `self (mod rhs)`. - /// - /// Since, for the positive integers, all common definitions of division are - /// equal, this is exactly equal to `self % rhs`. - /// - /// # Panics - /// - /// This function will panic if `rhs` is 0. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::U256; - /// assert_eq!(U256::new(7).rem_euclid(U256::new(4)), U256::new(3)); - /// ``` - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline(always)] - pub fn rem_euclid(self, rhs: Self) -> Self { - self % rhs - } - - /// Returns `true` if and only if `self == 2^k` for some `k`. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::U256; - /// assert!(U256::new(16).is_power_of_two()); - /// assert!(!U256::new(10).is_power_of_two()); - /// ``` - #[inline] - pub fn is_power_of_two(self) -> bool { - self.count_ones() == 1 - } - - /// Returns one less than next power of two. (For 8u8 next power of two is - /// 8u8 and for 6u8 it is 8u8). - /// - /// 8u8.one_less_than_next_power_of_two() == 7 - /// 6u8.one_less_than_next_power_of_two() == 7 - /// - /// This method cannot overflow, as in the `next_power_of_two` overflow - /// cases it instead ends up returning the maximum value of the type, and - /// can return 0 for 0. - #[inline] - fn one_less_than_next_power_of_two(self) -> Self { - if self <= 1 { - return U256::ZERO; - } - - let p = self - 1; - let z = p.leading_zeros(); - U256::MAX >> z - } - - /// Returns the smallest power of two greater than or equal to `self`. - /// - /// When return value overflows (i.e., `self > (1 << (N-1))` for type `uN`), - /// it panics in debug mode and return value is wrapped to 0 in release mode - /// (the only situation in which method can return 0). - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::U256; - /// assert_eq!(U256::new(2).next_power_of_two(), U256::new(2)); - /// assert_eq!(U256::new(3).next_power_of_two(), U256::new(4)); - /// ``` - #[inline] - pub fn next_power_of_two(self) -> Self { - self.one_less_than_next_power_of_two() + 1 - } - - /// Returns the smallest power of two greater than or equal to `n`. If the - /// next power of two is greater than the type's maximum value, `None` is - /// returned, otherwise the power of two is wrapped in `Some`. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # use ethnum::U256; - /// assert_eq!(U256::new(2).checked_next_power_of_two(), Some(U256::new(2))); - /// assert_eq!(U256::new(3).checked_next_power_of_two(), Some(U256::new(4))); - /// assert_eq!(U256::MAX.checked_next_power_of_two(), None); - /// ``` - #[inline] - pub fn checked_next_power_of_two(self) -> Option { - self.one_less_than_next_power_of_two() - .checked_add(U256::ONE) - } - - /// Return the memory representation of this integer as a byte array in big - /// endian (network) byte order. - /// - /// # Examples - /// - /// ``` - /// # use ethnum::U256; - /// let bytes = U256::from_words( - /// 0x00010203_04050607_08090a0b_0c0d0e0f, - /// 0x10111213_14151617_18191a1b_1c1d1e1f, - /// ); - /// assert_eq!( - /// bytes.to_be_bytes(), - /// [ - /// 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - /// 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - /// ], - /// ); - /// ``` - #[inline] - pub fn to_be_bytes(self) -> [u8; mem::size_of::()] { - self.to_be().to_ne_bytes() - } - - /// Return the memory representation of this integer as a byte array in - /// little endian byte order. - /// - /// # Examples - /// - /// ``` - /// # use ethnum::U256; - /// let bytes = U256::from_words( - /// 0x00010203_04050607_08090a0b_0c0d0e0f, - /// 0x10111213_14151617_18191a1b_1c1d1e1f, - /// ); - /// assert_eq!( - /// bytes.to_le_bytes(), - /// [ - /// 0x1f, 0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, - /// 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, - /// ], - /// ); - /// ``` - #[inline] - pub fn to_le_bytes(self) -> [u8; mem::size_of::()] { - self.to_le().to_ne_bytes() - } - - /// Return the memory representation of this integer as a byte array in - /// native byte order. - /// - /// As the target platform's native endianness is used, portable code should - /// use [`to_be_bytes`] or [`to_le_bytes`], as appropriate, instead. - /// - /// [`to_be_bytes`]: #method.to_be_bytes - /// [`to_le_bytes`]: #method.to_le_bytes - /// - /// # Examples - /// - /// ``` - /// # use ethnum::U256; - /// let bytes = U256::from_words( - /// 0x00010203_04050607_08090a0b_0c0d0e0f, - /// 0x10111213_14151617_18191a1b_1c1d1e1f, - /// ); - /// assert_eq!( - /// bytes.to_ne_bytes(), - /// if cfg!(target_endian = "big") { - /// [ - /// 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - /// 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - /// ] - /// } else { - /// [ - /// 0x1f, 0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, - /// 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, - /// ] - /// } - /// ); - /// ``` - #[inline] - pub fn to_ne_bytes(self) -> [u8; mem::size_of::()] { - unsafe { mem::transmute(self) } - } - - /// Create an integer value from its representation as a byte array in big - /// endian. - /// - /// # Examples - /// - /// ``` - /// # use ethnum::U256; - /// let value = U256::from_be_bytes([ - /// 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - /// 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - /// ]); - /// assert_eq!( - /// value, - /// U256::from_words( - /// 0x00010203_04050607_08090a0b_0c0d0e0f, - /// 0x10111213_14151617_18191a1b_1c1d1e1f, - /// ), - /// ); - /// ``` - /// - /// When starting from a slice rather than an array, fallible conversion - /// APIs can be used: - /// - /// ``` - /// # use ethnum::U256; - /// use std::convert::TryInto; - /// - /// fn read_be_u256(input: &mut &[u8]) -> U256 { - /// let (int_bytes, rest) = input.split_at(std::mem::size_of::()); - /// *input = rest; - /// U256::from_be_bytes(int_bytes.try_into().unwrap()) - /// } - /// ``` - #[inline] - pub fn from_be_bytes(bytes: [u8; mem::size_of::()]) -> Self { - Self::from_be(Self::from_ne_bytes(bytes)) - } - - /// Create an integer value from its representation as a byte array in - /// little endian. - /// - /// # Examples - /// - /// ``` - /// # use ethnum::U256; - /// let value = U256::from_le_bytes([ - /// 0x1f, 0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, - /// 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, - /// ]); - /// assert_eq!( - /// value, - /// U256::from_words( - /// 0x00010203_04050607_08090a0b_0c0d0e0f, - /// 0x10111213_14151617_18191a1b_1c1d1e1f, - /// ), - /// ); - /// ``` - /// - /// When starting from a slice rather than an array, fallible conversion - /// APIs can be used: - /// - /// ``` - /// # use ethnum::U256; - /// use std::convert::TryInto; - /// - /// fn read_be_u256(input: &mut &[u8]) -> U256 { - /// let (int_bytes, rest) = input.split_at(std::mem::size_of::()); - /// *input = rest; - /// U256::from_le_bytes(int_bytes.try_into().unwrap()) - /// } - /// ``` - #[inline] - pub fn from_le_bytes(bytes: [u8; mem::size_of::()]) -> Self { - Self::from_le(Self::from_ne_bytes(bytes)) - } - - /// Create an integer value from its memory representation as a byte array - /// in native endianness. - /// - /// As the target platform's native endianness is used, portable code likely - /// wants to use [`from_be_bytes`] or [`from_le_bytes`], as appropriate - /// instead. - /// - /// [`from_be_bytes`]: #method.from_be_bytes - /// [`from_le_bytes`]: #method.from_le_bytes - /// - /// # Examples - /// - /// ``` - /// # use ethnum::U256; - /// let value = U256::from_ne_bytes(if cfg!(target_endian = "big") { - /// [ - /// 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - /// 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - /// ] - /// } else { - /// [ - /// 0x1f, 0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, - /// 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, - /// ] - /// }); - /// assert_eq!( - /// value, - /// U256::from_words( - /// 0x00010203_04050607_08090a0b_0c0d0e0f, - /// 0x10111213_14151617_18191a1b_1c1d1e1f, - /// ), - /// ); - /// ``` - /// - /// When starting from a slice rather than an array, fallible conversion - /// APIs can be used: - /// - /// ``` - /// # use ethnum::U256; - /// use std::convert::TryInto; - /// - /// fn read_be_u256(input: &mut &[u8]) -> U256 { - /// let (int_bytes, rest) = input.split_at(std::mem::size_of::()); - /// *input = rest; - /// U256::from_ne_bytes(int_bytes.try_into().unwrap()) - /// } - /// ``` - #[inline] - pub fn from_ne_bytes(bytes: [u8; mem::size_of::()]) -> Self { - unsafe { mem::transmute(bytes) } - } -} diff --git a/Contract/ethnum-patch/src/uint/cmp.rs b/Contract/ethnum-patch/src/uint/cmp.rs deleted file mode 100644 index 25639e5..0000000 --- a/Contract/ethnum-patch/src/uint/cmp.rs +++ /dev/null @@ -1,62 +0,0 @@ -//! Module with comparison implementations for `U256`. -//! -//! `PartialEq` is derived and not implemented, which is important for ensuring -//! that `match` can be used with `U256`. -//! -//! ``` -//! # use ethnum::U256; -//! # let value = U256::new(42); -//! -//! match (value) { -//! U256::ZERO => println!("I am zero"), -//! U256::ONE => println!("I am one"), -//! _ => println!("I am something else"), -//! } -//! ``` -//! -//! `PartialEq` and `PartialOrd` implementations for `u128` are also provided -//! to allow notation such as: -//! -//! ``` -//! # use ethnum::U256; -//! -//! assert_eq!(U256::new(42), 42); -//! assert!(U256::ONE > 0 && U256::ZERO == 0); -//! ``` - -use crate::uint::U256; -use core::cmp::Ordering; - -impl Ord for U256 { - #[inline] - fn cmp(&self, other: &Self) -> Ordering { - self.into_words().cmp(&other.into_words()) - } -} - -impl_cmp! { - impl Cmp for U256 (u128); -} - -#[cfg(test)] -mod tests { - use super::*; - use core::cmp::Ordering; - - #[test] - fn cmp() { - // 1e38 - let x = U256::from_words(0, 100000000000000000000000000000000000000); - // 1e48 - let y = U256::from_words(2938735877, 18960114910927365649471927446130393088); - assert!(x < y); - assert_eq!(x.cmp(&y), Ordering::Less); - assert!(y > x); - assert_eq!(y.cmp(&x), Ordering::Greater); - - let x = U256::new(100); - let y = U256::new(100); - assert!(x <= y); - assert_eq!(x.cmp(&y), Ordering::Equal); - } -} diff --git a/Contract/ethnum-patch/src/uint/convert.rs b/Contract/ethnum-patch/src/uint/convert.rs deleted file mode 100644 index da2bdd3..0000000 --- a/Contract/ethnum-patch/src/uint/convert.rs +++ /dev/null @@ -1,198 +0,0 @@ -//! Module contains conversions for [`U256`] to and from primimitive types. - -use super::U256; -use crate::{error::tfie, int::I256}; -use core::{convert::TryFrom, num::TryFromIntError}; - -macro_rules! impl_from { - ($($t:ty),* $(,)?) => {$( - impl From<$t> for U256 { - #[inline] - fn from(value: $t) -> Self { - U256::new(value.into()) - } - } - )*}; -} - -impl_from! { - bool, u8, u16, u32, u64, u128, -} - -macro_rules! impl_try_from { - ($($t:ty),* $(,)?) => {$( - impl TryFrom<$t> for U256 { - type Error = TryFromIntError; - - #[inline] - fn try_from(value: $t) -> Result { - Ok(U256::new(u128::try_from(value)?)) - } - } - )*}; -} - -impl_try_from! { - i8, i16, i32, i64, i128, - isize, usize, -} - -impl TryFrom for U256 { - type Error = TryFromIntError; - - fn try_from(value: I256) -> Result { - if value < 0 { - return Err(tfie()); - } - Ok(value.as_u256()) - } -} - -/// This trait defines `as` conversions (casting) from primitive types to -/// [`U256`]. -/// -/// [`U256`]: struct.U256.html -/// -/// # Examples -/// -/// Note that in Rust casting from a negative signed integer sign to a larger -/// unsigned interger sign extends. Additionally casting a floating point value -/// to an integer is a saturating operation, with `NaN` converting to `0`. So: -/// -/// ``` -/// # use ethnum::{U256, AsU256}; -/// assert_eq!((-1i32).as_u256(), U256::MAX); -/// assert_eq!(u32::MAX.as_u256(), 0xffffffff); -/// -/// assert_eq!(f64::NEG_INFINITY.as_u256(), 0); -/// assert_eq!((-1.0f64).as_u256(), 0); -/// assert_eq!(f64::INFINITY.as_u256(), U256::MAX); -/// assert_eq!(2.0f64.powi(257).as_u256(), U256::MAX); -/// assert_eq!(f64::NAN.as_u256(), 0); -/// ``` -pub trait AsU256 { - /// Perform an `as` conversion to a [`U256`]. - /// - /// [`U256`]: struct.U256.html - #[allow(clippy::wrong_self_convention)] - fn as_u256(self) -> U256; -} - -impl AsU256 for U256 { - #[inline] - fn as_u256(self) -> U256 { - self - } -} - -impl AsU256 for I256 { - #[inline] - fn as_u256(self) -> U256 { - I256::as_u256(self) - } -} - -macro_rules! impl_as_u256 { - ($($t:ty),* $(,)?) => {$( - impl AsU256 for $t { - #[inline] - fn as_u256(self) -> U256 { - #[allow(unused_comparisons)] - let hi = if self >= 0 { 0 } else { !0 }; - U256::from_words(hi, self as _) - } - } - )*}; -} - -impl_as_u256! { - i8, i16, i32, i64, i128, - u8, u16, u32, u64, u128, - isize, usize, -} - -impl AsU256 for bool { - #[inline] - fn as_u256(self) -> U256 { - U256::new(self as _) - } -} - -macro_rules! impl_as_u256_float { - ($($t:ty [$b:ty]),* $(,)?) => {$( - impl AsU256 for $t { - #[inline] - fn as_u256(self) -> U256 { - // The conversion follows roughly the same rules as converting - // `f64` to other primitive integer types: - // - `NaN` => `0` - // - `(-∞, 0]` => `0` - // - `(0, U256::MAX]` => `value as U256` - // - `(U256::MAX, +∞)` => `U256::MAX` - - const M: $b = (<$t>::MANTISSA_DIGITS - 1) as _; - const MAN_MASK: $b = !(!0 << M); - const MAN_ONE: $b = 1 << M; - const EXP_MASK: $b = !0 >> <$t>::MANTISSA_DIGITS; - const EXP_OFFSET: $b = EXP_MASK / 2; - - if self >= 1.0 { - let bits = self.to_bits(); - let exponent = ((bits >> M) & EXP_MASK) - EXP_OFFSET; - let mantissa = (bits & MAN_MASK) | MAN_ONE; - if exponent <= M { - U256::from(mantissa >> (M - exponent)) - } else if exponent < 256 { - U256::from(mantissa) << (exponent - M) - } else { - U256::MAX - } - } else { - U256::ZERO - } - } - } - )*}; -} - -impl_as_u256_float! { - f32[u32], f64[u64], -} - -macro_rules! impl_try_into { - ($($t:ty),* $(,)?) => {$( - impl TryFrom for $t { - type Error = TryFromIntError; - - #[inline] - fn try_from(x: U256) -> Result { - if x <= <$t>::MAX.as_u256() { - Ok(*x.low() as _) - } else { - Err(tfie()) - } - } - } - )*}; -} - -impl_try_into! { - i8, i16, i32, i64, i128, - u8, u16, u32, u64, u128, - isize, usize, -} - -macro_rules! impl_into_float { - ($($t:ty => $f:ident),* $(,)?) => {$( - impl From for $t { - #[inline] - fn from(x: U256) -> $t { - x.$f() - } - } - )*}; -} - -impl_into_float! { - f32 => as_f32, f64 => as_f64, -} diff --git a/Contract/ethnum-patch/src/uint/fmt.rs b/Contract/ethnum-patch/src/uint/fmt.rs deleted file mode 100644 index aa8bf9e..0000000 --- a/Contract/ethnum-patch/src/uint/fmt.rs +++ /dev/null @@ -1,51 +0,0 @@ -//! Module implementing formatting for `U256` type. - -use crate::uint::U256; - -impl_fmt! { - impl Fmt for U256; -} - -#[cfg(test)] -mod tests { - use super::*; - use alloc::format; - - #[test] - fn debug() { - assert_eq!( - format!("{:?}", U256::MAX), - "115792089237316195423570985008687907853269984665640564039457584007913129639935", - ); - assert_eq!( - format!("{:x?}", U256::MAX), - "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - ); - assert_eq!( - format!("{:#X?}", U256::MAX), - "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", - ); - } - - #[test] - fn display() { - assert_eq!( - format!("{}", U256::MAX), - "115792089237316195423570985008687907853269984665640564039457584007913129639935", - ); - } - - #[test] - fn radix() { - assert_eq!(format!("{:b}", U256::new(42)), "101010"); - assert_eq!(format!("{:o}", U256::new(42)), "52"); - assert_eq!(format!("{:x}", U256::new(42)), "2a"); - } - - #[test] - fn exp() { - assert_eq!(format!("{:e}", U256::new(42)), "4.2e1"); - assert_eq!(format!("{:e}", U256::new(10).pow(77)), "1e77"); - assert_eq!(format!("{:E}", U256::new(10).pow(39) * 1337), "1.337E42"); - } -} diff --git a/Contract/ethnum-patch/src/uint/iter.rs b/Contract/ethnum-patch/src/uint/iter.rs deleted file mode 100644 index f2e2f14..0000000 --- a/Contract/ethnum-patch/src/uint/iter.rs +++ /dev/null @@ -1,7 +0,0 @@ -//! Module contains iterator specific trait implementations. - -use super::U256; - -impl_iter! { - impl Iter for U256; -} diff --git a/Contract/ethnum-patch/src/uint/ops.rs b/Contract/ethnum-patch/src/uint/ops.rs deleted file mode 100644 index cbfbfe7..0000000 --- a/Contract/ethnum-patch/src/uint/ops.rs +++ /dev/null @@ -1,305 +0,0 @@ -//! Module `core::ops` trait implementations. -//! -//! Trait implementations for `i128` are also provided to allow notation such -//! as: -//! -//! ``` -//! # use ethnum::U256; -//! -//! let a = 1 + U256::ONE; -//! let b = U256::ONE + 1; -//! dbg!(a, b); -//! ``` - -use super::U256; -use crate::intrinsics::signed::*; - -impl_ops! { - for U256 | u128 { - add => uadd2, uadd3, uaddc; - mul => umul2, umul3, umulc; - sub => usub2, usub3, usubc; - - div => udiv2, udiv3; - rem => urem2, urem3; - - shl => ushl2, ushl3; - shr => ushr2, ushr3; - } -} - -#[cfg(test)] -mod tests { - use super::*; - use core::ops::*; - - #[test] - fn trait_implementations() { - trait Implements {} - impl Implements for U256 {} - impl Implements for &'_ U256 {} - - fn assert_ops() - where - for<'a> T: Implements - + Add<&'a u128> - + Add<&'a U256> - + Add - + Add - + AddAssign<&'a u128> - + AddAssign<&'a U256> - + AddAssign - + AddAssign - + BitAnd<&'a u128> - + BitAnd<&'a U256> - + BitAnd - + BitAnd - + BitAndAssign<&'a u128> - + BitAndAssign<&'a U256> - + BitAndAssign - + BitAndAssign - + BitOr<&'a u128> - + BitOr<&'a U256> - + BitOr - + BitOr - + BitOrAssign<&'a u128> - + BitOrAssign<&'a U256> - + BitOrAssign - + BitOrAssign - + BitXor<&'a u128> - + BitXor<&'a U256> - + BitXor - + BitXor - + BitXorAssign<&'a u128> - + BitXorAssign<&'a U256> - + BitXorAssign - + BitXorAssign - + Div<&'a u128> - + Div<&'a U256> - + Div - + Div - + DivAssign<&'a u128> - + DivAssign<&'a U256> - + DivAssign - + DivAssign - + Mul<&'a u128> - + Mul<&'a U256> - + Mul - + Mul - + MulAssign<&'a u128> - + MulAssign<&'a U256> - + MulAssign - + MulAssign - + Not - + Rem<&'a u128> - + Rem<&'a U256> - + Rem - + Rem - + RemAssign<&'a u128> - + RemAssign<&'a U256> - + RemAssign - + RemAssign - + Shl<&'a i128> - + Shl<&'a i16> - + Shl<&'a i32> - + Shl<&'a i64> - + Shl<&'a i8> - + Shl<&'a isize> - + Shl<&'a u128> - + Shl<&'a u16> - + Shl<&'a U256> - + Shl<&'a u32> - + Shl<&'a u64> - + Shl<&'a u8> - + Shl<&'a usize> - + Shl - + Shl - + Shl - + Shl - + Shl - + Shl - + Shl - + Shl - + Shl - + Shl - + Shl - + Shl - + Shl - + ShlAssign<&'a i128> - + ShlAssign<&'a i16> - + ShlAssign<&'a i32> - + ShlAssign<&'a i64> - + ShlAssign<&'a i8> - + ShlAssign<&'a isize> - + ShlAssign<&'a u128> - + ShlAssign<&'a u16> - + ShlAssign<&'a U256> - + ShlAssign<&'a u32> - + ShlAssign<&'a u64> - + ShlAssign<&'a u8> - + ShlAssign<&'a usize> - + ShlAssign - + ShlAssign - + ShlAssign - + ShlAssign - + ShlAssign - + ShlAssign - + ShlAssign - + ShlAssign - + ShlAssign - + ShlAssign - + ShlAssign - + ShlAssign - + ShlAssign - + Shr<&'a i128> - + Shr<&'a i16> - + Shr<&'a i32> - + Shr<&'a i64> - + Shr<&'a i8> - + Shr<&'a isize> - + Shr<&'a u128> - + Shr<&'a u16> - + Shr<&'a U256> - + Shr<&'a u32> - + Shr<&'a u64> - + Shr<&'a u8> - + Shr<&'a usize> - + Shr - + Shr - + Shr - + Shr - + Shr - + Shr - + Shr - + Shr - + Shr - + Shr - + Shr - + Shr - + Shr - + ShrAssign<&'a i128> - + ShrAssign<&'a i16> - + ShrAssign<&'a i32> - + ShrAssign<&'a i64> - + ShrAssign<&'a i8> - + ShrAssign<&'a isize> - + ShrAssign<&'a u128> - + ShrAssign<&'a u16> - + ShrAssign<&'a U256> - + ShrAssign<&'a u32> - + ShrAssign<&'a u64> - + ShrAssign<&'a u8> - + ShrAssign<&'a usize> - + ShrAssign - + ShrAssign - + ShrAssign - + ShrAssign - + ShrAssign - + ShrAssign - + ShrAssign - + ShrAssign - + ShrAssign - + ShrAssign - + ShrAssign - + ShrAssign - + ShrAssign - + Sub<&'a u128> - + Sub<&'a U256> - + Sub - + Sub - + SubAssign<&'a u128> - + SubAssign<&'a U256> - + SubAssign - + SubAssign, - for<'a> &'a T: Implements - + Add<&'a u128> - + Add<&'a U256> - + Add - + Add - + BitAnd<&'a u128> - + BitAnd<&'a U256> - + BitAnd - + BitAnd - + BitOr<&'a u128> - + BitOr<&'a U256> - + BitOr - + BitOr - + BitXor<&'a u128> - + BitXor<&'a U256> - + BitXor - + BitXor - + Div<&'a u128> - + Div<&'a U256> - + Div - + Div - + Mul<&'a u128> - + Mul<&'a U256> - + Mul - + Mul - + Not - + Rem<&'a u128> - + Rem<&'a U256> - + Rem - + Rem - + Shl<&'a i128> - + Shl<&'a i16> - + Shl<&'a i32> - + Shl<&'a i64> - + Shl<&'a i8> - + Shl<&'a isize> - + Shl<&'a u128> - + Shl<&'a u16> - + Shl<&'a U256> - + Shl<&'a u32> - + Shl<&'a u64> - + Shl<&'a u8> - + Shl<&'a usize> - + Shl - + Shl - + Shl - + Shl - + Shl - + Shl - + Shl - + Shl - + Shl - + Shl - + Shl - + Shl - + Shl - + Shr<&'a i128> - + Shr<&'a i16> - + Shr<&'a i32> - + Shr<&'a i64> - + Shr<&'a i8> - + Shr<&'a isize> - + Shr<&'a u128> - + Shr<&'a u16> - + Shr<&'a U256> - + Shr<&'a u32> - + Shr<&'a u64> - + Shr<&'a u8> - + Shr<&'a usize> - + Shr - + Shr - + Shr - + Shr - + Shr - + Shr - + Shr - + Shr - + Shr - + Shr - + Shr - + Shr - + Shr - + Sub<&'a u128> - + Sub<&'a U256> - + Sub - + Sub, - { - } - - assert_ops::(); - } -} diff --git a/Contract/ethnum-patch/src/uint/parse.rs b/Contract/ethnum-patch/src/uint/parse.rs deleted file mode 100644 index 3c4dcbe..0000000 --- a/Contract/ethnum-patch/src/uint/parse.rs +++ /dev/null @@ -1,115 +0,0 @@ -//! Module implementing parsing for `U256` type. - -use crate::uint::U256; - -impl_from_str! { - impl FromStr for U256; -} - -pub const fn const_from_str_prefixed(src: &str) -> U256 { - assert!(!src.is_empty(), "empty string"); - - let bytes = src.as_bytes(); - let start = bytes[0] == b'+'; - crate::parse::const_from_str_prefixed(bytes, start as _) -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::parse::from_str_radix; - use core::num::IntErrorKind; - - #[test] - fn from_str() { - assert_eq!("42".parse::().unwrap(), 42); - } - - #[test] - fn from_str_prefixed() { - assert_eq!(from_str_radix::("0b101", 2, Some("0b")).unwrap(), 5); - assert_eq!(from_str_radix::("0xf", 16, Some("0x")).unwrap(), 15); - } - - #[test] - fn from_str_errors() { - assert_eq!( - from_str_radix::("", 2, None).unwrap_err().kind(), - &IntErrorKind::Empty, - ); - assert_eq!( - from_str_radix::("?", 2, None).unwrap_err().kind(), - &IntErrorKind::InvalidDigit, - ); - assert_eq!( - from_str_radix::("1", 16, Some("0x")) - .unwrap_err() - .kind(), - &IntErrorKind::InvalidDigit, - ); - assert_eq!( - from_str_radix::("-1", 10, None).unwrap_err().kind(), - &IntErrorKind::InvalidDigit, - ); - assert_eq!( - from_str_radix::( - "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz", - 36, - None - ) - .unwrap_err() - .kind(), - &IntErrorKind::PosOverflow, - ); - } - - #[test] - fn const_parse() { - assert_eq!(const_from_str_prefixed("+0b1101"), 0b1101); - assert_eq!(const_from_str_prefixed("0o777"), 0o777); - assert_eq!(const_from_str_prefixed("+0x1f"), 0x1f); - assert_eq!(const_from_str_prefixed("42"), 42); - - assert_eq!( - const_from_str_prefixed( - "0xffff_ffff_ffff_ffff_ffff_ffff_ffff_fffe\ - baae_dce6_af48_a03b_bfd2_5e8c_d036_4141" - ), - U256::from_words( - 0xffff_ffff_ffff_ffff_ffff_ffff_ffff_fffe, - 0xbaae_dce6_af48_a03b_bfd2_5e8c_d036_4141, - ), - ); - - assert_eq!( - const_from_str_prefixed( - "0x0000_0000_0000_0000_0000_0000_0000_0000\ - 0000_0000_0000_0000_0000_0000_0000_0000" - ), - U256::MIN, - ); - assert_eq!( - const_from_str_prefixed( - "+0xffff_ffff_ffff_ffff_ffff_ffff_ffff_ffff\ - ffff_ffff_ffff_ffff_ffff_ffff_ffff_ffff" - ), - U256::MAX, - ); - } - - #[test] - #[should_panic] - fn const_parse_overflow() { - const_from_str_prefixed( - "0x1\ - 0000_0000_0000_0000_0000_0000_0000_0000\ - 0000_0000_0000_0000_0000_0000_0000_0000", - ); - } - - #[test] - #[should_panic] - fn const_parse_invalid() { - const_from_str_prefixed("invalid"); - } -} diff --git a/Contract/vault/src/lib.rs b/Contract/vault/src/lib.rs index b5c828d..9bb158f 100644 --- a/Contract/vault/src/lib.rs +++ b/Contract/vault/src/lib.rs @@ -310,11 +310,6 @@ impl VaultContract { StorageHelper::touch_vault(&env, &balances_key); env.events().publish( - (vault_id.0.clone(), from, amount), - (DepositMade { - vault_id: vault_id.0.clone(), - depositor: from, - asset: metadata.asset.symbol, (DepositMade::topic(&env), vault_id.0.clone()), DepositMade { vault_id: vault_id.0,