Permalink
Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.
Sign up| // Copyright 2015-2017 Parity Technologies | |
| // | |
| // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |
| // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |
| // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |
| // option. This file may not be copied, modified, or distributed | |
| // except according to those terms. | |
| // Code derived from original work by Andrew Poelstra <apoelstra@wpsoftware.net> | |
| // Rust Bitcoin Library | |
| // Written in 2014 by | |
| // Andrew Poelstra <apoelstra@wpsoftware.net> | |
| // | |
| // 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 <http://creativecommons.org/publicdomain/zero/1.0/>. | |
| // | |
| //! Big unsigned integer types. | |
| //! | |
| //! Implementation of a various large-but-fixed sized unsigned integer types. | |
| //! The functions here are designed to be fast. There are optional `x86_64` | |
| //! implementations for even more speed, hidden behind the `x64_arithmetic` | |
| //! feature flag. | |
| /// Conversion from decimal string error | |
| #[derive(Debug, PartialEq)] | |
| pub enum FromDecStrErr { | |
| /// Char not from range 0-9 | |
| InvalidCharacter, | |
| /// Value does not fit into type | |
| InvalidLength, | |
| } | |
| #[macro_export] | |
| #[doc(hidden)] | |
| macro_rules! impl_map_from { | |
| ($thing:ident, $from:ty, $to:ty) => { | |
| impl From<$from> for $thing { | |
| fn from(value: $from) -> $thing { | |
| From::from(value as $to) | |
| } | |
| } | |
| } | |
| } | |
| #[macro_export] | |
| #[doc(hidden)] | |
| macro_rules! uint_overflowing_add { | |
| ($name:ident, $n_words: tt, $self_expr: expr, $other: expr) => ({ | |
| uint_overflowing_add_reg!($name, $n_words, $self_expr, $other) | |
| }) | |
| } | |
| #[macro_export] | |
| #[doc(hidden)] | |
| macro_rules! uint_overflowing_add_reg { | |
| ($name:ident, $n_words: tt, $self_expr: expr, $other: expr) => ({ | |
| uint_overflowing_binop!( | |
| $name, | |
| $n_words, | |
| $self_expr, | |
| $other, | |
| u64::overflowing_add | |
| ) | |
| }) | |
| } | |
| #[macro_export] | |
| #[doc(hidden)] | |
| macro_rules! uint_overflowing_sub { | |
| ($name:ident, $n_words: tt, $self_expr: expr, $other: expr) => ({ | |
| uint_overflowing_sub_reg!($name, $n_words, $self_expr, $other) | |
| }) | |
| } | |
| #[macro_export] | |
| #[doc(hidden)] | |
| macro_rules! uint_overflowing_binop { | |
| ($name:ident, $n_words: tt, $self_expr: expr, $other: expr, $fn:expr) => ({ | |
| let $name(ref me) = $self_expr; | |
| let $name(ref you) = $other; | |
| let mut ret = unsafe { $crate::core_::mem::uninitialized() }; | |
| let ret_ptr = &mut ret as *mut [u64; $n_words] as *mut u64; | |
| let mut carry = 0u64; | |
| unroll! { | |
| for i in 0..$n_words { | |
| use $crate::core_::ptr; | |
| if carry != 0 { | |
| let (res1, overflow1) = ($fn)(me[i], you[i]); | |
| let (res2, overflow2) = ($fn)(res1, carry); | |
| unsafe { | |
| ptr::write( | |
| ret_ptr.offset(i as _), | |
| res2 | |
| ); | |
| } | |
| carry = (overflow1 as u8 + overflow2 as u8) as u64; | |
| } else { | |
| let (res, overflow) = ($fn)(me[i], you[i]); | |
| unsafe { | |
| ptr::write( | |
| ret_ptr.offset(i as _), | |
| res | |
| ); | |
| } | |
| carry = overflow as u64; | |
| } | |
| } | |
| } | |
| ($name(ret), carry > 0) | |
| }) | |
| } | |
| #[macro_export] | |
| #[doc(hidden)] | |
| macro_rules! uint_overflowing_sub_reg { | |
| ($name:ident, $n_words: tt, $self_expr: expr, $other: expr) => ({ | |
| uint_overflowing_binop!( | |
| $name, | |
| $n_words, | |
| $self_expr, | |
| $other, | |
| u64::overflowing_sub | |
| ) | |
| }) | |
| } | |
| #[macro_export] | |
| #[doc(hidden)] | |
| macro_rules! uint_overflowing_mul { | |
| ($name:ident, $n_words: tt, $self_expr: expr, $other: expr) => ({ | |
| uint_overflowing_mul_reg!($name, $n_words, $self_expr, $other) | |
| }) | |
| } | |
| #[macro_export] | |
| #[doc(hidden)] | |
| macro_rules! uint_full_mul_reg { | |
| ($name:ident, 8, $self_expr:expr, $other:expr) => { | |
| uint_full_mul_reg!($name, 8, $self_expr, $other, |a, b| a != 0 || b != 0); | |
| }; | |
| ($name:ident, $n_words:tt, $self_expr:expr, $other:expr) => { | |
| uint_full_mul_reg!($name, $n_words, $self_expr, $other, |_, _| true); | |
| }; | |
| ($name:ident, $n_words:tt, $self_expr:expr, $other:expr, $check:expr) => ({{ | |
| #![allow(unused_assignments)] | |
| let $name(ref me) = $self_expr; | |
| let $name(ref you) = $other; | |
| let mut ret = [0u64; $n_words * 2]; | |
| unroll! { | |
| for i in 0..$n_words { | |
| let mut carry = 0u64; | |
| let b = you[i]; | |
| unroll! { | |
| for j in 0..$n_words { | |
| if $check(me[j], carry) { | |
| let a = me[j]; | |
| let (hi, low) = $crate::split_u128(a as u128 * b as u128); | |
| let overflow = { | |
| let existing_low = &mut ret[i + j]; | |
| let (low, o) = low.overflowing_add(*existing_low); | |
| *existing_low = low; | |
| o | |
| }; | |
| carry = { | |
| let existing_hi = &mut ret[i + j + 1]; | |
| let hi = hi + overflow as u64; | |
| let (hi, o0) = hi.overflowing_add(carry); | |
| let (hi, o1) = hi.overflowing_add(*existing_hi); | |
| *existing_hi = hi; | |
| (o0 | o1) as u64 | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } | |
| ret | |
| }}); | |
| } | |
| #[macro_export] | |
| #[doc(hidden)] | |
| macro_rules! uint_overflowing_mul_reg { | |
| ($name:ident, $n_words: tt, $self_expr: expr, $other: expr) => ({ | |
| let ret: [u64; $n_words * 2] = uint_full_mul_reg!($name, $n_words, $self_expr, $other); | |
| // The safety of this is enforced by the compiler | |
| let ret: [[u64; $n_words]; 2] = unsafe { $crate::core_::mem::transmute(ret) }; | |
| // The compiler WILL NOT inline this if you remove this annotation. | |
| #[inline(always)] | |
| fn any_nonzero(arr: &[u64; $n_words]) -> bool { | |
| unroll! { | |
| for i in 0..$n_words { | |
| if arr[i] != 0 { | |
| return true; | |
| } | |
| } | |
| } | |
| false | |
| } | |
| ($name(ret[0]), any_nonzero(&ret[1])) | |
| }) | |
| } | |
| #[macro_export] | |
| #[doc(hidden)] | |
| macro_rules! overflowing { | |
| ($op: expr, $overflow: expr) => ( | |
| { | |
| let (overflow_x, overflow_overflow) = $op; | |
| $overflow |= overflow_overflow; | |
| overflow_x | |
| } | |
| ); | |
| ($op: expr) => ( | |
| { | |
| let (overflow_x, _overflow_overflow) = $op; | |
| overflow_x | |
| } | |
| ); | |
| } | |
| #[macro_export] | |
| #[doc(hidden)] | |
| macro_rules! panic_on_overflow { | |
| ($name: expr) => { | |
| if $name { | |
| panic!("arithmetic operation overflow") | |
| } | |
| } | |
| } | |
| #[macro_export] | |
| #[doc(hidden)] | |
| macro_rules! impl_mul_from { | |
| ($name: ty, $other: ident) => { | |
| impl $crate::core_::ops::Mul<$other> for $name { | |
| type Output = $name; | |
| fn mul(self, other: $other) -> $name { | |
| let bignum: $name = other.into(); | |
| let (result, overflow) = self.overflowing_mul(bignum); | |
| panic_on_overflow!(overflow); | |
| result | |
| } | |
| } | |
| impl<'a> $crate::core_::ops::Mul<&'a $other> for $name { | |
| type Output = $name; | |
| fn mul(self, other: &'a $other) -> $name { | |
| let bignum: $name = (*other).into(); | |
| let (result, overflow) = self.overflowing_mul(bignum); | |
| panic_on_overflow!(overflow); | |
| result | |
| } | |
| } | |
| impl<'a> $crate::core_::ops::Mul<&'a $other> for &'a $name { | |
| type Output = $name; | |
| fn mul(self, other: &'a $other) -> $name { | |
| let bignum: $name = (*other).into(); | |
| let (result, overflow) = self.overflowing_mul(bignum); | |
| panic_on_overflow!(overflow); | |
| result | |
| } | |
| } | |
| impl<'a> $crate::core_::ops::Mul<$other> for &'a $name { | |
| type Output = $name; | |
| fn mul(self, other: $other) -> $name { | |
| let bignum: $name = other.into(); | |
| let (result, overflow) = self.overflowing_mul(bignum); | |
| panic_on_overflow!(overflow); | |
| result | |
| } | |
| } | |
| } | |
| } | |
| #[macro_export] | |
| #[doc(hidden)] | |
| macro_rules! impl_mulassign_from { | |
| ($name: ident, $other: ident) => { | |
| impl $crate::core_::ops::MulAssign<$other> for $name { | |
| fn mul_assign(&mut self, other: $other) { | |
| let result = *self * other; | |
| *self = result | |
| } | |
| } | |
| } | |
| } | |
| #[inline(always)] | |
| #[doc(hidden)] | |
| pub fn mul_u32(a: (u64, u64), b: u64, carry: u64) -> (u64, u64) { | |
| let upper = b * a.0; | |
| let lower = b * a.1; | |
| let (res1, overflow1) = lower.overflowing_add(upper << 32); | |
| let (res2, overflow2) = res1.overflowing_add(carry); | |
| let carry = (upper >> 32) + overflow1 as u64 + overflow2 as u64; | |
| (res2, carry) | |
| } | |
| #[inline(always)] | |
| #[doc(hidden)] | |
| pub fn split(a: u64) -> (u64, u64) { | |
| (a >> 32, a & 0xFFFF_FFFF) | |
| } | |
| #[inline(always)] | |
| #[doc(hidden)] | |
| pub fn split_u128(a: u128) -> (u64, u64) { | |
| ((a >> 64) as _, (a & 0xFFFFFFFFFFFFFFFF) as _) | |
| } | |
| #[macro_export] | |
| macro_rules! construct_uint { | |
| ( $(#[$attr:meta])* $visibility:vis struct $name:ident ( $n_words:tt ); ) => { | |
| /// Little-endian large integer type | |
| #[repr(C)] | |
| $(#[$attr])* | |
| #[derive(Copy, Clone, Eq, PartialEq, Hash)] | |
| $visibility struct $name (pub [u64; $n_words]); | |
| impl AsRef<$name> for $name { | |
| fn as_ref(&self) -> &$name { | |
| &self | |
| } | |
| } | |
| impl<'a> From<&'a $name> for $name { | |
| fn from(x: &'a $name) -> $name { | |
| *x | |
| } | |
| } | |
| impl $name { | |
| /// Maximum value. | |
| pub const MAX: $name = $name([u64::max_value(); $n_words]); | |
| /// Convert from a decimal string. | |
| pub fn from_dec_str(value: &str) -> Result<Self, $crate::FromDecStrErr> { | |
| if !value.bytes().all(|b| b >= 48 && b <= 57) { | |
| return Err($crate::FromDecStrErr::InvalidCharacter) | |
| } | |
| let mut res = Self::default(); | |
| for b in value.bytes().map(|b| b - 48) { | |
| let (r, overflow) = res.overflowing_mul_u32(10); | |
| if overflow { | |
| return Err($crate::FromDecStrErr::InvalidLength); | |
| } | |
| let (r, overflow) = r.overflowing_add(b.into()); | |
| if overflow { | |
| return Err($crate::FromDecStrErr::InvalidLength); | |
| } | |
| res = r; | |
| } | |
| Ok(res) | |
| } | |
| /// Conversion to u32 | |
| #[inline] | |
| pub fn low_u32(&self) -> u32 { | |
| let &$name(ref arr) = self; | |
| arr[0] as u32 | |
| } | |
| /// Low word (u64) | |
| #[inline] | |
| pub fn low_u64(&self) -> u64 { | |
| let &$name(ref arr) = self; | |
| arr[0] | |
| } | |
| /// Conversion to u32 with overflow checking | |
| /// | |
| /// # Panics | |
| /// | |
| /// Panics if the number is larger than 2^32. | |
| #[inline] | |
| pub fn as_u32(&self) -> u32 { | |
| let &$name(ref arr) = self; | |
| if (arr[0] & (0xffffffffu64 << 32)) != 0 { | |
| panic!("Integer overflow when casting U256") | |
| } | |
| self.as_u64() as u32 | |
| } | |
| /// Conversion to u64 with overflow checking | |
| /// | |
| /// # Panics | |
| /// | |
| /// Panics if the number is larger than u64::max_value(). | |
| #[inline] | |
| pub fn as_u64(&self) -> u64 { | |
| let &$name(ref arr) = self; | |
| for i in 1..$n_words { | |
| if arr[i] != 0 { | |
| panic!("Integer overflow when casting U256") | |
| } | |
| } | |
| arr[0] | |
| } | |
| /// Conversion to usize with overflow checking | |
| /// | |
| /// # Panics | |
| /// | |
| /// Panics if the number is larger than usize::max_value(). | |
| #[inline] | |
| pub fn as_usize(&self) -> usize { | |
| let &$name(ref arr) = self; | |
| for i in 1..$n_words { | |
| if arr[i] != 0 { | |
| panic!("Integer overflow when casting U256") | |
| } | |
| } | |
| if arr[0] > usize::max_value() as u64 { | |
| panic!("Integer overflow when casting U256") | |
| } | |
| arr[0] as usize | |
| } | |
| /// Whether this is zero. | |
| #[inline] | |
| pub fn is_zero(&self) -> bool { | |
| let &$name(ref arr) = self; | |
| for i in 0..$n_words { if arr[i] != 0 { return false; } } | |
| return true; | |
| } | |
| /// Return the least number of bits needed to represent the number | |
| #[inline] | |
| pub fn bits(&self) -> usize { | |
| let &$name(ref arr) = self; | |
| for i in 1..$n_words { | |
| if arr[$n_words - i] > 0 { return (0x40 * ($n_words - i + 1)) - arr[$n_words - i].leading_zeros() as usize; } | |
| } | |
| 0x40 - arr[0].leading_zeros() as usize | |
| } | |
| /// Return if specific bit is set. | |
| /// | |
| /// # Panics | |
| /// | |
| /// Panics if `index` exceeds the bit width of the number. | |
| #[inline] | |
| pub fn bit(&self, index: usize) -> bool { | |
| let &$name(ref arr) = self; | |
| arr[index / 64] & (1 << (index % 64)) != 0 | |
| } | |
| /// Returns the number of leading zeros in the binary representation of self. | |
| pub fn leading_zeros(&self) -> u32 { | |
| let mut r = 0; | |
| for i in 0..$n_words { | |
| let w = self.0[$n_words - i - 1]; | |
| if w == 0 { | |
| r += 64; | |
| } else { | |
| r += w.leading_zeros(); | |
| break; | |
| } | |
| } | |
| r | |
| } | |
| /// Returns the number of leading zeros in the binary representation of self. | |
| pub fn trailing_zeros(&self) -> u32 { | |
| let mut r = 0; | |
| for i in 0..$n_words { | |
| let w = self.0[i]; | |
| if w == 0 { | |
| r += 64; | |
| } else { | |
| r += w.trailing_zeros(); | |
| break; | |
| } | |
| } | |
| r | |
| } | |
| /// Return specific byte. | |
| /// | |
| /// # Panics | |
| /// | |
| /// Panics if `index` exceeds the byte width of the number. | |
| #[inline] | |
| pub fn byte(&self, index: usize) -> u8 { | |
| let &$name(ref arr) = self; | |
| (arr[index / 8] >> (((index % 8)) * 8)) as u8 | |
| } | |
| /// Write to the slice in big-endian format. | |
| #[inline] | |
| pub fn to_big_endian(&self, bytes: &mut [u8]) { | |
| use $crate::byteorder::{ByteOrder, BigEndian}; | |
| debug_assert!($n_words * 8 == bytes.len()); | |
| for i in 0..$n_words { | |
| BigEndian::write_u64(&mut bytes[8 * i..], self.0[$n_words - i - 1]); | |
| } | |
| } | |
| /// Write to the slice in little-endian format. | |
| #[inline] | |
| pub fn to_little_endian(&self, bytes: &mut [u8]) { | |
| use $crate::byteorder::{ByteOrder, LittleEndian}; | |
| debug_assert!($n_words * 8 == bytes.len()); | |
| for i in 0..$n_words { | |
| LittleEndian::write_u64(&mut bytes[8 * i..], self.0[i]); | |
| } | |
| } | |
| /// Create `10**n` as this type. | |
| /// | |
| /// # Panics | |
| /// | |
| /// Panics if the result overflows the type. | |
| #[inline] | |
| pub fn exp10(n: usize) -> Self { | |
| match n { | |
| 0 => Self::from(1u64), | |
| _ => Self::exp10(n - 1) * 10u32 | |
| } | |
| } | |
| /// Zero (additive identity) of this type. | |
| #[inline] | |
| pub fn zero() -> Self { | |
| From::from(0u64) | |
| } | |
| /// One (multiplicative identity) of this type. | |
| #[inline] | |
| pub fn one() -> Self { | |
| From::from(1u64) | |
| } | |
| /// The maximum value which can be inhabited by this type. | |
| #[inline] | |
| pub fn max_value() -> Self { | |
| let mut result = [0; $n_words]; | |
| for i in 0..$n_words { | |
| result[i] = u64::max_value(); | |
| } | |
| $name(result) | |
| } | |
| /// Fast exponentation by squaring | |
| /// https://en.wikipedia.org/wiki/Exponentiation_by_squaring | |
| /// | |
| /// # Panics | |
| /// | |
| /// Panics if the result overflows the type. | |
| pub fn pow(self, expon: Self) -> Self { | |
| if expon.is_zero() { | |
| return Self::one() | |
| } | |
| let is_even = |x : &Self| x.low_u64() & 1 == 0; | |
| let u_one = Self::one(); | |
| let mut y = u_one; | |
| let mut n = expon; | |
| let mut x = self; | |
| while n > u_one { | |
| if is_even(&n) { | |
| x = x * x; | |
| n = n >> 1usize; | |
| } else { | |
| y = x * y; | |
| x = x * x; | |
| // to reduce odd number by 1 we should just clear the last bit | |
| n.0[$n_words-1] = n.0[$n_words-1] & ((!0u64)>>1); | |
| n = n >> 1usize; | |
| } | |
| } | |
| x * y | |
| } | |
| /// Fast exponentation by squaring. Returns result and overflow flag. | |
| pub fn overflowing_pow(self, expon: Self) -> (Self, bool) { | |
| if expon.is_zero() { return (Self::one(), false) } | |
| let is_even = |x : &Self| x.low_u64() & 1 == 0; | |
| let u_one = Self::one(); | |
| let mut y = u_one; | |
| let mut n = expon; | |
| let mut x = self; | |
| let mut overflow = false; | |
| while n > u_one { | |
| if is_even(&n) { | |
| x = overflowing!(x.overflowing_mul(x), overflow); | |
| n = n >> 1usize; | |
| } else { | |
| y = overflowing!(x.overflowing_mul(y), overflow); | |
| x = overflowing!(x.overflowing_mul(x), overflow); | |
| n = (n - u_one) >> 1usize; | |
| } | |
| } | |
| let res = overflowing!(x.overflowing_mul(y), overflow); | |
| (res, overflow) | |
| } | |
| /// Add with overflow. | |
| #[inline(always)] | |
| pub fn overflowing_add(self, other: $name) -> ($name, bool) { | |
| uint_overflowing_add!($name, $n_words, self, other) | |
| } | |
| /// Addition which saturates at the maximum value (Self::max_value()). | |
| pub fn saturating_add(self, other: $name) -> $name { | |
| match self.overflowing_add(other) { | |
| (_, true) => $name::max_value(), | |
| (val, false) => val, | |
| } | |
| } | |
| /// Checked addition. Returns `None` if overflow occurred. | |
| pub fn checked_add(self, other: $name) -> Option<$name> { | |
| match self.overflowing_add(other) { | |
| (_, true) => None, | |
| (val, _) => Some(val), | |
| } | |
| } | |
| /// Subtraction which underflows and returns a flag if it does. | |
| #[inline(always)] | |
| pub fn overflowing_sub(self, other: $name) -> ($name, bool) { | |
| uint_overflowing_sub!($name, $n_words, self, other) | |
| } | |
| /// Subtraction which saturates at zero. | |
| pub fn saturating_sub(self, other: $name) -> $name { | |
| match self.overflowing_sub(other) { | |
| (_, true) => $name::zero(), | |
| (val, false) => val, | |
| } | |
| } | |
| /// Checked subtraction. Returns `None` if overflow occurred. | |
| pub fn checked_sub(self, other: $name) -> Option<$name> { | |
| match self.overflowing_sub(other) { | |
| (_, true) => None, | |
| (val, _) => Some(val), | |
| } | |
| } | |
| /// Multiply with overflow, returning a flag if it does. | |
| #[inline(always)] | |
| pub fn overflowing_mul(self, other: $name) -> ($name, bool) { | |
| uint_overflowing_mul!($name, $n_words, self, other) | |
| } | |
| /// Multiplication which saturates at the maximum value.. | |
| pub fn saturating_mul(self, other: $name) -> $name { | |
| match self.overflowing_mul(other) { | |
| (_, true) => $name::max_value(), | |
| (val, false) => val, | |
| } | |
| } | |
| /// Checked multiplication. Returns `None` if overflow occurred. | |
| pub fn checked_mul(self, other: $name) -> Option<$name> { | |
| match self.overflowing_mul(other) { | |
| (_, true) => None, | |
| (val, _) => Some(val), | |
| } | |
| } | |
| /// Checked division. Returns `None` if `other == 0`. | |
| pub fn checked_div(self, other: $name) -> Option<$name> { | |
| if other.is_zero() { | |
| None | |
| } else { | |
| Some(self / other) | |
| } | |
| } | |
| /// Checked modulus. Returns `None` if `other == 0`. | |
| pub fn checked_rem(self, other: $name) -> Option<$name> { | |
| if other.is_zero() { | |
| None | |
| } else { | |
| Some(self % other) | |
| } | |
| } | |
| /// Negation with overflow. | |
| pub fn overflowing_neg(self) -> ($name, bool) { | |
| if self.is_zero() { | |
| (self, false) | |
| } else { | |
| (!self, true) | |
| } | |
| } | |
| /// Checked negation. Returns `None` unless `self == 0`. | |
| pub fn checked_neg(self) -> Option<$name> { | |
| match self.overflowing_neg() { | |
| (_, true) => None, | |
| (zero, false) => Some(zero), | |
| } | |
| } | |
| /// Overflowing multiplication by u32. | |
| fn overflowing_mul_u32(self, other: u32) -> (Self, bool) { | |
| let $name(ref arr) = self; | |
| let mut ret = [0u64; $n_words]; | |
| let mut carry = 0; | |
| let o = other as u64; | |
| for i in 0..$n_words { | |
| let (res, carry2) = $crate::mul_u32($crate::split(arr[i]), o, carry); | |
| ret[i] = res; | |
| carry = carry2; | |
| } | |
| ($name(ret), carry > 0) | |
| } | |
| /// Converts from big endian representation bytes in memory. | |
| pub fn from_big_endian(slice: &[u8]) -> Self { | |
| assert!($n_words * 8 >= slice.len()); | |
| let mut ret = [0; $n_words]; | |
| unsafe { | |
| let ret_u8: &mut [u8; $n_words * 8] = $crate::core_::mem::transmute(&mut ret); | |
| let mut ret_ptr = ret_u8.as_mut_ptr(); | |
| let mut slice_ptr = slice.as_ptr().offset(slice.len() as isize - 1); | |
| for _ in 0..slice.len() { | |
| *ret_ptr = *slice_ptr; | |
| ret_ptr = ret_ptr.offset(1); | |
| slice_ptr = slice_ptr.offset(-1); | |
| } | |
| } | |
| $name(ret) | |
| } | |
| /// Converts from little endian representation bytes in memory. | |
| pub fn from_little_endian(slice: &[u8]) -> Self { | |
| assert!($n_words * 8 >= slice.len()); | |
| let mut ret = [0; $n_words]; | |
| unsafe { | |
| let ret_u8: &mut [u8; $n_words * 8] = $crate::core_::mem::transmute(&mut ret); | |
| ret_u8[0..slice.len()].copy_from_slice(&slice); | |
| } | |
| $name(ret) | |
| } | |
| } | |
| impl $crate::core_::convert::From<$name> for [u8; $n_words * 8] { | |
| fn from(number: $name) -> Self { | |
| let mut arr = [0u8; $n_words * 8]; | |
| number.to_big_endian(&mut arr); | |
| arr | |
| } | |
| } | |
| impl $crate::core_::convert::From<[u8; $n_words * 8]> for $name { | |
| fn from(bytes: [u8; $n_words * 8]) -> Self { | |
| bytes[..].as_ref().into() | |
| } | |
| } | |
| impl<'a> $crate::core_::convert::From<&'a [u8; $n_words * 8]> for $name { | |
| fn from(bytes: &[u8; $n_words * 8]) -> Self { | |
| bytes[..].into() | |
| } | |
| } | |
| impl $crate::core_::default::Default for $name { | |
| fn default() -> Self { | |
| $name::zero() | |
| } | |
| } | |
| impl $crate::core_::convert::From<u64> 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 $crate::core_::convert::From<i64> for $name { | |
| fn from(value: i64) -> $name { | |
| match value >= 0 { | |
| true => From::from(value as u64), | |
| false => { panic!("Unsigned integer can't be created from negative value"); } | |
| } | |
| } | |
| } | |
| impl_map_from!($name, i8, i64); | |
| impl_map_from!($name, i16, i64); | |
| impl_map_from!($name, i32, i64); | |
| impl_map_from!($name, isize, i64); | |
| // Converts from big endian representation of U256 | |
| impl<'a> $crate::core_::convert::From<&'a [u8]> for $name { | |
| fn from(bytes: &[u8]) -> $name { | |
| Self::from_big_endian(bytes) | |
| } | |
| } | |
| impl<T> $crate::core_::ops::Add<T> for $name where T: Into<$name> { | |
| type Output = $name; | |
| fn add(self, other: T) -> $name { | |
| let (result, overflow) = self.overflowing_add(other.into()); | |
| panic_on_overflow!(overflow); | |
| result | |
| } | |
| } | |
| impl<'a, T> $crate::core_::ops::Add<T> for &'a $name where T: Into<$name> { | |
| type Output = $name; | |
| fn add(self, other: T) -> $name { | |
| *self + other | |
| } | |
| } | |
| impl $crate::core_::ops::AddAssign<$name> for $name { | |
| fn add_assign(&mut self, other: $name) { | |
| let (result, overflow) = self.overflowing_add(other); | |
| panic_on_overflow!(overflow); | |
| *self = result | |
| } | |
| } | |
| impl<T> $crate::core_::ops::Sub<T> for $name where T: Into<$name> { | |
| type Output = $name; | |
| #[inline] | |
| fn sub(self, other: T) -> $name { | |
| let (result, overflow) = self.overflowing_sub(other.into()); | |
| panic_on_overflow!(overflow); | |
| result | |
| } | |
| } | |
| impl<'a, T> $crate::core_::ops::Sub<T> for &'a $name where T: Into<$name> { | |
| type Output = $name; | |
| fn sub(self, other: T) -> $name { | |
| *self - other | |
| } | |
| } | |
| impl $crate::core_::ops::SubAssign<$name> for $name { | |
| fn sub_assign(&mut self, other: $name) { | |
| let (result, overflow) = self.overflowing_sub(other); | |
| panic_on_overflow!(overflow); | |
| *self = result | |
| } | |
| } | |
| // specialization for u32 | |
| impl $crate::core_::ops::Mul<u32> for $name { | |
| type Output = $name; | |
| fn mul(self, other: u32) -> $name { | |
| let (ret, overflow) = self.overflowing_mul_u32(other); | |
| panic_on_overflow!(overflow); | |
| ret | |
| } | |
| } | |
| impl<'a> $crate::core_::ops::Mul<u32> for &'a $name { | |
| type Output = $name; | |
| fn mul(self, other: u32) -> $name { | |
| *self * other | |
| } | |
| } | |
| impl $crate::core_::ops::MulAssign<u32> for $name { | |
| fn mul_assign(&mut self, other: u32) { | |
| let result = *self * other; | |
| *self = result | |
| } | |
| } | |
| // all other impls | |
| impl_mul_from!($name, u8); | |
| impl_mul_from!($name, u16); | |
| impl_mul_from!($name, u64); | |
| impl_mul_from!($name, usize); | |
| impl_mul_from!($name, i8); | |
| impl_mul_from!($name, i16); | |
| impl_mul_from!($name, i64); | |
| impl_mul_from!($name, isize); | |
| impl_mul_from!($name, $name); | |
| impl_mulassign_from!($name, u8); | |
| impl_mulassign_from!($name, u16); | |
| impl_mulassign_from!($name, u64); | |
| impl_mulassign_from!($name, usize); | |
| impl_mulassign_from!($name, i8); | |
| impl_mulassign_from!($name, i16); | |
| impl_mulassign_from!($name, i64); | |
| impl_mulassign_from!($name, isize); | |
| impl_mulassign_from!($name, $name); | |
| impl<T> $crate::core_::ops::Div<T> for $name where T: Into<$name> { | |
| type Output = $name; | |
| fn div(self, other: T) -> $name { | |
| let other: Self = other.into(); | |
| let mut sub_copy = self; | |
| let mut 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; | |
| let mut shift_copy = other << shift; | |
| loop { | |
| if sub_copy >= shift_copy { | |
| ret[shift / 64] |= 1 << (shift % 64); | |
| sub_copy = overflowing!(sub_copy.overflowing_sub(shift_copy)); | |
| } | |
| if shift == 0 { break; } | |
| shift -= 1; | |
| shift_copy >>= 1usize; | |
| } | |
| $name(ret) | |
| } | |
| } | |
| impl<'a, T> $crate::core_::ops::Div<T> for &'a $name where T: Into<$name> { | |
| type Output = $name; | |
| fn div(self, other: T) -> $name { | |
| *self / other | |
| } | |
| } | |
| impl<T> $crate::core_::ops::DivAssign<T> for $name where T: Into<$name> { | |
| fn div_assign(&mut self, other: T) { | |
| *self = *self / other.into(); | |
| } | |
| } | |
| impl<T> $crate::core_::ops::Rem<T> for $name where T: Into<$name> + Copy { | |
| type Output = $name; | |
| fn rem(self, other: T) -> $name { | |
| let mut sub_copy = self; | |
| sub_copy %= other; | |
| sub_copy | |
| } | |
| } | |
| impl<'a, T> $crate::core_::ops::Rem<T> for &'a $name where T: Into<$name> + Copy { | |
| type Output = $name; | |
| fn rem(self, other: T) -> $name { | |
| *self % other | |
| } | |
| } | |
| impl<T> $crate::core_::ops::RemAssign<T> for $name where T: Into<$name> + Copy { | |
| fn rem_assign(&mut self, other: T) { | |
| let other: Self = other.into(); | |
| 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; | |
| } | |
| // Bitwise long division | |
| let mut shift = my_bits - your_bits; | |
| let mut shift_copy = other << shift; | |
| loop { | |
| if *self >= shift_copy { | |
| *self = overflowing!(self.overflowing_sub(shift_copy)); | |
| } | |
| if shift == 0 { break; } | |
| shift -= 1; | |
| shift_copy >>= 1usize; | |
| } | |
| } | |
| } | |
| impl $crate::core_::ops::BitAnd<$name> for $name { | |
| type Output = $name; | |
| #[inline] | |
| fn bitand(self, other: $name) -> $name { | |
| let $name(ref arr1) = self; | |
| let $name(ref arr2) = other; | |
| let mut ret = [0u64; $n_words]; | |
| for i in 0..$n_words { | |
| ret[i] = arr1[i] & arr2[i]; | |
| } | |
| $name(ret) | |
| } | |
| } | |
| impl $crate::core_::ops::BitXor<$name> for $name { | |
| type Output = $name; | |
| #[inline] | |
| fn bitxor(self, other: $name) -> $name { | |
| let $name(ref arr1) = self; | |
| let $name(ref arr2) = other; | |
| let mut ret = [0u64; $n_words]; | |
| for i in 0..$n_words { | |
| ret[i] = arr1[i] ^ arr2[i]; | |
| } | |
| $name(ret) | |
| } | |
| } | |
| impl $crate::core_::ops::BitOr<$name> for $name { | |
| type Output = $name; | |
| #[inline] | |
| fn bitor(self, other: $name) -> $name { | |
| let $name(ref arr1) = self; | |
| let $name(ref arr2) = other; | |
| let mut ret = [0u64; $n_words]; | |
| for i in 0..$n_words { | |
| ret[i] = arr1[i] | arr2[i]; | |
| } | |
| $name(ret) | |
| } | |
| } | |
| impl $crate::core_::ops::Not for $name { | |
| type Output = $name; | |
| #[inline] | |
| fn not(self) -> $name { | |
| let $name(ref arr) = self; | |
| let mut ret = [0u64; $n_words]; | |
| for i in 0..$n_words { | |
| ret[i] = !arr[i]; | |
| } | |
| $name(ret) | |
| } | |
| } | |
| impl<T> $crate::core_::ops::Shl<T> for $name where T: Into<$name> { | |
| type Output = $name; | |
| fn shl(self, shift: T) -> $name { | |
| let shift = shift.into().as_usize(); | |
| let $name(ref original) = self; | |
| let mut ret = [0u64; $n_words]; | |
| let word_shift = shift / 64; | |
| let bit_shift = shift % 64; | |
| // shift | |
| for i in word_shift..$n_words { | |
| ret[i] = original[i - word_shift] << bit_shift; | |
| } | |
| // carry | |
| if bit_shift > 0 { | |
| for i in word_shift+1..$n_words { | |
| ret[i] += original[i - 1 - word_shift] >> (64 - bit_shift); | |
| } | |
| } | |
| $name(ret) | |
| } | |
| } | |
| impl<'a, T> $crate::core_::ops::Shl<T> for &'a $name where T: Into<$name> { | |
| type Output = $name; | |
| fn shl(self, shift: T) -> $name { | |
| *self << shift | |
| } | |
| } | |
| impl<T> $crate::core_::ops::ShlAssign<T> for $name where T: Into<$name> { | |
| fn shl_assign(&mut self, shift: T) { | |
| *self = *self << shift; | |
| } | |
| } | |
| impl<T> $crate::core_::ops::Shr<T> for $name where T: Into<$name> { | |
| type Output = $name; | |
| fn shr(self, shift: T) -> $name { | |
| let shift = shift.into().as_usize(); | |
| let $name(ref original) = self; | |
| let mut ret = [0u64; $n_words]; | |
| let word_shift = shift / 64; | |
| let bit_shift = shift % 64; | |
| // shift | |
| for i in word_shift..$n_words { | |
| ret[i - word_shift] = original[i] >> bit_shift; | |
| } | |
| // Carry | |
| if bit_shift > 0 { | |
| for i in word_shift+1..$n_words { | |
| ret[i - word_shift - 1] += original[i] << (64 - bit_shift); | |
| } | |
| } | |
| $name(ret) | |
| } | |
| } | |
| impl<'a, T> $crate::core_::ops::Shr<T> for &'a $name where T: Into<$name> { | |
| type Output = $name; | |
| fn shr(self, shift: T) -> $name { | |
| *self >> shift | |
| } | |
| } | |
| impl<T> $crate::core_::ops::ShrAssign<T> for $name where T: Into<$name> { | |
| fn shr_assign(&mut self, shift: T) { | |
| *self = *self >> shift; | |
| } | |
| } | |
| impl $crate::core_::cmp::Ord for $name { | |
| fn cmp(&self, other: &$name) -> $crate::core_::cmp::Ordering { | |
| let &$name(ref me) = self; | |
| let &$name(ref you) = other; | |
| let mut i = $n_words; | |
| while i > 0 { | |
| i -= 1; | |
| if me[i] < you[i] { return $crate::core_::cmp::Ordering::Less; } | |
| if me[i] > you[i] { return $crate::core_::cmp::Ordering::Greater; } | |
| } | |
| $crate::core_::cmp::Ordering::Equal | |
| } | |
| } | |
| impl $crate::core_::cmp::PartialOrd for $name { | |
| fn partial_cmp(&self, other: &$name) -> Option<$crate::core_::cmp::Ordering> { | |
| Some(self.cmp(other)) | |
| } | |
| } | |
| impl $crate::core_::fmt::Debug for $name { | |
| fn fmt(&self, f: &mut $crate::core_::fmt::Formatter) -> $crate::core_::fmt::Result { | |
| $crate::core_::fmt::Display::fmt(self, f) | |
| } | |
| } | |
| impl $crate::core_::fmt::Display for $name { | |
| fn fmt(&self, f: &mut $crate::core_::fmt::Formatter) -> $crate::core_::fmt::Result { | |
| if self.is_zero() { | |
| return $crate::core_::write!(f, "0"); | |
| } | |
| let mut buf = [0_u8; $n_words*20]; | |
| let mut i = buf.len() - 1; | |
| let mut current = *self; | |
| let ten = $name::from(10); | |
| loop { | |
| let digit = (current % ten).low_u64() as u8; | |
| buf[i] = digit + b'0'; | |
| current = current / ten; | |
| if current.is_zero() { | |
| break; | |
| } | |
| i -= 1; | |
| } | |
| // sequence of `'0'..'9'` chars is guaranteed to be a valid UTF8 string | |
| let s = unsafe { | |
| $crate::core_::str::from_utf8_unchecked(&buf[i..]) | |
| }; | |
| f.write_str(s) | |
| } | |
| } | |
| impl $crate::core_::fmt::LowerHex for $name { | |
| fn fmt(&self, f: &mut $crate::core_::fmt::Formatter) -> $crate::core_::fmt::Result { | |
| let &$name(ref data) = self; | |
| if f.alternate() { | |
| $crate::core_::write!(f, "0x")?; | |
| } | |
| // special case. | |
| if self.is_zero() { | |
| return $crate::core_::write!(f, "0"); | |
| } | |
| let mut latch = false; | |
| for ch in data.iter().rev() { | |
| for x in 0..16 { | |
| let nibble = (ch & (15u64 << ((15 - x) * 4) as u64)) >> (((15 - x) * 4) as u64); | |
| if !latch { | |
| latch = nibble != 0; | |
| } | |
| if latch { | |
| $crate::core_::write!(f, "{:x}", nibble)?; | |
| } | |
| } | |
| } | |
| Ok(()) | |
| } | |
| } | |
| impl_std_for_uint!($name, $n_words); | |
| impl_heapsize_for_uint!($name); | |
| // `$n_words * 8` because macro expects bytes and | |
| // uints use 64 bit (8 byte) words | |
| impl_quickcheck_arbitrary_for_uint!($name, ($n_words * 8)); | |
| } | |
| } | |
| #[cfg(feature = "std")] | |
| #[macro_export] | |
| #[doc(hidden)] | |
| macro_rules! impl_std_for_uint { | |
| ($name: ident, $n_words: tt) => { | |
| impl $crate::core_::str::FromStr for $name { | |
| type Err = $crate::rustc_hex::FromHexError; | |
| fn from_str(value: &str) -> Result<$name, Self::Err> { | |
| use $crate::rustc_hex::FromHex; | |
| let bytes: Vec<u8> = match value.len() % 2 == 0 { | |
| true => value.from_hex()?, | |
| false => ("0".to_owned() + value).from_hex()? | |
| }; | |
| let bytes_ref: &[u8] = &bytes; | |
| Ok(From::from(bytes_ref)) | |
| } | |
| } | |
| impl $crate::core_::convert::From<&'static str> for $name { | |
| fn from(s: &'static str) -> Self { | |
| s.parse().unwrap() | |
| } | |
| } | |
| } | |
| } | |
| #[cfg(not(feature = "std"))] | |
| #[macro_export] | |
| #[doc(hidden)] | |
| macro_rules! impl_std_for_uint { | |
| ($name: ident, $n_words: tt) => {} | |
| } | |
| #[cfg(feature="heapsize")] | |
| #[macro_export] | |
| #[doc(hidden)] | |
| macro_rules! impl_heapsize_for_uint { | |
| ($name: ident) => { | |
| impl $crate::heapsize::HeapSizeOf for $name { | |
| fn heap_size_of_children(&self) -> usize { | |
| 0 | |
| } | |
| } | |
| } | |
| } | |
| #[cfg(not(feature="heapsize"))] | |
| #[macro_export] | |
| #[doc(hidden)] | |
| macro_rules! impl_heapsize_for_uint { | |
| ($name: ident) => {} | |
| } | |
| #[cfg(feature="quickcheck")] | |
| #[macro_export] | |
| #[doc(hidden)] | |
| macro_rules! impl_quickcheck_arbitrary_for_uint { | |
| ($uint: ty, $n_bytes: tt) => { | |
| impl $crate::quickcheck::Arbitrary for $uint { | |
| fn arbitrary<G: $crate::quickcheck::Gen>(g: &mut G) -> Self { | |
| let mut res = [0u8; $n_bytes]; | |
| let p = g.next_f64(); | |
| // make it more likely to generate smaller numbers that | |
| // don't use up the full $n_bytes | |
| let range = | |
| // 10% chance to generate number that uses up to $n_bytes | |
| if p < 0.1 { | |
| $n_bytes | |
| // 10% chance to generate number that uses up to $n_bytes / 2 | |
| } else if p < 0.2 { | |
| $n_bytes / 2 | |
| // 80% chance to generate number that uses up to $n_bytes / 5 | |
| } else { | |
| $n_bytes / 5 | |
| }; | |
| let size = g.gen_range(0, range); | |
| g.fill_bytes(&mut res[..size]); | |
| res.as_ref().into() | |
| } | |
| } | |
| } | |
| } | |
| #[cfg(not(feature="quickcheck"))] | |
| #[macro_export] | |
| #[doc(hidden)] | |
| macro_rules! impl_quickcheck_arbitrary_for_uint { | |
| ($uint: ty, $n_bytes: tt) => {} | |
| } |