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: Mutative version for QuoRoundUp #6437

Merged
merged 9 commits into from
Sep 20, 2023
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
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
* [#6437](https://github.com/osmosis-labs/osmosis/pull/6437) mutative version for QuoRoundUp

### Misc Improvements

Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ require (
github.com/mattn/go-sqlite3 v1.14.17
github.com/ory/dockertest/v3 v3.10.0
github.com/osmosis-labs/go-mutesting v0.0.0-20221208041716-b43bcd97b3b3
github.com/osmosis-labs/osmosis/osmomath v0.0.7-0.20230919070012-03a878db9dad
github.com/osmosis-labs/osmosis/osmomath v0.0.7-0.20230920134650-28712c635b4f
github.com/osmosis-labs/osmosis/osmoutils v0.0.7-0.20230911120014-b14342e08daf
github.com/osmosis-labs/osmosis/x/epochs v0.0.3-0.20230911120014-b14342e08daf
github.com/osmosis-labs/osmosis/x/ibc-hooks v0.0.9-0.20230911120014-b14342e08daf
Expand Down
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -957,12 +957,12 @@ 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.20230911120014-b14342e08daf h1:sXSC/RG9sxQCB5QJ5JB+M9Bok7Xbpv2zx9ee6287glw=
github.com/osmosis-labs/osmosis/osmomath v0.0.7-0.20230911120014-b14342e08daf/go.mod h1:pIItelRYvonB+H8A6KqucOi7xFnJxzDHaWJqOdFNLI4=
github.com/osmosis-labs/osmosis/osmomath v0.0.7-0.20230918184012-da92c9cdf6bd h1:U7r0uBLTWeLrgGOu1re0aTl10yreX1j3dNDu12KqBpE=
github.com/osmosis-labs/osmosis/osmomath v0.0.7-0.20230918184012-da92c9cdf6bd/go.mod h1:pIItelRYvonB+H8A6KqucOi7xFnJxzDHaWJqOdFNLI4=
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=
github.com/osmosis-labs/osmosis/osmoutils v0.0.7-0.20230911120014-b14342e08daf/go.mod h1:7VoXHwrSSx8Sii0UFc9YIixF6C/9XfV1pdU2Dliu4WA=
github.com/osmosis-labs/osmosis/x/epochs v0.0.3-0.20230911120014-b14342e08daf h1:8lkIsAj3L7zxvOZbqVLNJRpSdDxaYhYfAIG7XjPaJiU=
Expand Down
59 changes: 44 additions & 15 deletions osmomath/decimal.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,14 @@ const (
)

var (
precisionReuse = new(big.Int).Exp(big.NewInt(10), big.NewInt(PrecisionBigDec), nil)
precisionReuseSDK = new(big.Int).Exp(big.NewInt(10), big.NewInt(PrecisionDec), nil)
fivePrecision = new(big.Int).Quo(precisionReuse, big.NewInt(2))
precisionMultipliers []*big.Int
zeroInt = big.NewInt(0)
oneInt = big.NewInt(1)
tenInt = big.NewInt(10)
precisionReuse = new(big.Int).Exp(big.NewInt(10), big.NewInt(PrecisionBigDec), nil)
squaredPrecisionReuse = new(big.Int).Mul(precisionReuse, precisionReuse)
precisionReuseSDK = new(big.Int).Exp(big.NewInt(10), big.NewInt(PrecisionDec), nil)
fivePrecision = new(big.Int).Quo(precisionReuse, big.NewInt(2))
precisionMultipliers []*big.Int
zeroInt = big.NewInt(0)
oneInt = big.NewInt(1)
tenInt = big.NewInt(10)

// log_2(e)
// From: https://www.wolframalpha.com/input?i=log_2%28e%29+with+37+digits
Expand Down Expand Up @@ -401,6 +402,20 @@ func (d BigDec) QuoRoundUp(d2 BigDec) BigDec {
return BigDec{chopped}
}

// quotient, round up (mutative)
func (d BigDec) QuoRoundUpMut(d2 BigDec) BigDec {
hieuvubk 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)

chopPrecisionAndRoundUpMut(d.i, precisionReuse)

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

// quotient
func (d BigDec) QuoInt(i BigInt) BigDec {
mul := new(big.Int).Quo(d.i, i.i)
Expand Down Expand Up @@ -654,36 +669,44 @@ func chopPrecisionAndRound(d *big.Int) *big.Int {
}

// chopPrecisionAndRoundUpBigDec removes a Precision amount of rightmost digits and rounds up.
// Non-mutative.
func chopPrecisionAndRoundUpBigDec(d *big.Int) *big.Int {
return chopPrecisionAndRoundUp(d, precisionReuse)
// make copy
copy := new(big.Int).Set(d)
return chopPrecisionAndRoundUpMut(copy, precisionReuse)
}

// chopPrecisionAndRoundUpDec removes sdk.Precision amount of rightmost digits and rounds up.
// Non-mutative.
func chopPrecisionAndRoundUpDec(d *big.Int) *big.Int {
return chopPrecisionAndRoundUp(d, precisionReuseSDK)
copy := new(big.Int).Set(d)
return chopPrecisionAndRoundUpMut(copy, precisionReuseSDK)
}

// chopPrecisionAndRoundUp removes a Precision amount of rightmost digits and rounds up.
func chopPrecisionAndRoundUp(d *big.Int, precisionReuse *big.Int) *big.Int {
// Mutates input d.
// Mutations occur:
// - By calling chopPrecisionAndTruncateMut.
// - Using input d directly in QuoRem.
func chopPrecisionAndRoundUpMut(d *big.Int, precisionReuse *big.Int) *big.Int {
// remove the negative and add it back when returning
if d.Sign() == -1 {
// make d positive, compute chopped value, and then un-mutate d
d = d.Neg(d)
// truncate since d is negative...
d = chopPrecisionAndTruncate(d)
d = chopPrecisionAndTruncateMut(d)
d = d.Neg(d)
return d
}

// get the truncated quotient and remainder
quo, rem := d, big.NewInt(0)
quo, rem = quo.QuoRem(d, precisionReuse, rem)
_, rem := d.QuoRem(d, precisionReuse, big.NewInt(0))

if rem.Sign() == 0 { // remainder is zero
return quo
return d
}

return quo.Add(quo, oneInt)
return d.Add(d, oneInt)
}

func chopPrecisionAndRoundNonMutative(d *big.Int) *big.Int {
Expand Down Expand Up @@ -711,6 +734,12 @@ func chopPrecisionAndTruncate(d *big.Int) *big.Int {
return new(big.Int).Quo(d, precisionReuse)
}

// chopPrecisionAndTruncate is similar to chopPrecisionAndRound,
// but always rounds down. It mutates the input.
func chopPrecisionAndTruncateMut(d *big.Int) *big.Int {
return d.Quo(d, precisionReuse)
}

// TruncateInt64 truncates the decimals from the number and returns an int64
func (d BigDec) TruncateInt64() int64 {
chopped := chopPrecisionAndTruncate(d.i)
Expand Down
58 changes: 58 additions & 0 deletions osmomath/decimal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1502,3 +1502,61 @@ func (s *decimalTestSuite) TestPower() {
})
}
}

func (s *decimalTestSuite) TestQuoRoundUp_MutativeAndNonMutative() {
tests := []struct {
d1, d2, expQuoRoundUpMut 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.428571428571428571428571428571428572"),
},
{
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.009009009009009009009009009009009010"),
},
}

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

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

copy := tc.d1.Clone()

nonMutResult := copy.QuoRoundUp(tc.d2)

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

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

// Receiver is mutated.
tc.d1.QuoRoundUpMut(tc.d2)

// Make sure d1 equals to expected
s.Require().True(tc.expQuoRoundUpMut.Equal(tc.d1), "exp %v, res %v, tc %d", tc.expQuoRoundUpMut.String(), tc.d1.String(), tcIndex)
}
}
}
2 changes: 1 addition & 1 deletion x/concentrated-liquidity/math/math.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ func CalcAmount0Delta(liq, sqrtPriceA, sqrtPriceB osmomath.BigDec, roundUp bool)
// 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. This only matters in cases where at least one of the sqrt prices is below 1.
// TODO (perf): QuoRoundUpMut with no reallocation.
return liq.MulRoundUp(diff).QuoRoundUp(sqrtPriceB).QuoRoundUp(sqrtPriceA).Ceil()
return liq.MulRoundUp(diff).QuoRoundUpMut(sqrtPriceB).QuoRoundUpMut(sqrtPriceA).Ceil()
}
// These are truncated at precision end to round in favor of the pool when:
// - calculating amount out during swap
Expand Down