diff --git a/.travis.yml b/.travis.yml index d4704bc..829275e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,6 +8,5 @@ matrix: - rust: nightly script: - cargo test -p ethereum-types --no-default-features --release - - cargo test -p tests --release env: - RUST_LOG=quickcheck diff --git a/Cargo.toml b/Cargo.toml index 3a169fe..d7120e9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,2 +1,2 @@ [workspace] -members = ["uint", "fixed-hash", "ethereum-types", "tests", "ethbloom", "no-std-tests"] +members = ["ethereum-types", "ethbloom"] diff --git a/ethbloom/Cargo.toml b/ethbloom/Cargo.toml index e131f58..a0dd0a0 100644 --- a/ethbloom/Cargo.toml +++ b/ethbloom/Cargo.toml @@ -11,7 +11,8 @@ repository = "https://github.com/paritytech/primitives" [dependencies] tiny-keccak = "1.4" crunchy = { version = "0.1.6", features = ["limit_256"] } -fixed-hash = { version = "0.2.1", path = "../fixed-hash", default-features = false } +# TODO: remove `branch` when https://github.com/paritytech/parity-common/pull/12 lands +fixed-hash = { git = "https://github.com/paritytech/parity-common", branch = "add-fixed-hash", default_features = false } ethereum-types-serialize = { version = "0.2.1", path = "../serialize", optional = true } serde = { version = "1.0", optional = true } diff --git a/ethereum-types/Cargo.toml b/ethereum-types/Cargo.toml index b741f20..0794e7c 100644 --- a/ethereum-types/Cargo.toml +++ b/ethereum-types/Cargo.toml @@ -14,9 +14,12 @@ rustc_version = "0.2" crunchy = "0.1.5" ethbloom = { path = "../ethbloom", version = "0.5.0", default-features = false } ethereum-types-serialize = { version = "0.2.1", path = "../serialize", optional = true } -fixed-hash = { path = "../fixed-hash", version = "0.2" } +fixed-hash = { git = "https://github.com/paritytech/parity-common", default_features = false } serde = { version = "1.0", optional = true } -uint = { path = "../uint", version = "0.2.1", default-features = false } +uint = { git = "https://github.com/paritytech/parity-common", default_features = false } + +[dev-dependencies] +serde_json = "1.0" [features] default = ["std", "heapsizeof", "serialize"] diff --git a/ethereum-types/src/hash.rs b/ethereum-types/src/hash.rs index 00d7883..2203d62 100644 --- a/ethereum-types/src/hash.rs +++ b/ethereum-types/src/hash.rs @@ -118,3 +118,55 @@ impl<'a> From<&'a H160> for H256 { ret } } + +#[cfg(test)] +mod tests { + use super::{H160, H256}; + use serde_json as ser; + + #[test] + fn test_serialize_h160() { + let tests = vec![ + (H160::from(0), "0x0000000000000000000000000000000000000000"), + (H160::from(2), "0x0000000000000000000000000000000000000002"), + (H160::from(15), "0x000000000000000000000000000000000000000f"), + (H160::from(16), "0x0000000000000000000000000000000000000010"), + (H160::from(1_000), "0x00000000000000000000000000000000000003e8"), + (H160::from(100_000), "0x00000000000000000000000000000000000186a0"), + (H160::from(u64::max_value()), "0x000000000000000000000000ffffffffffffffff"), + ]; + + for (number, expected) in tests { + assert_eq!(format!("{:?}", expected), ser::to_string_pretty(&number).unwrap()); + assert_eq!(number, ser::from_str(&format!("{:?}", expected)).unwrap()); + } + } + + #[test] + fn test_serialize_h256() { + let tests = vec![ + (H256::from(0), "0x0000000000000000000000000000000000000000000000000000000000000000"), + (H256::from(2), "0x0000000000000000000000000000000000000000000000000000000000000002"), + (H256::from(15), "0x000000000000000000000000000000000000000000000000000000000000000f"), + (H256::from(16), "0x0000000000000000000000000000000000000000000000000000000000000010"), + (H256::from(1_000), "0x00000000000000000000000000000000000000000000000000000000000003e8"), + (H256::from(100_000), "0x00000000000000000000000000000000000000000000000000000000000186a0"), + (H256::from(u64::max_value()), "0x000000000000000000000000000000000000000000000000ffffffffffffffff"), + ]; + + for (number, expected) in tests { + assert_eq!(format!("{:?}", expected), ser::to_string_pretty(&number).unwrap()); + assert_eq!(number, ser::from_str(&format!("{:?}", expected)).unwrap()); + } + } + + #[test] + fn test_serialize_invalid() { + assert!(ser::from_str::("\"0x000000000000000000000000000000000000000000000000000000000000000\"").unwrap_err().is_data()); + assert!(ser::from_str::("\"0x000000000000000000000000000000000000000000000000000000000000000g\"").unwrap_err().is_data()); + assert!(ser::from_str::("\"0x00000000000000000000000000000000000000000000000000000000000000000\"").unwrap_err().is_data()); + assert!(ser::from_str::("\"\"").unwrap_err().is_data()); + assert!(ser::from_str::("\"0\"").unwrap_err().is_data()); + assert!(ser::from_str::("\"10\"").unwrap_err().is_data()); + } +} \ No newline at end of file diff --git a/ethereum-types/src/lib.rs b/ethereum-types/src/lib.rs index 2d44092..b9e6179 100644 --- a/ethereum-types/src/lib.rs +++ b/ethereum-types/src/lib.rs @@ -17,6 +17,9 @@ extern crate ethereum_types_serialize; #[cfg(feature="serialize")] extern crate serde; +#[cfg(test)] +extern crate serde_json; + mod hash; mod uint; diff --git a/ethereum-types/src/uint.rs b/ethereum-types/src/uint.rs index 8693372..d272ec4 100644 --- a/ethereum-types/src/uint.rs +++ b/ethereum-types/src/uint.rs @@ -359,3 +359,171 @@ impl From for [u8; 64] { arr } } + +#[cfg(test)] +mod tests { + use super::{U256, U512}; + use std::u64::MAX; + use serde_json as ser; + + macro_rules! test_serialize { + ($name: ident, $test_name: ident) => { + #[test] + fn $test_name() { + let tests = vec![ + ($name::from(0), "0x0"), + ($name::from(1), "0x1"), + ($name::from(2), "0x2"), + ($name::from(10), "0xa"), + ($name::from(15), "0xf"), + ($name::from(15), "0xf"), + ($name::from(16), "0x10"), + ($name::from(1_000), "0x3e8"), + ($name::from(100_000), "0x186a0"), + ($name::from(u64::max_value()), "0xffffffffffffffff"), + ($name::from(u64::max_value()) + 1, "0x10000000000000000"), + ]; + + for (number, expected) in tests { + assert_eq!(format!("{:?}", expected), ser::to_string_pretty(&number).unwrap()); + assert_eq!(number, ser::from_str(&format!("{:?}", expected)).unwrap()); + } + + // Invalid examples + assert!(ser::from_str::<$name>("\"0x\"").unwrap_err().is_data()); + assert!(ser::from_str::<$name>("\"0xg\"").unwrap_err().is_data()); + assert!(ser::from_str::<$name>("\"\"").unwrap_err().is_data()); + assert!(ser::from_str::<$name>("\"10\"").unwrap_err().is_data()); + assert!(ser::from_str::<$name>("\"0\"").unwrap_err().is_data()); + } + } + } + + test_serialize!(U256, test_u256); + test_serialize!(U512, test_u512); + + #[test] + fn test_serialize_large_values() { + assert_eq!( + ser::to_string_pretty(&!U256::zero()).unwrap(), + "\"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\"" + ); + assert!( + ser::from_str::("\"0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\"").unwrap_err().is_data() + ); + } + + #[test] + fn fixed_arrays_roundtrip() { + let raw: U256 = "7094875209347850239487502394881".into(); + let array: [u8; 32] = raw.into(); + let new_raw = array.into(); + + assert_eq!(raw, new_raw); + } + + #[test] + fn u256_multi_full_mul() { + let result = U256([0, 0, 0, 0]).full_mul(U256([0, 0, 0, 0])); + assert_eq!(U512([0, 0, 0, 0, 0, 0, 0, 0]), result); + + let result = U256([1, 0, 0, 0]).full_mul(U256([1, 0, 0, 0])); + assert_eq!(U512([1, 0, 0, 0, 0, 0, 0, 0]), result); + + let result = U256([5, 0, 0, 0]).full_mul(U256([5, 0, 0, 0])); + assert_eq!(U512([25, 0, 0, 0, 0, 0, 0, 0]), result); + + let result = U256([0, 5, 0, 0]).full_mul(U256([0, 5, 0, 0])); + assert_eq!(U512([0, 0, 25, 0, 0, 0, 0, 0]), result); + + let result = U256([0, 0, 0, 4]).full_mul(U256([4, 0, 0, 0])); + assert_eq!(U512([0, 0, 0, 16, 0, 0, 0, 0]), result); + + let result = U256([0, 0, 0, 5]).full_mul(U256([2, 0, 0, 0])); + assert_eq!(U512([0, 0, 0, 10, 0, 0, 0, 0]), result); + + let result = U256([0, 0, 2, 0]).full_mul(U256([0, 5, 0, 0])); + assert_eq!(U512([0, 0, 0, 10, 0, 0, 0, 0]), result); + + let result = U256([0, 3, 0, 0]).full_mul(U256([0, 0, 3, 0])); + assert_eq!(U512([0, 0, 0, 9, 0, 0, 0, 0]), result); + + let result = U256([0, 0, 8, 0]).full_mul(U256([0, 0, 6, 0])); + assert_eq!(U512([0, 0, 0, 0, 48, 0, 0, 0]), result); + + let result = U256([9, 0, 0, 0]).full_mul(U256([0, 3, 0, 0])); + assert_eq!(U512([0, 27, 0, 0, 0, 0, 0, 0]), result); + + let result = U256([MAX, 0, 0, 0]).full_mul(U256([MAX, 0, 0, 0])); + assert_eq!(U512([1, MAX-1, 0, 0, 0, 0, 0, 0]), result); + + let result = U256([0, MAX, 0, 0]).full_mul(U256([MAX, 0, 0, 0])); + assert_eq!(U512([0, 1, MAX-1, 0, 0, 0, 0, 0]), result); + + let result = U256([MAX, MAX, 0, 0]).full_mul(U256([MAX, 0, 0, 0])); + assert_eq!(U512([1, MAX, MAX-1, 0, 0, 0, 0, 0]), result); + + let result = U256([MAX, 0, 0, 0]).full_mul(U256([MAX, MAX, 0, 0])); + assert_eq!(U512([1, MAX, MAX-1, 0, 0, 0, 0, 0]), result); + + let result = U256([MAX, MAX, 0, 0]).full_mul(U256([MAX, MAX, 0, 0])); + assert_eq!(U512([1, 0, MAX-1, MAX, 0, 0, 0, 0]), result); + + let result = U256([MAX, 0, 0, 0]).full_mul(U256([MAX, MAX, MAX, 0])); + assert_eq!(U512([1, MAX, MAX, MAX-1, 0, 0, 0, 0]), result); + + let result = U256([MAX, MAX, MAX, 0]).full_mul(U256([MAX, 0, 0, 0])); + assert_eq!(U512([1, MAX, MAX, MAX-1, 0, 0, 0, 0]), result); + + let result = U256([MAX, 0, 0, 0]).full_mul(U256([MAX, MAX, MAX, MAX])); + assert_eq!(U512([1, MAX, MAX, MAX, MAX-1, 0, 0, 0]), result); + + let result = U256([MAX, MAX, MAX, MAX]).full_mul(U256([MAX, 0, 0, 0])); + assert_eq!(U512([1, MAX, MAX, MAX, MAX-1, 0, 0, 0]), result); + + let result = U256([MAX, MAX, MAX, 0]).full_mul(U256([MAX, MAX, 0, 0])); + assert_eq!(U512([1, 0, MAX, MAX-1, MAX, 0, 0, 0]), result); + + let result = U256([MAX, MAX, 0, 0]).full_mul(U256([MAX, MAX, MAX, 0])); + assert_eq!(U512([1, 0, MAX, MAX-1, MAX, 0, 0, 0]), result); + + let result = U256([MAX, MAX, MAX, MAX]).full_mul(U256([MAX, MAX, 0, 0])); + assert_eq!(U512([1, 0, MAX, MAX, MAX-1, MAX, 0, 0]), result); + + let result = U256([MAX, MAX, 0, 0]).full_mul(U256([MAX, MAX, MAX, MAX])); + assert_eq!(U512([1, 0, MAX, MAX, MAX-1, MAX, 0, 0]), result); + + let result = U256([MAX, MAX, MAX, 0]).full_mul(U256([MAX, MAX, MAX, 0])); + assert_eq!(U512([1, 0, 0, MAX-1, MAX, MAX, 0, 0]), result); + + let result = U256([MAX, MAX, MAX, 0]).full_mul(U256([MAX, MAX, MAX, MAX])); + assert_eq!(U512([1, 0, 0, MAX, MAX-1, MAX, MAX, 0]), result); + + let result = U256([MAX, MAX, MAX, MAX]).full_mul(U256([MAX, MAX, MAX, 0])); + assert_eq!(U512([1, 0, 0, MAX, MAX-1, MAX, MAX, 0]), result); + + let result = U256([MAX, MAX, MAX, MAX]).full_mul(U256([MAX, MAX, MAX, MAX])); + assert_eq!(U512([1, 0, 0, 0, MAX-1, MAX, MAX, MAX]), result); + + let result = U256([0, 0, 0, MAX]).full_mul(U256([0, 0, 0, MAX])); + assert_eq!(U512([0, 0, 0, 0, 0, 0, 1, MAX-1]), result); + + let result = U256([1, 0, 0, 0]).full_mul(U256([0, 0, 0, MAX])); + assert_eq!(U512([0, 0, 0, MAX, 0, 0, 0, 0]), result); + + let result = U256([1, 2, 3, 4]).full_mul(U256([5, 0, 0, 0])); + assert_eq!(U512([5, 10, 15, 20, 0, 0, 0, 0]), result); + + let result = U256([1, 2, 3, 4]).full_mul(U256([0, 6, 0, 0])); + assert_eq!(U512([0, 6, 12, 18, 24, 0, 0, 0]), result); + + let result = U256([1, 2, 3, 4]).full_mul(U256([0, 0, 7, 0])); + assert_eq!(U512([0, 0, 7, 14, 21, 28, 0, 0]), result); + + let result = U256([1, 2, 3, 4]).full_mul(U256([0, 0, 0, 8])); + assert_eq!(U512([0, 0, 0, 8, 16, 24, 32, 0]), result); + + let result = U256([1, 2, 3, 4]).full_mul(U256([5, 6, 7, 8])); + assert_eq!(U512([5, 16, 34, 60, 61, 52, 32, 0]), result); + } +} \ No newline at end of file diff --git a/fixed-hash/Cargo.toml b/fixed-hash/Cargo.toml deleted file mode 100644 index 0fe7bfa..0000000 --- a/fixed-hash/Cargo.toml +++ /dev/null @@ -1,22 +0,0 @@ -[package] -name = "fixed-hash" -version = "0.2.1" -authors = ["Parity Technologies "] -license = "MIT" -homepage = "https://github.com/paritytech/primitives" -description = "Fixed-size hashes" - -[dependencies] -heapsize = { version = "0.4", optional = true } -rand = { version = "0.4", optional = true } -rustc-hex = { version = "1.0", optional = true } -quickcheck = { version = "0.6", optional = true } - -[target.'cfg(not(target_os = "unknown"))'.dependencies] -libc = { version = "0.2", optional = true, default-features = false } - -[features] -default = ["libc"] -std = ["rustc-hex", "rand"] -heapsizeof = ["heapsize"] -impl_quickcheck_arbitrary = ["quickcheck"] diff --git a/fixed-hash/src/hash.rs b/fixed-hash/src/hash.rs deleted file mode 100644 index b5baf41..0000000 --- a/fixed-hash/src/hash.rs +++ /dev/null @@ -1,491 +0,0 @@ -// Copyright 2015-2017 Parity Technologies -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -/// Return `s` without the `0x` at the beginning of it, if any. -pub fn clean_0x(s: &str) -> &str { - if s.starts_with("0x") { - &s[2..] - } else { - s - } -} - -#[macro_export] -macro_rules! construct_hash { - ($from: ident, $size: expr) => { - #[repr(C)] - /// Unformatted binary data of fixed length. - pub struct $from (pub [u8; $size]); - - - impl From<[u8; $size]> for $from { - fn from(bytes: [u8; $size]) -> Self { - $from(bytes) - } - } - - impl From<$from> for [u8; $size] { - fn from(s: $from) -> Self { - s.0 - } - } - - impl ::core::ops::Deref for $from { - type Target = [u8]; - - #[inline] - fn deref(&self) -> &[u8] { - &self.0 - } - } - - impl AsRef<[u8]> for $from { - #[inline] - fn as_ref(&self) -> &[u8] { - &self.0 - } - } - - impl AsMut<[u8]> for $from { - #[inline] - fn as_mut(&mut self) -> &mut [u8] { - &mut self.0 - } - } - - impl AsRef<$from> for $from { - #[inline] - fn as_ref(&self) -> &$from { - &self - } - } - - impl ::core::ops::DerefMut for $from { - #[inline] - fn deref_mut(&mut self) -> &mut [u8] { - &mut self.0 - } - } - - impl $from { - /// Create a new, zero-initialised, instance. - pub fn new() -> $from { - $from([0; $size]) - } - - /// Synonym for `new()`. Prefer to new as it's more readable. - pub fn zero() -> $from { - $from([0; $size]) - } - - /// Get the size of this object in bytes. - pub fn len() -> usize { - $size - } - - #[inline] - /// Assign self to be of the same value as a slice of bytes of length `len()`. - pub fn clone_from_slice(&mut self, src: &[u8]) -> usize { - let min = ::core::cmp::min($size, src.len()); - self.0[..min].copy_from_slice(&src[..min]); - min - } - - /// Convert a slice of bytes of length `len()` to an instance of this type. - pub fn from_slice(src: &[u8]) -> Self { - let mut r = Self::new(); - r.clone_from_slice(src); - r - } - - /// Copy the data of this object into some mutable slice of length `len()`. - pub fn copy_to(&self, dest: &mut[u8]) { - let min = ::core::cmp::min($size, dest.len()); - dest[..min].copy_from_slice(&self.0[..min]); - } - - /// Returns `true` if all bits set in `b` are also set in `self`. - pub fn contains<'a>(&'a self, b: &'a Self) -> bool { - &(b & self) == b - } - - /// Returns `true` if no bits are set. - pub fn is_zero(&self) -> bool { - self.eq(&Self::new()) - } - - /// Returns the lowest 8 bytes interpreted as a BigEndian integer. - pub fn low_u64(&self) -> u64 { - let mut ret = 0u64; - for i in 0..::core::cmp::min($size, 8) { - ret |= (self.0[$size - 1 - i] as u64) << (i * 8); - } - ret - } - - impl_std_for_hash_internals!($from, $size); - } - - impl ::core::fmt::Debug for $from { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{:#x}", self) - } - } - - impl ::core::fmt::Display for $from { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "0x")?; - for i in &self.0[0..2] { - write!(f, "{:02x}", i)?; - } - write!(f, "…")?; - for i in &self.0[$size - 2..$size] { - write!(f, "{:02x}", i)?; - } - Ok(()) - } - } - - impl ::core::fmt::LowerHex for $from { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - if f.alternate() { - write!(f, "0x"); - } - for i in &self.0[..] { - write!(f, "{:02x}", i)?; - } - Ok(()) - } - } - - impl Copy for $from {} - #[cfg_attr(feature="dev", allow(expl_impl_clone_on_copy))] - impl Clone for $from { - fn clone(&self) -> $from { - let mut ret = $from::new(); - ret.0.copy_from_slice(&self.0); - ret - } - } - - impl Eq for $from {} - - impl PartialOrd for $from { - fn partial_cmp(&self, other: &Self) -> Option<::core::cmp::Ordering> { - Some(self.cmp(other)) - } - } - - impl ::core::hash::Hash for $from { - fn hash(&self, state: &mut H) where H: ::core::hash::Hasher { - state.write(&self.0); - state.finish(); - } - } - - impl ::core::ops::Index for $from { - type Output = u8; - - fn index(&self, index: usize) -> &u8 { - &self.0[index] - } - } - impl ::core::ops::IndexMut for $from { - fn index_mut(&mut self, index: usize) -> &mut u8 { - &mut self.0[index] - } - } - impl ::core::ops::Index<::core::ops::Range> for $from { - type Output = [u8]; - - fn index(&self, index: ::core::ops::Range) -> &[u8] { - &self.0[index] - } - } - impl ::core::ops::IndexMut<::core::ops::Range> for $from { - fn index_mut(&mut self, index: ::core::ops::Range) -> &mut [u8] { - &mut self.0[index] - } - } - impl ::core::ops::Index<::core::ops::RangeFull> for $from { - type Output = [u8]; - - fn index(&self, _index: ::core::ops::RangeFull) -> &[u8] { - &self.0 - } - } - impl ::core::ops::IndexMut<::core::ops::RangeFull> for $from { - fn index_mut(&mut self, _index: ::core::ops::RangeFull) -> &mut [u8] { - &mut self.0 - } - } - - /// `BitOr` on references - impl<'a> ::core::ops::BitOr for &'a $from { - type Output = $from; - - fn bitor(self, rhs: Self) -> Self::Output { - let mut ret: $from = $from::default(); - for i in 0..$size { - ret.0[i] = self.0[i] | rhs.0[i]; - } - ret - } - } - - /// Moving `BitOr` - impl ::core::ops::BitOr for $from { - type Output = $from; - - fn bitor(self, rhs: Self) -> Self::Output { - &self | &rhs - } - } - - /// `BitAnd` on references - impl <'a> ::core::ops::BitAnd for &'a $from { - type Output = $from; - - fn bitand(self, rhs: Self) -> Self::Output { - let mut ret: $from = $from::default(); - for i in 0..$size { - ret.0[i] = self.0[i] & rhs.0[i]; - } - ret - } - } - - /// Moving `BitAnd` - impl ::core::ops::BitAnd for $from { - type Output = $from; - - fn bitand(self, rhs: Self) -> Self::Output { - &self & &rhs - } - } - - /// `BitXor` on references - impl <'a> ::core::ops::BitXor for &'a $from { - type Output = $from; - - fn bitxor(self, rhs: Self) -> Self::Output { - let mut ret: $from = $from::default(); - for i in 0..$size { - ret.0[i] = self.0[i] ^ rhs.0[i]; - } - ret - } - } - - /// Moving `BitXor` - impl ::core::ops::BitXor for $from { - type Output = $from; - - fn bitxor(self, rhs: Self) -> Self::Output { - &self ^ &rhs - } - } - - impl Default for $from { - fn default() -> Self { $from::new() } - } - - impl From for $from { - fn from(mut value: u64) -> $from { - let mut ret = $from::new(); - for i in 0..8 { - if i < $size { - ret.0[$size - i - 1] = (value & 0xff) as u8; - value >>= 8; - } - } - ret - } - } - - impl<'a> From<&'a [u8]> for $from { - fn from(s: &'a [u8]) -> $from { - $from::from_slice(s) - } - } - - impl_std_for_hash!($from, $size); - impl_heapsize_for_hash!($from); - impl_libc_for_hash!($from, $size); - impl_quickcheck_arbitrary_for_hash!($from, $size); - } -} - -#[cfg(all(feature="heapsizeof", feature="libc", not(target_os = "unknown")))] -#[macro_export] -#[doc(hidden)] -macro_rules! impl_heapsize_for_hash { - ($name: ident) => { - impl $crate::heapsize::HeapSizeOf for $name { - fn heap_size_of_children(&self) -> usize { - 0 - } - } - } -} - -#[cfg(any(not(feature="heapsizeof"), not(feature="libc"), target_os = "unknown"))] -#[macro_export] -#[doc(hidden)] -macro_rules! impl_heapsize_for_hash { - ($name: ident) => {} -} - -#[cfg(feature="std")] -#[macro_export] -#[doc(hidden)] -macro_rules! impl_std_for_hash { - ($from: ident, $size: tt) => { - impl $from { - /// Get a hex representation. - #[deprecated(note="Use LowerHex or Debug formatting instead.")] - pub fn hex(&self) -> String { - format!("{:?}", self) - } - } - - impl $crate::rand::Rand for $from { - fn rand(r: &mut R) -> Self { - let mut hash = $from::new(); - r.fill_bytes(&mut hash.0); - hash - } - } - - impl ::core::str::FromStr for $from { - type Err = $crate::rustc_hex::FromHexError; - - fn from_str(s: &str) -> Result<$from, $crate::rustc_hex::FromHexError> { - use $crate::rustc_hex::FromHex; - let a = s.from_hex()?; - if a.len() != $size { - return Err($crate::rustc_hex::FromHexError::InvalidHexLength); - } - - let mut ret = [0; $size]; - ret.copy_from_slice(&a); - Ok($from(ret)) - } - } - - impl From<&'static str> for $from { - fn from(s: &'static str) -> $from { - let s = $crate::clean_0x(s); - if s.len() % 2 == 1 { - ("0".to_owned() + s).parse().unwrap() - } else { - s.parse().unwrap() - } - } - } - } -} - - -#[cfg(not(feature="std"))] -#[macro_export] -#[doc(hidden)] -macro_rules! impl_std_for_hash { - ($from: ident, $size: tt) => {} -} - - -#[cfg(feature="std")] -#[macro_export] -#[doc(hidden)] -macro_rules! impl_std_for_hash_internals { - ($from: ident, $size: tt) => { - /// Create a new, cryptographically random, instance. - pub fn random() -> $from { - let mut hash = $from::new(); - hash.randomize(); - hash - } - - /// Assign self have a cryptographically random value. - pub fn randomize(&mut self) { - let mut rng = $crate::rand::OsRng::new().unwrap(); - *self = $crate::rand::Rand::rand(&mut rng); - } - } -} - -#[cfg(not(feature="std"))] -#[macro_export] -#[doc(hidden)] -macro_rules! impl_std_for_hash_internals { - ($from: ident, $size: tt) => {} -} - -#[cfg(all(feature="libc", not(target_os = "unknown")))] -#[macro_export] -#[doc(hidden)] -macro_rules! impl_libc_for_hash { - ($from: ident, $size: expr) => { - impl PartialEq for $from { - fn eq(&self, other: &Self) -> bool { - unsafe { $crate::libc::memcmp(self.0.as_ptr() as *const $crate::libc::c_void, other.0.as_ptr() as *const $crate::libc::c_void, $size) == 0 } - } - } - - impl Ord for $from { - fn cmp(&self, other: &Self) -> ::core::cmp::Ordering { - let r = unsafe { $crate::libc::memcmp(self.0.as_ptr() as *const $crate::libc::c_void, other.0.as_ptr() as *const $crate::libc::c_void, $size) }; - if r < 0 { return ::core::cmp::Ordering::Less } - if r > 0 { return ::core::cmp::Ordering::Greater } - return ::core::cmp::Ordering::Equal; - } - } - } -} - -#[cfg(any(not(feature="libc"), target_os = "unknown"))] -#[macro_export] -#[doc(hidden)] -macro_rules! impl_libc_for_hash { - ($from: ident, $size: expr) => { - impl PartialEq for $from { - fn eq(&self, other: &Self) -> bool { - &self.0[..] == &other.0[..] - } - } - - impl Ord for $from { - fn cmp(&self, other: &Self) -> ::core::cmp::Ordering { - self.0[..].cmp(&other.0[..]) - } - } - } -} - -#[cfg(feature="impl_quickcheck_arbitrary")] -#[macro_export] -#[doc(hidden)] -macro_rules! impl_quickcheck_arbitrary_for_hash { - ($name: ty, $n_bytes: tt) => { - impl $crate::quickcheck::Arbitrary for $name { - fn arbitrary(g: &mut G) -> Self { - let mut res = [0u8; $n_bytes]; - g.fill_bytes(&mut res[..$n_bytes]); - res.as_ref().into() - } - } - } -} - -#[cfg(not(feature="impl_quickcheck_arbitrary"))] -#[macro_export] -#[doc(hidden)] -macro_rules! impl_quickcheck_arbitrary_for_hash { - ($name: ty, $n_bytes: tt) => {} -} diff --git a/fixed-hash/src/lib.rs b/fixed-hash/src/lib.rs deleted file mode 100644 index 50d5892..0000000 --- a/fixed-hash/src/lib.rs +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2015-2017 Parity Technologies -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#![cfg_attr(not(feature = "std"), no_std)] - -#[cfg(all(feature="libc", not(target_os = "unknown")))] -#[doc(hidden)] -pub extern crate libc; - -#[cfg(not(feature="libc"))] -#[doc(hidden)] -pub mod libc { } - -#[cfg(feature="heapsizeof")] -#[doc(hidden)] -pub extern crate heapsize; - -#[cfg(feature="std")] -#[doc(hidden)] -pub extern crate core; - -#[cfg(feature="std")] -#[doc(hidden)] -pub extern crate rustc_hex; - -#[cfg(feature="std")] -#[doc(hidden)] -pub extern crate rand; - -#[cfg(feature="impl_quickcheck_arbitrary")] -#[doc(hidden)] -pub extern crate quickcheck; - -mod hash; -pub use hash::*; diff --git a/tests/Cargo.toml b/tests/Cargo.toml deleted file mode 100644 index 3f75929..0000000 --- a/tests/Cargo.toml +++ /dev/null @@ -1,17 +0,0 @@ -[package] -name = "tests" -version = "0.1.0" -authors = ["Parity Technologies "] - -[build-dependencies] -rustc_version = "0.2" - -[dependencies] -crunchy = "0.1.5" -ethereum-types = { version = "0.3.1", path ="../ethereum-types", features = ["std", "heapsizeof"] } -quickcheck = "0.6" -serde_json = "1.0" -uint = { path = "../uint" , features = ["impl_quickcheck_arbitrary"] } - -[features] -use_asm = ["uint/use_asm", "ethereum-types/use_asm"] diff --git a/tests/src/hash_tests.rs b/tests/src/hash_tests.rs deleted file mode 100644 index b21b560..0000000 --- a/tests/src/hash_tests.rs +++ /dev/null @@ -1,21 +0,0 @@ -use ethereum_types::{U128, H128}; - -#[test] -fn should_format_and_debug_correctly() { - let test = |x: usize, hex: &'static str, display: &'static str| { - let hash = H128::from(U128::from(x)); - assert_eq!(format!("{}", hash), format!("0x{}", display)); - assert_eq!(format!("{:?}", hash), format!("0x{}", hex)); - assert_eq!(format!("{:x}", hash), hex); - assert_eq!(format!("{:#x}", hash), format!("0x{}", hex)); - }; - - test(0x1, "00000000000000000000000000000001", "0000…0001"); - test(0xf, "0000000000000000000000000000000f", "0000…000f"); - test(0x10, "00000000000000000000000000000010", "0000…0010"); - test(0xff, "000000000000000000000000000000ff", "0000…00ff"); - test(0x100, "00000000000000000000000000000100", "0000…0100"); - test(0xfff, "00000000000000000000000000000fff", "0000…0fff"); - test(0x1000, "00000000000000000000000000001000", "0000…1000"); -} - diff --git a/tests/src/lib.rs b/tests/src/lib.rs deleted file mode 100644 index 374be64..0000000 --- a/tests/src/lib.rs +++ /dev/null @@ -1,21 +0,0 @@ -extern crate core; -extern crate ethereum_types; - -#[cfg(test)] -#[macro_use] -extern crate uint; -#[cfg(test)] -#[macro_use] -extern crate crunchy; -#[cfg(test)] -#[macro_use] -extern crate quickcheck; -#[cfg(test)] -extern crate serde_json; - -#[cfg(test)] -pub mod hash_tests; -#[cfg(test)] -pub mod uint_tests; -#[cfg(test)] -pub mod serialization; diff --git a/tests/src/serialization.rs b/tests/src/serialization.rs deleted file mode 100644 index 531a20a..0000000 --- a/tests/src/serialization.rs +++ /dev/null @@ -1,95 +0,0 @@ -use ethereum_types::{U256, U512, H160, H256}; -use serde_json as ser; - -macro_rules! test { - ($name: ident, $test_name: ident) => { - #[test] - fn $test_name() { - let tests = vec![ - ($name::from(0), "0x0"), - ($name::from(1), "0x1"), - ($name::from(2), "0x2"), - ($name::from(10), "0xa"), - ($name::from(15), "0xf"), - ($name::from(15), "0xf"), - ($name::from(16), "0x10"), - ($name::from(1_000), "0x3e8"), - ($name::from(100_000), "0x186a0"), - ($name::from(u64::max_value()), "0xffffffffffffffff"), - ($name::from(u64::max_value()) + 1, "0x10000000000000000"), - ]; - - for (number, expected) in tests { - assert_eq!(format!("{:?}", expected), ser::to_string_pretty(&number).unwrap()); - assert_eq!(number, ser::from_str(&format!("{:?}", expected)).unwrap()); - } - - // Invalid examples - assert!(ser::from_str::<$name>("\"0x\"").unwrap_err().is_data()); - assert!(ser::from_str::<$name>("\"0xg\"").unwrap_err().is_data()); - assert!(ser::from_str::<$name>("\"\"").unwrap_err().is_data()); - assert!(ser::from_str::<$name>("\"10\"").unwrap_err().is_data()); - assert!(ser::from_str::<$name>("\"0\"").unwrap_err().is_data()); - } - } -} - -test!(U256, test_u256); -test!(U512, test_u512); - -#[test] -fn test_large_values() { - assert_eq!( - ser::to_string_pretty(&!U256::zero()).unwrap(), - "\"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\"" - ); - assert!( - ser::from_str::("\"0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\"").unwrap_err().is_data() - ); -} - -#[test] -fn test_h160() { - let tests = vec![ - (H160::from(0), "0x0000000000000000000000000000000000000000"), - (H160::from(2), "0x0000000000000000000000000000000000000002"), - (H160::from(15), "0x000000000000000000000000000000000000000f"), - (H160::from(16), "0x0000000000000000000000000000000000000010"), - (H160::from(1_000), "0x00000000000000000000000000000000000003e8"), - (H160::from(100_000), "0x00000000000000000000000000000000000186a0"), - (H160::from(u64::max_value()), "0x000000000000000000000000ffffffffffffffff"), - ]; - - for (number, expected) in tests { - assert_eq!(format!("{:?}", expected), ser::to_string_pretty(&number).unwrap()); - assert_eq!(number, ser::from_str(&format!("{:?}", expected)).unwrap()); - } -} - -#[test] -fn test_h256() { - let tests = vec![ - (H256::from(0), "0x0000000000000000000000000000000000000000000000000000000000000000"), - (H256::from(2), "0x0000000000000000000000000000000000000000000000000000000000000002"), - (H256::from(15), "0x000000000000000000000000000000000000000000000000000000000000000f"), - (H256::from(16), "0x0000000000000000000000000000000000000000000000000000000000000010"), - (H256::from(1_000), "0x00000000000000000000000000000000000000000000000000000000000003e8"), - (H256::from(100_000), "0x00000000000000000000000000000000000000000000000000000000000186a0"), - (H256::from(u64::max_value()), "0x000000000000000000000000000000000000000000000000ffffffffffffffff"), - ]; - - for (number, expected) in tests { - assert_eq!(format!("{:?}", expected), ser::to_string_pretty(&number).unwrap()); - assert_eq!(number, ser::from_str(&format!("{:?}", expected)).unwrap()); - } -} - -#[test] -fn test_invalid() { - assert!(ser::from_str::("\"0x000000000000000000000000000000000000000000000000000000000000000\"").unwrap_err().is_data()); - assert!(ser::from_str::("\"0x000000000000000000000000000000000000000000000000000000000000000g\"").unwrap_err().is_data()); - assert!(ser::from_str::("\"0x00000000000000000000000000000000000000000000000000000000000000000\"").unwrap_err().is_data()); - assert!(ser::from_str::("\"\"").unwrap_err().is_data()); - assert!(ser::from_str::("\"0\"").unwrap_err().is_data()); - assert!(ser::from_str::("\"10\"").unwrap_err().is_data()); -} diff --git a/tests/src/uint_tests.rs b/tests/src/uint_tests.rs deleted file mode 100644 index d4bb887..0000000 --- a/tests/src/uint_tests.rs +++ /dev/null @@ -1,1195 +0,0 @@ -use std::u64::MAX; -use std::str::FromStr; -use uint::FromDecStrErr; -use ethereum_types::{U128, U256, U512}; - -#[test] -fn uint256_checked_ops() { - let z = U256::from(0); - let a = U256::from(10); - let b = !U256::from(1); - - assert_eq!(a.checked_add(b), None); - assert_eq!(a.checked_add(a), Some(20.into())); - - assert_eq!(a.checked_sub(b), None); - assert_eq!(a.checked_sub(a), Some(0.into())); - - assert_eq!(a.checked_mul(b), None); - assert_eq!(a.checked_mul(a), Some(100.into())); - - assert_eq!(a.checked_div(z), None); - assert_eq!(a.checked_div(a), Some(1.into())); - - assert_eq!(a.checked_rem(z), None); - assert_eq!(a.checked_rem(a), Some(0.into())); - - assert_eq!(a.checked_neg(), None); - assert_eq!(z.checked_neg(), Some(z)); -} - -#[test] -fn uint256_from() { - let e = U256([10, 0, 0, 0]); - - // test unsigned initialization - let ua = U256::from(10u8); - let ub = U256::from(10u16); - let uc = U256::from(10u32); - let ud = U256::from(10u64); - assert_eq!(e, ua); - assert_eq!(e, ub); - assert_eq!(e, uc); - assert_eq!(e, ud); - - // test initialization from bytes - let va = U256::from(&[10u8][..]); - assert_eq!(e, va); - - // more tests for initialization from bytes - assert_eq!(U256([0x1010, 0, 0, 0]), U256::from(&[0x10u8, 0x10][..])); - assert_eq!(U256([0x12f0, 0, 0, 0]), U256::from(&[0x12u8, 0xf0][..])); - assert_eq!(U256([0x12f0, 0, 0, 0]), U256::from(&[0, 0x12u8, 0xf0][..])); - assert_eq!(U256([0x12f0, 0 , 0, 0]), U256::from(&[0, 0, 0, 0, 0, 0, 0, 0x12u8, 0xf0][..])); - assert_eq!(U256([0x12f0, 1 , 0, 0]), U256::from(&[1, 0, 0, 0, 0, 0, 0, 0x12u8, 0xf0][..])); - assert_eq!( - U256([0x12f0, 1 , 0x0910203040506077, 0x8090a0b0c0d0e0f0]), - U256::from(& - [ - 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, - 0x09, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x77, - 0, 0, 0, 0, 0, 0, 0, 1, - 0, 0, 0, 0, 0, 0, 0x12u8, 0xf0 - ][..] - ) - ); - assert_eq!( - U256([0x00192437100019fa, 0x243710, 0, 0]), - U256::from(&[0x24u8, 0x37, 0x10,0, 0x19, 0x24, 0x37, 0x10, 0, 0x19, 0xfa][..]) - ); - - // test initializtion from string - let sa = U256::from_str("0a").unwrap(); - assert_eq!(e, sa); - assert_eq!(U256([0x1010, 0, 0, 0]), U256::from_str("1010").unwrap()); - assert_eq!(U256([0x12f0, 0, 0, 0]), U256::from_str("12f0").unwrap()); - assert_eq!(U256([0x12f0, 0, 0, 0]), U256::from_str("12f0").unwrap()); - assert_eq!(U256([0x12f0, 0 , 0, 0]), U256::from_str("0000000012f0").unwrap()); - assert_eq!(U256([0x12f0, 1 , 0, 0]), U256::from_str("0100000000000012f0").unwrap()); - assert_eq!( - U256([0x12f0, 1 , 0x0910203040506077, 0x8090a0b0c0d0e0f0]), - U256::from_str("8090a0b0c0d0e0f00910203040506077000000000000000100000000000012f0").unwrap() - ); -} - -#[test] -fn uint256_to() { - let hex = "8090a0b0c0d0e0f00910203040506077583a2cf8264910e1436bda32571012f0"; - let uint = U256::from_str(hex).unwrap(); - let mut bytes = [0u8; 32]; - uint.to_big_endian(&mut bytes); - let uint2 = U256::from(&bytes[..]); - assert_eq!(uint, uint2); -} - -#[test] -fn uint256_bits_test() { - assert_eq!(U256::from(0u64).bits(), 0); - assert_eq!(U256::from(255u64).bits(), 8); - assert_eq!(U256::from(256u64).bits(), 9); - assert_eq!(U256::from(300u64).bits(), 9); - assert_eq!(U256::from(60000u64).bits(), 16); - assert_eq!(U256::from(70000u64).bits(), 17); - - //// Try to read the following lines out loud quickly - let mut shl = U256::from(70000u64); - shl = shl << 100; - assert_eq!(shl.bits(), 117); - shl = shl << 100; - assert_eq!(shl.bits(), 217); - shl = shl << 100; - assert_eq!(shl.bits(), 0); - - //// Bit set check - //// 01010 - assert!(!U256::from(10u8).bit(0)); - assert!(U256::from(10u8).bit(1)); - assert!(!U256::from(10u8).bit(2)); - assert!(U256::from(10u8).bit(3)); - assert!(!U256::from(10u8).bit(4)); - - //// byte check - assert_eq!(U256::from(10u8).byte(0), 10); - assert_eq!(U256::from(0xffu64).byte(0), 0xff); - assert_eq!(U256::from(0xffu64).byte(1), 0); - assert_eq!(U256::from(0x01ffu64).byte(0), 0xff); - assert_eq!(U256::from(0x01ffu64).byte(1), 0x1); - assert_eq!(U256([0u64, 0xfc, 0, 0]).byte(8), 0xfc); - assert_eq!(U256([0u64, 0, 0, u64::max_value()]).byte(31), 0xff); - assert_eq!(U256([0u64, 0, 0, (u64::max_value() >> 8) + 1]).byte(31), 0x01); -} - -#[test] -#[cfg_attr(feature="dev", allow(eq_op))] -fn uint256_comp_test() { - let small = U256([10u64, 0, 0, 0]); - let big = U256([0x8C8C3EE70C644118u64, 0x0209E7378231E632, 0, 0]); - let bigger = U256([0x9C8C3EE70C644118u64, 0x0209E7378231E632, 0, 0]); - let biggest = U256([0x5C8C3EE70C644118u64, 0x0209E7378231E632, 0, 1]); - - assert!(small < big); - assert!(big < bigger); - assert!(bigger < biggest); - assert!(bigger <= biggest); - assert!(biggest <= biggest); - assert!(bigger >= big); - assert!(bigger >= small); - assert!(small <= small); -} - -#[test] -fn uint256_arithmetic_test() { - let init = U256::from(0xDEADBEEFDEADBEEFu64); - let copy = init; - - let add = init + copy; - assert_eq!(add, U256([0xBD5B7DDFBD5B7DDEu64, 1, 0, 0])); - // Bitshifts - let shl = add << 88; - assert_eq!(shl, U256([0u64, 0xDFBD5B7DDE000000, 0x1BD5B7D, 0])); - let shr = shl >> 40; - assert_eq!(shr, U256([0x7DDE000000000000u64, 0x0001BD5B7DDFBD5B, 0, 0])); - // Increment - let incr = shr + U256::from(1u64); - assert_eq!(incr, U256([0x7DDE000000000001u64, 0x0001BD5B7DDFBD5B, 0, 0])); - // Subtraction - let sub = overflowing!(incr.overflowing_sub(init)); - assert_eq!(sub, U256([0x9F30411021524112u64, 0x0001BD5B7DDFBD5A, 0, 0])); - // Multiplication - let mult = sub * 300u32; - assert_eq!(mult, U256([0x8C8C3EE70C644118u64, 0x0209E7378231E632, 0, 0])); - // Division - assert_eq!(U256::from(105u8) / U256::from(5u8), U256::from(21u8)); - let div = mult / U256::from(300u16); - assert_eq!(div, U256([0x9F30411021524112u64, 0x0001BD5B7DDFBD5A, 0, 0])); - - let a = U256::from_str("ff000000000000000000000000000000000000000000000000000000000000d1").unwrap(); - let b = U256::from_str("00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2e").unwrap(); - println!("{:x}", a); - println!("{:x}", b); - assert_eq!(!a, b); - assert_eq!(a, !b); -} - -#[test] -fn uint256_simple_mul() { - let a = U256::from_str("10000000000000000").unwrap(); - let b = U256::from_str("10000000000000000").unwrap(); - - let c = U256::from_str("100000000000000000000000000000000").unwrap(); - println!("Multiplying"); - let result = a.overflowing_mul(b); - println!("Got result"); - assert_eq!(result, (c, false)) -} - -#[test] -fn uint256_extreme_bitshift_test() { - //// Shifting a u64 by 64 bits gives an undefined value, so make sure that - //// we're doing the Right Thing here - let init = U256::from(0xDEADBEEFDEADBEEFu64); - - assert_eq!(init << 64, U256([0, 0xDEADBEEFDEADBEEF, 0, 0])); - let add = (init << 64) + init; - assert_eq!(add, U256([0xDEADBEEFDEADBEEF, 0xDEADBEEFDEADBEEF, 0, 0])); - assert_eq!(add >> 0, U256([0xDEADBEEFDEADBEEF, 0xDEADBEEFDEADBEEF, 0, 0])); - assert_eq!(add << 0, U256([0xDEADBEEFDEADBEEF, 0xDEADBEEFDEADBEEF, 0, 0])); - assert_eq!(add >> 64, U256([0xDEADBEEFDEADBEEF, 0, 0, 0])); - assert_eq!(add << 64, U256([0, 0xDEADBEEFDEADBEEF, 0xDEADBEEFDEADBEEF, 0])); -} - -#[test] -fn uint256_exp10() { - assert_eq!(U256::exp10(0), U256::from(1u64)); - println!("\none: {:?}", U256::from(1u64)); - println!("ten: {:?}", U256::from(10u64)); - assert_eq!(U256::from(2u64) * U256::from(10u64), U256::from(20u64)); - assert_eq!(U256::exp10(1), U256::from(10u64)); - assert_eq!(U256::exp10(2), U256::from(100u64)); - assert_eq!(U256::exp10(5), U256::from(100000u64)); -} - -#[test] -fn uint256_mul32() { - assert_eq!(U256::from(0u64) * 2u32, U256::from(0u64)); - assert_eq!(U256::from(1u64) * 2u32, U256::from(2u64)); - assert_eq!(U256::from(10u64) * 2u32, U256::from(20u64)); - assert_eq!(U256::from(10u64) * 5u32, U256::from(50u64)); - assert_eq!(U256::from(1000u64) * 50u32, U256::from(50000u64)); -} - -#[test] -fn uint256_mul32_old() { - assert_eq!(U256::from(0u64).mul_u32(2), U256::from(0u64)); - assert_eq!(U256::from(1u64).mul_u32(2), U256::from(2u64)); - assert_eq!(U256::from(10u64).mul_u32(2), U256::from(20u64)); - assert_eq!(U256::from(10u64).mul_u32(5), U256::from(50u64)); - assert_eq!(U256::from(1000u64).mul_u32(50), U256::from(50000u64)); -} - -#[test] -fn uint256_pow() { - assert_eq!(U256::from(10).pow(U256::from(0)), U256::from(1)); - assert_eq!(U256::from(10).pow(U256::from(1)), U256::from(10)); - assert_eq!(U256::from(10).pow(U256::from(2)), U256::from(100)); - assert_eq!(U256::from(10).pow(U256::from(3)), U256::from(1000)); - assert_eq!(U256::from(10).pow(U256::from(20)), U256::exp10(20)); -} - -#[test] -#[should_panic] -fn uint256_pow_overflow_panic() { - U256::from(2).pow(U256::from(0x100)); -} - -#[test] -fn should_format_and_debug_correctly() { - let test = |x: usize, hex: &'static str, display: &'static str| { - assert_eq!(format!("{}", U256::from(x)), display); - assert_eq!(format!("{:?}", U256::from(x)), format!("0x{}", hex)); - assert_eq!(format!("{:x}", U256::from(x)), hex); - assert_eq!(format!("{:#x}", U256::from(x)), format!("0x{}", hex)); - }; - - test(0x1, "1", "1"); - test(0xf, "f", "15"); - test(0x10, "10", "16"); - test(0xff, "ff", "255"); - test(0x100, "100", "256"); - test(0xfff, "fff", "4095"); - test(0x1000, "1000", "4096"); -} - -#[test] -fn uint256_overflowing_pow() { - assert_eq!( - U256::from(2).overflowing_pow(U256::from(0xff)), - (U256::from_str("8000000000000000000000000000000000000000000000000000000000000000").unwrap(), false) - ); - assert_eq!( - U256::from(2).overflowing_pow(U256::from(0x100)), - (U256::zero(), true) - ); -} - -#[test] -fn uint256_mul1() { - assert_eq!(U256::from(1u64) * U256::from(10u64), U256::from(10u64)); -} - -#[test] -fn uint256_mul2() { - let a = U512::from_str("10000000000000000fffffffffffffffe").unwrap(); - let b = U512::from_str("ffffffffffffffffffffffffffffffff").unwrap(); - - assert_eq!(a * b, U512::from_str("10000000000000000fffffffffffffffcffffffffffffffff0000000000000002").unwrap()); -} - -#[test] -fn uint256_overflowing_mul() { - assert_eq!( - U256::from_str("100000000000000000000000000000000").unwrap().overflowing_mul( - U256::from_str("100000000000000000000000000000000").unwrap() - ), - (U256::zero(), true) - ); -} - -#[test] -fn uint128_add() { - assert_eq!( - U128::from_str("fffffffffffffffff").unwrap() + U128::from_str("fffffffffffffffff").unwrap(), - U128::from_str("1ffffffffffffffffe").unwrap() - ); -} - -#[test] -fn uint128_add_overflow() { - assert_eq!( - U128::from_str("ffffffffffffffffffffffffffffffff").unwrap() - .overflowing_add( - U128::from_str("ffffffffffffffffffffffffffffffff").unwrap() - ), - (U128::from_str("fffffffffffffffffffffffffffffffe").unwrap(), true) - ); -} - -#[test] -#[should_panic] -#[cfg(debug_assertions)] -fn uint128_add_overflow_panic() { - U128::from_str("ffffffffffffffffffffffffffffffff").unwrap() - + - U128::from_str("ffffffffffffffffffffffffffffffff").unwrap(); -} - -#[test] -fn uint128_mul() { - assert_eq!( - U128::from_str("fffffffff").unwrap() * U128::from_str("fffffffff").unwrap(), - U128::from_str("ffffffffe000000001").unwrap()); -} - -#[test] -fn uint512_mul() { - assert_eq!( - U512::from_str("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap() - * - U512::from_str("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap(), - U512::from_str("3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000001").unwrap() - ); -} - -#[test] -fn uint256_mul_overflow() { - assert_eq!( - U256::from_str("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap() - .overflowing_mul( - U256::from_str("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap() - ), - (U256::from_str("1").unwrap(), true) - ); -} - -#[test] -#[should_panic] -fn uint256_mul_overflow_panic() { - U256::from_str("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap() - * - U256::from_str("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap(); -} - -#[test] -fn uint256_sub_overflow() { - assert_eq!( - U256::from_str("0").unwrap() - .overflowing_sub( - U256::from_str("1").unwrap() - ), - (U256::from_str("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap(), true) - ); -} - -#[test] -#[should_panic] -fn uint256_sub_overflow_panic() { - U256::from_str("0").unwrap() - - - U256::from_str("1").unwrap(); -} - -#[test] -fn uint256_shl() { - assert_eq!( - U256::from_str("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap() - << 4, - U256::from_str("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0").unwrap() - ); -} - -#[test] -fn uint256_shl_words() { - assert_eq!( - U256::from_str("0000000000000001ffffffffffffffffffffffffffffffffffffffffffffffff").unwrap() - << 64, - U256::from_str("ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000").unwrap() - ); - assert_eq!( - U256::from_str("0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffff").unwrap() - << 64, - U256::from_str("ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000").unwrap() - ); -} - -#[test] -fn uint256_mul() { - assert_eq!( - U256::from_str("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap() - * - U256::from_str("2").unwrap(), - U256::from_str("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe").unwrap() - ); -} - -#[test] -fn uint256_div() { - assert_eq!(U256::from(10u64) / U256::from(1u64), U256::from(10u64)); - assert_eq!(U256::from(10u64) / U256::from(2u64), U256::from(5u64)); - assert_eq!(U256::from(10u64) / U256::from(3u64), U256::from(3u64)); -} - -#[test] -fn uint256_rem() { - assert_eq!(U256::from(10u64) % U256::from(1u64), U256::from(0u64)); - assert_eq!(U256::from(10u64) % U256::from(3u64), U256::from(1u64)); -} - -#[test] -fn uint256_from_dec_str() { - assert_eq!(U256::from_dec_str("10").unwrap(), U256::from(10u64)); - assert_eq!(U256::from_dec_str("1024").unwrap(), U256::from(1024u64)); - assert_eq!(U256::from_dec_str("115792089237316195423570985008687907853269984665640564039457584007913129639936"), Err(FromDecStrErr::InvalidLength)); - assert_eq!(U256::from_dec_str("0x11"), Err(FromDecStrErr::InvalidCharacter)); -} - -#[test] -fn display_uint() { - let s = "12345678987654321023456789"; - assert_eq!(format!("{}", U256::from_dec_str(s).unwrap()), s); -} - -#[test] -fn display_uint_zero() { - assert_eq!(format!("{}", U256::from(0)), "0"); -} - -#[test] -fn u512_multi_adds() { - let (result, _) = U512([0, 0, 0, 0, 0, 0, 0, 0]).overflowing_add(U512([0, 0, 0, 0, 0, 0, 0, 0])); - assert_eq!(result, U512([0, 0, 0, 0, 0, 0, 0, 0])); - - let (result, _) = U512([1, 0, 0, 0, 0, 0, 0, 1]).overflowing_add(U512([1, 0, 0, 0, 0, 0, 0, 1])); - assert_eq!(result, U512([2, 0, 0, 0, 0, 0, 0, 2])); - - let (result, _) = U512([0, 0, 0, 0, 0, 0, 0, 1]).overflowing_add(U512([0, 0, 0, 0, 0, 0, 0, 1])); - assert_eq!(result, U512([0, 0, 0, 0, 0, 0, 0, 2])); - - let (result, _) = U512([0, 0, 0, 0, 0, 0, 2, 1]).overflowing_add(U512([0, 0, 0, 0, 0, 0, 3, 1])); - assert_eq!(result, U512([0, 0, 0, 0, 0, 0, 5, 2])); - - let (result, _) = U512([1, 2, 3, 4, 5, 6, 7, 8]).overflowing_add(U512([9, 10, 11, 12, 13, 14, 15, 16])); - assert_eq!(result, U512([10, 12, 14, 16, 18, 20, 22, 24])); - - let (_, overflow) = U512([0, 0, 0, 0, 0, 0, 2, 1]).overflowing_add(U512([0, 0, 0, 0, 0, 0, 3, 1])); - assert!(!overflow); - - let (_, overflow) = U512([MAX, MAX, MAX, MAX, MAX, MAX, MAX, MAX]) - .overflowing_add(U512([MAX, MAX, MAX, MAX, MAX, MAX, MAX, MAX])); - assert!(overflow); - - let (_, overflow) = U512([0, 0, 0, 0, 0, 0, 0, MAX]) - .overflowing_add(U512([0, 0, 0, 0, 0, 0, 0, MAX])); - assert!(overflow); - - let (_, overflow) = U512([0, 0, 0, 0, 0, 0, 0, MAX]) - .overflowing_add(U512([0, 0, 0, 0, 0, 0, 0, 0])); - assert!(!overflow); -} - -#[test] -fn u256_multi_adds() { - let (result, _) = U256([0, 0, 0, 0]).overflowing_add(U256([0, 0, 0, 0])); - assert_eq!(result, U256([0, 0, 0, 0])); - - let (result, _) = U256([0, 0, 0, 1]).overflowing_add(U256([0, 0, 0, 1])); - assert_eq!(result, U256([0, 0, 0, 2])); - - let (result, overflow) = U256([0, 0, 2, 1]).overflowing_add(U256([0, 0, 3, 1])); - assert_eq!(result, U256([0, 0, 5, 2])); - assert!(!overflow); - - let (_, overflow) = U256([MAX, MAX, MAX, MAX]) - .overflowing_add(U256([MAX, MAX, MAX, MAX])); - assert!(overflow); - - let (_, overflow) = U256([0, 0, 0, MAX]).overflowing_add(U256([0, 0, 0, MAX])); - assert!(overflow); -} - - -#[test] -fn u256_multi_subs() { - let (result, _) = U256([0, 0, 0, 0]).overflowing_sub(U256([0, 0, 0, 0])); - assert_eq!(result, U256([0, 0, 0, 0])); - - let (result, _) = U256([0, 0, 0, 1]).overflowing_sub(U256([0, 0, 0, 1])); - assert_eq!(result, U256([0, 0, 0, 0])); - - let (_, overflow) = U256([0, 0, 2, 1]).overflowing_sub(U256([0, 0, 3, 1])); - assert!(overflow); - - let (result, overflow) = - U256([MAX, MAX, MAX, MAX]) - .overflowing_sub(U256([MAX/2, MAX/2, MAX/2, MAX/2])); - - assert!(!overflow); - assert_eq!(U256([MAX/2+1, MAX/2+1, MAX/2+1, MAX/2+1]), result); - - let (result, overflow) = U256([0, 0, 0, 1]).overflowing_sub(U256([0, 0, 1, 0])); - assert!(!overflow); - assert_eq!(U256([0, 0, MAX, 0]), result); - - let (result, overflow) = U256([0, 0, 0, 1]).overflowing_sub(U256([1, 0, 0, 0])); - assert!(!overflow); - assert_eq!(U256([MAX, MAX, MAX, 0]), result); -} - -#[test] -fn u512_multi_subs() { - let (result, _) = U512([0, 0, 0, 0, 0, 0, 0, 0]).overflowing_sub(U512([0, 0, 0, 0, 0, 0, 0, 0])); - assert_eq!(result, U512([0, 0, 0, 0, 0, 0, 0, 0])); - - let (result, _) = U512([10, 9, 8, 7, 6, 5, 4, 3]).overflowing_sub(U512([9, 8, 7, 6, 5, 4, 3, 2])); - assert_eq!(result, U512([1, 1, 1, 1, 1, 1, 1, 1])); - - let (_, overflow) = U512([10, 9, 8, 7, 6, 5, 4, 3]).overflowing_sub(U512([9, 8, 7, 6, 5, 4, 3, 2])); - assert!(!overflow); - - let (_, overflow) = U512([9, 8, 7, 6, 5, 4, 3, 2]).overflowing_sub(U512([10, 9, 8, 7, 6, 5, 4, 3])); - assert!(overflow); -} - -#[test] -fn u256_multi_carry_all() { - let (result, _) = U256([MAX, 0, 0, 0]).overflowing_mul(U256([MAX, 0, 0, 0])); - assert_eq!(U256([1, MAX-1, 0, 0]), result); - - let (result, _) = U256([0, MAX, 0, 0]).overflowing_mul(U256([MAX, 0, 0, 0])); - assert_eq!(U256([0, 1, MAX-1, 0]), result); - - let (result, _) = U256([MAX, MAX, 0, 0]).overflowing_mul(U256([MAX, 0, 0, 0])); - assert_eq!(U256([1, MAX, MAX-1, 0]), result); - - let (result, _) = U256([MAX, 0, 0, 0]).overflowing_mul(U256([MAX, MAX, 0, 0])); - assert_eq!(U256([1, MAX, MAX-1, 0]), result); - - let (result, _) = U256([MAX, MAX, 0, 0]) - .overflowing_mul(U256([MAX, MAX, 0, 0])); - assert_eq!(U256([1, 0, MAX-1, MAX]), result); - - let (result, _) = U256([MAX, 0, 0, 0]).overflowing_mul(U256([MAX, MAX, MAX, 0])); - assert_eq!(U256([1, MAX, MAX, MAX-1]), result); - - let (result, _) = U256([MAX, MAX, MAX, 0]).overflowing_mul(U256([MAX, 0, 0, 0])); - assert_eq!(U256([1, MAX, MAX, MAX-1]), result); - - let (result, _) = U256([MAX, 0, 0, 0]).overflowing_mul( - U256([MAX, MAX, MAX, MAX])); - assert_eq!(U256([1, MAX, MAX, MAX]), result); - - let (result, _) = U256([MAX, MAX, MAX, MAX]) - .overflowing_mul(U256([MAX, 0, 0, 0])); - assert_eq!(U256([1, MAX, MAX, MAX]), result); - - let (result, _) = U256([MAX, MAX, MAX, 0]) - .overflowing_mul(U256([MAX, MAX, 0, 0])); - assert_eq!(U256([1, 0, MAX, MAX-1]), result); - - let (result, _) = U256([MAX, MAX, 0, 0]) - .overflowing_mul(U256([MAX, MAX, MAX, 0])); - assert_eq!(U256([1, 0, MAX, MAX-1]), result); - - let (result, _) = U256([MAX, MAX, MAX, MAX]) - .overflowing_mul(U256([MAX, MAX, 0, 0])); - assert_eq!(U256([1, 0, MAX, MAX]), result); - - let (result, _) = U256([MAX, MAX, 0, 0]) - .overflowing_mul(U256([MAX, MAX, MAX, MAX])); - assert_eq!(U256([1, 0, MAX, MAX]), result); - - let (result, _) = U256([MAX, MAX, MAX, 0]) - .overflowing_mul(U256([MAX, MAX, MAX, 0])); - assert_eq!(U256([1, 0, 0, MAX-1]), result); - - let (result, _) = U256([MAX, MAX, MAX, 0]) - .overflowing_mul(U256([MAX, MAX, MAX, MAX])); - assert_eq!(U256([1, 0, 0, MAX]), result); - - let (result, _) = U256([MAX, MAX, MAX, MAX]) - .overflowing_mul(U256([MAX, MAX, MAX, 0])); - assert_eq!(U256([1, 0, 0, MAX]), result); - - let (result, _) = U256([0, 0, 0, MAX]).overflowing_mul(U256([0, 0, 0, MAX])); - assert_eq!(U256([0, 0, 0, 0]), result); - - let (result, _) = U256([1, 0, 0, 0]).overflowing_mul(U256([0, 0, 0, MAX])); - assert_eq!(U256([0, 0, 0, MAX]), result); - - let (result, _) = U256([MAX, MAX, MAX, MAX]) - .overflowing_mul(U256([MAX, MAX, MAX, MAX])); - assert_eq!(U256([1, 0, 0, 0]), result); -} - -#[test] -fn u256_multi_muls() { - let (result, _) = U256([0, 0, 0, 0]).overflowing_mul(U256([0, 0, 0, 0])); - assert_eq!(U256([0, 0, 0, 0]), result); - - let (result, _) = U256([1, 0, 0, 0]).overflowing_mul(U256([1, 0, 0, 0])); - assert_eq!(U256([1, 0, 0, 0]), result); - - let (result, _) = U256([5, 0, 0, 0]).overflowing_mul(U256([5, 0, 0, 0])); - assert_eq!(U256([25, 0, 0, 0]), result); - - let (result, _) = U256([0, 5, 0, 0]).overflowing_mul(U256([0, 5, 0, 0])); - assert_eq!(U256([0, 0, 25, 0]), result); - - let (result, _) = U256([0, 0, 0, 1]).overflowing_mul(U256([1, 0, 0, 0])); - assert_eq!(U256([0, 0, 0, 1]), result); - - let (result, _) = U256([0, 0, 0, 5]).overflowing_mul(U256([2, 0, 0, 0])); - assert_eq!(U256([0, 0, 0, 10]), result); - - let (result, _) = U256([0, 0, 1, 0]).overflowing_mul(U256([0, 5, 0, 0])); - assert_eq!(U256([0, 0, 0, 5]), result); - - let (result, _) = U256([0, 0, 8, 0]).overflowing_mul(U256([0, 0, 7, 0])); - assert_eq!(U256([0, 0, 0, 0]), result); - - let (result, _) = U256([2, 0, 0, 0]).overflowing_mul(U256([0, 5, 0, 0])); - assert_eq!(U256([0, 10, 0, 0]), result); - - let (result, _) = U256([1, 0, 0, 0]).overflowing_mul(U256([0, 0, 0, MAX])); - assert_eq!(U256([0, 0, 0, MAX]), result); -} - -#[test] -fn u256_multi_muls_overflow() { - let (_, overflow) = U256([1, 0, 0, 0]).overflowing_mul(U256([0, 0, 0, 0])); - assert!(!overflow); - - let (_, overflow) = U256([1, 0, 0, 0]).overflowing_mul(U256([0, 0, 0, MAX])); - assert!(!overflow); - - let (_, overflow) = U256([0, 1, 0, 0]).overflowing_mul(U256([0, 0, 0, MAX])); - assert!(overflow); - - let (_, overflow) = U256([0, 1, 0, 0]).overflowing_mul(U256([0, 1, 0, 0])); - assert!(!overflow); - - let (_, overflow) = U256([0, 1, 0, MAX]).overflowing_mul(U256([0, 1, 0, MAX])); - assert!(overflow); - - let (_, overflow) = U256([0, MAX, 0, 0]).overflowing_mul(U256([0, MAX, 0, 0])); - assert!(!overflow); - - let (_, overflow) = U256([1, 0, 0, 0]).overflowing_mul(U256([10, 0, 0, 0])); - assert!(!overflow); - - let (_, overflow) = U256([2, 0, 0, 0]).overflowing_mul(U256([0, 0, 0, MAX / 2])); - assert!(!overflow); - - let (_, overflow) = U256([0, 0, 8, 0]).overflowing_mul(U256([0, 0, 7, 0])); - assert!(overflow); -} - -#[test] -fn big_endian() { - let source = U256([1, 0, 0, 0]); - let mut target = vec![0u8; 32]; - - assert_eq!(source, U256::from(1)); - - source.to_big_endian(&mut target); - assert_eq!( - vec![0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, - 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8], - target); - - let source = U256([512, 0, 0, 0]); - let mut target = vec![0u8; 32]; - - source.to_big_endian(&mut target); - assert_eq!( - vec![0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, - 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8], - target); - - let source = U256([0, 512, 0, 0]); - let mut target = vec![0u8; 32]; - - source.to_big_endian(&mut target); - assert_eq!( - vec![0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, - 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8], - target); - - let source = U256::from_str("0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20").unwrap(); - source.to_big_endian(&mut target); - assert_eq!( - vec![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, 0x20], - target); -} - -#[test] -#[cfg_attr(feature="dev", allow(cyclomatic_complexity))] -fn u256_multi_full_mul() { - let result = U256([0, 0, 0, 0]).full_mul(U256([0, 0, 0, 0])); - assert_eq!(U512([0, 0, 0, 0, 0, 0, 0, 0]), result); - - let result = U256([1, 0, 0, 0]).full_mul(U256([1, 0, 0, 0])); - assert_eq!(U512([1, 0, 0, 0, 0, 0, 0, 0]), result); - - let result = U256([5, 0, 0, 0]).full_mul(U256([5, 0, 0, 0])); - assert_eq!(U512([25, 0, 0, 0, 0, 0, 0, 0]), result); - - let result = U256([0, 5, 0, 0]).full_mul(U256([0, 5, 0, 0])); - assert_eq!(U512([0, 0, 25, 0, 0, 0, 0, 0]), result); - - let result = U256([0, 0, 0, 4]).full_mul(U256([4, 0, 0, 0])); - assert_eq!(U512([0, 0, 0, 16, 0, 0, 0, 0]), result); - - let result = U256([0, 0, 0, 5]).full_mul(U256([2, 0, 0, 0])); - assert_eq!(U512([0, 0, 0, 10, 0, 0, 0, 0]), result); - - let result = U256([0, 0, 2, 0]).full_mul(U256([0, 5, 0, 0])); - assert_eq!(U512([0, 0, 0, 10, 0, 0, 0, 0]), result); - - let result = U256([0, 3, 0, 0]).full_mul(U256([0, 0, 3, 0])); - assert_eq!(U512([0, 0, 0, 9, 0, 0, 0, 0]), result); - - let result = U256([0, 0, 8, 0]).full_mul(U256([0, 0, 6, 0])); - assert_eq!(U512([0, 0, 0, 0, 48, 0, 0, 0]), result); - - let result = U256([9, 0, 0, 0]).full_mul(U256([0, 3, 0, 0])); - assert_eq!(U512([0, 27, 0, 0, 0, 0, 0, 0]), result); - - let result = U256([MAX, 0, 0, 0]).full_mul(U256([MAX, 0, 0, 0])); - assert_eq!(U512([1, MAX-1, 0, 0, 0, 0, 0, 0]), result); - - let result = U256([0, MAX, 0, 0]).full_mul(U256([MAX, 0, 0, 0])); - assert_eq!(U512([0, 1, MAX-1, 0, 0, 0, 0, 0]), result); - - let result = U256([MAX, MAX, 0, 0]).full_mul(U256([MAX, 0, 0, 0])); - assert_eq!(U512([1, MAX, MAX-1, 0, 0, 0, 0, 0]), result); - - let result = U256([MAX, 0, 0, 0]).full_mul(U256([MAX, MAX, 0, 0])); - assert_eq!(U512([1, MAX, MAX-1, 0, 0, 0, 0, 0]), result); - - let result = U256([MAX, MAX, 0, 0]).full_mul(U256([MAX, MAX, 0, 0])); - assert_eq!(U512([1, 0, MAX-1, MAX, 0, 0, 0, 0]), result); - - let result = U256([MAX, 0, 0, 0]).full_mul(U256([MAX, MAX, MAX, 0])); - assert_eq!(U512([1, MAX, MAX, MAX-1, 0, 0, 0, 0]), result); - - let result = U256([MAX, MAX, MAX, 0]).full_mul(U256([MAX, 0, 0, 0])); - assert_eq!(U512([1, MAX, MAX, MAX-1, 0, 0, 0, 0]), result); - - let result = U256([MAX, 0, 0, 0]).full_mul(U256([MAX, MAX, MAX, MAX])); - assert_eq!(U512([1, MAX, MAX, MAX, MAX-1, 0, 0, 0]), result); - - let result = U256([MAX, MAX, MAX, MAX]).full_mul(U256([MAX, 0, 0, 0])); - assert_eq!(U512([1, MAX, MAX, MAX, MAX-1, 0, 0, 0]), result); - - let result = U256([MAX, MAX, MAX, 0]).full_mul(U256([MAX, MAX, 0, 0])); - assert_eq!(U512([1, 0, MAX, MAX-1, MAX, 0, 0, 0]), result); - - let result = U256([MAX, MAX, 0, 0]).full_mul(U256([MAX, MAX, MAX, 0])); - assert_eq!(U512([1, 0, MAX, MAX-1, MAX, 0, 0, 0]), result); - - let result = U256([MAX, MAX, MAX, MAX]).full_mul(U256([MAX, MAX, 0, 0])); - assert_eq!(U512([1, 0, MAX, MAX, MAX-1, MAX, 0, 0]), result); - - let result = U256([MAX, MAX, 0, 0]).full_mul(U256([MAX, MAX, MAX, MAX])); - assert_eq!(U512([1, 0, MAX, MAX, MAX-1, MAX, 0, 0]), result); - - let result = U256([MAX, MAX, MAX, 0]).full_mul(U256([MAX, MAX, MAX, 0])); - assert_eq!(U512([1, 0, 0, MAX-1, MAX, MAX, 0, 0]), result); - - let result = U256([MAX, MAX, MAX, 0]).full_mul(U256([MAX, MAX, MAX, MAX])); - assert_eq!(U512([1, 0, 0, MAX, MAX-1, MAX, MAX, 0]), result); - - let result = U256([MAX, MAX, MAX, MAX]).full_mul(U256([MAX, MAX, MAX, 0])); - assert_eq!(U512([1, 0, 0, MAX, MAX-1, MAX, MAX, 0]), result); - - let result = U256([MAX, MAX, MAX, MAX]).full_mul(U256([MAX, MAX, MAX, MAX])); - assert_eq!(U512([1, 0, 0, 0, MAX-1, MAX, MAX, MAX]), result); - - let result = U256([0, 0, 0, MAX]).full_mul(U256([0, 0, 0, MAX])); - assert_eq!(U512([0, 0, 0, 0, 0, 0, 1, MAX-1]), result); - - let result = U256([1, 0, 0, 0]).full_mul(U256([0, 0, 0, MAX])); - assert_eq!(U512([0, 0, 0, MAX, 0, 0, 0, 0]), result); - - let result = U256([1, 2, 3, 4]).full_mul(U256([5, 0, 0, 0])); - assert_eq!(U512([5, 10, 15, 20, 0, 0, 0, 0]), result); - - let result = U256([1, 2, 3, 4]).full_mul(U256([0, 6, 0, 0])); - assert_eq!(U512([0, 6, 12, 18, 24, 0, 0, 0]), result); - - let result = U256([1, 2, 3, 4]).full_mul(U256([0, 0, 7, 0])); - assert_eq!(U512([0, 0, 7, 14, 21, 28, 0, 0]), result); - - let result = U256([1, 2, 3, 4]).full_mul(U256([0, 0, 0, 8])); - assert_eq!(U512([0, 0, 0, 8, 16, 24, 32, 0]), result); - - let result = U256([1, 2, 3, 4]).full_mul(U256([5, 6, 7, 8])); - assert_eq!(U512([5, 16, 34, 60, 61, 52, 32, 0]), result); -} - -#[test] -fn u256_multi_muls2() { - - let (result, _) = U256([0, 0, 0, 0]).overflowing_mul(U256([0, 0, 0, 0])); - assert_eq!(U256([0, 0, 0, 0]), result); - - let (result, _) = U256([1, 0, 0, 0]).overflowing_mul(U256([1, 0, 0, 0])); - assert_eq!(U256([1, 0, 0, 0]), result); - - let (result, _) = U256([5, 0, 0, 0]).overflowing_mul(U256([5, 0, 0, 0])); - assert_eq!(U256([25, 0, 0, 0]), result); - - let (result, _) = U256([0, 5, 0, 0]).overflowing_mul(U256([0, 5, 0, 0])); - assert_eq!(U256([0, 0, 25, 0]), result); - - let (result, _) = U256([0, 0, 0, 1]).overflowing_mul(U256([1, 0, 0, 0])); - assert_eq!(U256([0, 0, 0, 1]), result); - - let (result, _) = U256([0, 0, 0, 5]).overflowing_mul(U256([2, 0, 0, 0])); - assert_eq!(U256([0, 0, 0, 10]), result); - - let (result, _) = U256([0, 0, 1, 0]).overflowing_mul(U256([0, 5, 0, 0])); - assert_eq!(U256([0, 0, 0, 5]), result); - - let (result, _) = U256([0, 0, 8, 0]).overflowing_mul(U256([0, 0, 7, 0])); - assert_eq!(U256([0, 0, 0, 0]), result); - - let (result, _) = U256([2, 0, 0, 0]).overflowing_mul(U256([0, 5, 0, 0])); - assert_eq!(U256([0, 10, 0, 0]), result); - - let (result, _) = U256([1, 0, 0, 0]).overflowing_mul(U256([0, 0, 0, u64::max_value()])); - assert_eq!(U256([0, 0, 0, u64::max_value()]), result); - - let x1: U256 = "0000000000000000000000000000000000000000000000000000012365124623".into(); - let x2sqr_right: U256 = "000000000000000000000000000000000000000000014baeef72e0378e2328c9".into(); - let x1sqr = x1 * x1; - assert_eq!(x2sqr_right, x1sqr); - - let x1cube = x1sqr * x1; - let x1cube_right: U256 = "0000000000000000000000000000000001798acde139361466f712813717897b".into(); - assert_eq!(x1cube_right, x1cube); - - let x1quad = x1cube * x1; - let x1quad_right: U256 = "000000000000000000000001adbdd6bd6ff027485484b97f8a6a4c7129756dd1".into(); - assert_eq!(x1quad_right, x1quad); - - let x1penta = x1quad * x1; - let x1penta_right: U256 = "00000000000001e92875ac24be246e1c57e0507e8c46cc8d233b77f6f4c72993".into(); - assert_eq!(x1penta_right, x1penta); - - let x1septima = x1penta * x1; - let x1septima_right: U256 = "00022cca1da3f6e5722b7d3cc5bbfb486465ebc5a708dd293042f932d7eee119".into(); - assert_eq!(x1septima_right, x1septima); -} - -#[test] -fn example() { - let mut val: U256 = 1023.into(); - for _ in 0..200 { val = val * U256::from(2) } - assert_eq!(&format!("{}", val), "1643897619276947051879427220465009342380213662639797070513307648"); -} - -#[test] -fn little_endian() { - let number: U256 = "00022cca1da3f6e5722b7d3cc5bbfb486465ebc5a708dd293042f932d7eee119".into(); - let expected = [ - 0x19, 0xe1, 0xee, 0xd7, - 0x32, 0xf9, 0x42, 0x30, - 0x29, 0xdd, 0x08, 0xa7, - 0xc5, 0xeb, 0x65, 0x64, - 0x48, 0xfb, 0xbb, 0xc5, - 0x3c, 0x7d, 0x2b, 0x72, - 0xe5, 0xf6, 0xa3, 0x1d, - 0xca, 0x2c, 0x02, 0x00 - ]; - let mut result = [0u8; 32]; - number.to_little_endian(&mut result); - assert_eq!(expected, result); -} - -#[test] -fn slice_roundtrip() { - let raw = [ - 1u8, 2, 3, 5, 7, 11, 13, 17, - 19, 23, 29, 31, 37, 41, 43, 47, - 53, 59, 61, 67, 71, 73, 79, 83, - 89, 97, 101, 103, 107, 109, 113, 127 - ]; - - let u256: U256 = (&raw[..]).into(); - - let mut new_raw = [0u8; 32]; - - u256.to_big_endian(&mut new_raw); - - assert_eq!(&raw, &new_raw); -} - -#[test] -fn slice_roundtrip_le() { - let raw = [ - 1u8, 2, 3, 5, 7, 11, 13, 17, - 19, 23, 29, 31, 37, 41, 43, 47, - 53, 59, 61, 67, 71, 73, 79, 83, - 89, 97, 101, 103, 107, 109, 113, 127 - ]; - - let u256 = U256::from_little_endian(&raw[..]); - - let mut new_raw = [0u8; 32]; - - u256.to_little_endian(&mut new_raw); - - assert_eq!(&raw, &new_raw); -} - -#[test] -fn slice_roundtrip_le2() { - let raw = [ - 2, 3, 5, 7, 11, 13, 17, - 19, 23, 29, 31, 37, 41, 43, 47, - 53, 59, 61, 67, 71, 73, 79, 83, - 89, 97, 101, 103, 107, 109, 113, 127 - ]; - - let u256 = U256::from_little_endian(&raw[..]); - - let mut new_raw = [0u8; 32]; - - u256.to_little_endian(&mut new_raw); - - assert_eq!(&raw, &new_raw[..31]); -} - -#[test] -fn fixed_arrays_roundtrip() { - let raw: U256 = "7094875209347850239487502394881".into(); - let array: [u8; 32] = raw.into(); - let new_raw = array.into(); - - assert_eq!(raw, new_raw); -} - -#[test] -fn from_little_endian() { - let source: [u8; 32] = [ - 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - ]; - - let number = U256::from_little_endian(&source[..]); - - assert_eq!(U256::from(1), number); -} - -#[test] -fn from_big_endian() { - let source: [u8; 32] = [ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1, - ]; - - let number = U256::from_big_endian(&source[..]); - - assert_eq!(U256::from(1), number); -} - -#[test] -fn leading_zeros() { - assert_eq!(U256::from("000000000000000000000001adbdd6bd6ff027485484b97f8a6a4c7129756dd1").leading_zeros(), 95); - assert_eq!(U256::from("f00000000000000000000001adbdd6bd6ff027485484b97f8a6a4c7129756dd1").leading_zeros(), 0); - assert_eq!(U256::from("0000000000000000000000000000000000000000000000000000000000000001").leading_zeros(), 255); - assert_eq!(U256::from("0000000000000000000000000000000000000000000000000000000000000000").leading_zeros(), 256); -} - -#[test] -fn trailing_zeros() { - assert_eq!(U256::from("1adbdd6bd6ff027485484b97f8a6a4c7129756dd100000000000000000000000").trailing_zeros(), 92); - assert_eq!(U256::from("1adbdd6bd6ff027485484b97f8a6a4c7129756dd10000000000000000000000f").trailing_zeros(), 0); - assert_eq!(U256::from("8000000000000000000000000000000000000000000000000000000000000000").trailing_zeros(), 255); - assert_eq!(U256::from("0000000000000000000000000000000000000000000000000000000000000000").trailing_zeros(), 256); -} - -pub mod laws { - macro_rules! uint_laws { - ($mod_name:ident, $uint_ty:ident) => { - mod $mod_name { - use quickcheck::TestResult; - use super::{$uint_ty}; - - quickcheck! { - fn associative_add(x: $uint_ty, y: $uint_ty, z: $uint_ty) -> TestResult { - if x.overflowing_add(y).1 || y.overflowing_add(z).1 || (x + y).overflowing_add(z).1 { - return TestResult::discard(); - } - - TestResult::from_bool( - (x + y) + z == x + (y + z) - ) - } - } - - quickcheck! { - fn associative_mul(x: $uint_ty, y: $uint_ty, z: $uint_ty) -> TestResult { - if x.overflowing_mul(y).1 || y.overflowing_mul(z).1 || (x * y).overflowing_mul(z).1 { - return TestResult::discard(); - } - - TestResult::from_bool( - (x * y) * z == x * (y * z) - ) - } - } - - quickcheck! { - fn commutative_add(x: $uint_ty, y: $uint_ty) -> TestResult { - if x.overflowing_add(y).1 { - return TestResult::discard(); - } - - TestResult::from_bool( - x + y == y + x - ) - } - } - - quickcheck! { - fn commutative_mul(x: $uint_ty, y: $uint_ty) -> TestResult { - if x.overflowing_mul(y).1 { - return TestResult::discard(); - } - - TestResult::from_bool( - x * y == y * x - ) - } - } - - quickcheck! { - fn identity_add(x: $uint_ty) -> bool { - x + $uint_ty::zero() == x - } - } - - quickcheck! { - fn identity_mul(x: $uint_ty) -> bool { - x * $uint_ty::one() == x - } - } - - quickcheck! { - fn identity_div(x: $uint_ty) -> bool { - x / $uint_ty::one() == x - } - } - - quickcheck! { - fn absorbing_rem(x: $uint_ty) -> bool { - x % $uint_ty::one() == $uint_ty::zero() - } - } - - quickcheck! { - fn absorbing_sub(x: $uint_ty) -> bool { - x - x == $uint_ty::zero() - } - } - - quickcheck! { - fn absorbing_mul(x: $uint_ty) -> bool { - x * $uint_ty::zero() == $uint_ty::zero() - } - } - - quickcheck! { - fn distributive_mul_over_add(x: $uint_ty, y: $uint_ty, z: $uint_ty) -> TestResult { - if y.overflowing_add(z).1 || x.overflowing_mul(y + z).1 || x.overflowing_add(y).1 || (x + y).overflowing_mul(z).1 { - return TestResult::discard(); - } - - TestResult::from_bool( - (x * (y + z) == (x * y + x * z)) && (((x + y) * z) == (x * z + y * z)) - ) - } - } - - quickcheck! { - fn pow_mul(x: $uint_ty) -> TestResult { - if x.overflowing_pow($uint_ty::from(2)).1 || x.overflowing_pow($uint_ty::from(3)).1 { - return TestResult::discard(); - } - - TestResult::from_bool( - x.pow($uint_ty::from(2)) == x * x && x.pow($uint_ty::from(3)) == x * x * x - ) - } - } - - quickcheck! { - fn add_increases(x: $uint_ty, y: $uint_ty) -> TestResult { - if y.is_zero() || x.overflowing_add(y).1 { - return TestResult::discard(); - } - - TestResult::from_bool( - x + y > x - ) - } - } - - quickcheck! { - fn mul_increases(x: $uint_ty, y: $uint_ty) -> TestResult { - if y.is_zero() || x.overflowing_mul(y).1 { - return TestResult::discard(); - } - - TestResult::from_bool( - x * y >= x - ) - } - } - - quickcheck! { - fn div_decreases_dividend(x: $uint_ty, y: $uint_ty) -> TestResult { - if y.is_zero() { - return TestResult::discard(); - } - - TestResult::from_bool( - x / y <= x - ) - } - } - - quickcheck! { - fn rem_decreases_divisor(x: $uint_ty, y: $uint_ty) -> TestResult { - if y.is_zero() { - return TestResult::discard(); - } - - TestResult::from_bool( - x % y < y - ) - } - } - } - } - } - - construct_uint!(U64, 1); - construct_uint!(U128, 2); - construct_uint!(U256, 4); - construct_uint!(U512, 8); - construct_uint!(U1024, 16); - - uint_laws!(u64, U64); - uint_laws!(u128, U128); - uint_laws!(u256, U256); - uint_laws!(u512, U512); - uint_laws!(u1024, U1024); -} diff --git a/uint/Cargo.toml b/uint/Cargo.toml deleted file mode 100644 index 3cbe5fb..0000000 --- a/uint/Cargo.toml +++ /dev/null @@ -1,31 +0,0 @@ -[package] -description = "Large fixed-size integers arithmetics" -homepage = "http://parity.io" -repository = "https://github.com/paritytech/primitives" -license = "MIT/Apache-2.0" -name = "uint" -version = "0.2.1" -authors = ["Parity Technologies "] -build = "build.rs" - -[build-dependencies] -rustc_version = "0.2" - -[dependencies] -byteorder = { version = "1", default-features = false } -heapsize = { version = "0.4.2", optional = true } -rustc-hex = { version = "1.0", optional = true } -quickcheck = { version = "0.6", optional = true } - -[dev-dependencies] -crunchy = "0.1.5" - -[features] -std = ["rustc-hex", "byteorder/std"] -heapsizeof = ["heapsize"] -use_asm = [] -impl_quickcheck_arbitrary = ["quickcheck"] - -[[example]] -name = "modular" -required-features = ["std"] diff --git a/uint/build.rs b/uint/build.rs deleted file mode 100644 index 3ba1687..0000000 --- a/uint/build.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2015-2017 Parity Technologies -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -extern crate rustc_version; - -use rustc_version::{version_meta, Channel}; - -fn main() { - if cfg!(feature = "use_asm") { - if let Channel::Nightly = version_meta().unwrap().channel { - println!("cargo:rustc-cfg=asm_available"); - } - } -} diff --git a/uint/examples/modular.rs b/uint/examples/modular.rs deleted file mode 100644 index b7ce44a..0000000 --- a/uint/examples/modular.rs +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright 2015-2017 Parity Technologies -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[cfg(feature="std")] -extern crate core; - -#[macro_use] -extern crate crunchy; - -#[macro_use] -extern crate uint; - -construct_uint!(U256, 32); - -fn main() { - // Example modular arithmetic using bigint U256 primitives - - // imagine the field 0..p - // where the p is defined below - // (it's a prime!) - let p = U256::from_dec_str( - "38873241744847760218045702002058062581688990428170398542849190507947196700873" - ).expect("p to be a good number in the example"); - - // then, on this field, - // (p-1) + (p+1) = 0 - - // (p - 1) mod p - let p_minus_1 = (p - 1) % p; - // (p + 1) mod p - let p_plus_1 = (p + 1) % p; - // ((p - 1) mod p + (p + 1) mod p) mod p - let sum = (p_minus_1 + p_plus_1) % p; - assert_eq!(sum, 0.into()); - - // on this field, - // (p-1) + (p-1) = p-2 - let p_minus_1 = (p - 1) % p; - let sum = (p_minus_1 + p_minus_1) % p; - assert_eq!(sum, p - 2); - - // on this field, - // (p-1) * 3 = p-3 - let p_minus_1 = (p - 1) % p; - - // multiplication is a series of additions - let multiplicator = 3; - let mul = { - let mut result = p_minus_1; - for _ in 0..multiplicator-1 { - result = (p_minus_1 + result) % p; - } - result - }; - - assert_eq!(mul, p - 3); -} diff --git a/uint/src/lib.rs b/uint/src/lib.rs deleted file mode 100644 index 40a3a8d..0000000 --- a/uint/src/lib.rs +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2015-2017 Parity Technologies -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Efficient large, fixed-size big integers and hashes. - -#![cfg_attr(asm_available, feature(asm))] -#![cfg_attr(not(feature = "std"), no_std)] - -#[doc(hidden)] -pub extern crate byteorder; - -#[cfg(feature="heapsizeof")] -#[doc(hidden)] -pub extern crate heapsize; - -#[cfg(feature="std")] -#[doc(hidden)] -pub extern crate core; - -#[cfg(feature = "std")] -#[doc(hidden)] -pub extern crate rustc_hex; - -#[cfg(feature="impl_quickcheck_arbitrary")] -#[doc(hidden)] -pub extern crate quickcheck; - -mod uint; -pub use uint::*; diff --git a/uint/src/uint.rs b/uint/src/uint.rs deleted file mode 100644 index b5ee3d0..0000000 --- a/uint/src/uint.rs +++ /dev/null @@ -1,1621 +0,0 @@ -// Copyright 2015-2017 Parity Technologies -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Code derived from original work by Andrew Poelstra - -// Rust Bitcoin Library -// Written in 2014 by -// Andrew Poelstra -// -// To the extent possible under law, the author(s) have dedicated all -// copyright and related and neighboring rights to this software to -// the public domain worldwide. This software is distributed without -// any warranty. -// -// You should have received a copy of the CC0 Public Domain Dedication -// along with this software. -// If not, see . -// - -//! Big unsigned integer types. -//! -//! Implementation of a various large-but-fixed sized unsigned integer types. -//! The functions here are designed to be fast. There are optional `x86_64` -//! implementations for even more speed, hidden behind the `x64_arithmetic` -//! feature flag. - -/// Conversion from decimal string error -#[derive(Debug, PartialEq)] -pub enum FromDecStrErr { - /// Char not from range 0-9 - InvalidCharacter, - /// Value does not fit into type - InvalidLength, -} - -#[macro_export] -#[doc(hidden)] -macro_rules! impl_map_from { - ($thing:ident, $from:ty, $to:ty) => { - impl From<$from> for $thing { - fn from(value: $from) -> $thing { - From::from(value as $to) - } - } - } -} - -#[cfg(not(all(asm_available, target_arch="x86_64")))] -#[macro_export] -#[doc(hidden)] -macro_rules! uint_overflowing_add { - ($name:ident, $n_words: tt, $self_expr: expr, $other: expr) => ({ - uint_overflowing_add_reg!($name, $n_words, $self_expr, $other) - }) -} - -#[macro_export] -#[doc(hidden)] -macro_rules! uint_overflowing_add_reg { - ($name:ident, $n_words: tt, $self_expr: expr, $other: expr) => ({ - uint_overflowing_binop!( - $name, - $n_words, - $self_expr, - $other, - u64::overflowing_add - ) - }) -} - -#[cfg(all(asm_available, target_arch="x86_64"))] -#[macro_export] -#[doc(hidden)] -macro_rules! uint_overflowing_add { - (U256, $n_words: tt, $self_expr: expr, $other: expr) => ({ - let mut result: [u64; $n_words] = unsafe { ::core::mem::uninitialized() }; - let self_t: &[u64; $n_words] = &$self_expr.0; - let other_t: &[u64; $n_words] = &$other.0; - - let overflow: u8; - unsafe { - asm!(" - add $9, $0 - adc $10, $1 - adc $11, $2 - adc $12, $3 - setc %al - " - : "=r"(result[0]), "=r"(result[1]), "=r"(result[2]), "=r"(result[3]), "={al}"(overflow) - : "0"(self_t[0]), "1"(self_t[1]), "2"(self_t[2]), "3"(self_t[3]), - "mr"(other_t[0]), "mr"(other_t[1]), "mr"(other_t[2]), "mr"(other_t[3]) - : - : - ); - } - (U256(result), overflow != 0) - }); - (U512, $n_words: tt, $self_expr: expr, $other: expr) => ({ - let mut result: [u64; $n_words] = unsafe { ::core::mem::uninitialized() }; - let self_t: &[u64; $n_words] = &$self_expr.0; - let other_t: &[u64; $n_words] = &$other.0; - - let overflow: u8; - - unsafe { - asm!(" - add $15, $0 - adc $16, $1 - adc $17, $2 - adc $18, $3 - lodsq - adc $11, %rax - stosq - lodsq - adc $12, %rax - stosq - lodsq - adc $13, %rax - stosq - lodsq - adc $14, %rax - stosq - setc %al - - ": "=r"(result[0]), "=r"(result[1]), "=r"(result[2]), "=r"(result[3]), - - "={al}"(overflow) /* $0 - $4 */ - - : "{rdi}"(&result[4] as *const u64) /* $5 */ - "{rsi}"(&other_t[4] as *const u64) /* $6 */ - "0"(self_t[0]), "1"(self_t[1]), "2"(self_t[2]), "3"(self_t[3]), - "m"(self_t[4]), "m"(self_t[5]), "m"(self_t[6]), "m"(self_t[7]), - /* $7 - $14 */ - - "mr"(other_t[0]), "mr"(other_t[1]), "mr"(other_t[2]), "mr"(other_t[3]), - "m"(other_t[4]), "m"(other_t[5]), "m"(other_t[6]), "m"(other_t[7]) /* $15 - $22 */ - : "rdi", "rsi" - : - ); - } - (U512(result), overflow != 0) - }); - - ($name:ident, $n_words: tt, $self_expr: expr, $other: expr) => ( - uint_overflowing_add_reg!($name, $n_words, $self_expr, $other) - ) -} - -#[cfg(not(all(asm_available, target_arch="x86_64")))] -#[macro_export] -#[doc(hidden)] -macro_rules! uint_overflowing_sub { - ($name:ident, $n_words: tt, $self_expr: expr, $other: expr) => ({ - uint_overflowing_sub_reg!($name, $n_words, $self_expr, $other) - }) -} - -#[macro_export] -#[doc(hidden)] -macro_rules! uint_overflowing_binop { - ($name:ident, $n_words: tt, $self_expr: expr, $other: expr, $fn:expr) => ({ - let $name(ref me) = $self_expr; - let $name(ref you) = $other; - - let mut ret = unsafe { ::core::mem::uninitialized() }; - let ret_ptr = &mut ret as *mut [u64; $n_words] as *mut u64; - let mut carry = 0u64; - - unroll! { - for i in 0..$n_words { - use ::core::ptr; - - if carry != 0 { - let (res1, overflow1) = ($fn)(me[i], you[i]); - let (res2, overflow2) = ($fn)(res1, carry); - - unsafe { - ptr::write( - ret_ptr.offset(i as _), - res2 - ); - } - carry = (overflow1 as u8 + overflow2 as u8) as u64; - } else { - let (res, overflow) = ($fn)(me[i], you[i]); - - unsafe { - ptr::write( - ret_ptr.offset(i as _), - res - ); - } - - carry = overflow as u64; - } - } - } - - ($name(ret), carry > 0) - }) -} - -#[macro_export] -#[doc(hidden)] -macro_rules! uint_overflowing_sub_reg { - ($name:ident, $n_words: tt, $self_expr: expr, $other: expr) => ({ - uint_overflowing_binop!( - $name, - $n_words, - $self_expr, - $other, - u64::overflowing_sub - ) - }) -} - -#[cfg(all(asm_available, target_arch="x86_64"))] -#[macro_export] -#[doc(hidden)] -macro_rules! uint_overflowing_sub { - (U256, $n_words: tt, $self_expr: expr, $other: expr) => ({ - let mut result: [u64; $n_words] = unsafe { ::core::mem::uninitialized() }; - let self_t: &[u64; $n_words] = &$self_expr.0; - let other_t: &[u64; $n_words] = &$other.0; - - let overflow: u8; - unsafe { - asm!(" - sub $9, $0 - sbb $10, $1 - sbb $11, $2 - sbb $12, $3 - setb %al - " - : "=r"(result[0]), "=r"(result[1]), "=r"(result[2]), "=r"(result[3]), "={al}"(overflow) - : "0"(self_t[0]), "1"(self_t[1]), "2"(self_t[2]), "3"(self_t[3]), "mr"(other_t[0]), "mr"(other_t[1]), "mr"(other_t[2]), "mr"(other_t[3]) - : - : - ); - } - (U256(result), overflow != 0) - }); - (U512, $n_words: tt, $self_expr: expr, $other: expr) => ({ - let mut result: [u64; $n_words] = unsafe { ::core::mem::uninitialized() }; - let self_t: &[u64; $n_words] = &$self_expr.0; - let other_t: &[u64; $n_words] = &$other.0; - - let overflow: u8; - - unsafe { - asm!(" - sub $15, $0 - sbb $16, $1 - sbb $17, $2 - sbb $18, $3 - lodsq - sbb $19, %rax - stosq - lodsq - sbb $20, %rax - stosq - lodsq - sbb $21, %rax - stosq - lodsq - sbb $22, %rax - stosq - setb %al - " - : "=r"(result[0]), "=r"(result[1]), "=r"(result[2]), "=r"(result[3]), - - "={al}"(overflow) /* $0 - $4 */ - - : "{rdi}"(&result[4] as *const u64) /* $5 */ - "{rsi}"(&self_t[4] as *const u64) /* $6 */ - "0"(self_t[0]), "1"(self_t[1]), "2"(self_t[2]), "3"(self_t[3]), - "m"(self_t[4]), "m"(self_t[5]), "m"(self_t[6]), "m"(self_t[7]), - /* $7 - $14 */ - - "m"(other_t[0]), "m"(other_t[1]), "m"(other_t[2]), "m"(other_t[3]), - "m"(other_t[4]), "m"(other_t[5]), "m"(other_t[6]), "m"(other_t[7]) /* $15 - $22 */ - : "rdi", "rsi" - : - ); - } - (U512(result), overflow != 0) - }); - ($name:ident, $n_words: tt, $self_expr: expr, $other: expr) => ({ - uint_overflowing_sub_reg!($name, $n_words, $self_expr, $other) - }) -} - -#[cfg(all(asm_available, target_arch="x86_64"))] -#[macro_export] -macro_rules! uint_overflowing_mul { - (U256, $n_words: tt, $self_expr: expr, $other: expr) => ({ - let mut result: [u64; $n_words] = unsafe { ::core::mem::uninitialized() }; - let self_t: &[u64; $n_words] = &$self_expr.0; - let other_t: &[u64; $n_words] = &$other.0; - - let overflow: u64; - unsafe { - asm!(" - mov $5, %rax - mulq $9 - mov %rax, $0 - mov %rdx, $1 - - mov $5, %rax - mulq $10 - add %rax, $1 - adc $$0, %rdx - mov %rdx, $2 - - mov $5, %rax - mulq $11 - add %rax, $2 - adc $$0, %rdx - mov %rdx, $3 - - mov $5, %rax - mulq $12 - add %rax, $3 - adc $$0, %rdx - mov %rdx, %rcx - - mov $6, %rax - mulq $9 - add %rax, $1 - adc %rdx, $2 - adc $$0, $3 - adc $$0, %rcx - - mov $6, %rax - mulq $10 - add %rax, $2 - adc %rdx, $3 - adc $$0, %rcx - adc $$0, $3 - adc $$0, %rcx - - mov $6, %rax - mulq $11 - add %rax, $3 - adc $$0, %rdx - or %rdx, %rcx - - mov $7, %rax - mulq $9 - add %rax, $2 - adc %rdx, $3 - adc $$0, %rcx - - mov $7, %rax - mulq $10 - add %rax, $3 - adc $$0, %rdx - or %rdx, %rcx - - mov $8, %rax - mulq $9 - add %rax, $3 - or %rdx, %rcx - - cmpq $$0, %rcx - jne 2f - - mov $8, %rcx - jrcxz 12f - - mov $12, %rcx - mov $11, %rax - or %rax, %rcx - mov $10, %rax - or %rax, %rcx - jmp 2f - - 12: - mov $12, %rcx - jrcxz 11f - - mov $7, %rcx - mov $6, %rax - or %rax, %rcx - - cmpq $$0, %rcx - jne 2f - - 11: - mov $11, %rcx - jrcxz 2f - mov $7, %rcx - - 2: - " - : /* $0 */ "={r8}"(result[0]), /* $1 */ "={r9}"(result[1]), /* $2 */ "={r10}"(result[2]), - /* $3 */ "={r11}"(result[3]), /* $4 */ "={rcx}"(overflow) - - : /* $5 */ "m"(self_t[0]), /* $6 */ "m"(self_t[1]), /* $7 */ "m"(self_t[2]), - /* $8 */ "m"(self_t[3]), /* $9 */ "m"(other_t[0]), /* $10 */ "m"(other_t[1]), - /* $11 */ "m"(other_t[2]), /* $12 */ "m"(other_t[3]) - : "rax", "rdx" - : - - ); - } - (U256(result), overflow > 0) - }); - ($name:ident, $n_words: tt, $self_expr: expr, $other: expr) => ( - uint_overflowing_mul_reg!($name, $n_words, $self_expr, $other) - ) -} - -#[cfg(not(all(asm_available, target_arch="x86_64")))] -#[macro_export] -#[doc(hidden)] -macro_rules! uint_overflowing_mul { - ($name:ident, $n_words: tt, $self_expr: expr, $other: expr) => ({ - uint_overflowing_mul_reg!($name, $n_words, $self_expr, $other) - }) -} - -#[macro_export] -#[doc(hidden)] -macro_rules! uint_full_mul_reg { - ($name:ident, $n_words: tt, $self_expr:expr, $other:expr) => ({{ - #![allow(unused_assignments)] - - let $name(ref me) = $self_expr; - let $name(ref you) = $other; - let mut ret = [0u64; 2*$n_words]; - - unroll! { - for i in 0..$n_words { - let mut carry = 0u64; - let (b_u, b_l) = $crate::split(you[i]); - - unroll! { - for j in 0..$n_words { - if me[j] != 0 || carry != 0 { - let a = $crate::split(me[j]); - - // multiply parts - let (c_l, overflow_l) = $crate::mul_u32(a, b_l, ret[i + j]); - let (c_u, overflow_u) = $crate::mul_u32(a, b_u, c_l >> 32); - ret[i + j] = (c_l & 0xFFFFFFFF) + (c_u << 32); - - // No overflow here - let res = (c_u >> 32) + (overflow_u << 32); - // possible overflows - let (res, o1) = res.overflowing_add(overflow_l + carry); - let (res, o2) = res.overflowing_add(ret[i + j + 1]); - ret[i + j + 1] = res; - - // Only single overflow possible there - carry = (o1 | o2) as u64; - } - } - } - } - } - - ret - }}) -} - -#[macro_export] -#[doc(hidden)] -macro_rules! uint_overflowing_mul_reg { - ($name:ident, $n_words: tt, $self_expr: expr, $other: expr) => ({ - let ret: [u64; $n_words * 2] = uint_full_mul_reg!($name, $n_words, $self_expr, $other); - - // The safety of this is enforced by the compiler - let ret: [[u64; $n_words]; 2] = unsafe { ::core::mem::transmute(ret) }; - - // The compiler WILL NOT inline this if you remove this annotation. - #[inline(always)] - fn any_nonzero(arr: &[u64; $n_words]) -> bool { - unroll! { - for i in 0..$n_words { - if arr[i] != 0 { - return true; - } - } - } - - false - } - - ($name(ret[0]), any_nonzero(&ret[1])) - }) -} - -#[macro_export] -#[doc(hidden)] -macro_rules! overflowing { - ($op: expr, $overflow: expr) => ( - { - let (overflow_x, overflow_overflow) = $op; - $overflow |= overflow_overflow; - overflow_x - } - ); - ($op: expr) => ( - { - let (overflow_x, _overflow_overflow) = $op; - overflow_x - } - ); -} - -#[macro_export] -#[doc(hidden)] -macro_rules! panic_on_overflow { - ($name: expr) => { - if $name { - panic!("arithmetic operation overflow") - } - } -} - -#[macro_export] -#[doc(hidden)] -macro_rules! impl_mul_from { - ($name: ty, $other: ident) => { - impl ::core::ops::Mul<$other> for $name { - type Output = $name; - - fn mul(self, other: $other) -> $name { - let bignum: $name = other.into(); - let (result, overflow) = self.overflowing_mul(bignum); - panic_on_overflow!(overflow); - result - } - } - - impl<'a> ::core::ops::Mul<&'a $other> for $name { - type Output = $name; - - fn mul(self, other: &'a $other) -> $name { - let bignum: $name = (*other).into(); - let (result, overflow) = self.overflowing_mul(bignum); - panic_on_overflow!(overflow); - result - } - } - - impl<'a> ::core::ops::Mul<&'a $other> for &'a $name { - type Output = $name; - - fn mul(self, other: &'a $other) -> $name { - let bignum: $name = (*other).into(); - let (result, overflow) = self.overflowing_mul(bignum); - panic_on_overflow!(overflow); - result - } - } - - impl<'a> ::core::ops::Mul<$other> for &'a $name { - type Output = $name; - - fn mul(self, other: $other) -> $name { - let bignum: $name = other.into(); - let (result, overflow) = self.overflowing_mul(bignum); - panic_on_overflow!(overflow); - result - } - } - } -} - -#[macro_export] -#[doc(hidden)] -macro_rules! impl_mulassign_from { - ($name: ident, $other: ident) => { - impl::core::ops::MulAssign<$other> for $name { - fn mul_assign(&mut self, other: $other) { - let result = *self * other; - *self = result - } - } - } -} - -#[inline(always)] -#[doc(hidden)] -pub fn mul_u32(a: (u64, u64), b: u64, carry: u64) -> (u64, u64) { - let upper = b * a.0; - let lower = b * a.1; - - let (res1, overflow1) = lower.overflowing_add(upper << 32); - let (res2, overflow2) = res1.overflowing_add(carry); - - let carry = (upper >> 32) + overflow1 as u64 + overflow2 as u64; - (res2, carry) -} - -#[inline(always)] -#[doc(hidden)] -pub fn split(a: u64) -> (u64, u64) { - (a >> 32, a & 0xFFFF_FFFF) -} - -#[macro_export] -macro_rules! construct_uint { - ($name:ident, $n_words: tt) => ( - /// Little-endian large integer type - #[repr(C)] - #[derive(Copy, Clone, Eq, PartialEq, Hash)] - pub struct $name(pub [u64; $n_words]); - - impl AsRef<$name> for $name { - fn as_ref(&self) -> &$name { - &self - } - } - - impl<'a> From<&'a $name> for $name { - fn from(x: &'a $name) -> $name { - *x - } - } - - impl $name { - /// Convert from a decimal string. - pub fn from_dec_str(value: &str) -> Result { - if !value.bytes().all(|b| b >= 48 && b <= 57) { - return Err($crate::FromDecStrErr::InvalidCharacter) - } - - let mut res = Self::default(); - for b in value.bytes().map(|b| b - 48) { - let (r, overflow) = res.overflowing_mul_u32(10); - if overflow { - return Err($crate::FromDecStrErr::InvalidLength); - } - let (r, overflow) = r.overflowing_add(b.into()); - if overflow { - return Err($crate::FromDecStrErr::InvalidLength); - } - res = r; - } - Ok(res) - } - - /// Conversion to u32 - #[inline] - pub fn low_u32(&self) -> u32 { - let &$name(ref arr) = self; - arr[0] as u32 - } - - /// Conversion to u64 - #[inline] - pub fn low_u64(&self) -> u64 { - let &$name(ref arr) = self; - arr[0] - } - - /// Conversion to u32 with overflow checking - /// - /// # Panics - /// - /// Panics if the number is larger than 2^32. - #[inline] - pub fn as_u32(&self) -> u32 { - let &$name(ref arr) = self; - if (arr[0] & (0xffffffffu64 << 32)) != 0 { - panic!("Integer overflow when casting U256") - } - self.as_u64() as u32 - } - - /// Conversion to u64 with overflow checking - /// - /// # Panics - /// - /// Panics if the number is larger than 2^64. - #[inline] - pub fn as_u64(&self) -> u64 { - let &$name(ref arr) = self; - for i in 1..$n_words { - if arr[i] != 0 { - panic!("Integer overflow when casting U256") - } - } - arr[0] - } - - /// Conversion to usize with overflow checking - /// - /// # Panics - /// - /// Panics if the number is larger than usize::max_value(). - #[inline] - pub fn as_usize(&self) -> usize { - let &$name(ref arr) = self; - for i in 1..$n_words { - if arr[i] != 0 { - panic!("Integer overflow when casting U256") - } - } - if arr[0] > usize::max_value() as u64 { - panic!("Integer overflow when casting U256") - } - arr[0] as usize - } - - /// Whether this is zero. - #[inline] - pub fn is_zero(&self) -> bool { - let &$name(ref arr) = self; - for i in 0..$n_words { if arr[i] != 0 { return false; } } - return true; - } - - /// Return the least number of bits needed to represent the number - #[inline] - pub fn bits(&self) -> usize { - let &$name(ref arr) = self; - for i in 1..$n_words { - if arr[$n_words - i] > 0 { return (0x40 * ($n_words - i + 1)) - arr[$n_words - i].leading_zeros() as usize; } - } - 0x40 - arr[0].leading_zeros() as usize - } - - /// Return if specific bit is set. - /// - /// # Panics - /// - /// Panics if `index` exceeds the bit width of the number. - #[inline] - pub fn bit(&self, index: usize) -> bool { - let &$name(ref arr) = self; - arr[index / 64] & (1 << (index % 64)) != 0 - } - - /// Returns the number of leading zeros in the binary representation of self. - pub fn leading_zeros(&self) -> u32 { - let mut r = 0; - for i in 0..$n_words { - let w = self.0[$n_words - i - 1]; - if w == 0 { - r += 64; - } else { - r += w.leading_zeros(); - break; - } - } - r - } - - /// Returns the number of leading zeros in the binary representation of self. - pub fn trailing_zeros(&self) -> u32 { - let mut r = 0; - for i in 0..$n_words { - let w = self.0[i]; - if w == 0 { - r += 64; - } else { - r += w.trailing_zeros(); - break; - } - } - r - } - - /// Return specific byte. - /// - /// # Panics - /// - /// Panics if `index` exceeds the byte width of the number. - #[inline] - pub fn byte(&self, index: usize) -> u8 { - let &$name(ref arr) = self; - (arr[index / 8] >> (((index % 8)) * 8)) as u8 - } - - /// Write to the slice in big-endian format. - #[inline] - pub fn to_big_endian(&self, bytes: &mut [u8]) { - use $crate::byteorder::{ByteOrder, BigEndian}; - debug_assert!($n_words * 8 == bytes.len()); - for i in 0..$n_words { - BigEndian::write_u64(&mut bytes[8 * i..], self.0[$n_words - i - 1]); - } - } - - /// Write to the slice in little-endian format. - #[inline] - pub fn to_little_endian(&self, bytes: &mut [u8]) { - use $crate::byteorder::{ByteOrder, LittleEndian}; - debug_assert!($n_words * 8 == bytes.len()); - for i in 0..$n_words { - LittleEndian::write_u64(&mut bytes[8 * i..], self.0[i]); - } - } - - - /// Create `10**n` as this type. - /// - /// # Panics - /// - /// Panics if the result overflows the type. - #[inline] - pub fn exp10(n: usize) -> Self { - match n { - 0 => Self::from(1u64), - _ => Self::exp10(n - 1) * 10u32 - } - } - - /// Zero (additive identity) of this type. - #[inline] - pub fn zero() -> Self { - From::from(0u64) - } - - /// One (multiplicative identity) of this type. - #[inline] - pub fn one() -> Self { - From::from(1u64) - } - - /// The maximum value which can be inhabited by this type. - #[inline] - pub fn max_value() -> Self { - let mut result = [0; $n_words]; - for i in 0..$n_words { - result[i] = u64::max_value(); - } - $name(result) - } - - /// Fast exponentation by squaring - /// https://en.wikipedia.org/wiki/Exponentiation_by_squaring - /// - /// # Panics - /// - /// Panics if the result overflows the type. - pub fn pow(self, expon: Self) -> Self { - if expon.is_zero() { - return Self::one() - } - let is_even = |x : &Self| x.low_u64() & 1 == 0; - - let u_one = Self::one(); - let mut y = u_one; - let mut n = expon; - let mut x = self; - while n > u_one { - if is_even(&n) { - x = x * x; - n = n >> 1usize; - } else { - y = x * y; - x = x * x; - // to reduce odd number by 1 we should just clear the last bit - n.0[$n_words-1] = n.0[$n_words-1] & ((!0u64)>>1); - n = n >> 1usize; - } - } - x * y - } - - /// Fast exponentation by squaring - /// https://en.wikipedia.org/wiki/Exponentiation_by_squaring - pub fn overflowing_pow(self, expon: Self) -> (Self, bool) { - if expon.is_zero() { return (Self::one(), false) } - - let is_even = |x : &Self| x.low_u64() & 1 == 0; - - let u_one = Self::one(); - let mut y = u_one; - let mut n = expon; - let mut x = self; - let mut overflow = false; - - while n > u_one { - if is_even(&n) { - x = overflowing!(x.overflowing_mul(x), overflow); - n = n >> 1usize; - } else { - y = overflowing!(x.overflowing_mul(y), overflow); - x = overflowing!(x.overflowing_mul(x), overflow); - n = (n - u_one) >> 1usize; - } - } - let res = overflowing!(x.overflowing_mul(y), overflow); - (res, overflow) - } - - /// Optimized instructions - #[inline(always)] - pub fn overflowing_add(self, other: $name) -> ($name, bool) { - uint_overflowing_add!($name, $n_words, self, other) - } - - /// Addition which saturates at the maximum value. - pub fn saturating_add(self, other: $name) -> $name { - match self.overflowing_add(other) { - (_, true) => $name::max_value(), - (val, false) => val, - } - } - - /// Checked addition. Returns `None` if overflow occurred. - pub fn checked_add(self, other: $name) -> Option<$name> { - match self.overflowing_add(other) { - (_, true) => None, - (val, _) => Some(val), - } - } - - /// Subtraction which underflows and returns a flag if it does. - #[inline(always)] - pub fn overflowing_sub(self, other: $name) -> ($name, bool) { - uint_overflowing_sub!($name, $n_words, self, other) - } - - /// Subtraction which saturates at zero. - pub fn saturating_sub(self, other: $name) -> $name { - match self.overflowing_sub(other) { - (_, true) => $name::zero(), - (val, false) => val, - } - } - - /// Checked subtraction. Returns `None` if overflow occurred. - pub fn checked_sub(self, other: $name) -> Option<$name> { - match self.overflowing_sub(other) { - (_, true) => None, - (val, _) => Some(val), - } - } - - /// Multiply with overflow, returning a flag if it does. - #[inline(always)] - pub fn overflowing_mul(self, other: $name) -> ($name, bool) { - uint_overflowing_mul!($name, $n_words, self, other) - } - - /// Multiplication which saturates at the maximum value.. - pub fn saturating_mul(self, other: $name) -> $name { - match self.overflowing_mul(other) { - (_, true) => $name::max_value(), - (val, false) => val, - } - } - - /// Checked multiplication. Returns `None` if overflow occurred. - pub fn checked_mul(self, other: $name) -> Option<$name> { - match self.overflowing_mul(other) { - (_, true) => None, - (val, _) => Some(val), - } - } - - /// Division with overflow - pub fn overflowing_div(self, other: $name) -> ($name, bool) { - (self / other, false) - } - - /// Checked division. Returns `None` if `other == 0`. - pub fn checked_div(self, other: $name) -> Option<$name> { - if other.is_zero() { - None - } else { - Some(self / other) - } - } - - /// Modulus with overflow. - pub fn overflowing_rem(self, other: $name) -> ($name, bool) { - (self % other, false) - } - - /// Checked modulus. Returns `None` if `other == 0`. - pub fn checked_rem(self, other: $name) -> Option<$name> { - if other.is_zero() { - None - } else { - Some(self % other) - } - } - - /// Negation with overflow. - pub fn overflowing_neg(self) -> ($name, bool) { - if self.is_zero() { - (self, false) - } else { - (!self, true) - } - } - - /// Checked negation. Returns `None` unless `self == 0`. - pub fn checked_neg(self) -> Option<$name> { - match self.overflowing_neg() { - (_, true) => None, - (zero, false) => Some(zero), - } - } - - /// Multiplication by u32 - #[deprecated(note = "Use Mul instead.")] - pub fn mul_u32(self, other: u32) -> Self { - self * other - } - - /// Overflowing multiplication by u32 - #[allow(dead_code)] // not used when multiplied with inline assembly - fn overflowing_mul_u32(self, other: u32) -> (Self, bool) { - let $name(ref arr) = self; - let mut ret = [0u64; $n_words]; - let mut carry = 0; - let o = other as u64; - - for i in 0..$n_words { - let (res, carry2) = $crate::mul_u32($crate::split(arr[i]), o, carry); - ret[i] = res; - carry = carry2; - } - - ($name(ret), carry > 0) - } - - impl_std_for_uint_internals!($name, $n_words); - - /// Converts from big endian representation bytes in memory - /// Can also be used as (&slice).into(), as it is default `From` - /// slice implementation for U256 - pub fn from_big_endian(slice: &[u8]) -> Self { - assert!($n_words * 8 >= slice.len()); - - let mut ret = [0; $n_words]; - unsafe { - let ret_u8: &mut [u8; $n_words * 8] = ::core::mem::transmute(&mut ret); - let mut ret_ptr = ret_u8.as_mut_ptr(); - let mut slice_ptr = slice.as_ptr().offset(slice.len() as isize - 1); - for _ in 0..slice.len() { - *ret_ptr = *slice_ptr; - ret_ptr = ret_ptr.offset(1); - slice_ptr = slice_ptr.offset(-1); - } - } - - $name(ret) - } - - /// Converts from little endian representation bytes in memory - pub fn from_little_endian(slice: &[u8]) -> Self { - assert!($n_words * 8 >= slice.len()); - - let mut ret = [0; $n_words]; - unsafe { - let ret_u8: &mut [u8; $n_words * 8] = ::core::mem::transmute(&mut ret); - ret_u8[0..slice.len()].copy_from_slice(&slice); - } - - $name(ret) - } - } - - impl Default for $name { - fn default() -> Self { - $name::zero() - } - } - - impl From for $name { - fn from(value: u64) -> $name { - let mut ret = [0; $n_words]; - ret[0] = value; - $name(ret) - } - } - - - impl_map_from!($name, u8, u64); - impl_map_from!($name, u16, u64); - impl_map_from!($name, u32, u64); - impl_map_from!($name, usize, u64); - - impl From for $name { - fn from(value: i64) -> $name { - match value >= 0 { - true => From::from(value as u64), - false => { panic!("Unsigned integer can't be created from negative value"); } - } - } - } - - impl_map_from!($name, i8, i64); - impl_map_from!($name, i16, i64); - impl_map_from!($name, i32, i64); - impl_map_from!($name, isize, i64); - - // Converts from big endian representation of U256 - impl<'a> From<&'a [u8]> for $name { - fn from(bytes: &[u8]) -> $name { - Self::from_big_endian(bytes) - } - } - - impl ::core::ops::Add for $name where T: Into<$name> { - type Output = $name; - - fn add(self, other: T) -> $name { - let (result, overflow) = self.overflowing_add(other.into()); - panic_on_overflow!(overflow); - result - } - } - - impl<'a, T> ::core::ops::Add for &'a $name where T: Into<$name> { - type Output = $name; - - fn add(self, other: T) -> $name { - *self + other - } - } - - impl ::core::ops::AddAssign<$name> for $name { - fn add_assign(&mut self, other: $name) { - let (result, overflow) = self.overflowing_add(other); - panic_on_overflow!(overflow); - *self = result - } - } - - impl ::core::ops::Sub for $name where T: Into<$name> { - type Output = $name; - - #[inline] - fn sub(self, other: T) -> $name { - let (result, overflow) = self.overflowing_sub(other.into()); - panic_on_overflow!(overflow); - result - } - } - - impl<'a, T> ::core::ops::Sub for &'a $name where T: Into<$name> { - type Output = $name; - - fn sub(self, other: T) -> $name { - *self - other - } - } - - impl ::core::ops::SubAssign<$name> for $name { - fn sub_assign(&mut self, other: $name) { - let (result, overflow) = self.overflowing_sub(other); - panic_on_overflow!(overflow); - *self = result - } - } - - // specialization for u32 - impl ::core::ops::Mul for $name { - type Output = $name; - - fn mul(self, other: u32) -> $name { - let (ret, overflow) = self.overflowing_mul_u32(other); - panic_on_overflow!(overflow); - ret - } - } - - impl<'a> ::core::ops::Mul for &'a $name { - type Output = $name; - - fn mul(self, other: u32) -> $name { - *self * other - } - } - - impl ::core::ops::MulAssign for $name { - fn mul_assign(&mut self, other: u32) { - let result = *self * other; - *self = result - } - } - - // all other impls - impl_mul_from!($name, u8); - impl_mul_from!($name, u16); - impl_mul_from!($name, u64); - impl_mul_from!($name, usize); - - impl_mul_from!($name, i8); - impl_mul_from!($name, i16); - impl_mul_from!($name, i64); - impl_mul_from!($name, isize); - - impl_mul_from!($name, $name); - - impl_mulassign_from!($name, u8); - impl_mulassign_from!($name, u16); - impl_mulassign_from!($name, u64); - impl_mulassign_from!($name, usize); - - impl_mulassign_from!($name, i8); - impl_mulassign_from!($name, i16); - impl_mulassign_from!($name, i64); - impl_mulassign_from!($name, isize); - - impl_mulassign_from!($name, $name); - - impl ::core::ops::Div for $name where T: Into<$name> { - type Output = $name; - - fn div(self, other: T) -> $name { - let other: Self = other.into(); - let mut sub_copy = self; - let mut shift_copy = other; - let mut ret = [0u64; $n_words]; - - let my_bits = self.bits(); - let your_bits = other.bits(); - - // Check for division by 0 - assert!(your_bits != 0); - - // Early return in case we are dividing by a larger number than us - if my_bits < your_bits { - return $name(ret); - } - - // Bitwise long division - let mut shift = my_bits - your_bits; - shift_copy = shift_copy << shift; - loop { - if sub_copy >= shift_copy { - ret[shift / 64] |= 1 << (shift % 64); - sub_copy = overflowing!(sub_copy.overflowing_sub(shift_copy)); - } - shift_copy = shift_copy >> 1usize; - if shift == 0 { break; } - shift -= 1; - } - - $name(ret) - } - } - - impl<'a, T> ::core::ops::Div for &'a $name where T: Into<$name> { - type Output = $name; - - fn div(self, other: T) -> $name { - *self / other - } - } - - impl ::core::ops::DivAssign for $name where T: Into<$name> { - fn div_assign(&mut self, other: T) { - let (result, overflow) = self.overflowing_div(other.into()); - panic_on_overflow!(overflow); - *self = result - } - } - - impl ::core::ops::Rem for $name where T: Into<$name> + Copy { - type Output = $name; - - fn rem(self, other: T) -> $name { - let times = self / other; - self - (times * other.into()) - } - } - - impl<'a, T> ::core::ops::Rem for &'a $name where T: Into<$name> + Copy { - type Output = $name; - - fn rem(self, other: T) -> $name { - *self % other - } - } - - impl ::core::ops::RemAssign for $name where T: Into<$name> + Copy { - fn rem_assign(&mut self, other: T) { - let times = *self / other; - *self -= times * other.into() - } - } - - impl ::core::ops::BitAnd<$name> for $name { - type Output = $name; - - #[inline] - fn bitand(self, other: $name) -> $name { - let $name(ref arr1) = self; - let $name(ref arr2) = other; - let mut ret = [0u64; $n_words]; - for i in 0..$n_words { - ret[i] = arr1[i] & arr2[i]; - } - $name(ret) - } - } - - impl ::core::ops::BitXor<$name> for $name { - type Output = $name; - - #[inline] - fn bitxor(self, other: $name) -> $name { - let $name(ref arr1) = self; - let $name(ref arr2) = other; - let mut ret = [0u64; $n_words]; - for i in 0..$n_words { - ret[i] = arr1[i] ^ arr2[i]; - } - $name(ret) - } - } - - impl ::core::ops::BitOr<$name> for $name { - type Output = $name; - - #[inline] - fn bitor(self, other: $name) -> $name { - let $name(ref arr1) = self; - let $name(ref arr2) = other; - let mut ret = [0u64; $n_words]; - for i in 0..$n_words { - ret[i] = arr1[i] | arr2[i]; - } - $name(ret) - } - } - - impl ::core::ops::Not for $name { - type Output = $name; - - #[inline] - fn not(self) -> $name { - let $name(ref arr) = self; - let mut ret = [0u64; $n_words]; - for i in 0..$n_words { - ret[i] = !arr[i]; - } - $name(ret) - } - } - - impl ::core::ops::Shl for $name where T: Into<$name> { - type Output = $name; - - fn shl(self, shift: T) -> $name { - let shift = shift.into().as_usize(); - let $name(ref original) = self; - let mut ret = [0u64; $n_words]; - let word_shift = shift / 64; - let bit_shift = shift % 64; - - // shift - for i in word_shift..$n_words { - ret[i] = original[i - word_shift] << bit_shift; - } - // carry - if bit_shift > 0 { - for i in word_shift+1..$n_words { - ret[i] += original[i - 1 - word_shift] >> (64 - bit_shift); - } - } - $name(ret) - } - } - - impl<'a, T> ::core::ops::Shl for &'a $name where T: Into<$name> { - type Output = $name; - fn shl(self, shift: T) -> $name { - *self << shift - } - } - - impl ::core::ops::ShlAssign for $name where T: Into<$name> { - fn shl_assign(&mut self, shift: T) { - *self = *self << shift; - } - } - - impl ::core::ops::Shr for $name where T: Into<$name> { - type Output = $name; - - fn shr(self, shift: T) -> $name { - let shift = shift.into().as_usize(); - let $name(ref original) = self; - let mut ret = [0u64; $n_words]; - let word_shift = shift / 64; - let bit_shift = shift % 64; - - // shift - for i in word_shift..$n_words { - ret[i - word_shift] = original[i] >> bit_shift; - } - - // Carry - if bit_shift > 0 { - for i in word_shift+1..$n_words { - ret[i - word_shift - 1] += original[i] << (64 - bit_shift); - } - } - - $name(ret) - } - } - - impl<'a, T> ::core::ops::Shr for &'a $name where T: Into<$name> { - type Output = $name; - fn shr(self, shift: T) -> $name { - *self >> shift - } - } - - impl ::core::ops::ShrAssign for $name where T: Into<$name> { - fn shr_assign(&mut self, shift: T) { - *self = *self >> shift; - } - } - - impl Ord for $name { - fn cmp(&self, other: &$name) -> ::core::cmp::Ordering { - let &$name(ref me) = self; - let &$name(ref you) = other; - let mut i = $n_words; - while i > 0 { - i -= 1; - if me[i] < you[i] { return ::core::cmp::Ordering::Less; } - if me[i] > you[i] { return ::core::cmp::Ordering::Greater; } - } - ::core::cmp::Ordering::Equal - } - } - - impl PartialOrd for $name { - fn partial_cmp(&self, other: &$name) -> Option<::core::cmp::Ordering> { - Some(self.cmp(other)) - } - } - - impl_std_for_uint!($name, $n_words); - impl_heapsize_for_uint!($name); - // `$n_words * 8` because macro expects bytes and - // uints use 64 bit (8 byte) words - impl_quickcheck_arbitrary_for_uint!($name, ($n_words * 8)); - ); -} - -#[cfg(feature="std")] -#[macro_export] -#[doc(hidden)] -macro_rules! impl_std_for_uint_internals { - ($name: ident, $n_words: tt) => { - /// Convert to hex string. - #[deprecated(note = "Use LowerHex instead.")] - pub fn to_hex(&self) -> String { - format!("{:x}", self) - } - } -} - -#[cfg(feature="std")] -#[macro_export] -#[doc(hidden)] -macro_rules! impl_std_for_uint { - ($name: ident, $n_words: tt) => { - impl ::core::fmt::Debug for $name { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{:#x}", self) - } - } - - impl ::core::fmt::Display for $name { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - if self.is_zero() { - return write!(f, "0"); - } - - let mut s = String::new(); - let mut current = *self; - let ten = $name::from(10); - - while !current.is_zero() { - s = format!("{}{}", (current % ten).low_u32(), s); - current = current / ten; - } - - write!(f, "{}", s) - } - } - - impl ::core::str::FromStr for $name { - type Err = $crate::rustc_hex::FromHexError; - - fn from_str(value: &str) -> Result<$name, Self::Err> { - use $crate::rustc_hex::FromHex; - - let bytes: Vec = match value.len() % 2 == 0 { - true => try!(value.from_hex()), - false => try!(("0".to_owned() + value).from_hex()) - }; - - let bytes_ref: &[u8] = &bytes; - Ok(From::from(bytes_ref)) - } - } - - impl ::core::fmt::LowerHex for $name { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - let &$name(ref data) = self; - if f.alternate() { - write!(f, "0x"); - } - // special case. - if self.is_zero() { - return write!(f, "0"); - } - - let mut latch = false; - for ch in data.iter().rev() { - for x in 0..16 { - let nibble = (ch & (15u64 << ((15 - x) * 4) as u64)) >> (((15 - x) * 4) as u64); - if !latch { - latch = nibble != 0; - } - - if latch { - write!(f, "{:x}", nibble)?; - } - } - } - Ok(()) - } - } - - impl From<&'static str> for $name { - fn from(s: &'static str) -> Self { - s.parse().unwrap() - } - } - } -} - -#[cfg(not(feature="std"))] -#[macro_export] -#[doc(hidden)] -macro_rules! impl_std_for_uint { - ($name: ident, $n_words: tt) => {} -} - -#[cfg(not(feature="std"))] -#[macro_export] -#[doc(hidden)] -macro_rules! impl_std_for_uint_internals { - ($name: ident, $n_words: tt) => {} -} - -#[cfg(feature="heapsizeof")] -#[macro_export] -#[doc(hidden)] -macro_rules! impl_heapsize_for_uint { - ($name: ident) => { - impl $crate::heapsize::HeapSizeOf for $name { - fn heap_size_of_children(&self) -> usize { - 0 - } - } - } -} - -#[cfg(not(feature="heapsizeof"))] -#[macro_export] -#[doc(hidden)] -macro_rules! impl_heapsize_for_uint { - ($name: ident) => {} -} - -#[cfg(feature="impl_quickcheck_arbitrary")] -#[macro_export] -#[doc(hidden)] -macro_rules! impl_quickcheck_arbitrary_for_uint { - ($uint: ty, $n_bytes: tt) => { - impl $crate::quickcheck::Arbitrary for $uint { - fn arbitrary(g: &mut G) -> Self { - let mut res = [0u8; $n_bytes]; - - let p = g.next_f64(); - // make it more likely to generate smaller numbers that - // don't use up the full $n_bytes - let range = - // 10% chance to generate number that uses up to $n_bytes - if p < 0.1 { - $n_bytes - // 10% chance to generate number that uses up to $n_bytes / 2 - } else if p < 0.2 { - $n_bytes / 2 - // 80% chance to generate number that uses up to $n_bytes / 5 - } else { - $n_bytes / 5 - }; - - let size = g.gen_range(0, range); - g.fill_bytes(&mut res[..size]); - - res.as_ref().into() - } - } - } -} - -#[cfg(not(feature="impl_quickcheck_arbitrary"))] -#[macro_export] -#[doc(hidden)] -macro_rules! impl_quickcheck_arbitrary_for_uint { - ($uint: ty, $n_bytes: tt) => {} -}