Skip to content

Commit

Permalink
Speedup quo round up, start CL speedup integration (#8014)
Browse files Browse the repository at this point in the history
* Speedup quo round up

* Code reuse

* Missed a code re-use point

* Add future notes

* Comment cleanup

* Auto: update go.mod after push to dev/speedup_quoroundup that modified dependencies locally

* Add new fn: NewBigDecFromDecMulDec

* Auto: update go.mod after push to dev/speedup_quoroundup that modified dependencies locally

* Remove some extra ops from CL

* Further perf notes

* Make faster QuoRoundUpNextIntMut

* Auto: update go.mod after push to dev/speedup_quoroundup that modified dependencies locally

* Remove another 2 BigDec ops

* Add another dec op

* Auto: update go.mod after push to dev/speedup_quoroundup that modified dependencies locally

* Start moving some liquidity calls to Dec not BigDec

* One more BigDec x Dec op

* Auto: update go.mod after push to dev/speedup_quoroundup that modified dependencies locally

* Another liq BigDec -> Dec

* Missed one step

* Move another Liquidity BigDec -> Dec

* Minor spread reward update

* Make CalcAmount1Dec use Dec for Liquidity

* Make one more op mutative

* One more speedup

* Fix test

* Speedup SpotPrice impl

---------

Co-authored-by: github-actions <[email protected]>
  • Loading branch information
2 people authored and p0mvn committed Apr 12, 2024
1 parent e77a4a4 commit 615994c
Show file tree
Hide file tree
Showing 14 changed files with 321 additions and 206 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### State Compatible

* [#8006](https://github.com/osmosis-labs/osmosis/pull/8006) Speedup many BigDec operations
* [#8006](https://github.com/osmosis-labs/osmosis/pull/8006), [#8014](https://github.com/osmosis-labs/osmosis/pull/8014) Speedup many BigDec operations

## v24.0.1

Expand Down
155 changes: 81 additions & 74 deletions osmomath/decimal.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,14 @@ var (
squaredPrecisionReuse = new(big.Int).Mul(defaultBigDecPrecisionReuse, defaultBigDecPrecisionReuse)
bigDecDecPrecisionFactorDiff = new(big.Int).Exp(big.NewInt(10), big.NewInt(BigDecPrecision-DecPrecision), nil)

tenTimesPrecision = new(big.Int).Exp(big.NewInt(10), big.NewInt(BigDecPrecision+1), nil)
fivePrecision = new(big.Int).Quo(defaultBigDecPrecisionReuse, big.NewInt(2))
fivePrecisionSDKDec = new(big.Int).Quo(precisionReuseSDKDec, big.NewInt(2))

precisionMultipliers []*big.Int
zeroInt = big.NewInt(0)
oneInt = big.NewInt(1)
fiveInt = big.NewInt(5)
tenInt = big.NewInt(10)

// log_2(e)
Expand Down Expand Up @@ -172,6 +174,11 @@ func NewBigDecFromIntWithPrec(i BigInt, prec int64) BigDec {
}
}

func NewBigDecFromDecMulDec(a, b Dec) BigDec {
newBi := new(big.Int).Mul(a.BigIntMut(), b.BigIntMut())
return BigDec{newBi}
}

// create a decimal from an input decimal string.
// valid must come in the form:
//
Expand Down Expand Up @@ -294,9 +301,7 @@ func (d BigDec) Add(d2 BigDec) BigDec {
func (d BigDec) AddMut(d2 BigDec) BigDec {
d.i.Add(d.i, d2.i)

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

return d
}
Expand All @@ -310,10 +315,7 @@ func (d BigDec) Sub(d2 BigDec) BigDec {

func (d BigDec) SubMut(d2 BigDec) BigDec {
res := d.i.Sub(d.i, d2.i)

if res.BitLen() > maxDecBitLen {
panic("Int overflow")
}
assertMaxBitLen(res)
return BigDec{res}
}

Expand Down Expand Up @@ -344,9 +346,7 @@ func (d BigDec) MulMut(d2 BigDec) BigDec {
d.i.Mul(d.i, d2.i)
d.i = chopPrecisionAndRound(d.i)

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

Expand All @@ -360,62 +360,53 @@ func (d BigDec) MulDecMut(d2 Dec) BigDec {
d.i.Mul(d.i, d2.BigIntMut())
d.i = chopPrecisionAndRoundSdkDec(d.i)

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

// multiplication truncate
func (d BigDec) MulTruncate(d2 BigDec) BigDec {
mul := new(big.Int).Mul(d.i, d2.i)
chopped := chopPrecisionAndTruncateMut(mul, defaultBigDecPrecisionReuse)

if chopped.BitLen() > maxDecBitLen {
panic("Int overflow")
}
assertMaxBitLen(chopped)
return BigDec{chopped}
}

func (d BigDec) MulTruncateDec(d2 Dec) BigDec {
mul := new(big.Int).Mul(d.i, d2.BigIntMut())
chopped := chopPrecisionAndTruncateMut(mul, precisionReuseSDKDec)

if chopped.BitLen() > maxDecBitLen {
panic("Int overflow")
}
assertMaxBitLen(chopped)
return BigDec{chopped}
}

// multiplication round up
func (d BigDec) MulRoundUp(d2 BigDec) BigDec {
mul := new(big.Int).Mul(d.i, d2.i)
chopped := chopPrecisionAndRoundUpMut(mul, defaultBigDecPrecisionReuse)
assertMaxBitLen(chopped)
return BigDec{chopped}
}

if chopped.BitLen() > maxDecBitLen {
panic("Int overflow")
}
// multiplication round up by Dec
func (d BigDec) MulRoundUpDec(d2 Dec) BigDec {
mul := new(big.Int).Mul(d.i, d2.BigIntMut())
chopped := chopPrecisionAndRoundUpMut(mul, precisionReuseSDKDec)
assertMaxBitLen(chopped)
return BigDec{chopped}
}

// multiplication
func (d BigDec) MulInt(i BigInt) BigDec {
mul := new(big.Int).Mul(d.i, i.i)

if mul.BitLen() > maxDecBitLen {
panic("Int overflow")
}
assertMaxBitLen(mul)
return BigDec{mul}
}

// MulInt64 - multiplication with int64
func (d BigDec) MulInt64(i int64) BigDec {
bi := big.NewInt(i)
mul := bi.Mul(d.i, bi)

if mul.BitLen() > maxDecBitLen {
panic("Int overflow")
}
assertMaxBitLen(mul)
return BigDec{mul}
}

Expand All @@ -429,38 +420,31 @@ func (d BigDec) Quo(d2 BigDec) BigDec {
// mutative quotient
func (d BigDec) QuoMut(d2 BigDec) BigDec {
// multiply precision twice
// TODO: Use lower overhead thing here
d.i.Mul(d.i, squaredPrecisionReuse)

d.i.Quo(d.i, d2.i)
chopPrecisionAndRound(d.i)

if d.i.BitLen() > maxDecBitLen {
panic("Int overflow")
}
assertMaxBitLen(d.i)
return d
}
func (d BigDec) QuoRaw(d2 int64) BigDec {
// multiply precision, so we can chop it later
// TODO: There is certainly more efficient ways to do this, come back later
mul := new(big.Int).Mul(d.i, defaultBigDecPrecisionReuse)

quo := mul.Quo(mul, big.NewInt(d2))
chopped := chopPrecisionAndRound(quo)

if chopped.BitLen() > maxDecBitLen {
panic("Int overflow")
}
assertMaxBitLen(chopped)
return BigDec{chopped}
}

// quotient truncate
func (d BigDec) QuoTruncate(d2 BigDec) BigDec {
// multiply precision twice
mul := new(big.Int).Mul(d.i, defaultBigDecPrecisionReuse)
quo := mul.Quo(mul, d2.i)

if quo.BitLen() > maxDecBitLen {
panic("Int overflow")
}
assertMaxBitLen(quo)
return BigDec{quo}
}

Expand All @@ -469,10 +453,7 @@ func (d BigDec) QuoTruncateMut(d2 BigDec) BigDec {
// multiply bigDec precision
d.i.Mul(d.i, defaultBigDecPrecisionReuse)
d.i.Quo(d.i, d2.i)

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

Expand All @@ -481,10 +462,7 @@ func (d BigDec) QuoTruncateDec(d2 Dec) BigDec {
// multiply Dec Precision
mul := new(big.Int).Mul(d.i, precisionReuseSDKDec)
quo := mul.Quo(mul, d2.BigIntMut())

if quo.BitLen() > maxDecBitLen {
panic("Int overflow")
}
assertMaxBitLen(quo)
return BigDec{quo}
}

Expand All @@ -494,37 +472,53 @@ func (d BigDec) QuoTruncateDecMut(d2 Dec) BigDec {
d.i.Mul(d.i, precisionReuseSDKDec)
d.i.Quo(d.i, d2.BigIntMut())

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

// quotient, round up
func (d BigDec) QuoRoundUp(d2 BigDec) BigDec {
// multiply precision twice
mul := new(big.Int).Mul(d.i, squaredPrecisionReuse)
mul := new(big.Int).Mul(d.i, defaultBigDecPrecisionReuse)

quo := mul.Quo(mul, d2.i)
chopped := chopPrecisionAndRoundUpMut(quo, defaultBigDecPrecisionReuse)
chopped, rem := mul.QuoRem(mul, d2.i, new(big.Int))
if rem.Sign() > 0 {
chopped.Add(chopped, oneInt)
}

if chopped.BitLen() > maxDecBitLen {
panic("Int overflow")
assertMaxBitLen(chopped)
return BigDec{chopped}
}

// quotient, round up
func (d BigDec) QuoByDecRoundUp(d2 Dec) BigDec {
mul := new(big.Int).Mul(d.i, precisionReuseSDKDec)

chopped, rem := mul.QuoRem(mul, d2.BigIntMut(), new(big.Int))
if rem.Sign() > 0 {
chopped.Add(chopped, oneInt)
}

assertMaxBitLen(chopped)
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)
d.i.Mul(d.i, defaultBigDecPrecisionReuse)
_, rem := d.i.QuoRem(d.i, d2.i, new(big.Int))

chopPrecisionAndRoundUpMut(d.i, defaultBigDecPrecisionReuse)
d.i = incBasedOnRem(rem, d.i)
assertMaxBitLen(d.i)
return BigDec{d.i}
}

if d.i.BitLen() > maxDecBitLen {
panic("Int overflow")
}
// quotient, round up to next integer (mutative)
func (d BigDec) QuoRoundUpNextIntMut(d2 BigDec) BigDec {
_, rem := d.i.QuoRem(d.i, d2.i, new(big.Int))

d.i = incBasedOnRem(rem, d.i)
d.i.Mul(d.i, defaultBigDecPrecisionReuse)
assertMaxBitLen(d.i)
return BigDec{d.i}
}

Expand Down Expand Up @@ -588,6 +582,12 @@ func (d BigDec) ApproxRoot(root uint64) (guess BigDec, err error) {
return guess, nil
}

func assertMaxBitLen(i *big.Int) {
if i.BitLen() > maxDecBitLen {
panic("Int overflow")
}
}

// ApproxSqrt is a wrapper around ApproxRoot for the common special case
// of finding the square root of a number. It returns -(sqrt(abs(d)) if input is negative.
// TODO: Optimize this to be faster just using native big int sqrt.
Expand Down Expand Up @@ -863,6 +863,13 @@ func chopPrecisionAndRoundUpDec(d *big.Int) *big.Int {
return chopPrecisionAndRoundUpMut(copy, precisionReuseSDKDec)
}

func incBasedOnRem(rem *big.Int, d *big.Int) *big.Int {
if rem.Sign() == 0 {
return d
}
return d.Add(d, oneInt)
}

// chopPrecisionAndRoundUp removes a Precision amount of rightmost digits and rounds up.
// Mutates input d.
// Mutations occur:
Expand All @@ -881,12 +888,7 @@ func chopPrecisionAndRoundUpMut(d *big.Int, precisionReuse *big.Int) *big.Int {

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

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

return d.Add(d, oneInt)
return incBasedOnRem(rem, d)
}

func chopPrecisionAndRoundNonMutative(d *big.Int) *big.Int {
Expand Down Expand Up @@ -1245,6 +1247,11 @@ func (d BigDec) PowerInteger(power uint64) BigDec {
func (d BigDec) PowerIntegerMut(power uint64) BigDec {
if power == 0 {
return OneBigDec()
} else if power == 1 {
return d
} else if power == 2 {
// save a oneBigDec allocation
return d.MulMut(d)
}
tmp := OneBigDec()

Expand Down
Loading

0 comments on commit 615994c

Please sign in to comment.