Merge pull request #187 from gavofyork/wrapping_ops
fixed wrapping ops on latest nightly
This commit is contained in:
commit
ae64a6046b
@ -4,7 +4,6 @@ use common::*;
|
|||||||
use evm;
|
use evm;
|
||||||
use super::instructions as instructions;
|
use super::instructions as instructions;
|
||||||
use super::instructions::Instruction;
|
use super::instructions::Instruction;
|
||||||
use std::num::wrapping::OverflowingOps;
|
|
||||||
use std::marker::Copy;
|
use std::marker::Copy;
|
||||||
use evm::{MessageCallResult, ContractCreateResult};
|
use evm::{MessageCallResult, ContractCreateResult};
|
||||||
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
#![feature(cell_extras)]
|
#![feature(cell_extras)]
|
||||||
#![feature(augmented_assignments)]
|
#![feature(augmented_assignments)]
|
||||||
#![feature(wrapping)]
|
|
||||||
//#![feature(plugin)]
|
//#![feature(plugin)]
|
||||||
//#![plugin(interpolate_idents)]
|
//#![plugin(interpolate_idents)]
|
||||||
//! Ethcore's ethereum implementation
|
//! Ethcore's ethereum implementation
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
#![feature(op_assign_traits)]
|
#![feature(op_assign_traits)]
|
||||||
#![feature(augmented_assignments)]
|
#![feature(augmented_assignments)]
|
||||||
#![feature(associated_consts)]
|
#![feature(associated_consts)]
|
||||||
#![feature(wrapping)]
|
|
||||||
//! Ethcore-util library
|
//! Ethcore-util library
|
||||||
//!
|
//!
|
||||||
//! ### Rust version:
|
//! ### Rust version:
|
||||||
|
216
util/src/uint.rs
216
util/src/uint.rs
@ -23,7 +23,6 @@
|
|||||||
|
|
||||||
use standard::*;
|
use standard::*;
|
||||||
use from_json::*;
|
use from_json::*;
|
||||||
use std::num::wrapping::OverflowingOps;
|
|
||||||
|
|
||||||
macro_rules! impl_map_from {
|
macro_rules! impl_map_from {
|
||||||
($thing:ident, $from:ty, $to:ty) => {
|
($thing:ident, $from:ty, $to:ty) => {
|
||||||
@ -97,6 +96,23 @@ pub trait Uint: Sized + Default + FromStr + From<u64> + FromJson + fmt::Debug +
|
|||||||
fn pow(self, other: Self) -> Self;
|
fn pow(self, other: Self) -> Self;
|
||||||
/// Return wrapped eponentation `self**other` and flag if there was an overflow
|
/// Return wrapped eponentation `self**other` and flag if there was an overflow
|
||||||
fn overflowing_pow(self, other: Self) -> (Self, bool);
|
fn overflowing_pow(self, other: Self) -> (Self, bool);
|
||||||
|
|
||||||
|
|
||||||
|
fn overflowing_add(self, other: Self) -> (Self, bool);
|
||||||
|
|
||||||
|
fn overflowing_sub(self, other: Self) -> (Self, bool);
|
||||||
|
|
||||||
|
fn overflowing_mul(self, other: Self) -> (Self, bool);
|
||||||
|
|
||||||
|
fn overflowing_div(self, other: Self) -> (Self, bool);
|
||||||
|
|
||||||
|
fn overflowing_rem(self, other: Self) -> (Self, bool);
|
||||||
|
|
||||||
|
fn overflowing_neg(self) -> (Self, bool);
|
||||||
|
|
||||||
|
fn overflowing_shl(self, shift: u32) -> (Self, bool);
|
||||||
|
|
||||||
|
fn overflowing_shr(self, shift: u32) -> (Self, bool);
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! construct_uint {
|
macro_rules! construct_uint {
|
||||||
@ -259,6 +275,104 @@ macro_rules! construct_uint {
|
|||||||
let res = overflowing!(x.overflowing_mul(y), overflow);
|
let res = overflowing!(x.overflowing_mul(y), overflow);
|
||||||
(res, overflow)
|
(res, overflow)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn overflowing_add(self, other: $name) -> ($name, bool) {
|
||||||
|
let $name(ref me) = self;
|
||||||
|
let $name(ref you) = other;
|
||||||
|
let mut ret = [0u64; $n_words];
|
||||||
|
let mut carry = [0u64; $n_words];
|
||||||
|
let mut b_carry = false;
|
||||||
|
let mut overflow = false;
|
||||||
|
|
||||||
|
for i in 0..$n_words {
|
||||||
|
ret[i] = me[i].wrapping_add(you[i]);
|
||||||
|
|
||||||
|
if ret[i] < me[i] {
|
||||||
|
if i < $n_words - 1 {
|
||||||
|
carry[i + 1] = 1;
|
||||||
|
b_carry = true;
|
||||||
|
} else {
|
||||||
|
overflow = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if b_carry {
|
||||||
|
let ret = overflowing!($name(ret).overflowing_add($name(carry)), overflow);
|
||||||
|
(ret, overflow)
|
||||||
|
} else {
|
||||||
|
($name(ret), overflow)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn overflowing_sub(self, other: $name) -> ($name, bool) {
|
||||||
|
let res = overflowing!((!other).overflowing_add(From::from(1u64)));
|
||||||
|
let res = overflowing!(self.overflowing_add(res));
|
||||||
|
(res, self < other)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn overflowing_mul(self, other: $name) -> ($name, bool) {
|
||||||
|
let mut res = $name::from(0u64);
|
||||||
|
let mut overflow = false;
|
||||||
|
// TODO: be more efficient about this
|
||||||
|
for i in 0..(2 * $n_words) {
|
||||||
|
let v = overflowing!(self.overflowing_mul_u32((other >> (32 * i)).low_u32()), overflow);
|
||||||
|
let res2 = overflowing!(v.overflowing_shl(32 * i as u32), overflow);
|
||||||
|
res = overflowing!(res.overflowing_add(res2), overflow);
|
||||||
|
}
|
||||||
|
(res, overflow)
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn overflowing_shl(self, shift32: u32) -> ($name, bool) {
|
||||||
|
let $name(ref original) = self;
|
||||||
|
let mut ret = [0u64; $n_words];
|
||||||
|
let shift = shift32 as usize;
|
||||||
|
let word_shift = shift / 64;
|
||||||
|
let bit_shift = shift % 64;
|
||||||
|
for i in 0..$n_words {
|
||||||
|
// Shift
|
||||||
|
if i + word_shift < $n_words {
|
||||||
|
ret[i + word_shift] += original[i] << bit_shift;
|
||||||
|
}
|
||||||
|
// Carry
|
||||||
|
if bit_shift > 0 && i + word_shift + 1 < $n_words {
|
||||||
|
ret[i + word_shift + 1] += original[i] >> (64 - bit_shift);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Detecting overflow
|
||||||
|
let last = $n_words - word_shift - if bit_shift > 0 { 1 } else { 0 };
|
||||||
|
let overflow = if bit_shift > 0 {
|
||||||
|
(original[last] >> (64 - bit_shift)) > 0
|
||||||
|
} else if word_shift > 0 {
|
||||||
|
original[last] > 0
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
};
|
||||||
|
|
||||||
|
for i in last+1..$n_words-1 {
|
||||||
|
if original[i] > 0 {
|
||||||
|
return ($name(ret), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
($name(ret), overflow)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn overflowing_shr(self, _shift32: u32) -> ($name, bool) {
|
||||||
|
// TODO [todr] not used for now
|
||||||
|
unimplemented!();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl $name {
|
impl $name {
|
||||||
@ -390,105 +504,6 @@ macro_rules! construct_uint {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl OverflowingOps for $name {
|
|
||||||
fn overflowing_add(self, other: $name) -> ($name, bool) {
|
|
||||||
let $name(ref me) = self;
|
|
||||||
let $name(ref you) = other;
|
|
||||||
let mut ret = [0u64; $n_words];
|
|
||||||
let mut carry = [0u64; $n_words];
|
|
||||||
let mut b_carry = false;
|
|
||||||
let mut overflow = false;
|
|
||||||
|
|
||||||
for i in 0..$n_words {
|
|
||||||
ret[i] = me[i].wrapping_add(you[i]);
|
|
||||||
|
|
||||||
if ret[i] < me[i] {
|
|
||||||
if i < $n_words - 1 {
|
|
||||||
carry[i + 1] = 1;
|
|
||||||
b_carry = true;
|
|
||||||
} else {
|
|
||||||
overflow = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if b_carry {
|
|
||||||
let ret = overflowing!($name(ret).overflowing_add($name(carry)), overflow);
|
|
||||||
(ret, overflow)
|
|
||||||
} else {
|
|
||||||
($name(ret), overflow)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn overflowing_sub(self, other: $name) -> ($name, bool) {
|
|
||||||
let res = overflowing!((!other).overflowing_add(From::from(1u64)));
|
|
||||||
let res = overflowing!(self.overflowing_add(res));
|
|
||||||
(res, self < other)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn overflowing_mul(self, other: $name) -> ($name, bool) {
|
|
||||||
let mut res = $name::from(0u64);
|
|
||||||
let mut overflow = false;
|
|
||||||
// TODO: be more efficient about this
|
|
||||||
for i in 0..(2 * $n_words) {
|
|
||||||
let v = overflowing!(self.overflowing_mul_u32((other >> (32 * i)).low_u32()), overflow);
|
|
||||||
let res2 = overflowing!(v.overflowing_shl(32 * i as u32), overflow);
|
|
||||||
res = overflowing!(res.overflowing_add(res2), overflow);
|
|
||||||
}
|
|
||||||
(res, overflow)
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn overflowing_shl(self, shift32: u32) -> ($name, bool) {
|
|
||||||
let $name(ref original) = self;
|
|
||||||
let mut ret = [0u64; $n_words];
|
|
||||||
let shift = shift32 as usize;
|
|
||||||
let word_shift = shift / 64;
|
|
||||||
let bit_shift = shift % 64;
|
|
||||||
for i in 0..$n_words {
|
|
||||||
// Shift
|
|
||||||
if i + word_shift < $n_words {
|
|
||||||
ret[i + word_shift] += original[i] << bit_shift;
|
|
||||||
}
|
|
||||||
// Carry
|
|
||||||
if bit_shift > 0 && i + word_shift + 1 < $n_words {
|
|
||||||
ret[i + word_shift + 1] += original[i] >> (64 - bit_shift);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Detecting overflow
|
|
||||||
let last = $n_words - word_shift - if bit_shift > 0 { 1 } else { 0 };
|
|
||||||
let overflow = if bit_shift > 0 {
|
|
||||||
(original[last] >> (64 - bit_shift)) > 0
|
|
||||||
} else if word_shift > 0 {
|
|
||||||
original[last] > 0
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
};
|
|
||||||
|
|
||||||
for i in last+1..$n_words-1 {
|
|
||||||
if original[i] > 0 {
|
|
||||||
return ($name(ret), true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
($name(ret), overflow)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn overflowing_shr(self, _shift32: u32) -> ($name, bool) {
|
|
||||||
// TODO [todr] not used for now
|
|
||||||
unimplemented!();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Add<$name> for $name {
|
impl Add<$name> for $name {
|
||||||
type Output = $name;
|
type Output = $name;
|
||||||
|
|
||||||
@ -915,7 +930,6 @@ pub const BAD_U256: U256 = U256([0xffffffffffffffffu64; 4]);
|
|||||||
mod tests {
|
mod tests {
|
||||||
use uint::{Uint, U128, U256, U512};
|
use uint::{Uint, U128, U256, U512};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::num::wrapping::OverflowingOps;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn assign_ops() {
|
pub fn assign_ops() {
|
||||||
|
Loading…
Reference in New Issue
Block a user