Skip to content

Commit

Permalink
Merge pull request #1343 from CosmWasm/1186-implement-saturating-meth…
Browse files Browse the repository at this point in the history
…ods-for-all-types

Implement saturating methods for all math types
  • Loading branch information
ueco-jb authored Jul 12, 2022
2 parents c42ded7 + 5bfe2d1 commit 0a31f55
Show file tree
Hide file tree
Showing 7 changed files with 136 additions and 22 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ and this project adheres to
`Decimal`/`Decimal256`.
- cosmwasm-std: Implement `pow`/`saturating_pow` for `Decimal`/`Decimal256`.
- cosmwasm-std: Implement `ceil`/`floor` for `Decimal`/`Decimal256`.
- cosmwasm-std: Implement `saturating_add`/`sub`/`mul` for
`Decimal`/`Decimal256`.

[#1334]: https://github.com/CosmWasm/cosmwasm/pull/1334

Expand Down
62 changes: 53 additions & 9 deletions packages/std/src/math/decimal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -278,14 +278,6 @@ impl Decimal {
})
}

/// Raises a value to the power of `exp`, returns MAX on overflow.
pub fn saturating_pow(self, exp: u32) -> Self {
match self.checked_pow(exp) {
Ok(value) => value,
Err(_) => Self::MAX,
}
}

pub fn checked_div(self, other: Self) -> Result<Self, CheckedFromRatioError> {
Decimal::checked_from_ratio(self.numerator(), other.numerator())
}
Expand Down Expand Up @@ -332,6 +324,34 @@ impl Decimal {
pub const fn abs_diff(self, other: Self) -> Self {
Self(self.0.abs_diff(other.0))
}

pub fn saturating_add(self, other: Self) -> Self {
match self.checked_add(other) {
Ok(value) => value,
Err(_) => Self::MAX,
}
}

pub fn saturating_sub(self, other: Self) -> Self {
match self.checked_sub(other) {
Ok(value) => value,
Err(_) => Self::zero(),
}
}

pub fn saturating_mul(self, other: Self) -> Self {
match self.checked_mul(other) {
Ok(value) => value,
Err(_) => Self::MAX,
}
}

pub fn saturating_pow(self, exp: u32) -> Self {
match self.checked_pow(exp) {
Ok(value) => value,
Err(_) => Self::MAX,
}
}
}

impl Fraction<Uint128> for Decimal {
Expand Down Expand Up @@ -1890,7 +1910,31 @@ mod tests {
}

#[test]
fn decimal_saturating_pow() {
fn decimal_saturating_works() {
assert_eq!(
Decimal::percent(200).saturating_add(Decimal::percent(200)),
Decimal::percent(400)
);
assert_eq!(
Decimal::MAX.saturating_add(Decimal::percent(200)),
Decimal::MAX
);
assert_eq!(
Decimal::percent(200).saturating_sub(Decimal::percent(100)),
Decimal::percent(100)
);
assert_eq!(
Decimal::zero().saturating_sub(Decimal::percent(200)),
Decimal::zero()
);
assert_eq!(
Decimal::percent(200).saturating_mul(Decimal::percent(50)),
Decimal::percent(100)
);
assert_eq!(
Decimal::MAX.saturating_mul(Decimal::percent(200)),
Decimal::MAX
);
assert_eq!(
Decimal::percent(400).saturating_pow(2u32),
Decimal::percent(1600)
Expand Down
62 changes: 53 additions & 9 deletions packages/std/src/math/decimal256.rs
Original file line number Diff line number Diff line change
Expand Up @@ -291,14 +291,6 @@ impl Decimal256 {
})
}

/// Raises a value to the power of `exp`, returns MAX on overflow.
pub fn saturating_pow(self, exp: u32) -> Self {
match self.checked_pow(exp) {
Ok(value) => value,
Err(_) => Self::MAX,
}
}

pub fn checked_div(self, other: Self) -> Result<Self, CheckedFromRatioError> {
Decimal256::checked_from_ratio(self.numerator(), other.numerator())
}
Expand Down Expand Up @@ -349,6 +341,34 @@ impl Decimal256 {
self - other
}
}

pub fn saturating_add(self, other: Self) -> Self {
match self.checked_add(other) {
Ok(value) => value,
Err(_) => Self::MAX,
}
}

pub fn saturating_sub(self, other: Self) -> Self {
match self.checked_sub(other) {
Ok(value) => value,
Err(_) => Self::zero(),
}
}

pub fn saturating_mul(self, other: Self) -> Self {
match self.checked_mul(other) {
Ok(value) => value,
Err(_) => Self::MAX,
}
}

pub fn saturating_pow(self, exp: u32) -> Self {
match self.checked_pow(exp) {
Ok(value) => value,
Err(_) => Self::MAX,
}
}
}

