-
Notifications
You must be signed in to change notification settings - Fork 3.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RRR4R: rational -> decimal #1819
Conversation
Codecov Report
@@ Coverage Diff @@
## develop #1819 +/- ##
========================================
Coverage 64.86% 64.86%
========================================
Files 115 115
Lines 6862 6862
========================================
Hits 4451 4451
Misses 2127 2127
Partials 284 284 |
types/decimal.go
Outdated
// nolint - go-cyclo | ||
// Remove a Precision amount of rightmost digits and perform bankers rounding | ||
// on the remainder (gaussian rounding) on the digits which have been removed. | ||
func ChopPrecisionAndRound(d *big.Int) (chopped *big.Int) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should make a mutative variant of this function to use internally. We can just write a TODO / make an issue for this. (The functions here don't need to allocate different memory for chopped after computing the result)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does it have to be publicly exposed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah it doesn't need to be exposed - updated this func to mutate d
now
types/decimal.go
Outdated
|
||
//zerosToAdd := int64(lenRem - 1 + leadingZeros) | ||
//multiplier := new(big.Int).Exp(big.NewInt(10), big.NewInt(zerosToAdd), nil) | ||
//fiveLine := new(big.Int).Mul(big.NewInt(5), multiplier) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you want to keep this code, or should we delete it? If we want it kept, lets leave a comment explaining what it is. I'm partial to not keeping commented out code, but thats nbd
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed, git has history, we don't need to keep comments
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah meant to delete - this should just be deleted never need it again
types/decimal.go
Outdated
chopped = quo | ||
return | ||
case 1: | ||
chopped = quo.Add(quo, big.NewInt(1)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should cache the one
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
++
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cached (and the one below)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, made a couple efficiency suggestions, but I think we can write them up into an issue and address later.
Also do we want to align / rename int /uint's |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor nits
types/decimal.go
Outdated
|
||
// first extract any negative symbol | ||
neg := false | ||
if string(str[0]) == "-" { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we just compare the character directly?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
addressed
types/decimal.go
Outdated
|
||
//zerosToAdd := int64(lenRem - 1 + leadingZeros) | ||
//multiplier := new(big.Int).Exp(big.NewInt(10), big.NewInt(zerosToAdd), nil) | ||
//fiveLine := new(big.Int).Mul(big.NewInt(5), multiplier) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed, git has history, we don't need to keep comments
types/decimal.go
Outdated
chopped = quo | ||
return | ||
case 1: | ||
chopped = quo.Add(quo, big.NewInt(1)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
++
types/decimal.go
Outdated
// wraps d.MarshalText() | ||
func (d Dec) MarshalAmino() (string, error) { | ||
if d.Int == nil { | ||
d.Int = new(big.Int) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we return a constant string here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
confused - expand?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As in use a constant string to represent the nil
case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and then manually load for this custom nil
case in UnmarshalAmino
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is what he was suggesting AFAICT.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
k - addressed - just define the zero values once now above
types/decimal.go
Outdated
// MarshalJSON defines custom encoding scheme | ||
func (d Dec) MarshalJSON() ([]byte, error) { | ||
if d.Int == nil { | ||
d.Int = new(big.Int) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we return a constant string here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
addressed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did a shallow review. LGTM. Would love to see this tested with something like https://github.com/dvyukov/go-fuzz. I can help with that.
types/decimal.go
Outdated
// | ||
// NOTE an error will return if more decimal places | ||
// are provided in the string than the constant Precision | ||
func NewDecFromStr(str string) (d Dec, err Error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add a note saying we're mutating the str
argument OR create a copy of str
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
addressed - this does not modify the string (or copy it even)
types/decimal.go
Outdated
|
||
combined, ok := new(big.Int).SetString(combinedStr, 10) | ||
if !ok { | ||
return d, ErrUnknownRequest("bad string to integer conversion") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be good to print combinedStr
here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
k done
types/decimal.go
Outdated
} | ||
|
||
if lenDecs > Precision { | ||
return d, ErrUnknownRequest("too much Precision in decimal") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be good to include Precision
(10) here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yup added that and the lenDec now
"testing" | ||
) | ||
|
||
// NOTE: never use new(Dec) or else we will panic unmarshalling into the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why not make the type private then?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Concrete structs get a bit better efficiency than interfaces. (Also follows the stdlib's standard)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
k just leaving for now
types/decimal.go
Outdated
// nolint - go-cyclo | ||
// Remove a Precision amount of rightmost digits and perform bankers rounding | ||
// on the remainder (gaussian rounding) on the digits which have been removed. | ||
func ChopPrecisionAndRound(d *big.Int) (chopped *big.Int) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does it have to be publicly exposed?
types/decimal.go
Outdated
mul.Mul(mul, precisionReuse) | ||
|
||
quo := new(big.Int).Quo(mul, d2.Int) | ||
chopped := ChopPrecisionAndRound(quo) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what about this check?
if chopped.BitLen() > 255+DecimalPrecisionBytes {
panic("Int overflow")
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks - added
} | ||
|
||
// intended to be used with require/assert: require.True(DecEq(...)) | ||
func DecEq(t *testing.T, exp, got Dec) (*testing.T, bool, string, Dec, Dec) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe move it to _test.go
file?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cannot, see: #1819 (comment)
@melekes @ValarDragon @cwgoes - all comments addressed |
|
||
// get the trucated quotient and remainder | ||
quo, rem := big.NewInt(0), big.NewInt(0) | ||
quo, rem = quo.QuoRem(d, precisionReuse, rem) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We actually don't need to use quo
here, it can just be d
, and then quo
never had to be allocated :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cool I'm going to make quo, rem := d, big.NewInt(0)
just to keep it explicit - makes the return statements more clear too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
okay - turns out this causes a few undesired side effects because often this function is expected to return a new decimal not modify the original - I'm going to leave as is for now, I feel like this is a pretty minor optimization - but feel free to make the modification and add the fixes (a bunch of lcd stuff fails)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure! I'll look into this more once we get get the main PR merged!
types/decimal.go
Outdated
|
||
// bytes required to represent the above precision | ||
// ceil(log2(9999999999)) | ||
DecimalPrecisionBytes = 34 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
DecimalPrecisionBits?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks, addressed
types/decimal.go
Outdated
return multiplier | ||
} | ||
|
||
// get the precision multiplier. Do not mutate result. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe a way to make Dec immutable so we can enforce it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These are only used within this file, so we don't need to add a separate method to enforce immutability.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
leaving for now
types/decimal.go
Outdated
//nolint | ||
func (d Dec) IsZero() bool { return (d.Int).Sign() == 0 } // Is equal to zero | ||
func (d Dec) Equal(d2 Dec) bool { return (d.Int).Cmp(d2.Int) == 0 } | ||
func (d Dec) GT(d2 Dec) bool { return (d.Int).Cmp(d2.Int) == 1 } // greater than |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I always use comparisons to zero, since the direction of comparison works on the values themselves.
(d.Int).Cmp(d2.Int) > 0 means d.Int > d2.Int, imo easier to grok visually.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yup I like it changed
// | | __ | ||
// | | | __|__|__ | ||
// |_____: / | $$$ | | ||
// |________| |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lul.
Merging - we can make further optimizations / adjustments in future PRs |
closes #1807
docs/
)PENDING.md
cmd/gaia
andexamples/
For Admin Use: