fix(math): revert to correct version of ApproxRoot from a former state breaking change (#17725)

This commit is contained in:
Roman 2023-09-18 09:55:51 -04:00 committed by GitHub
parent 6615ff4f76
commit 267cd15b07
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 11 additions and 15 deletions

View File

@ -34,6 +34,12 @@ Ref: https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.j
# Changelog
## [Unreleased]
### Bug Fixes
* [#17725](https://github.com/cosmos/cosmos-sdk/pull/17725) Fix state break in ApproxRoot. This has been present since math/v1.0.1. It changed the rounding behavior at precision end in an intermediary division from banker's to truncation. The truncation occurs from binary right shift in the case of square roots. The change is now reverted back to banker's rounding universally for any root.
## [math/v1.1.2](https://github.com/cosmos/cosmos-sdk/releases/tag/math/v1.1.2) - 2023-08-21
### Bug Fixes

View File

@ -42,6 +42,7 @@ var (
zeroInt = big.NewInt(0)
oneInt = big.NewInt(1)
tenInt = big.NewInt(10)
smallestDec = LegacySmallestDec()
)
// Decimal errors
@ -470,27 +471,15 @@ func (d LegacyDec) ApproxRoot(root uint64) (guess LegacyDec, err error) {
}
guess, delta := scratchOneDec, LegacyOneDec()
smallestDec := LegacySmallestDec()
for iter := 0; delta.AbsMut().GT(smallestDec) && iter < maxApproxRootIterations; iter++ {
// Set prev = guess^{root - 1}, with an optimization for sqrt
// where root=2 => prev = guess. (And thus no extra heap allocations)
prev := guess
if root != 2 {
prev = guess.Power(root - 1)
}
for iter := 0; iter < maxApproxRootIterations && delta.Abs().GT(smallestDec); iter++ {
prev := guess.Power(root - 1)
if prev.IsZero() {
prev = smallestDec
}
delta.Set(d).QuoMut(prev)
delta.SubMut(guess)
// delta = delta / root.
// We optimize for sqrt, where root=2 => delta = delta >> 1
if root == 2 {
delta.i.Rsh(delta.i, 1)
} else {
delta.QuoInt64Mut(int64(root))
}
delta.QuoInt64Mut(int64(root))
guess.AddMut(delta)
}

View File

@ -480,6 +480,7 @@ func (s *decimalTestSuite) TestApproxSqrt() {
math.LegacyNewDec(2).Power(127).Sub(math.LegacyOneDec()),
math.LegacyMustNewDecFromStr("13043817825332782212.349571806252508369"),
},
{math.LegacyMustNewDecFromStr("1.000000011823380862"), math.LegacyMustNewDecFromStr("1.000000005911690414")},
}
for i, tc := range testCases {