Skip to content

Commit

Permalink
Merge pull request #1459 from CosmWasm/wrapping-ints
Browse files Browse the repository at this point in the history
Add wrapping_* to Uint256/Uint512
  • Loading branch information
webmaster128 authored Oct 17, 2022
2 parents bbfc834 + b02f2f4 commit bbb5bc3
Show file tree
Hide file tree
Showing 5 changed files with 172 additions and 11 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ and this project adheres to

### Added

- cosmwasm-std: Add `wrapping_add`, `wrapping_sub`, `wrapping_mul` and
`wrapping_pow` to `Uint256`/`Uint512`.
- cosmwasm-schema: Better error messaging when attempting to compile schema
generator for `wasm32`
- cosmwasm-vm: In the `secp256k1_verify`, `secp256k1_recover_pubkey`,
Expand Down
29 changes: 23 additions & 6 deletions packages/std/src/math/uint128.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,18 +179,22 @@ impl Uint128 {
.ok_or_else(|| DivideByZeroError::new(self))
}

#[inline]
pub fn wrapping_add(self, other: Self) -> Self {
Self(self.0.wrapping_add(other.0))
}

#[inline]
pub fn wrapping_sub(self, other: Self) -> Self {
Self(self.0.wrapping_sub(other.0))
}

#[inline]
pub fn wrapping_mul(self, other: Self) -> Self {
Self(self.0.wrapping_mul(other.0))
}

#[inline]
pub fn wrapping_pow(self, other: u32) -> Self {
Self(self.0.wrapping_pow(other))
}
Expand Down Expand Up @@ -919,15 +923,28 @@ mod tests {
assert_eq!(Uint128(0).saturating_sub(Uint128(1)), Uint128(0));
assert_eq!(Uint128::MAX.saturating_mul(Uint128(2)), Uint128::MAX);
assert_eq!(Uint128::MAX.saturating_pow(2), Uint128::MAX);
}

// wrapping_*
assert_eq!(Uint128::MAX.wrapping_add(Uint128(1)), Uint128(0));
assert_eq!(Uint128(0).wrapping_sub(Uint128(1)), Uint128::MAX);
#[test]
fn uint128_wrapping_methods() {
// wrapping_add
assert_eq!(Uint128(2).wrapping_add(Uint128(2)), Uint128(4)); // non-wrapping
assert_eq!(Uint128::MAX.wrapping_add(Uint128(1)), Uint128(0)); // wrapping

// wrapping_sub
assert_eq!(Uint128(7).wrapping_sub(Uint128(5)), Uint128(2)); // non-wrapping
assert_eq!(Uint128(0).wrapping_sub(Uint128(1)), Uint128::MAX); // wrapping

// wrapping_mul
assert_eq!(Uint128(3).wrapping_mul(Uint128(2)), Uint128(6)); // non-wrapping
assert_eq!(
Uint128::MAX.wrapping_mul(Uint128(2)),
Uint128(u128::MAX - 1)
);
assert_eq!(Uint128::MAX.wrapping_pow(2), Uint128(1));
Uint128::MAX - Uint128::one()
); // wrapping

// wrapping_pow
assert_eq!(Uint128(2).wrapping_pow(3), Uint128(8)); // non-wrapping
assert_eq!(Uint128::MAX.wrapping_pow(2), Uint128(1)); // wrapping
}

#[test]
Expand Down
61 changes: 61 additions & 0 deletions packages/std/src/math/uint256.rs
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,30 @@ impl Uint256 {
Ok(Self(self.0.shl(other)))
}

#[inline]
pub fn wrapping_add(self, other: Self) -> Self {
let (value, _did_overflow) = self.0.overflowing_add(other.0);
Self(value)
}

#[inline]
pub fn wrapping_sub(self, other: Self) -> Self {
let (value, _did_overflow) = self.0.overflowing_sub(other.0);
Self(value)
}

#[inline]
pub fn wrapping_mul(self, other: Self) -> Self {
let (value, _did_overflow) = self.0.overflowing_mul(other.0);
Self(value)
}

#[inline]
pub fn wrapping_pow(self, other: u32) -> Self {
let (value, _did_overflow) = self.0.overflowing_pow(other.into());
Self(value)
}

pub fn saturating_add(self, other: Self) -> Self {
Self(self.0.saturating_add(other.0))
}
Expand Down Expand Up @@ -1173,6 +1197,43 @@ mod tests {
assert!(!Uint256::from(123u32).is_zero());
}

#[test]
fn uint256_wrapping_methods() {
// wrapping_add
assert_eq!(
Uint256::from(2u32).wrapping_add(Uint256::from(2u32)),
Uint256::from(4u32)
); // non-wrapping
assert_eq!(
Uint256::MAX.wrapping_add(Uint256::from(1u32)),
Uint256::from(0u32)
); // wrapping

// wrapping_sub
assert_eq!(
Uint256::from(7u32).wrapping_sub(Uint256::from(5u32)),
Uint256::from(2u32)
); // non-wrapping
assert_eq!(
Uint256::from(0u32).wrapping_sub(Uint256::from(1u32)),
Uint256::MAX
); // wrapping

// wrapping_mul
assert_eq!(
Uint256::from(3u32).wrapping_mul(Uint256::from(2u32)),
Uint256::from(6u32)
); // non-wrapping
assert_eq!(
Uint256::MAX.wrapping_mul(Uint256::from(2u32)),
Uint256::MAX - Uint256::one()
); // wrapping

// wrapping_pow
assert_eq!(Uint256::from(2u32).wrapping_pow(3), Uint256::from(8u32)); // non-wrapping
assert_eq!(Uint256::MAX.wrapping_pow(2), Uint256::from(1u32)); // wrapping
}