impl Fraction<Uint256> for Decimal256 {
Expand Down Expand Up @@ -2040,7 +2060,31 @@ mod tests {
}

#[test]
fn decimal256_saturating_pow() {
fn decimal256_saturating_works() {
assert_eq!(
Decimal256::percent(200).saturating_add(Decimal256::percent(200)),
Decimal256::percent(400)
);
assert_eq!(
Decimal256::MAX.saturating_add(Decimal256::percent(200)),
Decimal256::MAX
);
assert_eq!(
Decimal256::percent(200).saturating_sub(Decimal256::percent(100)),
Decimal256::percent(100)
);
assert_eq!(
Decimal256::zero().saturating_sub(Decimal256::percent(200)),
Decimal256::zero()
);
assert_eq!(
Decimal256::percent(200).saturating_mul(Decimal256::percent(50)),
Decimal256::percent(100)
);
assert_eq!(
Decimal256::MAX.saturating_mul(Decimal256::percent(200)),
Decimal256::MAX
);
assert_eq!(
Decimal256::percent(400).saturating_pow(2u32),
Decimal256::percent(1600)
Expand Down
4 changes: 2 additions & 2 deletions packages/std/src/math/uint128.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,8 +205,8 @@ impl Uint128 {
Self(self.0.saturating_mul(other.0))
}

pub fn saturating_pow(self, other: u32) -> Self {
Self(self.0.saturating_pow(other))
pub fn saturating_pow(self, exp: u32) -> Self {
Self(self.0.saturating_pow(exp))
}

pub const fn abs_diff(self, other: Self) -> Self {
Expand Down
12 changes: 12 additions & 0 deletions packages/std/src/math/uint256.rs
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,13 @@ impl Uint256 {
Self(self.0.saturating_mul(other.0))
}

pub fn saturating_pow(self, exp: u32) -> Self {
match self.checked_pow(exp) {
Ok(value) => value,
Err(_) => Self::MAX,
}
}

pub fn abs_diff(self, other: Self) -> Self {
if self < other {
other - self
Expand Down Expand Up @@ -1465,6 +1472,11 @@ mod tests {
Uint256::MAX.saturating_mul(Uint256::from(2u32)),
Uint256::MAX
);
assert_eq!(
Uint256::from(4u32).saturating_pow(2u32),
Uint256::from(16u32)
);
assert_eq!(Uint256::MAX.saturating_pow(2u32), Uint256::MAX);
}

#[test]
Expand Down
12 changes: 12 additions & 0 deletions packages/std/src/math/uint512.rs
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,13 @@ impl Uint512 {
Self(self.0.saturating_mul(other.0))
}

pub fn saturating_pow(self, exp: u32) -> Self {
match self.checked_pow(exp) {
Ok(value) => value,
Err(_) => Self::MAX,
}
}

pub fn abs_diff(self, other: Self) -> Self {
if self < other {
other - self
Expand Down Expand Up @@ -1100,6 +1107,11 @@ mod tests {
Uint512::MAX.saturating_mul(Uint512::from(2u32)),
Uint512::MAX
);
assert_eq!(
Uint512::from(4u32).saturating_pow(2u32),
Uint512::from(16u32)
);
assert_eq!(Uint512::MAX.saturating_pow(2u32), Uint512::MAX);
}

#[test]
Expand Down
4 changes: 2 additions & 2 deletions packages/std/src/math/uint64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,8 +201,8 @@ impl Uint64 {
Self(self.0.saturating_mul(other.0))
}

pub fn saturating_pow(self, other: u32) -> Self {
Self(self.0.saturating_pow(other))
pub fn saturating_pow(self, exp: u32) -> Self {
Self(self.0.saturating_pow(exp))
}

pub const fn abs_diff(self, other: Self) -> Self {
Expand Down

0 comments on commit 0a31f55

Please sign in to comment.