Merge PR #4058: Fix DecCoins Bugs

This commit is contained in:
Alexander Bezobchuk
2019-04-05 14:13:22 -04:00
committed by GitHub
parent 1a8ab1c321
commit 576eb51928
3 changed files with 107 additions and 16 deletions
+54 -16
View File
@@ -312,55 +312,93 @@ func (coins DecCoins) IsAnyNegative() bool {
return false
}
// multiply all the coins by a decimal
// MulDec multiplies all the coins by a decimal.
//
// CONTRACT: No zero coins will be returned.
func (coins DecCoins) MulDec(d Dec) DecCoins {
res := make([]DecCoin, len(coins))
for i, coin := range coins {
var res DecCoins
for _, coin := range coins {
product := DecCoin{
Denom: coin.Denom,
Amount: coin.Amount.Mul(d),
}
res[i] = product
if !product.IsZero() {
res = res.Add(DecCoins{product})
}
}
return res
}
// multiply all the coins by a decimal, truncating
// MulDecTruncate multiplies all the decimal coins by a decimal, truncating. It
// panics if d is zero.
//
// CONTRACT: No zero coins will be returned.
func (coins DecCoins) MulDecTruncate(d Dec) DecCoins {
res := make([]DecCoin, len(coins))
for i, coin := range coins {
if d.IsZero() {
panic("invalid zero decimal")
}
var res DecCoins
for _, coin := range coins {
product := DecCoin{
Denom: coin.Denom,
Amount: coin.Amount.MulTruncate(d),
}
res[i] = product
if !product.IsZero() {
res = res.Add(DecCoins{product})
}
}
return res
}
// divide all the coins by a decimal
// QuoDec divides all the decimal coins by a decimal. It panics if d is zero.
//
// CONTRACT: No zero coins will be returned.
func (coins DecCoins) QuoDec(d Dec) DecCoins {
res := make([]DecCoin, len(coins))
for i, coin := range coins {
if d.IsZero() {
panic("invalid zero decimal")
}
var res DecCoins
for _, coin := range coins {
quotient := DecCoin{
Denom: coin.Denom,
Amount: coin.Amount.Quo(d),
}
res[i] = quotient
if !quotient.IsZero() {
res = res.Add(DecCoins{quotient})
}
}
return res
}
// divide all the coins by a decimal, truncating
// QuoDecTruncate divides all the decimal coins by a decimal, truncating. It
// panics if d is zero.
//
// CONTRACT: No zero coins will be returned.
func (coins DecCoins) QuoDecTruncate(d Dec) DecCoins {
res := make([]DecCoin, len(coins))
for i, coin := range coins {
if d.IsZero() {
panic("invalid zero decimal")
}
var res DecCoins
for _, coin := range coins {
quotient := DecCoin{
Denom: coin.Denom,
Amount: coin.Amount.QuoTruncate(d),
}
res[i] = quotient
if !quotient.IsZero() {
res = res.Add(DecCoins{quotient})
}
}
return res
}
+25
View File
@@ -290,3 +290,28 @@ func TestDecCoinsTruncateDecimal(t *testing.T) {
)
}
}
func TestDecCoinsQuoDecTruncate(t *testing.T) {
x := MustNewDecFromStr("1.00")
y := MustNewDecFromStr("10000000000000000000.00")
testCases := []struct {
coins DecCoins
input Dec
result DecCoins
panics bool
}{
{DecCoins{}, ZeroDec(), DecCoins(nil), true},
{DecCoins{NewDecCoinFromDec("foo", x)}, y, DecCoins(nil), false},
{DecCoins{NewInt64DecCoin("foo", 5)}, NewDec(2), DecCoins{NewDecCoinFromDec("foo", MustNewDecFromStr("2.5"))}, false},
}
for i, tc := range testCases {
if tc.panics {
require.Panics(t, func() { tc.coins.QuoDecTruncate(tc.input) })
} else {
res := tc.coins.QuoDecTruncate(tc.input)
require.Equal(t, tc.result, res, "unexpected result; tc #%d, coins: %s, input: %s", i, tc.coins, tc.input)
}
}
}