#[test]
fn uint256_json() {
let orig = Uint256::from(1234567890987654321u128);
Expand Down
61 changes: 61 additions & 0 deletions packages/std/src/math/uint512.rs
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,30 @@ impl Uint512 {
Ok(Self(self.0.shr(other)))
}

#[inline]
pub fn wrapping_add(self, other: Self) -> Self {
let (value, _did_overflow) = self.0.overflowing_add(other.0);
Self(value)
}

#[inline]
pub fn wrapping_sub(self, other: Self) -> Self {
let (value, _did_overflow) = self.0.overflowing_sub(other.0);
Self(value)
}

#[inline]
pub fn wrapping_mul(self, other: Self) -> Self {
let (value, _did_overflow) = self.0.overflowing_mul(other.0);
Self(value)
}

#[inline]
pub fn wrapping_pow(self, other: u32) -> Self {
let (value, _did_overflow) = self.0.overflowing_pow(other.into());
Self(value)
}

pub fn saturating_add(self, other: Self) -> Self {
Self(self.0.saturating_add(other.0))
}
Expand Down Expand Up @@ -868,6 +892,43 @@ mod tests {
assert!(!Uint512::from(123u32).is_zero());
}

#[test]
fn uint512_wrapping_methods() {
// wrapping_add
assert_eq!(
Uint512::from(2u32).wrapping_add(Uint512::from(2u32)),
Uint512::from(4u32)
); // non-wrapping
assert_eq!(
Uint512::MAX.wrapping_add(Uint512::from(1u32)),
Uint512::from(0u32)
); // wrapping

// wrapping_sub
assert_eq!(
Uint512::from(7u32).wrapping_sub(Uint512::from(5u32)),
Uint512::from(2u32)
); // non-wrapping
assert_eq!(
Uint512::from(0u32).wrapping_sub(Uint512::from(1u32)),
Uint512::MAX
); // wrapping

// wrapping_mul
assert_eq!(
Uint512::from(3u32).wrapping_mul(Uint512::from(2u32)),
Uint512::from(6u32)
); // non-wrapping
assert_eq!(
Uint512::MAX.wrapping_mul(Uint512::from(2u32)),
Uint512::MAX - Uint512::one()
); // wrapping

// wrapping_pow
assert_eq!(Uint512::from(2u32).wrapping_pow(3), Uint512::from(8u32)); // non-wrapping
assert_eq!(Uint512::MAX.wrapping_pow(2), Uint512::from(1u32)); // wrapping
}

#[test]
fn uint512_json() {
let orig = Uint512::from(1234567890987654321u128);
Expand Down
30 changes: 25 additions & 5 deletions packages/std/src/math/uint64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,18 +175,22 @@ impl Uint64 {
.ok_or_else(|| DivideByZeroError::new(self))
}

#[inline]
pub fn wrapping_add(self, other: Self) -> Self {
Self(self.0.wrapping_add(other.0))
}

#[inline]
pub fn wrapping_sub(self, other: Self) -> Self {
Self(self.0.wrapping_sub(other.0))
}

#[inline]
pub fn wrapping_mul(self, other: Self) -> Self {
Self(self.0.wrapping_mul(other.0))
}

#[inline]
pub fn wrapping_pow(self, other: u32) -> Self {
Self(self.0.wrapping_pow(other))
}
Expand Down Expand Up @@ -835,12 +839,28 @@ mod tests {
assert_eq!(Uint64(0).saturating_sub(Uint64(1)), Uint64(0));
assert_eq!(Uint64::MAX.saturating_mul(Uint64(2)), Uint64::MAX);
assert_eq!(Uint64::MAX.saturating_pow(2), Uint64::MAX);
}

#[test]
fn uint64_wrapping_methods() {
// wrapping_add
assert_eq!(Uint64(2).wrapping_add(Uint64(2)), Uint64(4)); // non-wrapping
assert_eq!(Uint64::MAX.wrapping_add(Uint64(1)), Uint64(0)); // wrapping

// wrapping_sub
assert_eq!(Uint64(7).wrapping_sub(Uint64(5)), Uint64(2)); // non-wrapping
assert_eq!(Uint64(0).wrapping_sub(Uint64(1)), Uint64::MAX); // wrapping

// wrapping_mul
assert_eq!(Uint64(3).wrapping_mul(Uint64(2)), Uint64(6)); // non-wrapping
assert_eq!(
Uint64::MAX.wrapping_mul(Uint64(2)),
Uint64::MAX - Uint64::one()
); // wrapping

// wrapping_*
assert_eq!(Uint64::MAX.wrapping_add(Uint64(1)), Uint64(0));
assert_eq!(Uint64(0).wrapping_sub(Uint64(1)), Uint64::MAX);
assert_eq!(Uint64::MAX.wrapping_mul(Uint64(2)), Uint64(u64::MAX - 1));
assert_eq!(Uint64::MAX.wrapping_pow(2), Uint64(1));
// wrapping_pow
assert_eq!(Uint64(2).wrapping_pow(3), Uint64(8)); // non-wrapping
assert_eq!(Uint64::MAX.wrapping_pow(2), Uint64(1)); // wrapping
}

#[test]
Expand Down

0 comments on commit bbb5bc3

Please sign in to comment.