Skip to content

Commit

Permalink
Speedup some of the swap logic by doing more pre-computation in tick …
Browse files Browse the repository at this point in the history
…math (#5171)
  • Loading branch information
ValarDragon authored and pysel committed Jun 6, 2023
1 parent 9a8cf1c commit 4ce0d7b
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 16 deletions.
44 changes: 44 additions & 0 deletions x/concentrated-liquidity/math/precompute.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package math

import (
sdk "github.com/cosmos/cosmos-sdk/types"

"github.com/osmosis-labs/osmosis/osmomath"
)

var (
sdkOneInt = sdk.OneInt()
sdkOneDec = sdk.NewDec(1)
sdkNineDec = sdk.NewDec(9)
sdkTenDec = sdk.NewDec(10)
powersOfTen []sdk.Dec
negPowersOfTen []sdk.Dec

osmomathBigOneDec = osmomath.NewBigDec(1)
osmomathBigTenDec = osmomath.NewBigDec(10)
bigPowersOfTen []osmomath.BigDec
bigNegPowersOfTen []osmomath.BigDec
)

// Set precision multipliers
func init() {
negPowersOfTen = make([]sdk.Dec, sdk.Precision+1)
for i := 0; i <= sdk.Precision; i++ {
negPowersOfTen[i] = sdkOneDec.Quo(sdkTenDec.Power(uint64(i)))
}
// 10^77 < sdk.MaxInt < 10^78
powersOfTen = make([]sdk.Dec, 78)
for i := 0; i <= 77; i++ {
powersOfTen[i] = sdkTenDec.Power(uint64(i))
}

bigNegPowersOfTen = make([]osmomath.BigDec, osmomath.Precision+1)
for i := 0; i <= osmomath.Precision; i++ {
bigNegPowersOfTen[i] = osmomathBigOneDec.Quo(osmomathBigTenDec.PowerInteger(uint64(i)))
}
// 10^308 < osmomath.MaxInt < 10^309
bigPowersOfTen = make([]osmomath.BigDec, 309)
for i := 0; i <= 308; i++ {
bigPowersOfTen[i] = osmomathBigTenDec.PowerInteger(uint64(i))
}
}
27 changes: 11 additions & 16 deletions x/concentrated-liquidity/math/tick.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,6 @@ import (
"github.com/osmosis-labs/osmosis/v15/x/concentrated-liquidity/types"
)

var (
sdkNineDec = sdk.NewDec(9)
sdkTenDec = sdk.NewDec(10)
)

// TicksToSqrtPrice returns the sqrtPrice for the lower and upper ticks by
// individually calling `TickToSqrtPrice` method.
// Returns error if fails to calculate price.
Expand Down Expand Up @@ -77,7 +72,7 @@ func TickToPrice(tickIndex sdk.Int) (price sdk.Dec, err error) {
if tickIndex.IsNegative() {
// We must decrement the exponentAtCurrentTick when entering the negative tick range in order to constantly step up in precision when going further down in ticks
// Otherwise, from tick 0 to tick -(geometricExponentIncrementDistanceInTicks), we would use the same exponent as the exponentAtPriceOne
exponentAtCurrentTick = exponentAtCurrentTick.Sub(sdk.OneInt())
exponentAtCurrentTick = exponentAtCurrentTick.Sub(sdkOneInt)
}

// Knowing what our exponentAtCurrentTick is, we can then figure out what power of 10 this exponent corresponds to
Expand Down Expand Up @@ -146,16 +141,16 @@ func PriceToTickRoundDown(price sdk.Dec, tickSpacing uint64) (sdk.Int, error) {
// This is because the sdk.Dec.Power function does not support negative exponents
func PowTenInternal(exponent sdk.Int) sdk.Dec {
if exponent.GTE(sdk.ZeroInt()) {
return sdkTenDec.Power(exponent.Uint64())
return powersOfTen[exponent.Int64()]
}
return sdk.OneDec().Quo(sdkTenDec.Power(exponent.Abs().Uint64()))
return negPowersOfTen[-exponent.Int64()]
}

func powTenBigDec(exponent sdk.Int) osmomath.BigDec {
if exponent.GTE(sdk.ZeroInt()) {
return osmomath.NewBigDec(10).PowerInteger(exponent.Uint64())
return bigPowersOfTen[exponent.Int64()]
}
return osmomath.OneDec().Quo(osmomath.NewBigDec(10).PowerInteger(exponent.Abs().Uint64()))
return bigNegPowersOfTen[-exponent.Int64()]
}

// CalculatePriceToTick takes in a price and returns the corresponding tick index.
Expand All @@ -180,23 +175,23 @@ func CalculatePriceToTick(price sdk.Dec) (tickIndex sdk.Int) {
// as well as how many ticks that corresponds to
// In the opposite direction (price < 1), we do the same thing (just decrement the geometric exponent instead of incrementing).
// The only difference is we must reduce the increment distance by a factor of 10.
if price.GT(sdk.OneDec()) {
if price.GT(sdkOneDec) {
for currentPrice.LT(price) {
currentAdditiveIncrementInTicks = powTenBigDec(exponentAtCurrentTick)
maxPriceForCurrentAdditiveIncrementInTicks := osmomath.BigDecFromSDKDec(geometricExponentIncrementDistanceInTicks).Mul(currentAdditiveIncrementInTicks)
currentPrice = currentPrice.Add(maxPriceForCurrentAdditiveIncrementInTicks.SDKDec())
exponentAtCurrentTick = exponentAtCurrentTick.Add(sdk.OneInt())
currentPrice.AddMut(maxPriceForCurrentAdditiveIncrementInTicks.SDKDec())
exponentAtCurrentTick = exponentAtCurrentTick.Add(sdkOneInt)
ticksPassed = ticksPassed.Add(geometricExponentIncrementDistanceInTicks.TruncateInt())
}
} else {
// We must decrement the exponentAtCurrentTick by one when traversing negative ticks in order to constantly step up in precision when going further down in ticks
// Otherwise, from tick 0 to tick -(geometricExponentIncrementDistanceInTicks), we would use the same exponent as the exponentAtPriceOne
exponentAtCurrentTick := exponentAtPriceOne.Sub(sdk.OneInt())
exponentAtCurrentTick := exponentAtPriceOne.Sub(sdkOneInt)
for currentPrice.GT(price) {
currentAdditiveIncrementInTicks = powTenBigDec(exponentAtCurrentTick)
maxPriceForCurrentAdditiveIncrementInTicks := osmomath.BigDecFromSDKDec(geometricExponentIncrementDistanceInTicks).Mul(currentAdditiveIncrementInTicks)
currentPrice = currentPrice.Sub(maxPriceForCurrentAdditiveIncrementInTicks.SDKDec())
exponentAtCurrentTick = exponentAtCurrentTick.Sub(sdk.OneInt())
currentPrice.SubMut(maxPriceForCurrentAdditiveIncrementInTicks.SDKDec())
exponentAtCurrentTick = exponentAtCurrentTick.Sub(sdkOneInt)
ticksPassed = ticksPassed.Sub(geometricExponentIncrementDistanceInTicks.TruncateInt())
}
}
Expand Down

0 comments on commit 4ce0d7b

Please sign in to comment.