Skip to content

Commit

Permalink
osmomath: Mutative version for QuoRoundUp (backport #6437) (#6458)
Browse files Browse the repository at this point in the history
* osmomath: Mutative version for QuoRoundUp (backport #6437)

* fix bug

* go mod

* go mod

---------

Co-authored-by: roman <[email protected]>
  • Loading branch information
mergify[bot] and p0mvn authored Sep 20, 2023
1 parent 896a4be commit 407276f
Show file tree
Hide file tree
Showing 7 changed files with 112 additions and 23 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ 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. Replace some non-mutative calls with mutative for better performance.

* [#6416](https://github.com/osmosis-labs/osmosis/pull/6416) feat[CL]: add num initialized ticks query

### Bug Fixes
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.20230920090526-bc02685001d4
github.com/osmosis-labs/osmosis/osmomath v0.0.7-0.20230920173345-6401a459cb14
github.com/osmosis-labs/osmosis/osmoutils v0.0.7-0.20230920012324-f1a1ca887bd2
github.com/osmosis-labs/osmosis/x/epochs v0.0.2
github.com/osmosis-labs/osmosis/x/ibc-hooks v0.0.8
Expand Down
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -653,8 +653,8 @@ github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE=
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.2 h1:cfejS+Tpcp13yd5nYHWDI6qVCny6wyX2Mt5SGur2IGE=
github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek=
Expand Down Expand Up @@ -930,8 +930,8 @@ github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.10.2/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA=
github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc=
github.com/onsi/ginkgo/v2 v2.9.4 h1:xR7vG4IXt5RWx6FfIjyAtsoMAtnc3C/rFXBBd2AjZwE=
github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
Expand Down Expand Up @@ -963,10 +963,10 @@ github.com/osmosis-labs/cosmos-sdk v0.45.0-rc1.0.20230913192254-a2075590d5a3 h1:
github.com/osmosis-labs/cosmos-sdk v0.45.0-rc1.0.20230913192254-a2075590d5a3/go.mod h1:mFGH2RJhuZa6vBuFMNe4JN85fGtIhROtdeQIyIw9isA=
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.20230920090526-bc02685001d4 h1:inSXiNHfKdWXrff3oU4FYFVmbK/9VYSIc73MtOpKApg=
github.com/osmosis-labs/osmosis/osmomath v0.0.7-0.20230920090526-bc02685001d4/go.mod h1:oBmsOov8oxuWoI/yMQwyKGA6QfP0cBxylLt75gFbT8s=
github.com/osmosis-labs/osmosis/osmomath v0.0.7-0.20230920173345-6401a459cb14 h1:SR8J54Bi55oHr1KN7E+8PS1IZDXJJDPuBG+hrn/JoQA=
github.com/osmosis-labs/osmosis/osmomath v0.0.7-0.20230920173345-6401a459cb14/go.mod h1:oBmsOov8oxuWoI/yMQwyKGA6QfP0cBxylLt75gFbT8s=
github.com/osmosis-labs/osmosis/osmoutils v0.0.7-0.20230920012324-f1a1ca887bd2 h1:A1Z6/SpM31atGBVyrgcgG0g50G9wHcfBxx8gIgQT9IQ=
github.com/osmosis-labs/osmosis/osmoutils v0.0.7-0.20230920012324-f1a1ca887bd2/go.mod h1:ukjFgxfR9obDrMd8ZsxKcp3HWL7+boYORVL7Bt7YOZM=
github.com/osmosis-labs/osmosis/x/epochs v0.0.2 h1:aEeXHGCSJMgMtAvCucsD2RSaWZ8lISFLD5u4MyF9KPc=
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 {
// 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 @@ -1501,3 +1501,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)
}
}
}
4 changes: 2 additions & 2 deletions x/concentrated-liquidity/math/math.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ func GetNextSqrtPriceFromAmount0InRoundingUp(sqrtPriceCurrent, liquidity, amount
// denominator = product + liquidity
denominator := product
denominator.AddMut(liquidity)
return liquidity.Mul(sqrtPriceCurrent).QuoRoundUp(denominator)
return liquidity.Mul(sqrtPriceCurrent).QuoRoundUpMut(denominator)
}

// GetNextSqrtPriceFromAmount0OutRoundingUp utilizes sqrtPriceCurrent, liquidity, and amount of denom0 that still needs
Expand All @@ -150,7 +150,7 @@ func GetNextSqrtPriceFromAmount0OutRoundingUp(sqrtPriceCurrent, liquidity, amoun
denominator := liquidity.Sub(product)
// mul round up numerator to make the final result larger
// quo round up to make the final result larger
return liquidity.MulRoundUp(sqrtPriceCurrent).QuoRoundUp(denominator)
return liquidity.MulRoundUp(sqrtPriceCurrent).QuoRoundUpMut(denominator)
}

// GetNextSqrtPriceFromAmount1InRoundingDown utilizes the current sqrtPriceCurrent, liquidity, and amount of denom1 that still needs
Expand Down
2 changes: 1 addition & 1 deletion x/gamm/pool-models/stableswap/amm.go
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ func (p *Pool) calcInAmtGivenOut(tokenOut sdk.Coin, tokenInDenom string, spreadF
// We invert that negative here.
cfmmIn = cfmmIn.Neg()
// divide by (1 - spread factor) to force a corresponding increase in input asset
inAmt := cfmmIn.QuoRoundUp(oneMinus(spreadFactor))
inAmt := cfmmIn.QuoRoundUpMut(oneMinus(spreadFactor))
inCoinAmt := p.getDescaledPoolAmt(tokenInDenom, inAmt)
return inCoinAmt, nil
}
Expand Down

0 comments on commit 407276f

Please sign in to comment.