Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(osmomath): mutative PowerIntegerMut function on osmomath.BigDec #3680

Merged
merged 1 commit into from
Dec 10, 2022
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
4 changes: 2 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* [#3609](https://github.com/osmosis-labs/osmosis/pull/3609) Add Downtime-detection module.
* [#2788](https://github.com/osmosis-labs/osmosis/pull/2788) Add logarithm base 2 implementation.
* [#3677](https://github.com/osmosis-labs/osmosis/pull/3677) Add methods for cloning and mutative multiplication on osmomath.BigDec.
* [#3676](https://github.com/osmosis-labs/osmosis/pull/3676) implement `PowerInteger` function on `osmomath.BigDec`
* [#3678](https://github.com/osmosis-labs/osmosis/pull/3678) implement mutative `PowerIntegerMut` function on `osmomath.BigDec`.

### Bug fixes

Expand Down Expand Up @@ -88,8 +90,6 @@ This release includes stableswap, and expands the IBC safety & composability fun
- The v1beta1 queries actually have base asset and quote asset reversed, so you were always getting 1/correct spot price. People fixed this by reordering the arguments.
- This PR adds v2 queries for doing the correct thing, and giving people time to migrate from v1beta1 queries to v2.
- It also changes cosmwasm to only allow the v2 queries, as no contracts on Osmosis mainnet uses the v1beta1 queries.
* [#3676](https://github.com/osmosis-labs/osmosis/pull/3676) implement `PowerInteger` function on `osmomath.BigDec`


### Bug fixes

Expand Down
14 changes: 11 additions & 3 deletions osmomath/decimal.go
Original file line number Diff line number Diff line change
Expand Up @@ -994,18 +994,26 @@ func (x BigDec) CustomBaseLog(base BigDec) BigDec {
// and returns the result. Non-mutative. Uses square and multiply
// algorithm for performing the calculation.
func (d BigDec) PowerInteger(power uint64) BigDec {
clone := d.Clone()
return clone.PowerIntegerMut(power)
}

// PowerIntegerMut takes a given decimal to an integer power
// and returns the result. Mutative. Uses square and multiply
// algorithm for performing the calculation.
func (d BigDec) PowerIntegerMut(power uint64) BigDec {
if power == 0 {
return OneDec()
}
tmp := OneDec()

for i := power; i > 1; {
if i%2 != 0 {
tmp = tmp.Mul(d)
tmp = tmp.MulMut(d)
}
i /= 2
d = d.Mul(d)
d = d.MulMut(d)
}

return d.Mul(tmp)
return d.MulMut(tmp)
}
65 changes: 57 additions & 8 deletions osmomath/decimal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,20 @@ func TestDecimalTestSuite(t *testing.T) {
suite.Run(t, new(decimalTestSuite))
}

// assertMutResult given expected value after applying a math operation, a start value,
// mutative and non mutative results with start values, asserts that mutation are only applied
// to the mutative versions. Also, asserts that both results match the expected value.
func (s *decimalTestSuite) assertMutResult(expectedResult, startValue, mutativeResult, nonMutativeResult, mutativeStartValue, nonMutativeStartValue BigDec) {
// assert both results are as expected.
s.Require().Equal(expectedResult, mutativeResult)
s.Require().Equal(expectedResult, nonMutativeResult)

// assert that mutative method mutated the receiver
s.Require().Equal(mutativeStartValue, expectedResult)
// assert that non-mutative method did not mutate the receiver
s.Require().Equal(nonMutativeStartValue, startValue)
}

func TestDecApproxEq(t *testing.T) {
// d1 = 0.55, d2 = 0.6, tol = 0.1
d1 := NewDecWithPrec(55, 2)
Expand Down Expand Up @@ -1232,16 +1246,51 @@ func (s *decimalTestSuite) TestMul_Mutation() {
startNonMut := tc.startValue.Clone()

resultMut := startMut.MulMut(mulBy)
result := startNonMut.Mul(mulBy)
resultNonMut := startNonMut.Mul(mulBy)

s.assertMutResult(tc.expectedMulResult, tc.startValue, resultMut, resultNonMut, startMut, startNonMut)
})
}
}

// TestMul_Mutation tests that PowerIntegerMut mutates the receiver
// while PowerInteger is not.
func (s *decimalTestSuite) TestPowerInteger_Mutation() {

exponent := uint64(2)

tests := map[string]struct {
startValue BigDec
expectedResult BigDec
}{
"1": {
startValue: OneDec(),
expectedResult: OneDec(),
},
"-3": {
startValue: MustNewDecFromStr("-3"),
expectedResult: MustNewDecFromStr("9"),
},
"0": {
startValue: ZeroDec(),
expectedResult: ZeroDec(),
},
"4": {
startValue: MustNewDecFromStr("4.5"),
expectedResult: MustNewDecFromStr("20.25"),
},
}

for name, tc := range tests {
s.Run(name, func() {

startMut := tc.startValue.Clone()
startNonMut := tc.startValue.Clone()

// assert both results are as expectde.
s.Require().Equal(tc.expectedMulResult, resultMut)
s.Require().Equal(tc.expectedMulResult, result)
resultMut := startMut.PowerIntegerMut(exponent)
resultNonMut := startNonMut.PowerInteger(exponent)

// assert MulMut mutated the receiver
s.Require().Equal(tc.expectedMulResult, startMut)
// assert Mul did not mutate the receiver
s.Require().Equal(tc.startValue, startNonMut)
s.assertMutResult(tc.expectedResult, tc.startValue, resultMut, resultNonMut, startMut, startNonMut)
})
}
}