Skip to content

Commit

Permalink
Merge branch 'main' into is-zero
Browse files Browse the repository at this point in the history
  • Loading branch information
prestwich authored Jun 15, 2024
2 parents 5e32a0c + 345af9e commit d3822f8
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 89 deletions.
3 changes: 2 additions & 1 deletion deny.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ allow = [
"Unicode-DFS-2016",
"Unlicense",
"MPL-2.0",
"CC0-1.0"
"CC0-1.0",
"Unicode-3.0",
]

[sources]
Expand Down
86 changes: 19 additions & 67 deletions src/bits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -254,53 +254,22 @@ impl<const BITS: usize, const LIMBS: usize> Uint<BITS, LIMBS> {
/// the shift is larger than `BITS` (which is IMHO not very useful).
#[inline]
#[must_use]
pub fn overflowing_shl(mut self, rhs: usize) -> (Self, bool) {
pub fn overflowing_shl(self, rhs: usize) -> (Self, bool) {
let (limbs, bits) = (rhs / 64, rhs % 64);
if limbs >= LIMBS {
return (Self::ZERO, self != Self::ZERO);
}
if bits == 0 {
// Check for overflow
let mut overflow = false;
for i in (LIMBS - limbs)..LIMBS {
overflow |= self.limbs[i] != 0;
}
if self.limbs[LIMBS - limbs - 1] > Self::MASK {
overflow = true;
}

// Shift
for i in (limbs..LIMBS).rev() {
assume!(i >= limbs && i - limbs < LIMBS);
self.limbs[i] = self.limbs[i - limbs];
}
self.limbs[..limbs].fill(0);
self.limbs[LIMBS - 1] &= Self::MASK;
return (self, overflow);
}

// Check for overflow
let mut overflow = false;
for i in (LIMBS - limbs)..LIMBS {
overflow |= self.limbs[i] != 0;
}
if self.limbs[LIMBS - limbs - 1] >> (64 - bits) != 0 {
overflow = true;
let word_bits = 64;
let mut r = Self::ZERO;
let mut carry = 0;
for i in 0..Self::LIMBS - limbs {
let x = self.limbs[i];
r.limbs[i + limbs] = (x << bits) | carry;
carry = (x >> (word_bits - bits - 1)) >> 1;
}
if self.limbs[LIMBS - limbs - 1] << bits > Self::MASK {
overflow = true;
}

// Shift
for i in (limbs + 1..LIMBS).rev() {
assume!(i - limbs < LIMBS && i - limbs - 1 < LIMBS);
self.limbs[i] = self.limbs[i - limbs] << bits;
self.limbs[i] |= self.limbs[i - limbs - 1] >> (64 - bits);
}
self.limbs[limbs] = self.limbs[0] << bits;
self.limbs[..limbs].fill(0);
self.limbs[LIMBS - 1] &= Self::MASK;
(self, overflow)
r.limbs[LIMBS - 1] &= Self::MASK;
(r, carry != 0)
}

/// Left shift by `rhs` bits.
Expand Down Expand Up @@ -349,38 +318,21 @@ impl<const BITS: usize, const LIMBS: usize> Uint<BITS, LIMBS> {
/// the shift is larger than `BITS` (which is IMHO not very useful).
#[inline]
#[must_use]
pub fn overflowing_shr(mut self, rhs: usize) -> (Self, bool) {
pub fn overflowing_shr(self, rhs: usize) -> (Self, bool) {
let (limbs, bits) = (rhs / 64, rhs % 64);
if limbs >= LIMBS {
return (Self::ZERO, self != Self::ZERO);
}
if bits == 0 {
// Check for overflow
let mut overflow = false;
for i in 0..limbs {
overflow |= self.limbs[i] != 0;
}

// Shift
for i in 0..(LIMBS - limbs) {
self.limbs[i] = self.limbs[i + limbs];
}
self.limbs[LIMBS - limbs..].fill(0);
return (self, overflow);
}

// Check for overflow
let overflow = self.limbs[LIMBS - limbs - 1] >> (bits - 1) & 1 != 0;

// Shift
for i in 0..(LIMBS - limbs - 1) {
assume!(i + limbs < LIMBS && i + limbs + 1 < LIMBS);
self.limbs[i] = self.limbs[i + limbs] >> bits;
self.limbs[i] |= self.limbs[i + limbs + 1] << (64 - bits);
let word_bits = 64;
let mut r = Self::ZERO;
let mut carry = 0;
for i in 0..LIMBS - limbs {
let x = self.limbs[LIMBS - 1 - i];
r.limbs[LIMBS - 1 - i - limbs] = (x >> bits) | carry;
carry = (x << (word_bits - bits - 1)) << 1;
}
self.limbs[LIMBS - limbs - 1] = self.limbs[LIMBS - 1] >> bits;
self.limbs[LIMBS - limbs..].fill(0);
(self, overflow)
(r, carry != 0)
}

/// Right shift by `rhs` bits.
Expand Down
2 changes: 2 additions & 0 deletions src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ macro_rules! impl_bin_op {
};
}

#[allow(unused)]
macro_rules! assume {
($e:expr $(,)?) => {
if !$e {
Expand All @@ -89,6 +90,7 @@ macro_rules! assume {
};
}

#[allow(unused)]
macro_rules! debug_unreachable {
($($t:tt)*) => {
if cfg!(debug_assertions) {
Expand Down
25 changes: 4 additions & 21 deletions src/support/serde.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,29 +39,11 @@ impl<const BITS: usize, const LIMBS: usize> Uint<BITS, LIMBS> {
}

fn serialize_human_minimal<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
if BITS == 0 {
if self.is_zero() {
return s.serialize_str(ZERO_STR);
}

let le_bytes = self.as_le_bytes();
let mut bytes = le_bytes.iter().rev().skip_while(|b| **b == 0);

// We avoid String allocation if there is no non-0 byte
// If there is a first byte, we allocate a string, and write the prefix
// and first byte to it
let mut result = match bytes.next() {
Some(b) => {
let mut result = String::with_capacity(2 + nbytes(BITS) * 2);
write!(result, "0x{b:x}").unwrap();
result
}
None => return s.serialize_str(ZERO_STR),
};
bytes
.try_for_each(|byte| write!(result, "{byte:02x}"))
.unwrap();

s.serialize_str(&result)
s.serialize_str(&format!("{self:#x}"))
}

fn serialize_binary<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
Expand All @@ -83,7 +65,8 @@ impl<const BITS: usize, const LIMBS: usize> Serialize for Uint<BITS, LIMBS> {
}
}

/// Deserialize human readable hex strings or byte arrays into hashes.
/// Deserialize human readable hex strings or byte arrays into [`Uint`].
///
/// Hex strings can be upper/lower/mixed case, have an optional `0x` prefix, and
/// can be any length. They are interpreted big-endian.
impl<'de, const BITS: usize, const LIMBS: usize> Deserialize<'de> for Uint<BITS, LIMBS> {
Expand Down

0 comments on commit d3822f8

Please sign in to comment.