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

osmomath: QuoTruncate with no reallocation #6428

Merged
merged 16 commits into from
Sep 20, 2023
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Features

* [#6427](https://github.com/osmosis-labs/osmosis/pull/6427) sdk.Coins Mul and Quo helpers in osmoutils
* [#6428](https://github.com/osmosis-labs/osmosis/pull/6428) osmomath: QuoTruncateMut
* [#6437](https://github.com/osmosis-labs/osmosis/pull/6437) mutative version for QuoRoundUp

### Misc Improvements
Expand Down
4 changes: 0 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -957,10 +957,6 @@ github.com/osmosis-labs/cosmos-sdk v0.45.0-rc1.0.20230908065430-05346fa12992 h1:
github.com/osmosis-labs/cosmos-sdk v0.45.0-rc1.0.20230908065430-05346fa12992/go.mod h1:L6USUt+QX9lIqUVCRs8DFEVRZJbCYbemmtcXb7GfHYE=
github.com/osmosis-labs/go-mutesting v0.0.0-20221208041716-b43bcd97b3b3 h1:YlmchqTmlwdWSmrRmXKR+PcU96ntOd8u10vTaTZdcNY=
github.com/osmosis-labs/go-mutesting v0.0.0-20221208041716-b43bcd97b3b3/go.mod h1:lV6KnqXYD/ayTe7310MHtM3I2q8Z6bBfMAi+bhwPYtI=
github.com/osmosis-labs/osmosis/osmomath v0.0.7-0.20230919070012-03a878db9dad h1:I4m0TxfAAovSmxI0rYvijAVX6JhoYe12VmjM5vcABxU=
github.com/osmosis-labs/osmosis/osmomath v0.0.7-0.20230919070012-03a878db9dad/go.mod h1:pIItelRYvonB+H8A6KqucOi7xFnJxzDHaWJqOdFNLI4=
github.com/osmosis-labs/osmosis/osmomath v0.0.7-0.20230920134402-0622c30178eb h1:czhTR1cvT+a/f5EAz7kIrX3W9zEBWV/9TKIbxcfV2AE=
github.com/osmosis-labs/osmosis/osmomath v0.0.7-0.20230920134402-0622c30178eb/go.mod h1:pIItelRYvonB+H8A6KqucOi7xFnJxzDHaWJqOdFNLI4=
github.com/osmosis-labs/osmosis/osmomath v0.0.7-0.20230920134650-28712c635b4f h1:SwZwcklK2EHIQLD8gVTqMsUTD1GpTyF6X8HlMywrxTc=
github.com/osmosis-labs/osmosis/osmomath v0.0.7-0.20230920134650-28712c635b4f/go.mod h1:pIItelRYvonB+H8A6KqucOi7xFnJxzDHaWJqOdFNLI4=
github.com/osmosis-labs/osmosis/osmoutils v0.0.7-0.20230911120014-b14342e08daf h1:r5R/L3tzH+vGPahAdvnVB2Vo0KPhZR0oMNyX4+G2FEo=
Expand Down
13 changes: 13 additions & 0 deletions osmomath/decimal.go
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,19 @@ func (d BigDec) QuoTruncate(d2 BigDec) BigDec {
return BigDec{chopped}
}

// quotient truncate (mutative)
func (d BigDec) QuoTruncateMut(d2 BigDec) BigDec {
p0mvn marked this conversation as resolved.
Show resolved Hide resolved
// multiply precision twice
d.i.Mul(d.i, squaredPrecisionReuse)
d.i.Quo(d.i, d2.i)

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

// quotient, round up
func (d BigDec) QuoRoundUp(d2 BigDec) BigDec {
// multiply precision twice
Expand Down
59 changes: 59 additions & 0 deletions osmomath/decimal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1560,3 +1560,62 @@ func (s *decimalTestSuite) TestQuoRoundUp_MutativeAndNonMutative() {
}
}
}

func (s *decimalTestSuite) TestQuoTruncate_MutativeAndNonMutative() {
tests := []struct {
d1, d2, expQuoTruncateMut osmomath.BigDec
}{
{osmomath.NewBigDec(0), osmomath.NewBigDec(0), osmomath.NewBigDec(0)},
{osmomath.NewBigDec(1), osmomath.NewBigDec(0), osmomath.NewBigDec(0)},
{osmomath.NewBigDec(0), osmomath.NewBigDec(1), osmomath.NewBigDec(0)},
{osmomath.NewBigDec(0), osmomath.NewBigDec(-1), osmomath.NewBigDec(0)},
{osmomath.NewBigDec(-1), osmomath.NewBigDec(0), osmomath.NewBigDec(0)},

{osmomath.NewBigDec(1), osmomath.NewBigDec(1), osmomath.NewBigDec(1)},
{osmomath.NewBigDec(-1), osmomath.NewBigDec(-1), osmomath.NewBigDec(1)},
{osmomath.NewBigDec(1), osmomath.NewBigDec(-1), osmomath.NewBigDec(-1)},
{osmomath.NewBigDec(-1), osmomath.NewBigDec(1), osmomath.NewBigDec(-1)},

{
osmomath.NewBigDec(3), osmomath.NewBigDec(7), osmomath.MustNewBigDecFromStr("0.428571428571428571428571428571428571"),
},
{
osmomath.NewBigDec(2), osmomath.NewBigDec(4), osmomath.NewBigDecWithPrec(5, 1),
},

{osmomath.NewBigDec(100), osmomath.NewBigDec(100), osmomath.NewBigDec(1)},

{
osmomath.NewBigDecWithPrec(15, 1), osmomath.NewBigDecWithPrec(15, 1), osmomath.NewBigDec(1),
},
{
osmomath.NewBigDecWithPrec(3333, 4), osmomath.NewBigDecWithPrec(333, 4), osmomath.MustNewBigDecFromStr("10.009009009009009009009009009009009009"),
},
}

for tcIndex, tc := range tests {
tc := tc

if tc.d2.IsZero() { // panic for divide by zero
s.Require().Panics(func() { tc.d1.QuoTruncateMut(tc.d2) })
} else {

copy := tc.d1.Clone()

nonMutResult := copy.QuoTruncate(tc.d2)

// Return is as expected
s.Require().Equal(tc.expQuoTruncateMut, nonMutResult, "exp %v, res %v, tc %d", tc.expQuoTruncateMut.String(), tc.d1.String(), tcIndex)

// Receiver is not mutated
s.Require().Equal(tc.d1, copy, "exp %v, res %v, tc %d", tc.expQuoTruncateMut.String(), tc.d1.String(), tcIndex)

// Receiver is mutated.
tc.d1.QuoTruncateMut(tc.d2)
p0mvn marked this conversation as resolved.
Show resolved Hide resolved

// Make sure d1 equals to expected
s.Require().True(tc.expQuoTruncateMut.Equal(tc.d1), "exp %v, res %v, tc %d", tc.expQuoTruncateMut.String(), tc.d1.String(), tcIndex)
}
}
}

3 changes: 1 addition & 2 deletions x/concentrated-liquidity/math/math.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,7 @@ func CalcAmount0Delta(liq, sqrtPriceA, sqrtPriceB osmomath.BigDec, roundUp bool)
// Each intermediary step is truncated at precision end to get a smaller final amount.
// Note that the order of divisions is important here. First, we divide by a larger number (sqrtPriceB) and then by a smaller number (sqrtPriceA).
// This leads to a smaller error amplification.
// TODO (perf): QuoTruncate with no reallocation.
return liq.MulTruncate(diff).QuoTruncate(sqrtPriceB).QuoTruncate(sqrtPriceA)
return liq.MulTruncate(diff).QuoTruncateMut(sqrtPriceB).QuoTruncateMut(sqrtPriceA)
p0mvn marked this conversation as resolved.
Show resolved Hide resolved
}

// CalcAmount1Delta takes the asset with the smaller liquidity in the pool as well as the sqrtpCur and the nextPrice and calculates the amount of asset 1
Expand Down