diff --git a/Cargo.lock b/Cargo.lock index 60acec74a..155e5479f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -108,6 +108,17 @@ dependencies = [ "syntex_syntax 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "bigint" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "heapsize 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "bit-set" version = "0.4.0" @@ -377,10 +388,10 @@ dependencies = [ name = "ethcore-bigint" version = "0.1.2" dependencies = [ + "bigint 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2350,6 +2361,7 @@ dependencies = [ "checksum arrayvec 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)" = "16e3bdb2f54b3ace0285975d59a97cf8ed3855294b2b6bc651fcf22a9c352975" "checksum aster 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07d344974f0a155f091948aa389fb1b912d3a58414fbdb9c8d446d193ee3496a" "checksum aster 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4df293303e8a52e1df7984ac1415e195f5fcbf51e4bb7bda54557861a3954a08" +"checksum bigint 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2311bcd71b281e142a095311c22509f0d6bcd87b3000d7dbaa810929b9d6f6ae" "checksum bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9bf6104718e80d7b26a68fdbacff3481cfc05df670821affc7e9cbc1884400c" "checksum bit-vec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "5b97c2c8e8bbb4251754f559df8af22fb264853c7d009084a576cdf12565089d" "checksum bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dead7461c1127cf637931a1e50934eb6eee8bff2f74433ac7909e9afcee04a3" diff --git a/util/bigint/Cargo.toml b/util/bigint/Cargo.toml index 2b8d8313d..5fe02865c 100644 --- a/util/bigint/Cargo.toml +++ b/util/bigint/Cargo.toml @@ -6,12 +6,9 @@ license = "GPL-3.0" name = "ethcore-bigint" version = "0.1.2" authors = ["Parity Technologies "] -build = "build.rs" - -[build-dependencies] -rustc_version = "0.1" [dependencies] +bigint = "1.0" rustc-serialize = "0.3" heapsize = "0.3" rand = "0.3.12" diff --git a/util/bigint/build.rs b/util/bigint/build.rs deleted file mode 100644 index 2c945a24c..000000000 --- a/util/bigint/build.rs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2015, 2016 Parity Technologies (UK) Ltd. -// This file is part of Parity. - -// Parity is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity. If not, see . - -extern crate rustc_version; - -use rustc_version::{version_meta, Channel}; - -fn main() { - if let Channel::Nightly = version_meta().channel { - println!("cargo:rustc-cfg=asm_available"); - } -} diff --git a/util/bigint/src/hash.rs b/util/bigint/src/hash.rs index 29274fc52..cbfadc621 100644 --- a/util/bigint/src/hash.rs +++ b/util/bigint/src/hash.rs @@ -25,7 +25,7 @@ use std::str::FromStr; use rand::Rng; use rand::os::OsRng; use rustc_serialize::hex::{FromHex, FromHexError}; -use uint::{Uint, U256}; +use bigint::{Uint, U256}; /// Trait for a fixed-size byte array to be used as the output of hash functions. pub trait FixedHash: Sized { @@ -512,7 +512,7 @@ pub type H256FastSet = HashSet>; #[cfg(test)] mod tests { use hash::*; - use uint::*; + use bigint::*; use std::str::FromStr; #[test] diff --git a/util/bigint/src/lib.rs b/util/bigint/src/lib.rs index 30b47a24c..e394ba7fb 100644 --- a/util/bigint/src/lib.rs +++ b/util/bigint/src/lib.rs @@ -20,9 +20,9 @@ extern crate rand; extern crate rustc_serialize; +extern crate bigint; #[macro_use] extern crate heapsize; -pub mod uint; pub mod hash; /// A prelude module for re-exporting all the types defined in this crate. @@ -34,6 +34,6 @@ pub mod hash; /// let y = x + 1.into(); /// ``` pub mod prelude { - pub use ::uint::*; + pub use ::bigint::*; pub use ::hash::*; -} \ No newline at end of file +} diff --git a/util/bigint/src/uint.rs b/util/bigint/src/uint.rs deleted file mode 100644 index e2c06b664..000000000 --- a/util/bigint/src/uint.rs +++ /dev/null @@ -1,2290 +0,0 @@ -// Copyright 2015, 2016 Parity Technologies (UK) Ltd. -// This file is part of Parity. - -// Parity is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity. If not, see . - -// 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. - -use std::{mem, fmt, cmp}; -use std::str::{FromStr}; -use std::hash::Hash; -use std::ops::{Shr, Shl, BitAnd, BitOr, BitXor, Not, Div, Rem, Mul, Add, Sub}; -use std::cmp::Ordering; -use rustc_serialize::hex::{ToHex, FromHex, FromHexError}; - -/// 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_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_rules! uint_overflowing_add { - ($name:ident, $n_words:expr, $self_expr: expr, $other: expr) => ({ - uint_overflowing_add_reg!($name, $n_words, $self_expr, $other) - }) -} - -macro_rules! uint_overflowing_add_reg { - ($name:ident, $n_words:expr, $self_expr: expr, $other: expr) => ({ - let $name(ref me) = $self_expr; - let $name(ref you) = $other; - - let mut ret = [0u64; $n_words]; - let mut carry = 0u64; - - for i in 0..$n_words { - let (res1, overflow1) = me[i].overflowing_add(you[i]); - let (res2, overflow2) = res1.overflowing_add(carry); - - ret[i] = res2; - carry = overflow1 as u64 + overflow2 as u64; - } - - ($name(ret), carry > 0) - }) -} - -#[cfg(all(asm_available, target_arch="x86_64"))] -macro_rules! uint_overflowing_add { - (U256, $n_words: expr, $self_expr: expr, $other: expr) => ({ - let mut result: [u64; $n_words] = unsafe { 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: expr, $self_expr: expr, $other: expr) => ({ - let mut result: [u64; $n_words] = unsafe { 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:expr, $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_rules! uint_overflowing_sub { - ($name:ident, $n_words: expr, $self_expr: expr, $other: expr) => ({ - uint_overflowing_sub_reg!($name, $n_words, $self_expr, $other) - }) -} - -macro_rules! uint_overflowing_sub_reg { - ($name:ident, $n_words: expr, $self_expr: expr, $other: expr) => ({ - let $name(ref me) = $self_expr; - let $name(ref you) = $other; - - let mut ret = [0u64; $n_words]; - let mut carry = 0u64; - - for i in 0..$n_words { - let (res1, overflow1) = me[i].overflowing_sub(you[i]); - let (res2, overflow2) = res1.overflowing_sub(carry); - - ret[i] = res2; - carry = overflow1 as u64 + overflow2 as u64; - } - - ($name(ret), carry > 0) - - }) -} - -#[cfg(all(asm_available, target_arch="x86_64"))] -macro_rules! uint_overflowing_sub { - (U256, $n_words: expr, $self_expr: expr, $other: expr) => ({ - let mut result: [u64; $n_words] = unsafe { 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: expr, $self_expr: expr, $other: expr) => ({ - let mut result: [u64; $n_words] = unsafe { 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: expr, $self_expr: expr, $other: expr) => ({ - uint_overflowing_sub_reg!($name, $n_words, $self_expr, $other) - }) -} - -#[cfg(all(asm_available, target_arch="x86_64"))] -macro_rules! uint_overflowing_mul { - (U256, $n_words: expr, $self_expr: expr, $other: expr) => ({ - let mut result: [u64; $n_words] = unsafe { 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:expr, $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_rules! uint_overflowing_mul { - ($name:ident, $n_words: expr, $self_expr: expr, $other: expr) => ({ - uint_overflowing_mul_reg!($name, $n_words, $self_expr, $other) - }) -} - -macro_rules! uint_overflowing_mul_reg { - ($name:ident, $n_words: expr, $self_expr: expr, $other: expr) => ({ - let $name(ref me) = $self_expr; - let $name(ref you) = $other; - let mut ret = [0u64; 2*$n_words]; - - for i in 0..$n_words { - if you[i] == 0 { - continue; - } - - let mut carry2 = 0u64; - let (b_u, b_l) = split(you[i]); - - for j in 0..$n_words { - if me[j] == 0 && carry2 == 0 { - continue; - } - - let a = split(me[j]); - - // multiply parts - let (c_l, overflow_l) = mul_u32(a, b_l, ret[i + j]); - let (c_u, overflow_u) = 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); - let (res, o2) = res.overflowing_add(carry2); - let (res, o3) = res.overflowing_add(ret[i + j + 1]); - ret[i + j + 1] = res; - - // Only single overflow possible there - carry2 = (o1 | o2 | o3) as u64; - } - } - - let mut res = [0u64; $n_words]; - let mut overflow = false; - for i in 0..$n_words { - res[i] = ret[i]; - } - - for i in $n_words..2*$n_words { - overflow |= ret[i] != 0; - } - - ($name(res), overflow) - }) -} - -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_rules! panic_on_overflow { - ($name: expr) => { - if $name { - panic!("arithmetic operation overflow") - } - } -} - -#[inline(always)] -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)] -fn split(a: u64) -> (u64, u64) { - (a >> 32, a & 0xFFFFFFFF) -} - -/// Large, fixed-length unsigned integer type. -pub trait Uint: Sized + Default + FromStr + From + fmt::Debug + fmt::Display + PartialOrd + Ord + PartialEq + Eq + Hash { - - /// Returns new instance equalling zero. - fn zero() -> Self; - /// Returns new instance equalling one. - fn one() -> Self; - /// Returns the largest value that can be represented by this integer type. - fn max_value() -> Self; - - /// Convert from a decimal string. - fn from_dec_str(value: &str) -> Result; - - /// Conversion to u32 - fn low_u32(&self) -> u32; - - /// Conversion to u64 - fn low_u64(&self) -> u64; - - /// Conversion to u32 with overflow checking - fn as_u32(&self) -> u32; - - /// Conversion to u64 with overflow checking - fn as_u64(&self) -> u64; - - /// Return the least number of bits needed to represent the number - fn bits(&self) -> usize; - /// Return if specific bit is set - fn bit(&self, index: usize) -> bool; - /// Return single byte - fn byte(&self, index: usize) -> u8; - /// Convert to the sequence of bytes with a big endian - fn to_big_endian(&self, bytes: &mut[u8]); - /// Convert to a non-zero-prefixed hex representation (not prefixed by `0x`). - fn to_hex(&self) -> String; - /// Create `Uint(10**n)` - fn exp10(n: usize) -> Self; - /// Return eponentation `self**other`. Panic on overflow. - fn pow(self, other: Self) -> Self; - /// Return wrapped eponentation `self**other` and flag if there was an overflow - fn overflowing_pow(self, other: Self) -> (Self, bool); - - /// Add this `Uint` to other returning result and possible overflow - fn overflowing_add(self, other: Self) -> (Self, bool); - - /// Subtract another `Uint` from this returning result and possible overflow - fn overflowing_sub(self, other: Self) -> (Self, bool); - - /// Multiple this `Uint` with other returning result and possible overflow - fn overflowing_mul(self, other: Self) -> (Self, bool); - - /// Divide this `Uint` by other returning result and possible overflow - fn overflowing_div(self, other: Self) -> (Self, bool); - - /// Returns reminder of division of this `Uint` by other and possible overflow - fn overflowing_rem(self, other: Self) -> (Self, bool); - - /// Returns negation of this `Uint` and overflow (always true) - fn overflowing_neg(self) -> (Self, bool); - - /// Returns - fn is_zero(&self) -> bool; -} - -macro_rules! construct_uint { - ($name:ident, $n_words:expr) => ( - /// Little-endian large integer type - #[repr(C)] - #[derive(Copy, Clone, Eq, PartialEq, Hash)] - pub struct $name(pub [u64; $n_words]); - - impl Uint for $name { - - fn from_dec_str(value: &str) -> Result { - if !value.bytes().all(|b| b >= 48 && b <= 57) { - return Err(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(FromDecStrErr::InvalidLength); - } - let (r, overflow) = r.overflowing_add(b.into()); - if overflow { - return Err(FromDecStrErr::InvalidLength); - } - res = r; - } - Ok(res) - } - - #[inline] - fn low_u32(&self) -> u32 { - let &$name(ref arr) = self; - arr[0] as u32 - } - - #[inline] - fn low_u64(&self) -> u64 { - let &$name(ref arr) = self; - arr[0] - } - - /// Conversion to u32 with overflow checking - #[inline] - 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 - #[inline] - 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] - } - - #[inline] - 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] - 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 - } - - #[inline] - fn bit(&self, index: usize) -> bool { - let &$name(ref arr) = self; - arr[index / 64] & (1 << (index % 64)) != 0 - } - - #[inline] - fn byte(&self, index: usize) -> u8 { - let &$name(ref arr) = self; - (arr[index / 8] >> (((index % 8)) * 8)) as u8 - } - - #[cfg(any( - target_arch = "arm", - target_arch = "mips", - target_arch = "powerpc", - target_arch = "x86", - target_arch = "x86_64", - target_arch = "aarch64", - target_arch = "powerpc64"))] - #[inline] - fn to_big_endian(&self, bytes: &mut[u8]) { - debug_assert!($n_words * 8 == bytes.len()); - let &$name(ref arr) = self; - unsafe { - let mut out: *mut u64 = mem::transmute(bytes.as_mut_ptr()); - out = out.offset($n_words); - for i in 0..$n_words { - out = out.offset(-1); - *out = arr[i].swap_bytes(); - } - } - } - - #[cfg(not(any( - target_arch = "arm", - target_arch = "mips", - target_arch = "powerpc", - target_arch = "x86", - target_arch = "x86_64", - target_arch = "aarch64", - target_arch = "powerpc64")))] - #[inline] - fn to_big_endian(&self, bytes: &mut[u8]) { - debug_assert!($n_words * 8 == bytes.len()); - let &$name(ref arr) = self; - for i in 0..bytes.len() { - let rev = bytes.len() - 1 - i; - let pos = rev / 8; - bytes[i] = (arr[pos] >> ((rev % 8) * 8)) as u8; - } - } - - #[inline] - fn to_hex(&self) -> String { - if self.is_zero() { return "0".to_owned(); } // special case. - let mut bytes = [0u8; 8 * $n_words]; - self.to_big_endian(&mut bytes); - let bp7 = self.bits() + 7; - let len = cmp::max(bp7 / 8, 1); - let bytes_hex = bytes[bytes.len() - len..].to_hex(); - (&bytes_hex[1 - bp7 % 8 / 4..]).to_owned() - } - - #[inline] - fn exp10(n: usize) -> Self { - match n { - 0 => Self::from(1u64), - _ => Self::exp10(n - 1).mul_u32(10) - } - } - - #[inline] - fn zero() -> Self { - From::from(0u64) - } - - #[inline] - fn one() -> Self { - From::from(1u64) - } - - #[inline] - 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 - 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 >> 1; - } 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 >> 1; - } - } - x * y - } - - /// Fast exponentation by squaring - /// https://en.wikipedia.org/wiki/Exponentiation_by_squaring - 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 >> 1; - } else { - y = overflowing!(x.overflowing_mul(y), overflow); - x = overflowing!(x.overflowing_mul(x), overflow); - n = (n - u_one) >> 1; - } - } - let res = overflowing!(x.overflowing_mul(y), overflow); - (res, overflow) - } - - /// Optimized instructions - #[inline(always)] - fn overflowing_add(self, other: $name) -> ($name, bool) { - uint_overflowing_add!($name, $n_words, self, other) - } - - #[inline(always)] - fn overflowing_sub(self, other: $name) -> ($name, bool) { - uint_overflowing_sub!($name, $n_words, self, other) - } - - #[inline(always)] - fn overflowing_mul(self, other: $name) -> ($name, bool) { - uint_overflowing_mul!($name, $n_words, self, other) - } - - fn overflowing_div(self, other: $name) -> ($name, bool) { - (self / other, false) - } - - fn overflowing_rem(self, other: $name) -> ($name, bool) { - (self % other, false) - } - - fn overflowing_neg(self) -> ($name, bool) { - (!self, true) - } - } - - impl $name { - /// Multiplication by u32 - #[allow(dead_code)] // not used when multiplied with inline assembly - fn mul_u32(self, other: u32) -> Self { - let (ret, overflow) = self.overflowing_mul_u32(other); - panic_on_overflow!(overflow); - ret - } - - /// 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) = mul_u32(split(arr[i]), o, carry); - ret[i] = res; - carry = carry2; - } - - ($name(ret), carry > 0) - } - } - - 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); - - impl<'a> From<&'a [u8]> for $name { - fn from(bytes: &[u8]) -> $name { - assert!($n_words * 8 >= bytes.len()); - - let mut ret = [0; $n_words]; - for i in 0..bytes.len() { - let rev = bytes.len() - 1 - i; - let pos = rev / 8; - ret[pos] += (bytes[i] as u64) << ((rev % 8) * 8); - } - $name(ret) - } - } - - impl FromStr for $name { - type Err = FromHexError; - - fn from_str(value: &str) -> Result<$name, Self::Err> { - 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 Add<$name> for $name { - type Output = $name; - - fn add(self, other: $name) -> $name { - let (result, overflow) = self.overflowing_add(other); - panic_on_overflow!(overflow); - result - } - } - - impl Sub<$name> for $name { - type Output = $name; - - #[inline] - fn sub(self, other: $name) -> $name { - let (result, overflow) = self.overflowing_sub(other); - panic_on_overflow!(overflow); - result - } - } - - impl Mul<$name> for $name { - type Output = $name; - - fn mul(self, other: $name) -> $name { - let (result, overflow) = self.overflowing_mul(other); - panic_on_overflow!(overflow); - result - } - } - - impl Div<$name> for $name { - type Output = $name; - - fn div(self, other: $name) -> $name { - 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 >> 1; - if shift == 0 { break; } - shift -= 1; - } - - $name(ret) - } - } - - impl Rem<$name> for $name { - type Output = $name; - - fn rem(self, other: $name) -> $name { - let times = self / other; - self - (times * other) - } - } - - impl 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 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 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 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 Shl for $name { - type Output = $name; - - fn shl(self, shift: usize) -> $name { - 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 Shr for $name { - type Output = $name; - - fn shr(self, shift: usize) -> $name { - 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 Ord for $name { - fn cmp(&self, other: &$name) -> 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 Ordering::Less; } - if me[i] > you[i] { return Ordering::Greater; } - } - Ordering::Equal - } - } - - impl PartialOrd for $name { - fn partial_cmp(&self, other: &$name) -> Option { - Some(self.cmp(other)) - } - } - - impl fmt::Debug for $name { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Display::fmt(self, f) - } - } - - impl fmt::Display for $name { - fn fmt(&self, f: &mut fmt::Formatter) -> 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 fmt::LowerHex for $name { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let &$name(ref data) = self; - try!(write!(f, "0x")); - 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 { - try!(write!(f, "{:x}", nibble)); - } - } - } - Ok(()) - } - } - - impl From<&'static str> for $name { - fn from(s: &'static str) -> Self { - s.parse().unwrap() - } - } - ); -} - -construct_uint!(U512, 8); -construct_uint!(U256, 4); -construct_uint!(U128, 2); - -impl U256 { - /// Multiplies two 256-bit integers to produce full 512-bit integer - /// No overflow possible - #[cfg(all(asm_available, target_arch="x86_64"))] - pub fn full_mul(self, other: U256) -> U512 { - let self_t: &[u64; 4] = &self.0; - let other_t: &[u64; 4] = &other.0; - let mut result: [u64; 8] = unsafe { mem::uninitialized() }; - unsafe { - asm!(" - mov $8, %rax - mulq $12 - mov %rax, $0 - mov %rdx, $1 - - mov $8, %rax - mulq $13 - add %rax, $1 - adc $$0, %rdx - mov %rdx, $2 - - mov $8, %rax - mulq $14 - add %rax, $2 - adc $$0, %rdx - mov %rdx, $3 - - mov $8, %rax - mulq $15 - add %rax, $3 - adc $$0, %rdx - mov %rdx, $4 - - mov $9, %rax - mulq $12 - add %rax, $1 - adc %rdx, $2 - adc $$0, $3 - adc $$0, $4 - xor $5, $5 - adc $$0, $5 - xor $6, $6 - adc $$0, $6 - xor $7, $7 - adc $$0, $7 - - mov $9, %rax - mulq $13 - add %rax, $2 - adc %rdx, $3 - adc $$0, $4 - adc $$0, $5 - adc $$0, $6 - adc $$0, $7 - - mov $9, %rax - mulq $14 - add %rax, $3 - adc %rdx, $4 - adc $$0, $5 - adc $$0, $6 - adc $$0, $7 - - mov $9, %rax - mulq $15 - add %rax, $4 - adc %rdx, $5 - adc $$0, $6 - adc $$0, $7 - - mov $10, %rax - mulq $12 - add %rax, $2 - adc %rdx, $3 - adc $$0, $4 - adc $$0, $5 - adc $$0, $6 - adc $$0, $7 - - mov $10, %rax - mulq $13 - add %rax, $3 - adc %rdx, $4 - adc $$0, $5 - adc $$0, $6 - adc $$0, $7 - - mov $10, %rax - mulq $14 - add %rax, $4 - adc %rdx, $5 - adc $$0, $6 - adc $$0, $7 - - mov $10, %rax - mulq $15 - add %rax, $5 - adc %rdx, $6 - adc $$0, $7 - - mov $11, %rax - mulq $12 - add %rax, $3 - adc %rdx, $4 - adc $$0, $5 - adc $$0, $6 - adc $$0, $7 - - mov $11, %rax - mulq $13 - add %rax, $4 - adc %rdx, $5 - adc $$0, $6 - adc $$0, $7 - - mov $11, %rax - mulq $14 - add %rax, $5 - adc %rdx, $6 - adc $$0, $7 - - mov $11, %rax - mulq $15 - add %rax, $6 - adc %rdx, $7 - " - : /* $0 */ "={r8}"(result[0]), /* $1 */ "={r9}"(result[1]), /* $2 */ "={r10}"(result[2]), - /* $3 */ "={r11}"(result[3]), /* $4 */ "={r12}"(result[4]), /* $5 */ "={r13}"(result[5]), - /* $6 */ "={r14}"(result[6]), /* $7 */ "={r15}"(result[7]) - - : /* $8 */ "m"(self_t[0]), /* $9 */ "m"(self_t[1]), /* $10 */ "m"(self_t[2]), - /* $11 */ "m"(self_t[3]), /* $12 */ "m"(other_t[0]), /* $13 */ "m"(other_t[1]), - /* $14 */ "m"(other_t[2]), /* $15 */ "m"(other_t[3]) - : "rax", "rdx" - : - ); - } - U512(result) - } - - /// Multiplies two 256-bit integers to produce full 512-bit integer - /// No overflow possible - #[cfg(not(all(asm_available, target_arch="x86_64")))] - pub fn full_mul(self, other: U256) -> U512 { - let U256(ref me) = self; - let U256(ref you) = other; - let mut ret = [0u64; 8]; - - for i in 0..4 { - if you[i] == 0 { - continue; - } - - let mut carry2 = 0u64; - let (b_u, b_l) = split(you[i]); - - for j in 0..4 { - if me[j] == 0 && carry2 == 0 { - continue; - } - - let a = split(me[j]); - - // multiply parts - let (c_l, overflow_l) = mul_u32(a, b_l, ret[i + j]); - let (c_u, overflow_u) = 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); - let (res, o2) = res.overflowing_add(carry2); - let (res, o3) = res.overflowing_add(ret[i + j + 1]); - ret[i + j + 1] = res; - - // Only single overflow possible there - carry2 = (o1 | o2 | o3) as u64; - } - } - - U512(ret) - } -} - -impl From for U512 { - fn from(value: U256) -> U512 { - let U256(ref arr) = value; - let mut ret = [0; 8]; - ret[0] = arr[0]; - ret[1] = arr[1]; - ret[2] = arr[2]; - ret[3] = arr[3]; - U512(ret) - } -} - -impl From for U256 { - fn from(value: U512) -> U256 { - let U512(ref arr) = value; - if arr[4] | arr[5] | arr[6] | arr[7] != 0 { - panic!("Overflow"); - } - let mut ret = [0; 4]; - ret[0] = arr[0]; - ret[1] = arr[1]; - ret[2] = arr[2]; - ret[3] = arr[3]; - U256(ret) - } -} - -impl<'a> From<&'a U256> for U512 { - fn from(value: &'a U256) -> U512 { - let U256(ref arr) = *value; - let mut ret = [0; 8]; - ret[0] = arr[0]; - ret[1] = arr[1]; - ret[2] = arr[2]; - ret[3] = arr[3]; - U512(ret) - } -} - -impl<'a> From<&'a U512> for U256 { - fn from(value: &'a U512) -> U256 { - let U512(ref arr) = *value; - if arr[4] | arr[5] | arr[6] | arr[7] != 0 { - panic!("Overflow"); - } - let mut ret = [0; 4]; - ret[0] = arr[0]; - ret[1] = arr[1]; - ret[2] = arr[2]; - ret[3] = arr[3]; - U256(ret) - } -} - -impl From for U128 { - fn from(value: U256) -> U128 { - let U256(ref arr) = value; - if arr[2] | arr[3] != 0 { - panic!("Overflow"); - } - let mut ret = [0; 2]; - ret[0] = arr[0]; - ret[1] = arr[1]; - U128(ret) - } -} - -impl From for U128 { - fn from(value: U512) -> U128 { - let U512(ref arr) = value; - if arr[2] | arr[3] | arr[4] | arr[5] | arr[6] | arr[7] != 0 { - panic!("Overflow"); - } - let mut ret = [0; 2]; - ret[0] = arr[0]; - ret[1] = arr[1]; - U128(ret) - } -} - -impl From for U512 { - fn from(value: U128) -> U512 { - let U128(ref arr) = value; - let mut ret = [0; 8]; - ret[0] = arr[0]; - ret[1] = arr[1]; - U512(ret) - } -} - -impl From for U256 { - fn from(value: U128) -> U256 { - let U128(ref arr) = value; - let mut ret = [0; 4]; - ret[0] = arr[0]; - ret[1] = arr[1]; - U256(ret) - } -} - -impl From for u64 { - fn from(value: U256) -> u64 { - value.as_u64() - } -} - -impl From for u32 { - fn from(value: U256) -> u32 { - value.as_u32() - } -} - -known_heap_size!(0, U128, U256); - -#[cfg(test)] -mod tests { - use uint::{Uint, U128, U256, U512}; - use std::str::FromStr; - use super::FromDecStrErr; - - #[test] - pub 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] - pub 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] - pub 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))] - pub 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] - pub 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.mul_u32(300); - 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] - pub 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] - pub 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] - pub 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] - pub fn uint256_mul32() { - 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_hex_correctly() { - assert_eq!(&U256::from(0).to_hex(), &"0"); - assert_eq!(&U256::from(0x1).to_hex(), &"1"); - assert_eq!(&U256::from(0xf).to_hex(), &"f"); - assert_eq!(&U256::from(0x10).to_hex(), &"10"); - assert_eq!(&U256::from(0xff).to_hex(), &"ff"); - assert_eq!(&U256::from(0x100).to_hex(), &"100"); - assert_eq!(&U256::from(0xfff).to_hex(), &"fff"); - assert_eq!(&U256::from(0x1000).to_hex(), &"1000"); - } - - #[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] - pub fn uint256_mul1() { - assert_eq!(U256::from(1u64) * U256::from(10u64), U256::from(10u64)); - } - - #[test] - pub 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] - pub fn uint256_overflowing_mul() { - assert_eq!( - U256::from_str("100000000000000000000000000000000").unwrap().overflowing_mul( - U256::from_str("100000000000000000000000000000000").unwrap() - ), - (U256::zero(), true) - ); - } - - #[test] - pub fn uint128_add() { - assert_eq!( - U128::from_str("fffffffffffffffff").unwrap() + U128::from_str("fffffffffffffffff").unwrap(), - U128::from_str("1ffffffffffffffffe").unwrap() - ); - } - - #[test] - pub 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] - // overflows panic only in debug builds. Running this test with `--release` flag, always fails - #[ignore] - pub fn uint128_add_overflow_panic() { - U128::from_str("ffffffffffffffffffffffffffffffff").unwrap() - + - U128::from_str("ffffffffffffffffffffffffffffffff").unwrap(); - } - - #[test] - pub fn uint128_mul() { - assert_eq!( - U128::from_str("fffffffff").unwrap() * U128::from_str("fffffffff").unwrap(), - U128::from_str("ffffffffe000000001").unwrap()); - } - - #[test] - pub fn uint512_mul() { - assert_eq!( - U512::from_str("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap() - * - U512::from_str("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap(), - U512::from_str("3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000001").unwrap() - ); - } - - #[test] - pub 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] - pub fn uint256_mul_overflow_panic() { - U256::from_str("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap() - * - U256::from_str("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap(); - } - - #[test] - pub 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] - pub fn uint256_sub_overflow_panic() { - U256::from_str("0").unwrap() - - - U256::from_str("1").unwrap(); - } - - #[test] - pub fn uint256_shl() { - assert_eq!( - U256::from_str("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap() - << 4, - U256::from_str("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0").unwrap() - ); - } - - #[test] - pub 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] - pub 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([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX]) - .overflowing_add(U512([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX])); - assert!(overflow); - - let (_, overflow) = U512([0, 0, 0, 0, 0, 0, 0, ::std::u64::MAX]) - .overflowing_add(U512([0, 0, 0, 0, 0, 0, 0, ::std::u64::MAX])); - assert!(overflow); - - let (_, overflow) = U512([0, 0, 0, 0, 0, 0, 0, ::std::u64::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([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX]) - .overflowing_add(U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX])); - assert!(overflow); - - let (_, overflow) = U256([0, 0, 0, ::std::u64::MAX]).overflowing_add(U256([0, 0, 0, ::std::u64::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([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX]) - .overflowing_sub(U256([::std::u64::MAX/2, ::std::u64::MAX/2, ::std::u64::MAX/2, ::std::u64::MAX/2])); - assert!(!overflow); - assert_eq!(U256([::std::u64::MAX/2+1, ::std::u64::MAX/2+1, ::std::u64::MAX/2+1, ::std::u64::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, ::std::u64::MAX, 0]), result); - - let (result, overflow) = U256([0, 0, 0, 1]).overflowing_sub(U256([1, 0, 0, 0])); - assert!(!overflow); - assert_eq!(U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::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([::std::u64::MAX, 0, 0, 0]).overflowing_mul(U256([::std::u64::MAX, 0, 0, 0])); - assert_eq!(U256([1, ::std::u64::MAX-1, 0, 0]), result); - - let (result, _) = U256([0, ::std::u64::MAX, 0, 0]).overflowing_mul(U256([::std::u64::MAX, 0, 0, 0])); - assert_eq!(U256([0, 1, ::std::u64::MAX-1, 0]), result); - - let (result, _) = U256([::std::u64::MAX, ::std::u64::MAX, 0, 0]).overflowing_mul(U256([::std::u64::MAX, 0, 0, 0])); - assert_eq!(U256([1, ::std::u64::MAX, ::std::u64::MAX-1, 0]), result); - - let (result, _) = U256([::std::u64::MAX, 0, 0, 0]).overflowing_mul(U256([::std::u64::MAX, ::std::u64::MAX, 0, 0])); - assert_eq!(U256([1, ::std::u64::MAX, ::std::u64::MAX-1, 0]), result); - - let (result, _) = U256([::std::u64::MAX, ::std::u64::MAX, 0, 0]) - .overflowing_mul(U256([::std::u64::MAX, ::std::u64::MAX, 0, 0])); - assert_eq!(U256([1, 0, ::std::u64::MAX-1, ::std::u64::MAX]), result); - - let (result, _) = U256([::std::u64::MAX, 0, 0, 0]).overflowing_mul(U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, 0])); - assert_eq!(U256([1, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX-1]), result); - - let (result, _) = U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, 0]).overflowing_mul(U256([::std::u64::MAX, 0, 0, 0])); - assert_eq!(U256([1, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX-1]), result); - - let (result, _) = U256([::std::u64::MAX, 0, 0, 0]).overflowing_mul( - U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX])); - assert_eq!(U256([1, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX]), result); - - let (result, _) = U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX]) - .overflowing_mul(U256([::std::u64::MAX, 0, 0, 0])); - assert_eq!(U256([1, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX]), result); - - let (result, _) = U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, 0]) - .overflowing_mul(U256([::std::u64::MAX, ::std::u64::MAX, 0, 0])); - assert_eq!(U256([1, 0, ::std::u64::MAX, ::std::u64::MAX-1]), result); - - let (result, _) = U256([::std::u64::MAX, ::std::u64::MAX, 0, 0]) - .overflowing_mul(U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, 0])); - assert_eq!(U256([1, 0, ::std::u64::MAX, ::std::u64::MAX-1]), result); - - let (result, _) = U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX]) - .overflowing_mul(U256([::std::u64::MAX, ::std::u64::MAX, 0, 0])); - assert_eq!(U256([1, 0, ::std::u64::MAX, ::std::u64::MAX]), result); - - let (result, _) = U256([::std::u64::MAX, ::std::u64::MAX, 0, 0]) - .overflowing_mul(U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX])); - assert_eq!(U256([1, 0, ::std::u64::MAX, ::std::u64::MAX]), result); - - let (result, _) = U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, 0]) - .overflowing_mul(U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, 0])); - assert_eq!(U256([1, 0, 0, ::std::u64::MAX-1]), result); - - let (result, _) = U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, 0]) - .overflowing_mul(U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX])); - assert_eq!(U256([1, 0, 0, ::std::u64::MAX]), result); - - let (result, _) = U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX]) - .overflowing_mul(U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, 0])); - assert_eq!(U256([1, 0, 0, ::std::u64::MAX]), result); - - let (result, _) = U256([0, 0, 0, ::std::u64::MAX]).overflowing_mul(U256([0, 0, 0, ::std::u64::MAX])); - assert_eq!(U256([0, 0, 0, 0]), result); - - let (result, _) = U256([1, 0, 0, 0]).overflowing_mul(U256([0, 0, 0, ::std::u64::MAX])); - assert_eq!(U256([0, 0, 0, ::std::u64::MAX]), result); - - let (result, _) = U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX]) - .overflowing_mul(U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::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, ::std::u64::MAX])); - assert_eq!(U256([0, 0, 0, ::std::u64::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, ::std::u64::MAX])); - assert!(!overflow); - - let (_, overflow) = U256([0, 1, 0, 0]).overflowing_mul(U256([0, 0, 0, ::std::u64::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, ::std::u64::MAX]).overflowing_mul(U256([0, 1, 0, ::std::u64::MAX])); - assert!(overflow); - - let (_, overflow) = U256([0, ::std::u64::MAX, 0, 0]).overflowing_mul(U256([0, ::std::u64::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, ::std::u64::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([::std::u64::MAX, 0, 0, 0]).full_mul(U256([::std::u64::MAX, 0, 0, 0])); - assert_eq!(U512([1, ::std::u64::MAX-1, 0, 0, 0, 0, 0, 0]), result); - - let result = U256([0, ::std::u64::MAX, 0, 0]).full_mul(U256([::std::u64::MAX, 0, 0, 0])); - assert_eq!(U512([0, 1, ::std::u64::MAX-1, 0, 0, 0, 0, 0]), result); - - let result = U256([::std::u64::MAX, ::std::u64::MAX, 0, 0]).full_mul(U256([::std::u64::MAX, 0, 0, 0])); - assert_eq!(U512([1, ::std::u64::MAX, ::std::u64::MAX-1, 0, 0, 0, 0, 0]), result); - - let result = U256([::std::u64::MAX, 0, 0, 0]).full_mul(U256([::std::u64::MAX, ::std::u64::MAX, 0, 0])); - assert_eq!(U512([1, ::std::u64::MAX, ::std::u64::MAX-1, 0, 0, 0, 0, 0]), result); - - let result = U256([::std::u64::MAX, ::std::u64::MAX, 0, 0]).full_mul(U256([::std::u64::MAX, ::std::u64::MAX, 0, 0])); - assert_eq!(U512([1, 0, ::std::u64::MAX-1, ::std::u64::MAX, 0, 0, 0, 0]), result); - - let result = U256([::std::u64::MAX, 0, 0, 0]).full_mul(U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, 0])); - assert_eq!(U512([1, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX-1, 0, 0, 0, 0]), result); - - let result = U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, 0]).full_mul(U256([::std::u64::MAX, 0, 0, 0])); - assert_eq!(U512([1, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX-1, 0, 0, 0, 0]), result); - - let result = U256([::std::u64::MAX, 0, 0, 0]).full_mul(U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX])); - assert_eq!(U512([1, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX-1, 0, 0, 0]), result); - - let result = U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX]).full_mul(U256([::std::u64::MAX, 0, 0, 0])); - assert_eq!(U512([1, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX-1, 0, 0, 0]), result); - - let result = U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, 0]).full_mul(U256([::std::u64::MAX, ::std::u64::MAX, 0, 0])); - assert_eq!(U512([1, 0, ::std::u64::MAX, ::std::u64::MAX-1, ::std::u64::MAX, 0, 0, 0]), result); - - let result = U256([::std::u64::MAX, ::std::u64::MAX, 0, 0]).full_mul(U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, 0])); - assert_eq!(U512([1, 0, ::std::u64::MAX, ::std::u64::MAX-1, ::std::u64::MAX, 0, 0, 0]), result); - - let result = U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX]).full_mul(U256([::std::u64::MAX, ::std::u64::MAX, 0, 0])); - assert_eq!(U512([1, 0, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX-1, ::std::u64::MAX, 0, 0]), result); - - let result = U256([::std::u64::MAX, ::std::u64::MAX, 0, 0]).full_mul(U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX])); - assert_eq!(U512([1, 0, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX-1, ::std::u64::MAX, 0, 0]), result); - - let result = U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, 0]).full_mul(U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, 0])); - assert_eq!(U512([1, 0, 0, ::std::u64::MAX-1, ::std::u64::MAX, ::std::u64::MAX, 0, 0]), result); - - let result = U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, 0]).full_mul(U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX])); - assert_eq!(U512([1, 0, 0, ::std::u64::MAX, ::std::u64::MAX-1, ::std::u64::MAX, ::std::u64::MAX, 0]), result); - - let result = U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX]).full_mul(U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, 0])); - assert_eq!(U512([1, 0, 0, ::std::u64::MAX, ::std::u64::MAX-1, ::std::u64::MAX, ::std::u64::MAX, 0]), result); - - let result = U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX]).full_mul(U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX])); - assert_eq!(U512([1, 0, 0, 0, ::std::u64::MAX-1, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX]), result); - - let result = U256([0, 0, 0, ::std::u64::MAX]).full_mul(U256([0, 0, 0, ::std::u64::MAX])); - assert_eq!(U512([0, 0, 0, 0, 0, 0, 1, ::std::u64::MAX-1]), result); - - let result = U256([1, 0, 0, 0]).full_mul(U256([0, 0, 0, ::std::u64::MAX])); - assert_eq!(U512([0, 0, 0, ::std::u64::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); - } -} diff --git a/util/rlp/src/bytes.rs b/util/rlp/src/bytes.rs index a83e7ff94..c9079192e 100644 --- a/util/rlp/src/bytes.rs +++ b/util/rlp/src/bytes.rs @@ -21,8 +21,7 @@ use std::mem; use std::fmt; use std::cmp::Ordering; use std::error::Error as StdError; -use bigint::uint::{Uint, U128, U256}; -use bigint::hash::{H64, H128, H160, H256, H512, H520, H2048}; +use bigint::prelude::{Uint, U128, U256, H64, H128, H160, H256, H512, H520, H2048}; use elastic_array::*; /// Vector like object diff --git a/util/rlp/src/rlpin.rs b/util/rlp/src/rlpin.rs index ca1aaad79..562ff78e7 100644 --- a/util/rlp/src/rlpin.rs +++ b/util/rlp/src/rlpin.rs @@ -163,7 +163,7 @@ impl<'a, 'view> Iterator for RlpIterator<'a, 'view> { #[test] fn break_it() { use rustc_serialize::hex::FromHex; - use bigint::uint::U256; + use bigint::prelude::U256; let h: Vec = FromHex::from_hex("f84d0589010efbef67941f79b2a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470").unwrap(); let r: Rlp = Rlp::new(&h); diff --git a/util/rlp/src/tests.rs b/util/rlp/src/tests.rs index 83ad38a6e..ecd26245b 100644 --- a/util/rlp/src/tests.rs +++ b/util/rlp/src/tests.rs @@ -17,7 +17,7 @@ use std::{fmt, cmp}; use std::str::FromStr; use ::{Encodable, RlpDecodable, UntrustedRlp, RlpStream, View, Stream, DecoderError}; -use bigint::uint::U256; +use bigint::prelude::U256; #[test] fn rlp_at() { diff --git a/util/src/common.rs b/util/src/common.rs index c457948dd..3a4dc7807 100644 --- a/util/src/common.rs +++ b/util/src/common.rs @@ -22,8 +22,7 @@ pub use error::*; pub use bytes::*; pub use vector::*; pub use sha3::*; -pub use bigint::hash::*; -pub use bigint::uint::*; +pub use bigint::prelude::*; pub use bigint::hash; #[macro_export] diff --git a/util/src/from_json.rs b/util/src/from_json.rs index ebd1ce693..473688133 100644 --- a/util/src/from_json.rs +++ b/util/src/from_json.rs @@ -17,7 +17,7 @@ //! Coversion from json. use standard::*; -use bigint::uint::*; +use bigint::prelude::*; #[macro_export] macro_rules! xjson { diff --git a/util/src/stats.rs b/util/src/stats.rs index 9069be022..2222601d3 100644 --- a/util/src/stats.rs +++ b/util/src/stats.rs @@ -16,7 +16,7 @@ //! Statistical functions. -use bigint::uint::*; +use bigint::prelude::*; /// Discretised histogram. #[derive(Debug, PartialEq)] @@ -62,7 +62,7 @@ impl Histogram { #[cfg(test)] mod tests { - use bigint::uint::U256; + use bigint::prelude::U256; use super::Histogram; #[test]