diff --git a/util/bpmath/bp.go b/util/bpmath/bp.go index fe88dd7d27..825c7829d6 100644 --- a/util/bpmath/bp.go +++ b/util/bpmath/bp.go @@ -4,12 +4,22 @@ import ( "math" cmath "cosmossdk.io/math" + sdk "github.com/cosmos/cosmos-sdk/types" ) // BP represents values in basis points. Maximum value is 2^32-1. // Note: BP operations should not be chained - this causes precision losses. type BP uint32 +func (bp BP) ToDec() sdk.Dec { + return sdk.NewDecWithPrec(int64(bp), 4) +} + +// Mul return a*bp rounding towards zero. +func (bp BP) Mul(a cmath.Int) cmath.Int { + return Mul(a, bp) +} + // FromQuo returns a/b in basis points. // Contract: a>=0 and b > 0. // Panics if a/b >= MaxUint32/10'000 or if b==0. @@ -32,7 +42,7 @@ func quo(a, b cmath.Int, rounding Rounding, max uint64) uint64 { return x } -// Mul returns a * b_basis_points +// Mul returns a * b_basis_points rounding towards zero. // Contract: b in [0, MaxUint32] func Mul[T BP | FixedBP](a cmath.Int, b T) cmath.Int { if b == 0 { @@ -43,7 +53,3 @@ func Mul[T BP | FixedBP](a cmath.Int, b T) cmath.Int { } return a.MulRaw(int64(b)).Quo(oneBigInt) } - -func (bp BP) ToDec() cmath.LegacyDec { - return cmath.LegacyNewDecWithPrec(int64(bp), 4) -} diff --git a/util/bpmath/bp_test.go b/util/bpmath/bp_test.go index 2397b31008..4faa1f6f99 100644 --- a/util/bpmath/bp_test.go +++ b/util/bpmath/bp_test.go @@ -45,4 +45,14 @@ func TestInt(t *testing.T) { require.Equal(sresult, sdk.NewInt(12)) mresult = Mul(mi, bp) require.Equal(mresult, math.NewInt(12)) + + // test rounding + si = sdk.NewInt(1299) + require.Equal(bp.Mul(si), sdk.NewInt(12)) + + si = sdk.NewInt(-1299) + require.Equal(bp.Mul(si), sdk.NewInt(-12)) + + si = sdk.NewInt(-1201) + require.Equal(bp.Mul(si), sdk.NewInt(-12)) } diff --git a/util/bpmath/doc.go b/util/bpmath/doc.go index 3695092f21..a35b593b36 100644 --- a/util/bpmath/doc.go +++ b/util/bpmath/doc.go @@ -1,4 +1,4 @@ -// Package bpmath provides types and functions for doing basis point operations. -// There is no precision lost for operations like `a * b` where `a` or `b` is basis points, -// and the other variable is `Int`. +// Package bpmath provides types and functions for doing basis point operations with math.Int. +// So, the result is always math.Int, and follows the Go rounding semantic for integer nubmer: +// rounds towards zero. package bpmath diff --git a/util/bpmath/fixed_bp.go b/util/bpmath/fixed_bp.go index 79f4cec550..d28e4a4e22 100644 --- a/util/bpmath/fixed_bp.go +++ b/util/bpmath/fixed_bp.go @@ -2,6 +2,7 @@ package bpmath import ( "cosmossdk.io/math" + sdk "github.com/cosmos/cosmos-sdk/types" ) // FixedBP assures that all operations are in 0-10'000 range @@ -15,6 +16,11 @@ func FixedFromQuo(dividend, divisor math.Int, rounding Rounding) FixedBP { return FixedBP(quo(dividend, divisor, rounding, One)) } -func (bp FixedBP) ToDec() math.LegacyDec { - return math.LegacyNewDecWithPrec(int64(bp), 4) +func (bp FixedBP) ToDec() sdk.Dec { + return sdk.NewDecWithPrec(int64(bp), 4) +} + +// Mul return a*bp rounding towards zero. +func (bp FixedBP) Mul(a math.Int) math.Int { + return Mul(a, bp) }