Merge PR #1388: types/int: Switch Int, Uint to use pointers internally
* types/int: Switch Int, Uint to use pointers internally This reduces the amount of pointer refs & derefs. * Fix nil pointers on unmarshalling amino * Fix elusive bug in marshalling with unitialized big int * Remove debug code * Switch big.rat to use pointers internally
This commit is contained in:
parent
9ca3a16bb3
commit
d6df6b07d1
@ -26,6 +26,8 @@ FEATURES
|
||||
* [tools] Add checking for misspellings and for incorrectly formatted files in circle CI
|
||||
* [server] Default config now creates a profiler at port 6060, and increase p2p send/recv rates
|
||||
* [tests] Add WaitForNextNBlocksTM helper method
|
||||
* [types] Switches internal representation of Int/Uint/Rat to use pointers
|
||||
* [gaiad] unsafe_reset_all now resets addrbook.json
|
||||
|
||||
FIXES
|
||||
* \#1259 - fix bug where certain tests that could have a nil pointer in defer
|
||||
|
||||
102
types/int.go
102
types/int.go
@ -60,17 +60,17 @@ func unmarshalJSON(i *big.Int, bz []byte) error {
|
||||
// Checks overflow, underflow and division by zero
|
||||
// Exists in range from -(2^255-1) to 2^255-1
|
||||
type Int struct {
|
||||
i big.Int
|
||||
i *big.Int
|
||||
}
|
||||
|
||||
// BigInt converts Int to big.Int
|
||||
func (i Int) BigInt() *big.Int {
|
||||
return new(big.Int).Set(&(i.i))
|
||||
return new(big.Int).Set(i.i)
|
||||
}
|
||||
|
||||
// NewInt constructs Int from int64
|
||||
func NewInt(n int64) Int {
|
||||
return Int{*big.NewInt(n)}
|
||||
return Int{big.NewInt(n)}
|
||||
}
|
||||
|
||||
// NewIntFromBigInt constructs Int from big.Int
|
||||
@ -78,7 +78,7 @@ func NewIntFromBigInt(i *big.Int) Int {
|
||||
if i.BitLen() > 255 {
|
||||
panic("NewIntFromBigInt() out of bound")
|
||||
}
|
||||
return Int{*i}
|
||||
return Int{i}
|
||||
}
|
||||
|
||||
// NewIntFromString constructs Int from string
|
||||
@ -92,7 +92,7 @@ func NewIntFromString(s string) (res Int, ok bool) {
|
||||
ok = false
|
||||
return
|
||||
}
|
||||
return Int{*i}, true
|
||||
return Int{i}, true
|
||||
}
|
||||
|
||||
// NewIntWithDecimal constructs Int with decimal
|
||||
@ -103,14 +103,14 @@ func NewIntWithDecimal(n int64, dec int) Int {
|
||||
if i.BitLen() > 255 {
|
||||
panic("NewIntWithDecimal() out of bound")
|
||||
}
|
||||
return Int{*i}
|
||||
return Int{i}
|
||||
}
|
||||
|
||||
// ZeroInt returns Int value with zero
|
||||
func ZeroInt() Int { return Int{*big.NewInt(0)} }
|
||||
func ZeroInt() Int { return Int{big.NewInt(0)} }
|
||||
|
||||
// OneInt returns Int value with one
|
||||
func OneInt() Int { return Int{*big.NewInt(1)} }
|
||||
func OneInt() Int { return Int{big.NewInt(1)} }
|
||||
|
||||
// Int64 converts Int to int64
|
||||
// Panics if the value is out of range
|
||||
@ -133,22 +133,22 @@ func (i Int) Sign() int {
|
||||
|
||||
// Equal compares two Ints
|
||||
func (i Int) Equal(i2 Int) bool {
|
||||
return equal(&(i.i), &(i2.i))
|
||||
return equal(i.i, i2.i)
|
||||
}
|
||||
|
||||
// GT returns true if first Int is greater than second
|
||||
func (i Int) GT(i2 Int) bool {
|
||||
return gt((&i.i), &(i2.i))
|
||||
return gt(i.i, i2.i)
|
||||
}
|
||||
|
||||
// LT returns true if first Int is lesser than second
|
||||
func (i Int) LT(i2 Int) bool {
|
||||
return lt((&i.i), &(i2.i))
|
||||
return lt(i.i, i2.i)
|
||||
}
|
||||
|
||||
// Add adds Int from another
|
||||
func (i Int) Add(i2 Int) (res Int) {
|
||||
res = Int{*add(&(i.i), &(i2.i))}
|
||||
res = Int{add(i.i, i2.i)}
|
||||
// Check overflow
|
||||
if res.i.BitLen() > 255 {
|
||||
panic("Int overflow")
|
||||
@ -163,7 +163,7 @@ func (i Int) AddRaw(i2 int64) Int {
|
||||
|
||||
// Sub subtracts Int from another
|
||||
func (i Int) Sub(i2 Int) (res Int) {
|
||||
res = Int{*sub(&(i.i), &(i2.i))}
|
||||
res = Int{sub(i.i, i2.i)}
|
||||
// Check overflow
|
||||
if res.i.BitLen() > 255 {
|
||||
panic("Int overflow")
|
||||
@ -182,7 +182,7 @@ func (i Int) Mul(i2 Int) (res Int) {
|
||||
if i.i.BitLen()+i2.i.BitLen()-1 > 255 {
|
||||
panic("Int overflow")
|
||||
}
|
||||
res = Int{*mul(&(i.i), &(i2.i))}
|
||||
res = Int{mul(i.i, i2.i)}
|
||||
// Check overflow if sign of both are same
|
||||
if res.i.BitLen() > 255 {
|
||||
panic("Int overflow")
|
||||
@ -201,7 +201,7 @@ func (i Int) Div(i2 Int) (res Int) {
|
||||
if i2.i.Sign() == 0 {
|
||||
panic("Division by zero")
|
||||
}
|
||||
return Int{*div(&(i.i), &(i2.i))}
|
||||
return Int{div(i.i, i2.i)}
|
||||
}
|
||||
|
||||
// DivRaw divides Int with int64
|
||||
@ -211,46 +211,58 @@ func (i Int) DivRaw(i2 int64) Int {
|
||||
|
||||
// Neg negates Int
|
||||
func (i Int) Neg() (res Int) {
|
||||
return Int{*neg(&(i.i))}
|
||||
return Int{neg(i.i)}
|
||||
}
|
||||
|
||||
// MarshalAmino defines custom encoding scheme
|
||||
func (i Int) MarshalAmino() (string, error) {
|
||||
return marshalAmino(&(i.i))
|
||||
if i.i == nil { // Necessary since default Uint initialization has i.i as nil
|
||||
i.i = new(big.Int)
|
||||
}
|
||||
return marshalAmino(i.i)
|
||||
}
|
||||
|
||||
// UnmarshalAmino defines custom decoding scheme
|
||||
func (i *Int) UnmarshalAmino(text string) error {
|
||||
return unmarshalAmino(&(i.i), text)
|
||||
if i.i == nil { // Necessary since default Int initialization has i.i as nil
|
||||
i.i = new(big.Int)
|
||||
}
|
||||
return unmarshalAmino(i.i, text)
|
||||
}
|
||||
|
||||
// MarshalJSON defines custom encoding scheme
|
||||
func (i Int) MarshalJSON() ([]byte, error) {
|
||||
return marshalJSON(&(i.i))
|
||||
if i.i == nil { // Necessary since default Uint initialization has i.i as nil
|
||||
i.i = new(big.Int)
|
||||
}
|
||||
return marshalJSON(i.i)
|
||||
}
|
||||
|
||||
// UnmarshalJSON defines custom decoding scheme
|
||||
func (i *Int) UnmarshalJSON(bz []byte) error {
|
||||
return unmarshalJSON(&(i.i), bz)
|
||||
if i.i == nil { // Necessary since default Int initialization has i.i as nil
|
||||
i.i = new(big.Int)
|
||||
}
|
||||
return unmarshalJSON(i.i, bz)
|
||||
}
|
||||
|
||||
// Int wraps integer with 256 bit range bound
|
||||
// Checks overflow, underflow and division by zero
|
||||
// Exists in range from 0 to 2^256-1
|
||||
type Uint struct {
|
||||
i big.Int
|
||||
i *big.Int
|
||||
}
|
||||
|
||||
// BigInt converts Uint to big.Unt
|
||||
func (i Uint) BigInt() *big.Int {
|
||||
return new(big.Int).Set(&(i.i))
|
||||
return new(big.Int).Set(i.i)
|
||||
}
|
||||
|
||||
// NewUint constructs Uint from int64
|
||||
func NewUint(n uint64) Uint {
|
||||
i := new(big.Int)
|
||||
i.SetUint64(n)
|
||||
return Uint{*i}
|
||||
return Uint{i}
|
||||
}
|
||||
|
||||
// NewUintFromBigUint constructs Uint from big.Uint
|
||||
@ -259,7 +271,7 @@ func NewUintFromBigInt(i *big.Int) Uint {
|
||||
if i.Sign() == -1 || i.Sign() == 1 && i.BitLen() > 256 {
|
||||
panic("Uint overflow")
|
||||
}
|
||||
return Uint{*i}
|
||||
return Uint{i}
|
||||
}
|
||||
|
||||
// NewUintFromString constructs Uint from string
|
||||
@ -273,7 +285,7 @@ func NewUintFromString(s string) (res Uint, ok bool) {
|
||||
ok = false
|
||||
return
|
||||
}
|
||||
return Uint{*i}, true
|
||||
return Uint{i}, true
|
||||
}
|
||||
|
||||
// NewUintWithDecimal constructs Uint with decimal
|
||||
@ -284,14 +296,14 @@ func NewUintWithDecimal(n int64, dec int) Uint {
|
||||
if i.Sign() == -1 || i.Sign() == 1 && i.BitLen() > 256 {
|
||||
panic("NewUintWithDecimal() out of bound")
|
||||
}
|
||||
return Uint{*i}
|
||||
return Uint{i}
|
||||
}
|
||||
|
||||
// ZeroUint returns Uint value with zero
|
||||
func ZeroUint() Uint { return Uint{*big.NewInt(0)} }
|
||||
func ZeroUint() Uint { return Uint{big.NewInt(0)} }
|
||||
|
||||
// OneUint returns Uint value with one
|
||||
func OneUint() Uint { return Uint{*big.NewInt(1)} }
|
||||
func OneUint() Uint { return Uint{big.NewInt(1)} }
|
||||
|
||||
// Uint64 converts Uint to uint64
|
||||
// Panics if the value is out of range
|
||||
@ -314,22 +326,22 @@ func (i Uint) Sign() int {
|
||||
|
||||
// Equal compares two Uints
|
||||
func (i Uint) Equal(i2 Uint) bool {
|
||||
return equal(&(i.i), &(i2.i))
|
||||
return equal(i.i, i2.i)
|
||||
}
|
||||
|
||||
// GT returns true if first Uint is greater than second
|
||||
func (i Uint) GT(i2 Uint) bool {
|
||||
return gt(&(i.i), &(i2.i))
|
||||
return gt(i.i, i2.i)
|
||||
}
|
||||
|
||||
// LT returns true if first Uint is lesser than second
|
||||
func (i Uint) LT(i2 Uint) bool {
|
||||
return lt(&(i.i), &(i2.i))
|
||||
return lt(i.i, i2.i)
|
||||
}
|
||||
|
||||
// Add adds Uint from another
|
||||
func (i Uint) Add(i2 Uint) (res Uint) {
|
||||
res = Uint{*add(&(i.i), &(i2.i))}
|
||||
res = Uint{add(i.i, i2.i)}
|
||||
// Check overflow
|
||||
if res.Sign() == -1 || res.Sign() == 1 && res.i.BitLen() > 256 {
|
||||
panic("Uint overflow")
|
||||
@ -344,7 +356,7 @@ func (i Uint) AddRaw(i2 uint64) Uint {
|
||||
|
||||
// Sub subtracts Uint from another
|
||||
func (i Uint) Sub(i2 Uint) (res Uint) {
|
||||
res = Uint{*sub(&(i.i), &(i2.i))}
|
||||
res = Uint{sub(i.i, i2.i)}
|
||||
// Check overflow
|
||||
if res.Sign() == -1 || res.Sign() == 1 && res.i.BitLen() > 256 {
|
||||
panic("Uint overflow")
|
||||
@ -363,7 +375,7 @@ func (i Uint) Mul(i2 Uint) (res Uint) {
|
||||
if i.i.BitLen()+i2.i.BitLen()-1 > 256 {
|
||||
panic("Uint overflow")
|
||||
}
|
||||
res = Uint{*mul(&(i.i), &(i2.i))}
|
||||
res = Uint{mul(i.i, i2.i)}
|
||||
// Check overflow
|
||||
if res.Sign() == -1 || res.Sign() == 1 && res.i.BitLen() > 256 {
|
||||
panic("Uint overflow")
|
||||
@ -382,7 +394,7 @@ func (i Uint) Div(i2 Uint) (res Uint) {
|
||||
if i2.Sign() == 0 {
|
||||
panic("division-by-zero")
|
||||
}
|
||||
return Uint{*div(&(i.i), &(i2.i))}
|
||||
return Uint{div(i.i, i2.i)}
|
||||
}
|
||||
|
||||
// Div divides Uint with int64
|
||||
@ -392,20 +404,32 @@ func (i Uint) DivRaw(i2 uint64) Uint {
|
||||
|
||||
// MarshalAmino defines custom encoding scheme
|
||||
func (i Uint) MarshalAmino() (string, error) {
|
||||
return marshalAmino(&(i.i))
|
||||
if i.i == nil { // Necessary since default Uint initialization has i.i as nil
|
||||
i.i = new(big.Int)
|
||||
}
|
||||
return marshalAmino(i.i)
|
||||
}
|
||||
|
||||
// UnmarshalAmino defines custom decoding scheme
|
||||
func (i *Uint) UnmarshalAmino(text string) error {
|
||||
return unmarshalAmino(&(i.i), text)
|
||||
if i.i == nil { // Necessary since default Uint initialization has i.i as nil
|
||||
i.i = new(big.Int)
|
||||
}
|
||||
return unmarshalAmino(i.i, text)
|
||||
}
|
||||
|
||||
// MarshalJSON defines custom encoding scheme
|
||||
func (i Uint) MarshalJSON() ([]byte, error) {
|
||||
return marshalJSON(&(i.i))
|
||||
if i.i == nil { // Necessary since default Uint initialization has i.i as nil
|
||||
i.i = new(big.Int)
|
||||
}
|
||||
return marshalJSON(i.i)
|
||||
}
|
||||
|
||||
// UnmarshalJSON defines custom decoding scheme
|
||||
func (i *Uint) UnmarshalJSON(bz []byte) error {
|
||||
return unmarshalJSON(&(i.i), bz)
|
||||
if i.i == nil { // Necessary since default Uint initialization has i.i as nil
|
||||
i.i = new(big.Int)
|
||||
}
|
||||
return unmarshalJSON(i.i, bz)
|
||||
}
|
||||
|
||||
@ -18,20 +18,20 @@ import (
|
||||
// we will panic unmarshalling into the
|
||||
// nil embedded big.Rat
|
||||
type Rat struct {
|
||||
big.Rat `json:"rat"`
|
||||
*big.Rat `json:"rat"`
|
||||
}
|
||||
|
||||
// nolint - common values
|
||||
func ZeroRat() Rat { return Rat{*big.NewRat(0, 1)} }
|
||||
func OneRat() Rat { return Rat{*big.NewRat(1, 1)} }
|
||||
func ZeroRat() Rat { return Rat{big.NewRat(0, 1)} }
|
||||
func OneRat() Rat { return Rat{big.NewRat(1, 1)} }
|
||||
|
||||
// New - create a new Rat from integers
|
||||
func NewRat(Numerator int64, Denominator ...int64) Rat {
|
||||
switch len(Denominator) {
|
||||
case 0:
|
||||
return Rat{*big.NewRat(Numerator, 1)}
|
||||
return Rat{big.NewRat(Numerator, 1)}
|
||||
case 1:
|
||||
return Rat{*big.NewRat(Numerator, Denominator[0])}
|
||||
return Rat{big.NewRat(Numerator, Denominator[0])}
|
||||
default:
|
||||
panic("improper use of New, can only have one denominator")
|
||||
}
|
||||
@ -84,9 +84,9 @@ func NewRatFromDecimal(decimalStr string) (f Rat, err Error) {
|
||||
func NewRatFromBigInt(num *big.Int, denom ...*big.Int) Rat {
|
||||
switch len(denom) {
|
||||
case 0:
|
||||
return Rat{*new(big.Rat).SetInt(num)}
|
||||
return Rat{new(big.Rat).SetInt(num)}
|
||||
case 1:
|
||||
return Rat{*new(big.Rat).SetFrac(num, denom[0])}
|
||||
return Rat{new(big.Rat).SetFrac(num, denom[0])}
|
||||
default:
|
||||
panic("improper use of NewRatFromBigInt, can only have one denominator")
|
||||
}
|
||||
@ -96,26 +96,26 @@ func NewRatFromBigInt(num *big.Int, denom ...*big.Int) Rat {
|
||||
func NewRatFromInt(num Int, denom ...Int) Rat {
|
||||
switch len(denom) {
|
||||
case 0:
|
||||
return Rat{*new(big.Rat).SetInt(num.BigInt())}
|
||||
return Rat{new(big.Rat).SetInt(num.BigInt())}
|
||||
case 1:
|
||||
return Rat{*new(big.Rat).SetFrac(num.BigInt(), denom[0].BigInt())}
|
||||
return Rat{new(big.Rat).SetFrac(num.BigInt(), denom[0].BigInt())}
|
||||
default:
|
||||
panic("improper use of NewRatFromBigInt, can only have one denominator")
|
||||
}
|
||||
}
|
||||
|
||||
//nolint
|
||||
func (r Rat) Num() int64 { return r.Rat.Num().Int64() } // Num - return the numerator
|
||||
func (r Rat) Denom() int64 { return r.Rat.Denom().Int64() } // Denom - return the denominator
|
||||
func (r Rat) IsZero() bool { return r.Num() == 0 } // IsZero - Is the Rat equal to zero
|
||||
func (r Rat) Equal(r2 Rat) bool { return (&(r.Rat)).Cmp(&(r2.Rat)) == 0 }
|
||||
func (r Rat) GT(r2 Rat) bool { return (&(r.Rat)).Cmp(&(r2.Rat)) == 1 } // greater than
|
||||
func (r Rat) LT(r2 Rat) bool { return (&(r.Rat)).Cmp(&(r2.Rat)) == -1 } // less than
|
||||
func (r Rat) Mul(r2 Rat) Rat { return Rat{*new(big.Rat).Mul(&(r.Rat), &(r2.Rat))} } // Mul - multiplication
|
||||
func (r Rat) Quo(r2 Rat) Rat { return Rat{*new(big.Rat).Quo(&(r.Rat), &(r2.Rat))} } // Quo - quotient
|
||||
func (r Rat) Add(r2 Rat) Rat { return Rat{*new(big.Rat).Add(&(r.Rat), &(r2.Rat))} } // Add - addition
|
||||
func (r Rat) Sub(r2 Rat) Rat { return Rat{*new(big.Rat).Sub(&(r.Rat), &(r2.Rat))} } // Sub - subtraction
|
||||
func (r Rat) String() string { return r.Rat.String() }
|
||||
func (r Rat) Num() int64 { return r.Rat.Num().Int64() } // Num - return the numerator
|
||||
func (r Rat) Denom() int64 { return r.Rat.Denom().Int64() } // Denom - return the denominator
|
||||
func (r Rat) IsZero() bool { return r.Num() == 0 } // IsZero - Is the Rat equal to zero
|
||||
func (r Rat) Equal(r2 Rat) bool { return (r.Rat).Cmp(r2.Rat) == 0 }
|
||||
func (r Rat) GT(r2 Rat) bool { return (r.Rat).Cmp(r2.Rat) == 1 } // greater than
|
||||
func (r Rat) LT(r2 Rat) bool { return (r.Rat).Cmp(r2.Rat) == -1 } // less than
|
||||
func (r Rat) Mul(r2 Rat) Rat { return Rat{new(big.Rat).Mul(r.Rat, r2.Rat)} } // Mul - multiplication
|
||||
func (r Rat) Quo(r2 Rat) Rat { return Rat{new(big.Rat).Quo(r.Rat, r2.Rat)} } // Quo - quotient
|
||||
func (r Rat) Add(r2 Rat) Rat { return Rat{new(big.Rat).Add(r.Rat, r2.Rat)} } // Add - addition
|
||||
func (r Rat) Sub(r2 Rat) Rat { return Rat{new(big.Rat).Sub(r.Rat, r2.Rat)} } // Sub - subtraction
|
||||
func (r Rat) String() string { return r.Rat.String() }
|
||||
func (r Rat) FloatString() string { return r.Rat.FloatString(10) } // a human-friendly string format. The last digit is rounded to nearest, with halves rounded away from zero.
|
||||
|
||||
var (
|
||||
@ -169,8 +169,8 @@ func (r Rat) EvaluateInt() Int {
|
||||
|
||||
// round Rat with the provided precisionFactor
|
||||
func (r Rat) Round(precisionFactor int64) Rat {
|
||||
rTen := Rat{*new(big.Rat).Mul(&(r.Rat), big.NewRat(precisionFactor, 1))}
|
||||
return Rat{*big.NewRat(rTen.Evaluate(), precisionFactor)}
|
||||
rTen := Rat{new(big.Rat).Mul(r.Rat, big.NewRat(precisionFactor, 1))}
|
||||
return Rat{big.NewRat(rTen.Evaluate(), precisionFactor)}
|
||||
}
|
||||
|
||||
// TODO panic if negative or if totalDigits < len(initStr)???
|
||||
@ -185,7 +185,10 @@ func (r Rat) ToLeftPadded(totalDigits int8) string {
|
||||
|
||||
//Wraps r.MarshalText().
|
||||
func (r Rat) MarshalAmino() (string, error) {
|
||||
bz, err := (&(r.Rat)).MarshalText()
|
||||
if r.Rat == nil {
|
||||
r.Rat = new(big.Rat)
|
||||
}
|
||||
bz, err := r.Rat.MarshalText()
|
||||
return string(bz), err
|
||||
}
|
||||
|
||||
@ -196,7 +199,7 @@ func (r *Rat) UnmarshalAmino(text string) (err error) {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
r.Rat = *tempRat
|
||||
r.Rat = tempRat
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@ -180,8 +180,8 @@ func TestRound(t *testing.T) {
|
||||
precFactor int64
|
||||
}{
|
||||
{NewRat(333, 777), NewRat(429, 1000), 1000},
|
||||
{Rat{*new(big.Rat).SetFrac(big3, big7)}, NewRat(429, 1000), 1000},
|
||||
{Rat{*new(big.Rat).SetFrac(big3, big7)}, Rat{*big.NewRat(4285714286, 10000000000)}, 10000000000},
|
||||
{Rat{new(big.Rat).SetFrac(big3, big7)}, NewRat(429, 1000), 1000},
|
||||
{Rat{new(big.Rat).SetFrac(big3, big7)}, Rat{big.NewRat(4285714286, 10000000000)}, 10000000000},
|
||||
{NewRat(1, 2), NewRat(1, 2), 1000},
|
||||
}
|
||||
|
||||
@ -229,7 +229,7 @@ func TestSerializationText(t *testing.T) {
|
||||
bz, err := r.MarshalText()
|
||||
require.NoError(t, err)
|
||||
|
||||
var r2 Rat
|
||||
var r2 Rat = Rat{new(big.Rat)}
|
||||
err = r2.UnmarshalText(bz)
|
||||
require.NoError(t, err)
|
||||
assert.True(t, r.Equal(r2), "original: %v, unmarshalled: %v", r, r2)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user