From 15efb049052f0774041ae518fc35faaa0c5f391c Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Sat, 15 Oct 2022 15:04:37 +0200 Subject: [PATCH 1/2] Inline wrapping fucntions for Uint64/Uint128 and inprove testing --- packages/std/src/math/uint128.rs | 29 +++++++++++++++++++++++------ packages/std/src/math/uint64.rs | 30 +++++++++++++++++++++++++----- 2 files changed, 48 insertions(+), 11 deletions(-) diff --git a/packages/std/src/math/uint128.rs b/packages/std/src/math/uint128.rs index b04f88ed71..741aca4816 100644 --- a/packages/std/src/math/uint128.rs +++ b/packages/std/src/math/uint128.rs @@ -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)) } @@ -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] diff --git a/packages/std/src/math/uint64.rs b/packages/std/src/math/uint64.rs index e7f65db0f2..1eb8678cb6 100644 --- a/packages/std/src/math/uint64.rs +++ b/packages/std/src/math/uint64.rs @@ -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)) } @@ -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] From b02f2f4e0ce31843b7abb0dbb1a62e6764c7a9e2 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Sat, 15 Oct 2022 15:19:19 +0200 Subject: [PATCH 2/2] Add wrapping methods to Uint256/Uint512 --- CHANGELOG.md | 2 ++ packages/std/src/math/uint256.rs | 61 ++++++++++++++++++++++++++++++++ packages/std/src/math/uint512.rs | 61 ++++++++++++++++++++++++++++++++ 3 files changed, 124 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7e2e101a57..69539f7cf5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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`, diff --git a/packages/std/src/math/uint256.rs b/packages/std/src/math/uint256.rs index b7677c0118..bae551dbe2 100644 --- a/packages/std/src/math/uint256.rs +++ b/packages/std/src/math/uint256.rs @@ -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)) } @@ -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); diff --git a/packages/std/src/math/uint512.rs b/packages/std/src/math/uint512.rs index 75556c1d82..fe7c1c7a2d 100644 --- a/packages/std/src/math/uint512.rs +++ b/packages/std/src/math/uint512.rs @@ -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)) } @@ -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);