Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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