From 34756444852307b228cb46de2f72214579e410f0 Mon Sep 17 00:00:00 2001 From: Jakub Bogucki Date: Fri, 8 Jul 2022 15:38:10 +0200 Subject: [PATCH 1/4] Decimal/256: Implement pow --- packages/std/src/math/decimal.rs | 20 ++++++++++++++++++++ packages/std/src/math/decimal256.rs | 23 +++++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/packages/std/src/math/decimal.rs b/packages/std/src/math/decimal.rs index 13bc9b8082..6e77636ad3 100644 --- a/packages/std/src/math/decimal.rs +++ b/packages/std/src/math/decimal.rs @@ -212,6 +212,14 @@ impl Decimal { }) } + /// Raises a value to the power of `exp`, pancis 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 { // This uses the exponentiation by squaring algorithm: @@ -1835,4 +1843,16 @@ 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); + } } diff --git a/packages/std/src/math/decimal256.rs b/packages/std/src/math/decimal256.rs index c0f9005f8b..63777e5009 100644 --- a/packages/std/src/math/decimal256.rs +++ b/packages/std/src/math/decimal256.rs @@ -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 { // This uses the exponentiation by squaring algorithm: @@ -1982,4 +1990,19 @@ 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); + } } From a804ab2cbb74eea7a7790ef20cc9df25d97247ae Mon Sep 17 00:00:00 2001 From: Jakub Bogucki Date: Fri, 8 Jul 2022 15:55:01 +0200 Subject: [PATCH 2/4] Decimal/256: Implement saturating_pow --- packages/std/src/math/decimal.rs | 15 ++++++++++++++- packages/std/src/math/decimal256.rs | 13 +++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/packages/std/src/math/decimal.rs b/packages/std/src/math/decimal.rs index 6e77636ad3..8d9fe7e558 100644 --- a/packages/std/src/math/decimal.rs +++ b/packages/std/src/math/decimal.rs @@ -212,7 +212,7 @@ impl Decimal { }) } - /// Raises a value to the power of `exp`, pancis if an overflow occurred. + /// 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, @@ -253,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 { Decimal::checked_from_ratio(self.numerator(), other.numerator()) } @@ -1855,4 +1863,9 @@ mod tests { fn decimal_pow_overflow_panics() { Decimal::MAX.pow(2u32); } + + #[test] + fn decimal_saturating_pow() { + assert_eq!(Decimal::MAX.saturating_pow(2u32), Decimal::MAX); + } } diff --git a/packages/std/src/math/decimal256.rs b/packages/std/src/math/decimal256.rs index 63777e5009..d7e36960ee 100644 --- a/packages/std/src/math/decimal256.rs +++ b/packages/std/src/math/decimal256.rs @@ -266,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 { Decimal256::checked_from_ratio(self.numerator(), other.numerator()) } @@ -2005,4 +2013,9 @@ mod tests { fn decimal256_pow_overflow_panics() { Decimal256::MAX.pow(2u32); } + + #[test] + fn decimal_saturating_pow() { + assert_eq!(Decimal::MAX.saturating_pow(2u32), Decimal::MAX); + } } From fcce61d7536fd1e5719b447b04356aeee613f8fd Mon Sep 17 00:00:00 2001 From: Jakub Bogucki Date: Fri, 8 Jul 2022 15:58:23 +0200 Subject: [PATCH 3/4] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 44baac9c44..bd6ff727a6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 From afde9163caf35db636b2986097d186ccb87b0a75 Mon Sep 17 00:00:00 2001 From: Jakub Bogucki Date: Fri, 8 Jul 2022 16:42:07 +0200 Subject: [PATCH 4/4] Decimal/256: Add one more testcase to increase coverage --- packages/std/src/math/decimal.rs | 4 ++++ packages/std/src/math/decimal256.rs | 8 ++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/packages/std/src/math/decimal.rs b/packages/std/src/math/decimal.rs index 8d9fe7e558..cd00a4ccdb 100644 --- a/packages/std/src/math/decimal.rs +++ b/packages/std/src/math/decimal.rs @@ -1866,6 +1866,10 @@ mod tests { #[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); } } diff --git a/packages/std/src/math/decimal256.rs b/packages/std/src/math/decimal256.rs index d7e36960ee..508191c6fa 100644 --- a/packages/std/src/math/decimal256.rs +++ b/packages/std/src/math/decimal256.rs @@ -2015,7 +2015,11 @@ mod tests { } #[test] - fn decimal_saturating_pow() { - assert_eq!(Decimal::MAX.saturating_pow(2u32), Decimal::MAX); + fn decimal256_saturating_pow() { + assert_eq!( + Decimal256::percent(400).saturating_pow(2u32), + Decimal256::percent(1600) + ); + assert_eq!(Decimal256::MAX.saturating_pow(2u32), Decimal256::MAX); } }