Skip to content

Commit

Permalink
merge main
Browse files Browse the repository at this point in the history
  • Loading branch information
pysel committed Sep 4, 2023
1 parent 9d4c77e commit 0b8dac1
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 5 deletions.
28 changes: 23 additions & 5 deletions osmomath/decimal.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ var (
oneInt = big.NewInt(1)
tenInt = big.NewInt(10)

// precisionFactorSDK is used to adjust the scale of BigDec values to match the precision expected by sdk.Dec
precisionFactorSDK *big.Int
// precisionDiffFromSDKDec is a difference in precision between BigDec and sdk.Dec
precisionDiffFromSDKDec int

// log_2(e)
// From: https://www.wolframalpha.com/input?i=log_2%28e%29+with+37+digits
logOfEbase2 = MustNewBigDecFromStr("1.442695040888963407359924681001892137")
Expand All @@ -69,6 +74,13 @@ func init() {
for i := 0; i <= PrecisionBigDec; i++ {
precisionMultipliers[i] = calcPrecisionMultiplier(int64(i))
}

precisionDiffFromSDKDec = PrecisionBigDec - sdk.Precision
if precisionDiffFromSDKDec < 0 {
panic("invalid decimal precision")
}

precisionFactorSDK = new(big.Int).Exp(big.NewInt(10), big.NewInt(int64(precisionDiffFromSDKDec)), nil)
}

func precisionInt() *big.Int {
Expand Down Expand Up @@ -552,19 +564,25 @@ func (d BigDec) MustFloat64() float64 {
// Dec returns the osmomath.Dec representation of a BigDec.
// Values in any additional decimal places are truncated.
func (d BigDec) Dec() Dec {
precisionDiff := PrecisionBigDec - PrecisionDec
precisionFactor := new(big.Int).Exp(big.NewInt(10), big.NewInt(int64(precisionDiff)), nil)
return d.DecWithPrecision(sdk.Precision)
}

if precisionDiff < 0 {
panic("invalid decimal precision")
func (d BigDec) DecWithPrecision(precision int64) Dec {
var precisionFactor *big.Int
if precision >= sdk.Precision {
precisionFactor = precisionFactorSDK
precision = sdk.Precision
} else {
precisionDiff := PrecisionBigDec - precision
precisionFactor = new(big.Int).Exp(big.NewInt(10), big.NewInt(precisionDiff), nil)
}

// Truncate any additional decimal values that exist due to BigDec's additional precision
// This relies on big.Int's Quo function doing floor division
intRepresentation := new(big.Int).Quo(d.BigInt(), precisionFactor)

// convert int representation back to SDK Dec precision
truncatedDec := NewDecFromBigIntWithPrec(intRepresentation, PrecisionDec)
truncatedDec := NewDecFromBigIntWithPrec(intRepresentation, precision)

return truncatedDec
}
Expand Down
40 changes: 40 additions & 0 deletions osmomath/decimal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"math/big"
"testing"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"
"gopkg.in/yaml.v2"
Expand Down Expand Up @@ -1480,3 +1481,42 @@ func (s *decimalTestSuite) TestPower() {
})
}
}

func (s *decimalTestSuite) TestDecWithPrecision() {
tests := []struct {
d osmomath.BigDec
want osmomath.Dec
precision int64
expPanic bool
}{
// test cases for basic SDKDec() conversion
{osmomath.NewBigDec(0), sdk.MustNewDecFromStr("0.000000000000000000"), sdk.Precision, false},
{osmomath.NewBigDec(1), sdk.MustNewDecFromStr("1.000000000000000000"), sdk.Precision, false},
{osmomath.NewBigDec(10), sdk.MustNewDecFromStr("10.000000000000000000"), sdk.Precision, false},
{osmomath.NewBigDec(12340), sdk.MustNewDecFromStr("12340.000000000000000000"), sdk.Precision, false},
{osmomath.NewBigDecWithPrec(12340, 4), sdk.MustNewDecFromStr("1.234000000000000000"), sdk.Precision, false},
{osmomath.NewBigDecWithPrec(12340, 5), sdk.MustNewDecFromStr("0.123400000000000000"), sdk.Precision, false},
{osmomath.NewBigDecWithPrec(12340, 8), sdk.MustNewDecFromStr("0.000123400000000000"), sdk.Precision, false},
{osmomath.NewBigDecWithPrec(1009009009009009009, 17), sdk.MustNewDecFromStr("10.090090090090090090"), sdk.Precision, false},
// test cases w/ custom precision:
{osmomath.NewBigDec(0), sdk.MustNewDecFromStr("0.000000000000"), 12, false},
{osmomath.NewBigDec(1), sdk.MustNewDecFromStr("1.000000000000"), 12, false},
// specified precision is the same as the initial precision: 12.3453123123 -> 12.3453123123
{osmomath.NewBigDecWithPrec(123453123123, 10), sdk.MustNewDecFromStr("12.3453123123"), 10, false},
// cut precision to 5 decimals: 3212.4623423462346 - 3212.46234
{osmomath.NewBigDecWithPrec(32124623423462346, 13), sdk.MustNewDecFromStr("3212.46234"), 5, false},
// no decimal point: 18012004 -> 18012004
{osmomath.NewBigDecWithPrec(18012004, 0), sdk.MustNewDecFromStr("18012004"), 13, false},
// if we try to convert to sdk.Dec while specifying bigger precision than sdk.Dec has, converts with maximum precision possible (sdk.Precision)
{osmomath.NewBigDecWithPrec(1009009009009009009, 17), sdk.MustNewDecFromStr("10.090090090090090090"), sdk.Precision + 2, false},
}

for tcIndex, tc := range tests {
if tc.expPanic {
s.Require().Panics(func() { tc.d.DecWithPrecision(tc.precision) })
} else {
value := tc.d.DecWithPrecision(tc.precision)
s.Require().Equal(tc.want, value, "bad SdkDec(), index: %v", tcIndex)
}
}
}
1 change: 1 addition & 0 deletions osmomath/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,7 @@ github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vv
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI=
github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M=
github.com/osmosis-labs/cosmos-sdk v0.45.0-rc1.0.20230829222007-529c69c19915 h1:1VDV+B0rHSrbHjZz7P1tEjZTb2nro/GAhbOT8RAoQcw=
github.com/osmosis-labs/cosmos-sdk v0.45.0-rc1.0.20230829222007-529c69c19915/go.mod h1:L6USUt+QX9lIqUVCRs8DFEVRZJbCYbemmtcXb7GfHYE=
github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=
Expand Down

0 comments on commit 0b8dac1

Please sign in to comment.