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