diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c04aee000..3a0758dc40 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ and this project adheres to - cosmwasm-std: Implement `Decimal{,256}::checked_mul` and `Decimal{,256}::checked_pow`. - cosmwasm-std: Implement `Sub`/`SubAssign` for `Uint64`. +- cosmwasm-std: Implement `Mul`/`MulAssign` for `Uint64`. - cosmwasm-crypto: Upgrade ed25519-zebra to version 3. - cosmwasm-vm: Upgrade Wasmer to 2.2.1 diff --git a/packages/std/src/math/mod.rs b/packages/std/src/math/mod.rs index 4c956b0377..7908d7c3fe 100644 --- a/packages/std/src/math/mod.rs +++ b/packages/std/src/math/mod.rs @@ -31,11 +31,10 @@ mod tests { + Sub<&'a Self> + SubAssign + SubAssign<&'a Self> - // Uncomment when implementing Mul/MulAssign for Uint64 - // + Mul - // + Mul<&'a Self> - // + MulAssign - // + MulAssign<&'a Self> + + Mul + + Mul<&'a Self> + + MulAssign + + MulAssign<&'a Self> + Div + Div<&'a Self> + DivAssign diff --git a/packages/std/src/math/uint128.rs b/packages/std/src/math/uint128.rs index 87b667459c..98549b2af5 100644 --- a/packages/std/src/math/uint128.rs +++ b/packages/std/src/math/uint128.rs @@ -3,7 +3,7 @@ use schemars::JsonSchema; use serde::{de, ser, Deserialize, Deserializer, Serialize}; use std::convert::{TryFrom, TryInto}; use std::fmt::{self}; -use std::ops::{self, Rem, Sub, SubAssign}; +use std::ops::{self, Mul, MulAssign, Rem, Sub, SubAssign}; use std::str::FromStr; use crate::errors::{DivideByZeroError, OverflowError, OverflowOperation, StdError}; @@ -275,7 +275,7 @@ impl SubAssign for Uint128 { } forward_ref_op_assign!(impl SubAssign, sub_assign for Uint128, Uint128); -impl ops::Mul for Uint128 { +impl Mul for Uint128 { type Output = Self; fn mul(self, rhs: Self) -> Self::Output { @@ -286,14 +286,14 @@ impl ops::Mul for Uint128 { ) } } +forward_ref_binop!(impl Mul, mul for Uint128, Uint128); -impl<'a> ops::Mul<&'a Uint128> for Uint128 { - type Output = Self; - - fn mul(self, rhs: &'a Uint128) -> Self::Output { - self.mul(*rhs) +impl MulAssign for Uint128 { + fn mul_assign(&mut self, rhs: Self) { + *self = *self * rhs; } } +forward_ref_op_assign!(impl MulAssign, mul_assign for Uint128, Uint128); impl ops::Div for Uint128 { type Output = Self; @@ -347,18 +347,6 @@ impl<'a> ops::AddAssign<&'a Uint128> for Uint128 { } } -impl ops::MulAssign for Uint128 { - fn mul_assign(&mut self, rhs: Self) { - *self = *self * rhs; - } -} - -impl<'a> ops::MulAssign<&'a Uint128> for Uint128 { - fn mul_assign(&mut self, rhs: &'a Uint128) { - *self = *self * rhs; - } -} - impl ops::DivAssign for Uint128 { fn div_assign(&mut self, rhs: Self) { *self = *self / rhs; @@ -697,6 +685,38 @@ mod tests { assert_eq!(a, expected); } + #[test] + #[allow(clippy::op_ref)] + fn uint128_mul_works() { + assert_eq!( + Uint128::from(2u32) * Uint128::from(3u32), + Uint128::from(6u32) + ); + assert_eq!(Uint128::from(2u32) * Uint128::zero(), Uint128::zero()); + + // works for refs + let a = Uint128::from(11u32); + let b = Uint128::from(3u32); + let expected = Uint128::from(33u32); + assert_eq!(a * b, expected); + assert_eq!(a * &b, expected); + assert_eq!(&a * b, expected); + assert_eq!(&a * &b, expected); + } + + #[test] + fn uint128_mul_assign_works() { + let mut a = Uint128::from(14u32); + a *= Uint128::from(2u32); + assert_eq!(a, Uint128::from(28u32)); + + // works for refs + let mut a = Uint128::from(10u32); + let b = Uint128::from(3u32); + a *= &b; + assert_eq!(a, Uint128::from(30u32)); + } + #[test] fn uint128_multiply_ratio_works() { let base = Uint128(500); diff --git a/packages/std/src/math/uint256.rs b/packages/std/src/math/uint256.rs index bb4675696d..6210c789e3 100644 --- a/packages/std/src/math/uint256.rs +++ b/packages/std/src/math/uint256.rs @@ -3,7 +3,7 @@ use schemars::JsonSchema; use serde::{de, ser, Deserialize, Deserializer, Serialize}; use std::convert::{TryFrom, TryInto}; use std::fmt; -use std::ops::{self, Rem, Shl, Shr, Sub, SubAssign}; +use std::ops::{self, Mul, MulAssign, Rem, Shl, Shr, Sub, SubAssign}; use std::str::FromStr; use crate::errors::{ @@ -447,7 +447,7 @@ impl Rem for Uint256 { } forward_ref_binop!(impl Rem, rem for Uint256, Uint256); -impl ops::Mul for Uint256 { +impl Mul for Uint256 { type Output = Self; fn mul(self, rhs: Self) -> Self::Output { @@ -458,14 +458,14 @@ impl ops::Mul for Uint256 { ) } } +forward_ref_binop!(impl Mul, mul for Uint256, Uint256); -impl<'a> ops::Mul<&'a Uint256> for Uint256 { - type Output = Self; - - fn mul(self, rhs: &'a Uint256) -> Self::Output { - self.mul(*rhs) +impl MulAssign for Uint256 { + fn mul_assign(&mut self, rhs: Self) { + *self = *self * rhs; } } +forward_ref_op_assign!(impl MulAssign, mul_assign for Uint256, Uint256); impl ops::Shr for Uint256 { type Output = Self; @@ -521,18 +521,6 @@ impl<'a> ops::AddAssign<&'a Uint256> for Uint256 { } } -impl ops::MulAssign for Uint256 { - fn mul_assign(&mut self, rhs: Self) { - *self = *self * rhs; - } -} - -impl<'a> ops::MulAssign<&'a Uint256> for Uint256 { - fn mul_assign(&mut self, rhs: &'a Uint256) { - *self = *self * rhs; - } -} - impl ops::DivAssign for Uint256 { fn div_assign(&mut self, rhs: Self) { *self = *self / rhs; @@ -1255,6 +1243,38 @@ mod tests { assert_eq!(a, expected); } + #[test] + #[allow(clippy::op_ref)] + fn uint256_mul_works() { + assert_eq!( + Uint256::from(2u32) * Uint256::from(3u32), + Uint256::from(6u32) + ); + assert_eq!(Uint256::from(2u32) * Uint256::zero(), Uint256::zero()); + + // works for refs + let a = Uint256::from(11u32); + let b = Uint256::from(3u32); + let expected = Uint256::from(33u32); + assert_eq!(a * b, expected); + assert_eq!(a * &b, expected); + assert_eq!(&a * b, expected); + assert_eq!(&a * &b, expected); + } + + #[test] + fn uint256_mul_assign_works() { + let mut a = Uint256::from(14u32); + a *= Uint256::from(2u32); + assert_eq!(a, Uint256::from(28u32)); + + // works for refs + let mut a = Uint256::from(10u32); + let b = Uint256::from(3u32); + a *= &b; + assert_eq!(a, Uint256::from(30u32)); + } + #[test] fn uint256_multiply_ratio_works() { let base = Uint256::from(500u32); diff --git a/packages/std/src/math/uint512.rs b/packages/std/src/math/uint512.rs index 7c57b8995a..8d821a2a0f 100644 --- a/packages/std/src/math/uint512.rs +++ b/packages/std/src/math/uint512.rs @@ -3,7 +3,7 @@ use schemars::JsonSchema; use serde::{de, ser, Deserialize, Deserializer, Serialize}; use std::convert::{TryFrom, TryInto}; use std::fmt; -use std::ops::{self, Rem, Shr, Sub, SubAssign}; +use std::ops::{self, Mul, MulAssign, Rem, Shr, Sub, SubAssign}; use std::str::FromStr; use crate::errors::{ @@ -538,21 +538,21 @@ impl Rem for Uint512 { } forward_ref_binop!(impl Rem, rem for Uint512, Uint512); -impl ops::Mul for Uint512 { +impl Mul for Uint512 { type Output = Self; fn mul(self, rhs: Self) -> Self::Output { Self(self.0.checked_mul(rhs.0).unwrap()) } } +forward_ref_binop!(impl Mul, mul for Uint512, Uint512); -impl<'a> ops::Mul<&'a Uint512> for Uint512 { - type Output = Self; - - fn mul(self, rhs: &'a Uint512) -> Self::Output { - Self(self.0.checked_mul(rhs.0).unwrap()) +impl MulAssign for Uint512 { + fn mul_assign(&mut self, rhs: Self) { + self.0 = self.0.checked_mul(rhs.0).unwrap(); } } +forward_ref_op_assign!(impl MulAssign, mul_assign for Uint512, Uint512); impl ops::Shr for Uint512 { type Output = Self; @@ -599,18 +599,6 @@ impl<'a> ops::DivAssign<&'a Uint512> for Uint512 { } } -impl ops::MulAssign for Uint512 { - fn mul_assign(&mut self, rhs: Self) { - self.0 = self.0.checked_mul(rhs.0).unwrap(); - } -} - -impl<'a> ops::MulAssign<&'a Uint512> for Uint512 { - fn mul_assign(&mut self, rhs: &'a Uint512) { - self.0 = self.0.checked_mul(rhs.0).unwrap(); - } -} - impl ops::ShrAssign for Uint512 { fn shr_assign(&mut self, rhs: u32) { *self = Shr::::shr(*self, rhs); @@ -1027,6 +1015,38 @@ mod tests { assert_eq!(a, expected); } + #[test] + #[allow(clippy::op_ref)] + fn uint512_mul_works() { + assert_eq!( + Uint512::from(2u32) * Uint512::from(3u32), + Uint512::from(6u32) + ); + assert_eq!(Uint512::from(2u32) * Uint512::zero(), Uint512::zero()); + + // works for refs + let a = Uint512::from(11u32); + let b = Uint512::from(3u32); + let expected = Uint512::from(33u32); + assert_eq!(a * b, expected); + assert_eq!(a * &b, expected); + assert_eq!(&a * b, expected); + assert_eq!(&a * &b, expected); + } + + #[test] + fn uint512_mul_assign_works() { + let mut a = Uint512::from(14u32); + a *= Uint512::from(2u32); + assert_eq!(a, Uint512::from(28u32)); + + // works for refs + let mut a = Uint512::from(10u32); + let b = Uint512::from(3u32); + a *= &b; + assert_eq!(a, Uint512::from(30u32)); + } + #[test] fn uint512_shr_works() { let original = Uint512::new([ diff --git a/packages/std/src/math/uint64.rs b/packages/std/src/math/uint64.rs index 3c455c1ac2..45857b85b3 100644 --- a/packages/std/src/math/uint64.rs +++ b/packages/std/src/math/uint64.rs @@ -3,7 +3,7 @@ use schemars::JsonSchema; use serde::{de, ser, Deserialize, Deserializer, Serialize}; use std::convert::{TryFrom, TryInto}; use std::fmt::{self}; -use std::ops::{self, Rem, Sub, SubAssign}; +use std::ops::{self, Mul, MulAssign, Rem, Sub, SubAssign}; use crate::errors::{DivideByZeroError, OverflowError, OverflowOperation, StdError}; use crate::Uint128; @@ -230,6 +230,26 @@ impl SubAssign for Uint64 { } forward_ref_op_assign!(impl SubAssign, sub_assign for Uint64, Uint64); +impl Mul for Uint64 { + type Output = Self; + + fn mul(self, rhs: Self) -> Self::Output { + Self( + self.u64() + .checked_mul(rhs.u64()) + .expect("attempt to multiply with overflow"), + ) + } +} +forward_ref_binop!(impl Mul, mul for Uint64, Uint64); + +impl MulAssign for Uint64 { + fn mul_assign(&mut self, rhs: Self) { + *self = *self * rhs; + } +} +forward_ref_op_assign!(impl MulAssign, mul_assign for Uint64, Uint64); + impl ops::Div for Uint64 { type Output = Self; @@ -575,6 +595,35 @@ mod tests { assert_eq!(a, expected); } + #[test] + #[allow(clippy::op_ref)] + fn uint64_mul_works() { + assert_eq!(Uint64::from(2u32) * Uint64::from(3u32), Uint64::from(6u32)); + assert_eq!(Uint64::from(2u32) * Uint64::zero(), Uint64::zero()); + + // works for refs + let a = Uint64::from(11u32); + let b = Uint64::from(3u32); + let expected = Uint64::from(33u32); + assert_eq!(a * b, expected); + assert_eq!(a * &b, expected); + assert_eq!(&a * b, expected); + assert_eq!(&a * &b, expected); + } + + #[test] + fn uint64_mul_assign_works() { + let mut a = Uint64::from(14u32); + a *= Uint64::from(2u32); + assert_eq!(a, Uint64::from(28u32)); + + // works for refs + let mut a = Uint64::from(10u32); + let b = Uint64::from(3u32); + a *= &b; + assert_eq!(a, Uint64::from(30u32)); + } + #[test] #[should_panic] fn uint64_math_overflow_panics() {