Repository: osmosis-labs/osmosis
Pull request #3826 (2022-12-22 04:16:47)

osmomath: `AddMut` and `QuoMut` (backport #3779)
This is an automatic backport of pull request #3779 done by [Mergify](https://mergify.com).
Cherry-pick of ca6ccbd09f2e9e6778ddb2e45d75ee0de8bfaad8 has failed:
```
On branch mergify/bp/v13.x/pr-3779
Your branch is up to date with 'origin/v13.x'.

You are currently cherry-picking commit ca6ccbd0.
  (fix conflicts and run "git cherry-pick --continue")
  (use "git cherry-pick --skip" to skip this patch)
  (use "git cherry-pick --abort" to cancel the cherry-pick operation)

Changes to be committed:
	modified:   osmomath/decimal.go
	modified:   osmomath/decimal_test.go

Unmerged paths:
  (use "git add/rm <file>..." as appropriate to mark resolution)
	deleted by us:   osmomath/exp2.go

```


To fix up this pull request, you can check it out locally. See documentation: https://docs.github.com/en/github/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/checking-out-pull-requests-locally

---


<details>
<summary>Mergify commands and options</summary>

<br />

More conditions and actions can be found in the [documentation](https://docs.mergify.com/).

You can also trigger Mergify actions by commenting on this pull request:

- `@Mergifyio refresh` will re-evaluate the rules
- `@Mergifyio rebase` will rebase this PR on its base branch
- `@Mergifyio update` will merge the base branch into this PR
- `@Mergifyio backport <destination>` will backport this PR on `<destination>` branch

Additionally, on Mergify [dashboard](https://dashboard.mergify.com/) you can:

- look at your merge queues
- generate the Mergify configuration with the config editor.

Finally, you can contact us on https://mergify.com
</details>


Patch:
diff --git a/osmomath/decimal.go b/osmomath/decimal.go
index 955b6229f..e7801b481 100644
--- a/osmomath/decimal.go
+++ b/osmomath/decimal.go
@@ -240,12 +240,20 @@ func (d BigDec) BigInt() *big.Int {
 
 // addition
 func (d BigDec) Add(d2 BigDec) BigDec {
-	res := new(big.Int).Add(d.i, d2.i)
+	copy := d.Clone()
+	copy.AddMut(d2)
+	return copy
+}
 
-	if res.BitLen() > maxDecBitLen {
+// mutative addition
+func (d BigDec) AddMut(d2 BigDec) BigDec {
+	d.i.Add(d.i, d2.i)
+
+	if d.i.BitLen() > maxDecBitLen {
 		panic("Int overflow")
 	}
-	return BigDec{res}
+
+	return d
 }
 
 // subtraction
@@ -319,19 +327,25 @@ func (d BigDec) MulInt64(i int64) BigDec {
 
 // quotient
 func (d BigDec) Quo(d2 BigDec) BigDec {
+	copy := d.Clone()
+	copy.QuoMut(d2)
+	return copy
+}
+
+// mutative quotient
+func (d BigDec) QuoMut(d2 BigDec) BigDec {
 	// multiply precision twice
-	mul := new(big.Int).Mul(d.i, precisionReuse)
-	mul.Mul(mul, precisionReuse)
+	d.i.Mul(d.i, precisionReuse)
+	d.i.Mul(d.i, precisionReuse)
 
-	quo := new(big.Int).Quo(mul, d2.i)
-	chopped := chopPrecisionAndRound(quo)
+	d.i.Quo(d.i, d2.i)
+	chopPrecisionAndRound(d.i)
 
-	if chopped.BitLen() > maxDecBitLen {
+	if d.i.BitLen() > maxDecBitLen {
 		panic("Int overflow")
 	}
-	return BigDec{chopped}
+	return d
 }
-
 func (d BigDec) QuoRaw(d2 int64) BigDec {
 	// multiply precision, so we can chop it later
 	mul := new(big.Int).Mul(d.i, precisionReuse)


Test patch:
diff --git a/osmomath/decimal_test.go b/osmomath/decimal_test.go
index c1ed64eae..d68ec66f2 100644
--- a/osmomath/decimal_test.go
+++ b/osmomath/decimal_test.go
@@ -37,6 +37,53 @@ func (s *decimalTestSuite) assertMutResult(expectedResult, startValue, mutativeR
 	s.Require().Equal(nonMutativeStartValue, startValue)
 }
 
+func (s *decimalTestSuite) TestAddMut() {
+	toAdd := osmomath.MustNewDecFromStr("10")
+	tests := map[string]struct {
+		startValue        osmomath.BigDec
+		expectedMutResult osmomath.BigDec
+	}{
+		"0":  {osmomath.NewBigDec(0), osmomath.NewBigDec(10)},
+		"1":  {osmomath.NewBigDec(1), osmomath.NewBigDec(11)},
+		"10": {osmomath.NewBigDec(10), osmomath.NewBigDec(20)},
+	}
+
+	for name, tc := range tests {
+		s.Run(name, func() {
+			startMut := tc.startValue.Clone()
+			startNonMut := tc.startValue.Clone()
+
+			resultMut := startMut.AddMut(toAdd)
+			resultNonMut := startNonMut.Add(toAdd)
+
+			s.assertMutResult(tc.expectedMutResult, tc.startValue, resultMut, resultNonMut, startMut, startNonMut)
+		})
+	}
+}
+
+func (s *decimalTestSuite) TestQuoMut() {
+	quoBy := osmomath.MustNewDecFromStr("2")
+	tests := map[string]struct {
+		startValue        osmomath.BigDec
+		expectedMutResult osmomath.BigDec
+	}{
+		"0":  {osmomath.NewBigDec(0), osmomath.NewBigDec(0)},
+		"1":  {osmomath.NewBigDec(1), osmomath.MustNewDecFromStr("0.5")},
+		"10": {osmomath.NewBigDec(10), osmomath.NewBigDec(5)},
+	}
+
+	for name, tc := range tests {
+		s.Run(name, func() {
+			startMut := tc.startValue.Clone()
+			startNonMut := tc.startValue.Clone()
+
+			resultMut := startMut.QuoMut(quoBy)
+			resultNonMut := startNonMut.Quo(quoBy)
+
+			s.assertMutResult(tc.expectedMutResult, tc.startValue, resultMut, resultNonMut, startMut, startNonMut)
+		})
+	}
+}
 func TestDecApproxEq(t *testing.T) {
 	// d1 = 0.55, d2 = 0.6, tol = 0.1
 	d1 := osmomath.NewDecWithPrec(55, 2)