Skip to content

Commit

Permalink
feat(osmomath): BigDec Clone() and MulMut methods (backport #3678) (#…
Browse files Browse the repository at this point in the history
…3679)

Co-authored-by: Roman <[email protected]>
  • Loading branch information
mergify[bot] and p0mvn authored Dec 10, 2022
1 parent 28234a5 commit 8e77d98
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 5 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## Unreleased

### Misc Improvements

* [#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.

### Features

### Bug fixes
Expand Down
27 changes: 22 additions & 5 deletions osmomath/decimal.go
Original file line number Diff line number Diff line change
Expand Up @@ -260,15 +260,32 @@ func (d BigDec) Sub(d2 BigDec) BigDec {
return BigDec{res}
}

// multiplication
// Clone performs a deep copy of the receiver
// and returns the new result.
func (d BigDec) Clone() BigDec {
copy := BigDec{new(big.Int)}
copy.i.Set(d.i)
return copy
}

// Mut performs non-mutative multiplication.
// The receiver is not modifier but the result is.
func (d BigDec) Mul(d2 BigDec) BigDec {
mul := new(big.Int).Mul(d.i, d2.i)
chopped := chopPrecisionAndRound(mul)
copy := d.Clone()
copy.MulMut(d2)
return copy
}

if chopped.BitLen() > maxDecBitLen {
// Mut performs non-mutative multiplication.
// The receiver is not modifier but the result is.
func (d BigDec) MulMut(d2 BigDec) BigDec {
d.i.Mul(d.i, d2.i)
d.i = chopPrecisionAndRound(d.i)

if d.i.BitLen() > maxDecBitLen {
panic("Int overflow")
}
return BigDec{chopped}
return BigDec{d.i}
}

// multiplication truncate
Expand Down
82 changes: 82 additions & 0 deletions osmomath/decimal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1030,3 +1030,85 @@ func (s *decimalTestSuite) TestCustomBaseLog() {
})
}
}

func (s *decimalTestSuite) TestClone() {

// The value to change the underlying copy's
// internal value to assert on the original BigDec
// remaining unchanged.
changeValue := big.NewInt(10)

tests := map[string]struct {
startValue BigDec
}{
"1.1": {
startValue: MustNewDecFromStr("1.1"),
},
"-3": {
startValue: MustNewDecFromStr("-3"),
},
"0": {
startValue: MustNewDecFromStr("-3"),
},
}

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

copy := tc.startValue.Clone()

s.Require().Equal(tc.startValue, copy)

copy.i.Set(changeValue)
// copy and startValue do not share internals.
s.Require().NotEqual(tc.startValue, copy)
})
}
}

// TestMul_Mutation tests that MulMut mutates the receiver
// while Mut is not.
func (s *decimalTestSuite) TestMul_Mutation() {

mulBy := MustNewDecFromStr("2")

tests := map[string]struct {
startValue BigDec
expectedMulResult BigDec
}{
"1.1": {
startValue: MustNewDecFromStr("1.1"),
expectedMulResult: MustNewDecFromStr("2.2"),
},
"-3": {
startValue: MustNewDecFromStr("-3"),
expectedMulResult: MustNewDecFromStr("-6"),
},
"0": {
startValue: ZeroDec(),
expectedMulResult: ZeroDec(),
},
}

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

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

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

// assert both results are as expectde.
s.Require().Equal(tc.expectedMulResult, resultMut)
s.Require().Equal(tc.expectedMulResult, result)

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

0 comments on commit 8e77d98

Please sign in to comment.