perf: add inplace decimal operations (#11004)
closes #9046 * add mutable decimal methods * fix root * gofmt * add Clone(), rm assignment quo * add SetInt64 * fix SetInt64 * More mut speedups Co-authored-by: mconcat <monoidconcat@gmail.com> Co-authored-by: ValarDragon <dojha12@gmail.com> --- ### Author Checklist *All items are required. Please add a note to the item if the item is not applicable and please add links to any relevant follow up issues.* I have... - [ ] included the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title - [ ] added `!` to the type prefix if API or client breaking change - [ ] targeted the correct branch (see [PR Targeting](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#pr-targeting)) - [ ] provided a link to the relevant issue or specification - [ ] followed the guidelines for [building modules](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules) - [ ] included the necessary unit and integration [tests](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#testing) - [ ] added a changelog entry to `CHANGELOG.md` - [ ] included comments for [documenting Go code](https://blog.golang.org/godoc) - [ ] updated the relevant documentation or specification - [ ] reviewed "Files changed" and left comments if necessary - [ ] confirmed all CI checks have passed ### Reviewers Checklist *All items are required. Please add a note if the item is not applicable and please add your handle next to the items reviewed if you only reviewed selected items.* I have... - [ ] confirmed the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title - [ ] confirmed `!` in the type prefix if API or client breaking change - [ ] confirmed all author checklist items have been addressed - [ ] reviewed state machine logic - [ ] reviewed API design and naming - [ ] reviewed documentation is accurate - [ ] reviewed tests and test coverage - [ ] manually tested (if applicable)
This commit is contained in:
parent
2c184d2056
commit
2e1c32834e
|
@ -160,6 +160,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
|
||||||
* (deps) [\#10706](https://github.com/cosmos/cosmos-sdk/issues/10706) Bump rosetta-sdk-go to v0.7.2 and rosetta-cli to v0.7.3
|
* (deps) [\#10706](https://github.com/cosmos/cosmos-sdk/issues/10706) Bump rosetta-sdk-go to v0.7.2 and rosetta-cli to v0.7.3
|
||||||
* (types/errors) [\#10779](https://github.com/cosmos/cosmos-sdk/pull/10779) Move most functionality in `types/errors` to a standalone `errors` go module, except the `RootCodespace` errors and ABCI response helpers. All functions and types that used to live in `types/errors` are now aliased so this is not a breaking change.
|
* (types/errors) [\#10779](https://github.com/cosmos/cosmos-sdk/pull/10779) Move most functionality in `types/errors` to a standalone `errors` go module, except the `RootCodespace` errors and ABCI response helpers. All functions and types that used to live in `types/errors` are now aliased so this is not a breaking change.
|
||||||
* (gov) [\#10854](https://github.com/cosmos/cosmos-sdk/pull/10854) v1beta2's vote doesn't include the deprecate `option VoteOption` anymore. Instead, it only uses `WeightedVoteOption`.
|
* (gov) [\#10854](https://github.com/cosmos/cosmos-sdk/pull/10854) v1beta2's vote doesn't include the deprecate `option VoteOption` anymore. Instead, it only uses `WeightedVoteOption`.
|
||||||
|
* (types) [\#11004](https://github.com/cosmos/cosmos-sdk/pull/11004) Added mutable versions of many of the sdk.Dec types operations. This improves performance when used by avoiding reallocating a new bigint for each operation.
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
|
|
211
types/decimal.go
211
types/decimal.go
|
@ -208,7 +208,10 @@ func (d Dec) GTE(d2 Dec) bool { return (d.i).Cmp(d2.i) >= 0 } // greater
|
||||||
func (d Dec) LT(d2 Dec) bool { return (d.i).Cmp(d2.i) < 0 } // less than
|
func (d Dec) LT(d2 Dec) bool { return (d.i).Cmp(d2.i) < 0 } // less than
|
||||||
func (d Dec) LTE(d2 Dec) bool { return (d.i).Cmp(d2.i) <= 0 } // less than or equal
|
func (d Dec) LTE(d2 Dec) bool { return (d.i).Cmp(d2.i) <= 0 } // less than or equal
|
||||||
func (d Dec) Neg() Dec { return Dec{new(big.Int).Neg(d.i)} } // reverse the decimal sign
|
func (d Dec) Neg() Dec { return Dec{new(big.Int).Neg(d.i)} } // reverse the decimal sign
|
||||||
|
func (d Dec) NegMut() Dec { d.i.Neg(d.i); return d } // reverse the decimal sign, mutable
|
||||||
func (d Dec) Abs() Dec { return Dec{new(big.Int).Abs(d.i)} } // absolute value
|
func (d Dec) Abs() Dec { return Dec{new(big.Int).Abs(d.i)} } // absolute value
|
||||||
|
func (d Dec) Set(d2 Dec) Dec { d.i.Set(d2.i); return d } // set to existing dec value
|
||||||
|
func (d Dec) Clone() Dec { return Dec{new(big.Int).Set(d.i)} } // clone new dec
|
||||||
|
|
||||||
// BigInt returns a copy of the underlying big.Int.
|
// BigInt returns a copy of the underlying big.Int.
|
||||||
func (d Dec) BigInt() *big.Int {
|
func (d Dec) BigInt() *big.Int {
|
||||||
|
@ -220,123 +223,192 @@ func (d Dec) BigInt() *big.Int {
|
||||||
return cp.Set(d.i)
|
return cp.Set(d.i)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d Dec) ImmutOp(op func(Dec, Dec) Dec, d2 Dec) Dec {
|
||||||
|
return op(d.Clone(), d2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d Dec) ImmutOpInt(op func(Dec, Int) Dec, d2 Int) Dec {
|
||||||
|
return op(d.Clone(), d2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d Dec) ImmutOpInt64(op func(Dec, int64) Dec, d2 int64) Dec {
|
||||||
|
// TODO: use already allocated operand bigint to avoid
|
||||||
|
// newint each time, add mutex for race condition
|
||||||
|
// Issue: https://github.com/cosmos/cosmos-sdk/issues/11166
|
||||||
|
return op(d.Clone(), d2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d Dec) SetInt64(i int64) Dec {
|
||||||
|
d.i.SetInt64(i)
|
||||||
|
d.i.Mul(d.i, precisionReuse)
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
|
||||||
// addition
|
// addition
|
||||||
func (d Dec) Add(d2 Dec) Dec {
|
func (d Dec) Add(d2 Dec) Dec {
|
||||||
res := new(big.Int).Add(d.i, d2.i)
|
return d.ImmutOp(Dec.AddMut, d2)
|
||||||
|
}
|
||||||
|
|
||||||
if res.BitLen() > maxDecBitLen {
|
// mutable addition
|
||||||
|
func (d Dec) AddMut(d2 Dec) Dec {
|
||||||
|
d.i.Add(d.i, d2.i)
|
||||||
|
|
||||||
|
if d.i.BitLen() > maxDecBitLen {
|
||||||
panic("Int overflow")
|
panic("Int overflow")
|
||||||
}
|
}
|
||||||
return Dec{res}
|
return d
|
||||||
}
|
}
|
||||||
|
|
||||||
// subtraction
|
// subtraction
|
||||||
func (d Dec) Sub(d2 Dec) Dec {
|
func (d Dec) Sub(d2 Dec) Dec {
|
||||||
res := new(big.Int).Sub(d.i, d2.i)
|
return d.ImmutOp(Dec.SubMut, d2)
|
||||||
|
}
|
||||||
|
|
||||||
if res.BitLen() > maxDecBitLen {
|
// mutable subtraction
|
||||||
|
func (d Dec) SubMut(d2 Dec) Dec {
|
||||||
|
d.i.Sub(d.i, d2.i)
|
||||||
|
|
||||||
|
if d.i.BitLen() > maxDecBitLen {
|
||||||
panic("Int overflow")
|
panic("Int overflow")
|
||||||
}
|
}
|
||||||
return Dec{res}
|
return d
|
||||||
}
|
}
|
||||||
|
|
||||||
// multiplication
|
// multiplication
|
||||||
func (d Dec) Mul(d2 Dec) Dec {
|
func (d Dec) Mul(d2 Dec) Dec {
|
||||||
mul := new(big.Int).Mul(d.i, d2.i)
|
return d.ImmutOp(Dec.MulMut, d2)
|
||||||
chopped := chopPrecisionAndRound(mul)
|
}
|
||||||
|
|
||||||
|
// mutable multiplication
|
||||||
|
func (d Dec) MulMut(d2 Dec) Dec {
|
||||||
|
d.i.Mul(d.i, d2.i)
|
||||||
|
chopped := chopPrecisionAndRound(d.i)
|
||||||
|
|
||||||
if chopped.BitLen() > maxDecBitLen {
|
if chopped.BitLen() > maxDecBitLen {
|
||||||
panic("Int overflow")
|
panic("Int overflow")
|
||||||
}
|
}
|
||||||
return Dec{chopped}
|
*d.i = *chopped
|
||||||
|
return d
|
||||||
}
|
}
|
||||||
|
|
||||||
// multiplication truncate
|
// multiplication truncate
|
||||||
func (d Dec) MulTruncate(d2 Dec) Dec {
|
func (d Dec) MulTruncate(d2 Dec) Dec {
|
||||||
mul := new(big.Int).Mul(d.i, d2.i)
|
return d.ImmutOp(Dec.MulTruncateMut, d2)
|
||||||
chopped := chopPrecisionAndTruncate(mul)
|
}
|
||||||
|
|
||||||
if chopped.BitLen() > maxDecBitLen {
|
// mutable multiplication truncage
|
||||||
|
func (d Dec) MulTruncateMut(d2 Dec) Dec {
|
||||||
|
d.i.Mul(d.i, d2.i)
|
||||||
|
chopPrecisionAndTruncate(d.i)
|
||||||
|
|
||||||
|
if d.i.BitLen() > maxDecBitLen {
|
||||||
panic("Int overflow")
|
panic("Int overflow")
|
||||||
}
|
}
|
||||||
return Dec{chopped}
|
return d
|
||||||
}
|
}
|
||||||
|
|
||||||
// multiplication
|
// multiplication
|
||||||
func (d Dec) MulInt(i Int) Dec {
|
func (d Dec) MulInt(i Int) Dec {
|
||||||
mul := new(big.Int).Mul(d.i, i.i)
|
return d.ImmutOpInt(Dec.MulIntMut, i)
|
||||||
|
}
|
||||||
|
|
||||||
if mul.BitLen() > maxDecBitLen {
|
func (d Dec) MulIntMut(i Int) Dec {
|
||||||
|
d.i.Mul(d.i, i.i)
|
||||||
|
if d.i.BitLen() > maxDecBitLen {
|
||||||
panic("Int overflow")
|
panic("Int overflow")
|
||||||
}
|
}
|
||||||
return Dec{mul}
|
return d
|
||||||
}
|
}
|
||||||
|
|
||||||
// MulInt64 - multiplication with int64
|
// MulInt64 - multiplication with int64
|
||||||
func (d Dec) MulInt64(i int64) Dec {
|
func (d Dec) MulInt64(i int64) Dec {
|
||||||
mul := new(big.Int).Mul(d.i, big.NewInt(i))
|
return d.ImmutOpInt64(Dec.MulInt64Mut, i)
|
||||||
|
}
|
||||||
|
|
||||||
if mul.BitLen() > maxDecBitLen {
|
func (d Dec) MulInt64Mut(i int64) Dec {
|
||||||
|
d.i.Mul(d.i, big.NewInt(i))
|
||||||
|
|
||||||
|
if d.i.BitLen() > maxDecBitLen {
|
||||||
panic("Int overflow")
|
panic("Int overflow")
|
||||||
}
|
}
|
||||||
return Dec{mul}
|
return d
|
||||||
}
|
}
|
||||||
|
|
||||||
// quotient
|
// quotient
|
||||||
func (d Dec) Quo(d2 Dec) Dec {
|
func (d Dec) Quo(d2 Dec) Dec {
|
||||||
|
return d.ImmutOp(Dec.QuoMut, d2)
|
||||||
|
}
|
||||||
|
|
||||||
|
// mutable quotient
|
||||||
|
func (d Dec) QuoMut(d2 Dec) Dec {
|
||||||
// multiply precision twice
|
// multiply precision twice
|
||||||
mul := new(big.Int).Mul(d.i, precisionReuse)
|
d.i.Mul(d.i, precisionReuse)
|
||||||
mul.Mul(mul, precisionReuse)
|
d.i.Mul(d.i, precisionReuse)
|
||||||
|
d.i.Quo(d.i, d2.i)
|
||||||
|
|
||||||
quo := new(big.Int).Quo(mul, d2.i)
|
chopPrecisionAndRound(d.i)
|
||||||
chopped := chopPrecisionAndRound(quo)
|
if d.i.BitLen() > maxDecBitLen {
|
||||||
|
|
||||||
if chopped.BitLen() > maxDecBitLen {
|
|
||||||
panic("Int overflow")
|
panic("Int overflow")
|
||||||
}
|
}
|
||||||
return Dec{chopped}
|
return d
|
||||||
}
|
}
|
||||||
|
|
||||||
// quotient truncate
|
// quotient truncate
|
||||||
func (d Dec) QuoTruncate(d2 Dec) Dec {
|
func (d Dec) QuoTruncate(d2 Dec) Dec {
|
||||||
|
return d.ImmutOp(Dec.QuoTruncateMut, d2)
|
||||||
|
}
|
||||||
|
|
||||||
|
// mutable quotient truncate
|
||||||
|
func (d Dec) QuoTruncateMut(d2 Dec) Dec {
|
||||||
// multiply precision twice
|
// multiply precision twice
|
||||||
mul := new(big.Int).Mul(d.i, precisionReuse)
|
d.i.Mul(d.i, precisionReuse)
|
||||||
mul.Mul(mul, precisionReuse)
|
d.i.Mul(d.i, precisionReuse)
|
||||||
|
d.i.Quo(d.i, d2.i)
|
||||||
|
|
||||||
quo := mul.Quo(mul, d2.i)
|
chopPrecisionAndTruncate(d.i)
|
||||||
chopped := chopPrecisionAndTruncate(quo)
|
if d.i.BitLen() > maxDecBitLen {
|
||||||
|
|
||||||
if chopped.BitLen() > maxDecBitLen {
|
|
||||||
panic("Int overflow")
|
panic("Int overflow")
|
||||||
}
|
}
|
||||||
return Dec{chopped}
|
return d
|
||||||
}
|
}
|
||||||
|
|
||||||
// quotient, round up
|
// quotient, round up
|
||||||
func (d Dec) QuoRoundUp(d2 Dec) Dec {
|
func (d Dec) QuoRoundUp(d2 Dec) Dec {
|
||||||
|
return d.ImmutOp(Dec.QuoRoundupMut, d2)
|
||||||
|
}
|
||||||
|
|
||||||
|
// mutable quotient, round up
|
||||||
|
func (d Dec) QuoRoundupMut(d2 Dec) Dec {
|
||||||
// multiply precision twice
|
// multiply precision twice
|
||||||
mul := new(big.Int).Mul(d.i, precisionReuse)
|
d.i.Mul(d.i, precisionReuse)
|
||||||
mul.Mul(mul, precisionReuse)
|
d.i.Mul(d.i, precisionReuse)
|
||||||
|
d.i.Quo(d.i, d2.i)
|
||||||
|
|
||||||
quo := new(big.Int).Quo(mul, d2.i)
|
chopPrecisionAndRoundUp(d.i)
|
||||||
chopped := chopPrecisionAndRoundUp(quo)
|
if d.i.BitLen() > maxDecBitLen {
|
||||||
|
|
||||||
if chopped.BitLen() > maxDecBitLen {
|
|
||||||
panic("Int overflow")
|
panic("Int overflow")
|
||||||
}
|
}
|
||||||
return Dec{chopped}
|
return d
|
||||||
}
|
}
|
||||||
|
|
||||||
// quotient
|
// quotient
|
||||||
func (d Dec) QuoInt(i Int) Dec {
|
func (d Dec) QuoInt(i Int) Dec {
|
||||||
mul := new(big.Int).Quo(d.i, i.i)
|
return d.ImmutOpInt(Dec.QuoIntMut, i)
|
||||||
return Dec{mul}
|
}
|
||||||
|
|
||||||
|
func (d Dec) QuoIntMut(i Int) Dec {
|
||||||
|
d.i.Quo(d.i, i.i)
|
||||||
|
return d
|
||||||
}
|
}
|
||||||
|
|
||||||
// QuoInt64 - quotient with int64
|
// QuoInt64 - quotient with int64
|
||||||
func (d Dec) QuoInt64(i int64) Dec {
|
func (d Dec) QuoInt64(i int64) Dec {
|
||||||
mul := new(big.Int).Quo(d.i, big.NewInt(i))
|
return d.ImmutOpInt64(Dec.QuoInt64Mut, i)
|
||||||
return Dec{mul}
|
}
|
||||||
|
|
||||||
|
func (d Dec) QuoInt64Mut(i int64) Dec {
|
||||||
|
d.i.Quo(d.i, big.NewInt(i))
|
||||||
|
return d
|
||||||
}
|
}
|
||||||
|
|
||||||
// ApproxRoot returns an approximate estimation of a Dec's positive real nth root
|
// ApproxRoot returns an approximate estimation of a Dec's positive real nth root
|
||||||
|
@ -357,8 +429,8 @@ func (d Dec) ApproxRoot(root uint64) (guess Dec, err error) {
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if d.IsNegative() {
|
if d.IsNegative() {
|
||||||
absRoot, err := d.MulInt64(-1).ApproxRoot(root)
|
absRoot, err := d.Neg().ApproxRoot(root)
|
||||||
return absRoot.MulInt64(-1), err
|
return absRoot.NegMut(), err
|
||||||
}
|
}
|
||||||
|
|
||||||
if root == 1 || d.IsZero() || d.Equal(OneDec()) {
|
if root == 1 || d.IsZero() || d.Equal(OneDec()) {
|
||||||
|
@ -369,7 +441,6 @@ func (d Dec) ApproxRoot(root uint64) (guess Dec, err error) {
|
||||||
return OneDec(), nil
|
return OneDec(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
rootInt := NewIntFromUint64(root)
|
|
||||||
guess, delta := OneDec(), OneDec()
|
guess, delta := OneDec(), OneDec()
|
||||||
|
|
||||||
for iter := 0; delta.Abs().GT(SmallestDec()) && iter < maxApproxRootIterations; iter++ {
|
for iter := 0; delta.Abs().GT(SmallestDec()) && iter < maxApproxRootIterations; iter++ {
|
||||||
|
@ -377,11 +448,11 @@ func (d Dec) ApproxRoot(root uint64) (guess Dec, err error) {
|
||||||
if prev.IsZero() {
|
if prev.IsZero() {
|
||||||
prev = SmallestDec()
|
prev = SmallestDec()
|
||||||
}
|
}
|
||||||
delta = d.Quo(prev)
|
delta.Set(d).QuoMut(prev)
|
||||||
delta = delta.Sub(guess)
|
delta.SubMut(guess)
|
||||||
delta = delta.QuoInt(rootInt)
|
delta.QuoInt64Mut(int64(root))
|
||||||
|
|
||||||
guess = guess.Add(delta)
|
guess.AddMut(delta)
|
||||||
}
|
}
|
||||||
|
|
||||||
return guess, nil
|
return guess, nil
|
||||||
|
@ -389,20 +460,26 @@ func (d Dec) ApproxRoot(root uint64) (guess Dec, err error) {
|
||||||
|
|
||||||
// Power returns a the result of raising to a positive integer power
|
// Power returns a the result of raising to a positive integer power
|
||||||
func (d Dec) Power(power uint64) Dec {
|
func (d Dec) Power(power uint64) Dec {
|
||||||
|
res := Dec{new(big.Int).Set(d.i)}
|
||||||
|
return res.PowerMut(power)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d Dec) PowerMut(power uint64) Dec {
|
||||||
if power == 0 {
|
if power == 0 {
|
||||||
return OneDec()
|
d.SetInt64(1)
|
||||||
|
return d
|
||||||
}
|
}
|
||||||
tmp := OneDec()
|
tmp := OneDec()
|
||||||
|
|
||||||
for i := power; i > 1; {
|
for i := power; i > 1; {
|
||||||
if i%2 != 0 {
|
if i%2 != 0 {
|
||||||
tmp = tmp.Mul(d)
|
tmp.MulMut(d)
|
||||||
}
|
}
|
||||||
i /= 2
|
i /= 2
|
||||||
d = d.Mul(d)
|
d.MulMut(d)
|
||||||
}
|
}
|
||||||
|
|
||||||
return d.Mul(tmp)
|
return d.MulMut(tmp)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ApproxSqrt is a wrapper around ApproxRoot for the common special case
|
// ApproxSqrt is a wrapper around ApproxRoot for the common special case
|
||||||
|
@ -543,7 +620,7 @@ func chopPrecisionAndRoundUp(d *big.Int) *big.Int {
|
||||||
// make d positive, compute chopped value, and then un-mutate d
|
// make d positive, compute chopped value, and then un-mutate d
|
||||||
d = d.Neg(d)
|
d = d.Neg(d)
|
||||||
// truncate since d is negative...
|
// truncate since d is negative...
|
||||||
d = chopPrecisionAndTruncate(d)
|
chopPrecisionAndTruncate(d)
|
||||||
d = d.Neg(d)
|
d = d.Neg(d)
|
||||||
return d
|
return d
|
||||||
}
|
}
|
||||||
|
@ -580,13 +657,19 @@ func (d Dec) RoundInt() Int {
|
||||||
|
|
||||||
// chopPrecisionAndTruncate is similar to chopPrecisionAndRound,
|
// chopPrecisionAndTruncate is similar to chopPrecisionAndRound,
|
||||||
// but always rounds down. It does not mutate the input.
|
// but always rounds down. It does not mutate the input.
|
||||||
func chopPrecisionAndTruncate(d *big.Int) *big.Int {
|
func chopPrecisionAndTruncate(d *big.Int) {
|
||||||
return new(big.Int).Quo(d, precisionReuse)
|
d.Quo(d, precisionReuse)
|
||||||
|
}
|
||||||
|
|
||||||
|
func chopPrecisionAndTruncateNonMutative(d *big.Int) *big.Int {
|
||||||
|
tmp := new(big.Int).Set(d)
|
||||||
|
chopPrecisionAndTruncate(tmp)
|
||||||
|
return tmp
|
||||||
}
|
}
|
||||||
|
|
||||||
// TruncateInt64 truncates the decimals from the number and returns an int64
|
// TruncateInt64 truncates the decimals from the number and returns an int64
|
||||||
func (d Dec) TruncateInt64() int64 {
|
func (d Dec) TruncateInt64() int64 {
|
||||||
chopped := chopPrecisionAndTruncate(d.i)
|
chopped := chopPrecisionAndTruncateNonMutative(d.i)
|
||||||
if !chopped.IsInt64() {
|
if !chopped.IsInt64() {
|
||||||
panic("Int64() out of bound")
|
panic("Int64() out of bound")
|
||||||
}
|
}
|
||||||
|
@ -595,12 +678,12 @@ func (d Dec) TruncateInt64() int64 {
|
||||||
|
|
||||||
// TruncateInt truncates the decimals from the number and returns an Int
|
// TruncateInt truncates the decimals from the number and returns an Int
|
||||||
func (d Dec) TruncateInt() Int {
|
func (d Dec) TruncateInt() Int {
|
||||||
return NewIntFromBigInt(chopPrecisionAndTruncate(d.i))
|
return NewIntFromBigInt(chopPrecisionAndTruncateNonMutative(d.i))
|
||||||
}
|
}
|
||||||
|
|
||||||
// TruncateDec truncates the decimals from the number and returns a Dec
|
// TruncateDec truncates the decimals from the number and returns a Dec
|
||||||
func (d Dec) TruncateDec() Dec {
|
func (d Dec) TruncateDec() Dec {
|
||||||
return NewDecFromBigInt(chopPrecisionAndTruncate(d.i))
|
return NewDecFromBigInt(chopPrecisionAndTruncateNonMutative(d.i))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ceil returns the smallest interger value (as a decimal) that is greater than
|
// Ceil returns the smallest interger value (as a decimal) that is greater than
|
||||||
|
@ -625,7 +708,11 @@ func (d Dec) Ceil() Dec {
|
||||||
|
|
||||||
// MaxSortableDec is the largest Dec that can be passed into SortableDecBytes()
|
// MaxSortableDec is the largest Dec that can be passed into SortableDecBytes()
|
||||||
// Its negative form is the least Dec that can be passed in.
|
// Its negative form is the least Dec that can be passed in.
|
||||||
var MaxSortableDec = OneDec().Quo(SmallestDec())
|
var MaxSortableDec Dec
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
MaxSortableDec = OneDec().Quo(SmallestDec())
|
||||||
|
}
|
||||||
|
|
||||||
// ValidSortableDec ensures that a Dec is within the sortable bounds,
|
// ValidSortableDec ensures that a Dec is within the sortable bounds,
|
||||||
// a Dec can't have a precision of less than 10^-18.
|
// a Dec can't have a precision of less than 10^-18.
|
||||||
|
|
|
@ -376,6 +376,7 @@ func (s *decimalTestSuite) TestPower() {
|
||||||
power uint64
|
power uint64
|
||||||
expected sdk.Dec
|
expected sdk.Dec
|
||||||
}{
|
}{
|
||||||
|
{sdk.NewDec(100), 0, sdk.OneDec()}, // 10 ^ (0) => 1.0
|
||||||
{sdk.OneDec(), 10, sdk.OneDec()}, // 1.0 ^ (10) => 1.0
|
{sdk.OneDec(), 10, sdk.OneDec()}, // 1.0 ^ (10) => 1.0
|
||||||
{sdk.NewDecWithPrec(5, 1), 2, sdk.NewDecWithPrec(25, 2)}, // 0.5 ^ 2 => 0.25
|
{sdk.NewDecWithPrec(5, 1), 2, sdk.NewDecWithPrec(25, 2)}, // 0.5 ^ 2 => 0.25
|
||||||
{sdk.NewDecWithPrec(2, 1), 2, sdk.NewDecWithPrec(4, 2)}, // 0.2 ^ 2 => 0.04
|
{sdk.NewDecWithPrec(2, 1), 2, sdk.NewDecWithPrec(4, 2)}, // 0.2 ^ 2 => 0.04
|
||||||
|
@ -386,7 +387,13 @@ func (s *decimalTestSuite) TestPower() {
|
||||||
|
|
||||||
for i, tc := range testCases {
|
for i, tc := range testCases {
|
||||||
res := tc.input.Power(tc.power)
|
res := tc.input.Power(tc.power)
|
||||||
s.Require().True(tc.expected.Sub(res).Abs().LTE(sdk.SmallestDec()), "unexpected result for test case %d, input: %v", i, tc.input)
|
s.Require().True(tc.expected.Sub(res).Abs().LTE(sdk.SmallestDec()), "unexpected result for test case %d, normal power, input: %v", i, tc.input)
|
||||||
|
|
||||||
|
mutableInput := tc.input
|
||||||
|
mutableInput.PowerMut(tc.power)
|
||||||
|
s.Require().True(tc.expected.Sub(mutableInput).Abs().LTE(sdk.SmallestDec()),
|
||||||
|
"unexpected result for test case %d, input %v", i, tc.input)
|
||||||
|
s.Require().True(res.Equal(tc.input), "unexpected result for test case %d, mutable power, input: %v", i, tc.input)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue