Skip to content

Commit

Permalink
Merge pull request #1342 from CosmWasm/1186-decimal-pow-saturating
Browse files Browse the repository at this point in the history
`Decimal`/`Decimal256`: Implement `pow`/`saturating_pow`
  • Loading branch information
ueco-jb authored Jul 11, 2022
2 parents 08efa35 + afde916 commit ac6050b
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ and this project adheres to
- cosmwasm-std: Implement `Rem`/`RemAssign` for `Decimal`/`Decimal256`.
- cosmwasm-std: Implement `checked_add`/`_sub`/`_div`/`_rem` for
`Decimal`/`Decimal256`.
- cosmwasm-std: Implement `pow`/`saturating_pow` for `Decimal`/`Decimal256`.

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

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

/// Raises a value to the power of `exp`, panics if an overflow occurred.
pub fn pow(self, exp: u32) -> Self {
match self.checked_pow(exp) {
Ok(value) => value,
Err(_) => panic!("Multiplication overflow"),
}
}

/// Raises a value to the power of `exp`, returning an `OverflowError` if an overflow occurred.
pub fn checked_pow(self, exp: u32) -> Result<Self, OverflowError> {
// This uses the exponentiation by squaring algorithm:
Expand Down Expand Up @@ -245,6 +253,14 @@ 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 @@ -1835,4 +1851,25 @@ mod tests {
Err(DivideByZeroError { .. })
));
}

#[test]
fn decimal_pow_works() {
assert_eq!(Decimal::percent(200).pow(2), Decimal::percent(400));
assert_eq!(Decimal::percent(200).pow(10), Decimal::percent(102400));
}

#[test]
#[should_panic]
fn decimal_pow_overflow_panics() {
Decimal::MAX.pow(2u32);
}

#[test]
fn decimal_saturating_pow() {
assert_eq!(
Decimal::percent(400).saturating_pow(2u32),
Decimal::percent(1600)
);
assert_eq!(Decimal::MAX.saturating_pow(2u32), Decimal::MAX);
}
}
40 changes: 40 additions & 0 deletions packages/std/src/math/decimal256.rs
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,14 @@ impl Decimal256 {
})
}

/// Raises a value to the power of `exp`, panics if an overflow occurred.
pub fn pow(self, exp: u32) -> Self {
match self.checked_pow(exp) {
Ok(value) => value,
Err(_) => panic!("Multiplication overflow"),
}
}

/// Raises a value to the power of `exp`, returning an `OverflowError` if an overflow occurred.
pub fn checked_pow(self, exp: u32) -> Result<Self, OverflowError> {
// This uses the exponentiation by squaring algorithm:
Expand Down Expand Up @@ -258,6 +266,14 @@ 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 @@ -1982,4 +1998,28 @@ mod tests {
Err(DivideByZeroError { .. })
));
}

#[test]
fn decimal256_pow_works() {
assert_eq!(Decimal256::percent(200).pow(2), Decimal256::percent(400));
assert_eq!(
Decimal256::percent(200).pow(10),
Decimal256::percent(102400)
);
}

#[test]
#[should_panic]
fn decimal256_pow_overflow_panics() {
Decimal256::MAX.pow(2u32);
}

#[test]
fn decimal256_saturating_pow() {
assert_eq!(
Decimal256::percent(400).saturating_pow(2u32),
Decimal256::percent(1600)
);
assert_eq!(Decimal256::MAX.saturating_pow(2u32), Decimal256::MAX);
}
}

0 comments on commit ac6050b

Please sign in to comment.