Merge branch 'master' into nv

This commit is contained in:
Nikolay Volf 2018-08-22 16:56:54 +03:00 committed by GitHub
commit 562aecfe00
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 108 additions and 70 deletions

View File

@ -4,7 +4,7 @@ homepage = "http://parity.io"
repository = "https://github.com/paritytech/parity-common"
license = "MIT/Apache-2.0"
name = "uint"
version = "0.3.0"
version = "0.4.1"
authors = ["Parity Technologies <admin@parity.io>"]
[dependencies]

View File

@ -1,8 +1,8 @@
# Big unsigned integer types
Implementation of a various large-but-fixed sized unsigned integer types.
Macros to implement large-but-fixed sized unsigned integer types.
The functions here are designed to be fast.
The crate exports two commonly used types: `U256` and `U512`. Other sizes can be constructed with `construct_uint!(NAME, SIZE_IN_WORDS)`, e.g. `construct_uint!(U128, 2);`.
The crate builds and exports two commonly used types: `U256` and `U512`. Other sizes can be constructed with `construct_uint!(NAME, SIZE_IN_WORDS)`, e.g. `construct_uint!(U128, 2);`.
Run tests with `cargo test --features=std,impl_quickcheck_arbitrary`.
Run tests with `cargo test --features=std,impl_quickcheck_arbitrary --release`.

View File

@ -16,25 +16,12 @@
extern crate core;
extern crate test;
#[macro_use]
extern crate crunchy;
#[macro_use]
extern crate uint;
construct_uint!(U128, 2);
construct_uint!(U256, 4);
construct_uint!(U512, 8);
use uint::{U256, U512};
use test::{Bencher, black_box};
impl U256 {
/// Multiplies two 256-bit integers to produce full 512-bit integer
/// No overflow possible
#[inline(always)]
pub fn full_mul(self, other: U256) -> U512 {
U512(uint_full_mul_reg!(U256, 4, self, other))
}
}
#[bench]
fn u256_add(b: &mut Bencher) {
b.iter(|| {
@ -134,11 +121,13 @@ fn u256_full_mul(b: &mut Bencher) {
#[bench]
// NOTE: uses native `u128` and does not measure this crates performance,
// but might be interesting as a comparison.
fn u128_mul(b: &mut Bencher) {
b.iter(|| {
let n = black_box(10000);
(1..n).fold(U128([12345u64, 0u64]), |old, new| {
old.overflowing_mul(U128::from(new | 1)).0
(1..n).fold(12345u128, |old, new| {
old.overflowing_mul(u128::from(new | 1u32)).0
})
});
}
@ -228,3 +217,30 @@ fn u256_from_be(b: &mut Bencher) {
let _ = U256::from_big_endian(&raw[..]);
});
}
#[bench]
fn from_fixed_array(b: &mut Bencher) {
let ary512 : [u8; 64] = [
255, 0, 0, 123, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 121, 0, 0, 0, 0,
0, 213, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 100, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 45, 0, 0, 67, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 123
];
let ary256 : [u8; 32] = [
255, 0, 0, 123, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 121, 0, 0, 0, 0,
0, 213, 0, 0, 0, 0, 0, 0,
];
b.iter(|| {
let n = black_box(1000);
for _i in 0..n {
let _ : U512 = black_box(ary512).into();
let _ : U256 = black_box(ary256).into();
}
})
}

View File

@ -810,6 +810,19 @@ macro_rules! construct_uint {
arr
}
}
impl From<[u8; $n_words * 8]> for $name {
fn from(bytes: [u8; $n_words * 8]) -> Self {
bytes[..].as_ref().into()
}
}
impl<'a> From<&'a [u8; $n_words * 8]> for $name {
fn from(bytes: &[u8; $n_words * 8]) -> Self {
bytes[..].into()
}
}
impl Default for $name {
fn default() -> Self {
$name::zero()
@ -1374,3 +1387,13 @@ macro_rules! impl_quickcheck_arbitrary_for_uint {
construct_uint!(U256, 4);
construct_uint!(U512, 8);
#[doc(hidden)]
impl U256 {
/// Multiplies two 256-bit integers to produce full 512-bit integer
/// No overflow possible
#[inline(always)]
pub fn full_mul(self, other: U256) -> U512 {
U512(uint_full_mul_reg!(U256, 4, self, other))
}
}

View File

@ -12,8 +12,6 @@ use core::u64::MAX;
use core::str::FromStr;
use uint::{U256, U512, FromDecStrErr};
construct_uint!(U128, 2);
#[test]
fn uint256_checked_ops() {
let z = U256::from(0);
@ -360,14 +358,6 @@ fn should_format_and_debug_correctly() {
test(0x1000, "1000", "4096");
}
#[test]
pub fn display_u128() {
let expected = "340282366920938463463374607431768211455";
let value = U128::MAX;
assert_eq!(format!("{}", value), expected);
assert_eq!(format!("{:?}", value), expected);
}
#[test]
pub fn display_u256() {
let expected = "115792089237316195423570985008687907853269984665640564039457584007913129639935";
@ -419,42 +409,6 @@ fn uint256_overflowing_mul() {
);
}
#[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)]
#[allow(unused_must_use)]
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!(
@ -1001,7 +955,7 @@ fn from_big_endian() {
}
#[test]
fn from_fixed_array() {
fn into_fixed_array() {
let expected: [u8; 32] = [
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
@ -1012,6 +966,53 @@ fn from_fixed_array() {
assert_eq!(ary, expected);
}
#[test]
fn test_u256_from_fixed_array() {
let ary = [
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1,
0, 0, 0, 0, 0, 0, 0, 123,
];
let num : U256 = ary.into();
assert_eq!( num, U256::from(std::u64::MAX) + 1 + 123);
let a_ref : &U256 = &ary.into();
assert_eq!( a_ref, &(U256::from(std::u64::MAX) + 1 + 123));
}
#[test]
fn test_from_ref_to_fixed_array() {
let ary : &[u8; 32] = &[
1,0,1,2,1,0,1,2,
3,0,3,4,3,0,3,4,
5,0,5,6,5,0,5,6,
7,0,7,8,7,0,7,8
];
let big : U256 = ary.into();
// the numbers are each row of 8 bytes reversed and cast to u64
assert_eq!(big, U256([504410889324070664, 360293493601469702, 216176097878868740, 72058702156267778u64]));
}
#[test]
fn test_u512_from_fixed_array() {
let ary = [
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, 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, 0, 123
];
let num : U512 = ary.into();
assert_eq!( num, U512::from(123) );
let a_ref : &U512 = &ary.into();
assert_eq!( a_ref, &U512::from(123) );
}
#[test]
fn leading_zeros() {
assert_eq!(U256::from("000000000000000000000001adbdd6bd6ff027485484b97f8a6a4c7129756dd1").leading_zeros(), 95);
@ -1196,13 +1197,11 @@ pub mod laws {
}
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);