2018-06-15 14:16:45 -07:00
|
|
|
package types
|
|
|
|
|
|
|
|
import (
|
2020-01-24 07:32:00 -08:00
|
|
|
"encoding"
|
2018-06-28 17:54:47 -07:00
|
|
|
"encoding/json"
|
2019-02-08 14:33:29 -08:00
|
|
|
"fmt"
|
2018-10-12 01:11:09 -07:00
|
|
|
"testing"
|
2018-06-28 17:54:47 -07:00
|
|
|
|
2018-06-15 14:16:45 -07:00
|
|
|
"math/big"
|
|
|
|
)
|
|
|
|
|
2021-06-16 07:18:02 -07:00
|
|
|
const maxBitLen = 256
|
2019-02-08 14:33:29 -08:00
|
|
|
|
2018-06-15 14:16:45 -07:00
|
|
|
func newIntegerFromString(s string) (*big.Int, bool) {
|
|
|
|
return new(big.Int).SetString(s, 0)
|
|
|
|
}
|
|
|
|
|
|
|
|
func equal(i *big.Int, i2 *big.Int) bool { return i.Cmp(i2) == 0 }
|
|
|
|
|
|
|
|
func gt(i *big.Int, i2 *big.Int) bool { return i.Cmp(i2) == 1 }
|
|
|
|
|
2019-02-07 18:14:54 -08:00
|
|
|
func gte(i *big.Int, i2 *big.Int) bool { return i.Cmp(i2) >= 0 }
|
|
|
|
|
2018-06-15 14:16:45 -07:00
|
|
|
func lt(i *big.Int, i2 *big.Int) bool { return i.Cmp(i2) == -1 }
|
|
|
|
|
2019-02-07 17:41:23 -08:00
|
|
|
func lte(i *big.Int, i2 *big.Int) bool { return i.Cmp(i2) <= 0 }
|
|
|
|
|
2018-06-15 14:16:45 -07:00
|
|
|
func add(i *big.Int, i2 *big.Int) *big.Int { return new(big.Int).Add(i, i2) }
|
|
|
|
|
|
|
|
func sub(i *big.Int, i2 *big.Int) *big.Int { return new(big.Int).Sub(i, i2) }
|
|
|
|
|
|
|
|
func mul(i *big.Int, i2 *big.Int) *big.Int { return new(big.Int).Mul(i, i2) }
|
|
|
|
|
2019-02-21 09:35:55 -08:00
|
|
|
func div(i *big.Int, i2 *big.Int) *big.Int { return new(big.Int).Quo(i, i2) }
|
2018-06-15 14:16:45 -07:00
|
|
|
|
|
|
|
func mod(i *big.Int, i2 *big.Int) *big.Int { return new(big.Int).Mod(i, i2) }
|
|
|
|
|
|
|
|
func neg(i *big.Int) *big.Int { return new(big.Int).Neg(i) }
|
|
|
|
|
2021-03-24 09:33:55 -07:00
|
|
|
func abs(i *big.Int) *big.Int { return new(big.Int).Abs(i) }
|
|
|
|
|
2018-07-09 13:54:28 -07:00
|
|
|
func min(i *big.Int, i2 *big.Int) *big.Int {
|
|
|
|
if i.Cmp(i2) == 1 {
|
|
|
|
return new(big.Int).Set(i2)
|
|
|
|
}
|
2019-01-14 08:11:24 -08:00
|
|
|
|
2018-07-09 13:54:28 -07:00
|
|
|
return new(big.Int).Set(i)
|
|
|
|
}
|
|
|
|
|
2019-01-02 12:29:47 -08:00
|
|
|
func max(i *big.Int, i2 *big.Int) *big.Int {
|
2019-01-14 08:11:24 -08:00
|
|
|
if i.Cmp(i2) == -1 {
|
|
|
|
return new(big.Int).Set(i2)
|
2019-01-02 12:29:47 -08:00
|
|
|
}
|
2019-01-14 08:11:24 -08:00
|
|
|
|
|
|
|
return new(big.Int).Set(i)
|
2019-01-02 12:29:47 -08:00
|
|
|
}
|
|
|
|
|
2019-02-08 14:33:29 -08:00
|
|
|
func unmarshalText(i *big.Int, text string) error {
|
|
|
|
if err := i.UnmarshalText([]byte(text)); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if i.BitLen() > maxBitLen {
|
|
|
|
return fmt.Errorf("integer out of range: %s", text)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2020-01-24 07:32:00 -08:00
|
|
|
var _ CustomProtobufType = (*Int)(nil)
|
2018-06-15 14:16:45 -07:00
|
|
|
|
2021-06-16 07:18:02 -07:00
|
|
|
// Int wraps big.Int with a 257 bit range bound
|
2018-06-15 14:16:45 -07:00
|
|
|
// Checks overflow, underflow and division by zero
|
2021-06-16 07:18:02 -07:00
|
|
|
// Exists in range from -(2^256 - 1) to 2^256 - 1
|
2018-06-15 14:16:45 -07:00
|
|
|
type Int struct {
|
2018-06-26 18:10:34 -07:00
|
|
|
i *big.Int
|
2018-06-15 14:16:45 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// BigInt converts Int to big.Int
|
|
|
|
func (i Int) BigInt() *big.Int {
|
2020-08-18 06:16:23 -07:00
|
|
|
if i.IsNil() {
|
|
|
|
return nil
|
|
|
|
}
|
2018-06-26 18:10:34 -07:00
|
|
|
return new(big.Int).Set(i.i)
|
2018-06-15 14:16:45 -07:00
|
|
|
}
|
|
|
|
|
2020-08-18 06:16:23 -07:00
|
|
|
// IsNil returns true if Int is uninitialized
|
|
|
|
func (i Int) IsNil() bool {
|
|
|
|
return i.i == nil
|
|
|
|
}
|
|
|
|
|
2018-06-15 14:16:45 -07:00
|
|
|
// NewInt constructs Int from int64
|
|
|
|
func NewInt(n int64) Int {
|
2018-06-26 18:10:34 -07:00
|
|
|
return Int{big.NewInt(n)}
|
2018-06-15 14:16:45 -07:00
|
|
|
}
|
|
|
|
|
2020-01-04 12:16:12 -08:00
|
|
|
// NewIntFromUint64 constructs an Int from a uint64.
|
|
|
|
func NewIntFromUint64(n uint64) Int {
|
|
|
|
b := big.NewInt(0)
|
|
|
|
b.SetUint64(n)
|
|
|
|
return Int{b}
|
|
|
|
}
|
|
|
|
|
2018-06-15 14:16:45 -07:00
|
|
|
// NewIntFromBigInt constructs Int from big.Int
|
|
|
|
func NewIntFromBigInt(i *big.Int) Int {
|
2019-02-08 14:33:29 -08:00
|
|
|
if i.BitLen() > maxBitLen {
|
2018-06-15 14:16:45 -07:00
|
|
|
panic("NewIntFromBigInt() out of bound")
|
|
|
|
}
|
2018-06-26 18:10:34 -07:00
|
|
|
return Int{i}
|
2018-06-15 14:16:45 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// NewIntFromString constructs Int from string
|
|
|
|
func NewIntFromString(s string) (res Int, ok bool) {
|
|
|
|
i, ok := newIntegerFromString(s)
|
|
|
|
if !ok {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
// Check overflow
|
2019-02-08 14:33:29 -08:00
|
|
|
if i.BitLen() > maxBitLen {
|
2018-06-15 14:16:45 -07:00
|
|
|
ok = false
|
|
|
|
return
|
|
|
|
}
|
2018-06-26 18:10:34 -07:00
|
|
|
return Int{i}, true
|
2018-06-15 14:16:45 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// NewIntWithDecimal constructs Int with decimal
|
|
|
|
// Result value is n*10^dec
|
|
|
|
func NewIntWithDecimal(n int64, dec int) Int {
|
2018-08-06 12:00:49 -07:00
|
|
|
if dec < 0 {
|
|
|
|
panic("NewIntWithDecimal() decimal is negative")
|
|
|
|
}
|
|
|
|
exp := new(big.Int).Exp(big.NewInt(10), big.NewInt(int64(dec)), nil)
|
|
|
|
i := new(big.Int)
|
|
|
|
i.Mul(big.NewInt(n), exp)
|
|
|
|
|
2018-06-15 14:16:45 -07:00
|
|
|
// Check overflow
|
2019-02-08 14:33:29 -08:00
|
|
|
if i.BitLen() > maxBitLen {
|
2018-06-15 14:16:45 -07:00
|
|
|
panic("NewIntWithDecimal() out of bound")
|
|
|
|
}
|
2018-06-26 18:10:34 -07:00
|
|
|
return Int{i}
|
2018-06-15 14:16:45 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// ZeroInt returns Int value with zero
|
2018-06-26 18:10:34 -07:00
|
|
|
func ZeroInt() Int { return Int{big.NewInt(0)} }
|
2018-06-15 14:16:45 -07:00
|
|
|
|
|
|
|
// OneInt returns Int value with one
|
2018-06-26 18:10:34 -07:00
|
|
|
func OneInt() Int { return Int{big.NewInt(1)} }
|
2018-06-15 14:16:45 -07:00
|
|
|
|
2019-02-21 00:05:31 -08:00
|
|
|
// ToDec converts Int to Dec
|
|
|
|
func (i Int) ToDec() Dec {
|
|
|
|
return NewDecFromInt(i)
|
|
|
|
}
|
|
|
|
|
2018-06-15 14:16:45 -07:00
|
|
|
// Int64 converts Int to int64
|
|
|
|
// Panics if the value is out of range
|
|
|
|
func (i Int) Int64() int64 {
|
|
|
|
if !i.i.IsInt64() {
|
|
|
|
panic("Int64() out of bound")
|
|
|
|
}
|
|
|
|
return i.i.Int64()
|
|
|
|
}
|
|
|
|
|
2018-08-06 12:00:49 -07:00
|
|
|
// IsInt64 returns true if Int64() not panics
|
|
|
|
func (i Int) IsInt64() bool {
|
|
|
|
return i.i.IsInt64()
|
|
|
|
}
|
|
|
|
|
2020-01-04 12:16:12 -08:00
|
|
|
// Uint64 converts Int to uint64
|
|
|
|
// Panics if the value is out of range
|
|
|
|
func (i Int) Uint64() uint64 {
|
|
|
|
if !i.i.IsUint64() {
|
|
|
|
panic("Uint64() out of bounds")
|
|
|
|
}
|
|
|
|
return i.i.Uint64()
|
|
|
|
}
|
|
|
|
|
|
|
|
// IsUint64 returns true if Uint64() not panics
|
|
|
|
func (i Int) IsUint64() bool {
|
|
|
|
return i.i.IsUint64()
|
|
|
|
}
|
|
|
|
|
2018-06-15 14:16:45 -07:00
|
|
|
// IsZero returns true if Int is zero
|
|
|
|
func (i Int) IsZero() bool {
|
|
|
|
return i.i.Sign() == 0
|
|
|
|
}
|
|
|
|
|
2019-01-02 12:29:47 -08:00
|
|
|
// IsNegative returns true if Int is negative
|
|
|
|
func (i Int) IsNegative() bool {
|
|
|
|
return i.i.Sign() == -1
|
|
|
|
}
|
|
|
|
|
|
|
|
// IsPositive returns true if Int is positive
|
|
|
|
func (i Int) IsPositive() bool {
|
|
|
|
return i.i.Sign() == 1
|
|
|
|
}
|
|
|
|
|
2018-06-15 14:16:45 -07:00
|
|
|
// Sign returns sign of Int
|
|
|
|
func (i Int) Sign() int {
|
|
|
|
return i.i.Sign()
|
|
|
|
}
|
|
|
|
|
|
|
|
// Equal compares two Ints
|
|
|
|
func (i Int) Equal(i2 Int) bool {
|
2018-06-26 18:10:34 -07:00
|
|
|
return equal(i.i, i2.i)
|
2018-06-15 14:16:45 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// GT returns true if first Int is greater than second
|
|
|
|
func (i Int) GT(i2 Int) bool {
|
2018-06-26 18:10:34 -07:00
|
|
|
return gt(i.i, i2.i)
|
2018-06-15 14:16:45 -07:00
|
|
|
}
|
|
|
|
|
2019-02-07 18:14:54 -08:00
|
|
|
// GTE returns true if receiver Int is greater than or equal to the parameter
|
|
|
|
// Int.
|
|
|
|
func (i Int) GTE(i2 Int) bool {
|
|
|
|
return gte(i.i, i2.i)
|
|
|
|
}
|
|
|
|
|
2018-06-15 14:16:45 -07:00
|
|
|
// LT returns true if first Int is lesser than second
|
|
|
|
func (i Int) LT(i2 Int) bool {
|
2018-06-26 18:10:34 -07:00
|
|
|
return lt(i.i, i2.i)
|
2018-06-15 14:16:45 -07:00
|
|
|
}
|
|
|
|
|
2019-02-07 17:41:23 -08:00
|
|
|
// LTE returns true if first Int is less than or equal to second
|
|
|
|
func (i Int) LTE(i2 Int) bool {
|
|
|
|
return lte(i.i, i2.i)
|
|
|
|
}
|
|
|
|
|
2018-06-15 14:16:45 -07:00
|
|
|
// Add adds Int from another
|
|
|
|
func (i Int) Add(i2 Int) (res Int) {
|
2018-06-26 18:10:34 -07:00
|
|
|
res = Int{add(i.i, i2.i)}
|
2018-06-15 14:16:45 -07:00
|
|
|
// Check overflow
|
2019-02-08 14:33:29 -08:00
|
|
|
if res.i.BitLen() > maxBitLen {
|
2018-06-15 14:16:45 -07:00
|
|
|
panic("Int overflow")
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// AddRaw adds int64 to Int
|
|
|
|
func (i Int) AddRaw(i2 int64) Int {
|
|
|
|
return i.Add(NewInt(i2))
|
|
|
|
}
|
|
|
|
|
|
|
|
// Sub subtracts Int from another
|
|
|
|
func (i Int) Sub(i2 Int) (res Int) {
|
2018-06-26 18:10:34 -07:00
|
|
|
res = Int{sub(i.i, i2.i)}
|
2018-06-15 14:16:45 -07:00
|
|
|
// Check overflow
|
2019-02-08 14:33:29 -08:00
|
|
|
if res.i.BitLen() > maxBitLen {
|
2018-06-15 14:16:45 -07:00
|
|
|
panic("Int overflow")
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// SubRaw subtracts int64 from Int
|
|
|
|
func (i Int) SubRaw(i2 int64) Int {
|
|
|
|
return i.Sub(NewInt(i2))
|
|
|
|
}
|
|
|
|
|
|
|
|
// Mul multiples two Ints
|
|
|
|
func (i Int) Mul(i2 Int) (res Int) {
|
|
|
|
// Check overflow
|
2019-02-08 14:33:29 -08:00
|
|
|
if i.i.BitLen()+i2.i.BitLen()-1 > maxBitLen {
|
2018-06-15 14:16:45 -07:00
|
|
|
panic("Int overflow")
|
|
|
|
}
|
2018-06-26 18:10:34 -07:00
|
|
|
res = Int{mul(i.i, i2.i)}
|
2018-06-15 14:16:45 -07:00
|
|
|
// Check overflow if sign of both are same
|
2019-02-08 14:33:29 -08:00
|
|
|
if res.i.BitLen() > maxBitLen {
|
2018-06-15 14:16:45 -07:00
|
|
|
panic("Int overflow")
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// MulRaw multipies Int and int64
|
|
|
|
func (i Int) MulRaw(i2 int64) Int {
|
|
|
|
return i.Mul(NewInt(i2))
|
|
|
|
}
|
|
|
|
|
2019-02-21 09:35:55 -08:00
|
|
|
// Quo divides Int with Int
|
|
|
|
func (i Int) Quo(i2 Int) (res Int) {
|
2018-06-15 14:16:45 -07:00
|
|
|
// Check division-by-zero
|
|
|
|
if i2.i.Sign() == 0 {
|
|
|
|
panic("Division by zero")
|
|
|
|
}
|
2018-06-26 18:10:34 -07:00
|
|
|
return Int{div(i.i, i2.i)}
|
2018-06-15 14:16:45 -07:00
|
|
|
}
|
|
|
|
|
2019-02-21 09:35:55 -08:00
|
|
|
// QuoRaw divides Int with int64
|
|
|
|
func (i Int) QuoRaw(i2 int64) Int {
|
|
|
|
return i.Quo(NewInt(i2))
|
2018-06-15 14:16:45 -07:00
|
|
|
}
|
|
|
|
|
2018-08-06 12:00:49 -07:00
|
|
|
// Mod returns remainder after dividing with Int
|
|
|
|
func (i Int) Mod(i2 Int) Int {
|
|
|
|
if i2.Sign() == 0 {
|
|
|
|
panic("division-by-zero")
|
|
|
|
}
|
|
|
|
return Int{mod(i.i, i2.i)}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ModRaw returns remainder after dividing with int64
|
|
|
|
func (i Int) ModRaw(i2 int64) Int {
|
|
|
|
return i.Mod(NewInt(i2))
|
|
|
|
}
|
|
|
|
|
2018-06-15 14:16:45 -07:00
|
|
|
// Neg negates Int
|
|
|
|
func (i Int) Neg() (res Int) {
|
2018-06-26 18:10:34 -07:00
|
|
|
return Int{neg(i.i)}
|
2018-06-15 14:16:45 -07:00
|
|
|
}
|
|
|
|
|
2021-03-24 09:33:55 -07:00
|
|
|
// Abs returns the absolute value of Int.
|
|
|
|
func (i Int) Abs() Int {
|
|
|
|
return Int{abs(i.i)}
|
|
|
|
}
|
|
|
|
|
2019-01-02 12:29:47 -08:00
|
|
|
// return the minimum of the ints
|
2018-07-09 13:54:28 -07:00
|
|
|
func MinInt(i1, i2 Int) Int {
|
|
|
|
return Int{min(i1.BigInt(), i2.BigInt())}
|
|
|
|
}
|
|
|
|
|
2019-01-14 08:11:24 -08:00
|
|
|
// MaxInt returns the maximum between two integers.
|
|
|
|
func MaxInt(i, i2 Int) Int {
|
|
|
|
return Int{max(i.BigInt(), i2.BigInt())}
|
2019-01-02 12:29:47 -08:00
|
|
|
}
|
|
|
|
|
2018-08-06 12:00:49 -07:00
|
|
|
// Human readable string
|
2018-06-29 13:30:12 -07:00
|
|
|
func (i Int) String() string {
|
|
|
|
return i.i.String()
|
|
|
|
}
|
|
|
|
|
2020-01-24 07:32:00 -08:00
|
|
|
// MarshalJSON defines custom encoding scheme
|
|
|
|
func (i Int) MarshalJSON() ([]byte, error) {
|
2018-06-26 18:10:34 -07:00
|
|
|
if i.i == nil { // Necessary since default Uint initialization has i.i as nil
|
|
|
|
i.i = new(big.Int)
|
|
|
|
}
|
2020-01-24 07:32:00 -08:00
|
|
|
return marshalJSON(i.i)
|
2018-06-15 14:16:45 -07:00
|
|
|
}
|
|
|
|
|
2020-01-24 07:32:00 -08:00
|
|
|
// UnmarshalJSON defines custom decoding scheme
|
|
|
|
func (i *Int) UnmarshalJSON(bz []byte) error {
|
2018-06-26 18:10:34 -07:00
|
|
|
if i.i == nil { // Necessary since default Int initialization has i.i as nil
|
|
|
|
i.i = new(big.Int)
|
|
|
|
}
|
2020-01-24 07:32:00 -08:00
|
|
|
return unmarshalJSON(i.i, bz)
|
2018-06-15 14:16:45 -07:00
|
|
|
}
|
|
|
|
|
2020-01-24 07:32:00 -08:00
|
|
|
// MarshalJSON for custom encoding scheme
|
|
|
|
// Must be encoded as a string for JSON precision
|
|
|
|
func marshalJSON(i encoding.TextMarshaler) ([]byte, error) {
|
|
|
|
text, err := i.MarshalText()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return json.Marshal(string(text))
|
|
|
|
}
|
|
|
|
|
|
|
|
// UnmarshalJSON for custom decoding scheme
|
|
|
|
// Must be encoded as a string for JSON precision
|
|
|
|
func unmarshalJSON(i *big.Int, bz []byte) error {
|
|
|
|
var text string
|
|
|
|
if err := json.Unmarshal(bz, &text); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return unmarshalText(i, text)
|
|
|
|
}
|
|
|
|
|
|
|
|
// MarshalYAML returns the YAML representation.
|
|
|
|
func (i Int) MarshalYAML() (interface{}, error) {
|
|
|
|
return i.String(), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Marshal implements the gogo proto custom type interface.
|
|
|
|
func (i Int) Marshal() ([]byte, error) {
|
|
|
|
if i.i == nil {
|
2018-06-26 18:10:34 -07:00
|
|
|
i.i = new(big.Int)
|
|
|
|
}
|
2020-01-24 07:32:00 -08:00
|
|
|
return i.i.MarshalText()
|
2018-06-15 14:16:45 -07:00
|
|
|
}
|
|
|
|
|
2020-01-24 07:32:00 -08:00
|
|
|
// MarshalTo implements the gogo proto custom type interface.
|
|
|
|
func (i *Int) MarshalTo(data []byte) (n int, err error) {
|
|
|
|
if i.i == nil {
|
2018-06-26 18:10:34 -07:00
|
|
|
i.i = new(big.Int)
|
|
|
|
}
|
types: use (*math/big.Int).BitLen() == 0 to check if value is 0 (#8580)
Instead of using len((*math/big.Int).Bytes()) == 0, which expensively
creates a byte slice and marshals a value, on the majority hot path,
instead use the cheaper method .BitLen() to check if 0.
Benchmarking results, just from types:
name old time/op new time/op delta
CoinsAdditionIntersect/sizes:_A_1,_B_1-8 132ns ± 2% 126ns ±13% -4.55% (p=0.050 n=10+10)
CoinsAdditionIntersect/sizes:_A_5,_B_5-8 1.41µs ± 3% 1.41µs ± 2% ~ (p=1.000 n=10+10)
CoinsAdditionIntersect/sizes:_A_5,_B_20-8 2.30µs ± 1% 2.27µs ± 3% ~ (p=0.066 n=10+10)
CoinsAdditionIntersect/sizes:_A_1,_B_1000-8 30.9µs ± 3% 30.7µs ± 1% ~ (p=0.218 n=10+10)
CoinsAdditionIntersect/sizes:_A_2,_B_1000-8 31.4µs ± 3% 30.8µs ± 2% -1.94% (p=0.015 n=10+10)
CoinsAdditionNoIntersect/sizes:_A_1,_B_1-8 116ns ± 1% 114ns ± 4% ~ (p=0.142 n=10+10)
CoinsAdditionNoIntersect/sizes:_A_5,_B_5-8 1.11µs ± 1% 1.08µs ± 3% -2.36% (p=0.003 n=8+10)
CoinsAdditionNoIntersect/sizes:_A_5,_B_20-8 1.85µs ± 2% 1.82µs ± 1% -1.38% (p=0.001 n=10+9)
CoinsAdditionNoIntersect/sizes:_A_1,_B_1000-8 30.7µs ± 1% 30.6µs ± 3% ~ (p=0.393 n=10+10)
CoinsAdditionNoIntersect/sizes:_A_2,_B_1000-8 31.1µs ± 1% 30.7µs ± 2% -1.32% (p=0.015 n=10+10)
CoinsAdditionNoIntersect/sizes:_A_1000,_B_2-8 31.0µs ± 2% 30.7µs ± 2% ~ (p=0.190 n=10+10)
Bech32ifyPubKey-8 28.8µs ± 5% 28.8µs ± 3% ~ (p=0.965 n=10+8)
GetPubKeyFromBech32-8 38.8µs ± 3% 39.4µs ± 2% +1.70% (p=0.013 n=9+10)
ParseCoin-8 16.7µs ± 6% 15.8µs ± 4% -5.21% (p=0.001 n=10+10)
MarshalTo-8 521ns ± 5% 508ns ± 3% -2.56% (p=0.029 n=10+10)
UintMarshal-8 3.10µs ±17% 2.56µs ± 3% -17.45% (p=0.000 n=10+9)
IntMarshal-8 2.52µs ±10% 1.94µs ± 2% -23.10% (p=0.000 n=10+10)
name old alloc/op new alloc/op delta
Bech32ifyPubKey-8 4.02kB ± 0% 4.02kB ± 0% ~ (all equal)
GetPubKeyFromBech32-8 2.48kB ± 0% 2.48kB ± 0% ~ (all equal)
ParseCoin-8 2.21kB ± 0% 2.21kB ± 0% ~ (all equal)
MarshalTo-8 80.0B ± 0% 80.0B ± 0% ~ (all equal)
UintMarshal-8 440B ± 0% 392B ± 0% -10.91% (p=0.000 n=10+10)
IntMarshal-8 216B ± 0% 168B ± 0% -22.22% (p=0.000 n=10+10)
name old allocs/op new allocs/op delta
Bech32ifyPubKey-8 25.0 ± 0% 25.0 ± 0% ~ (all equal)
GetPubKeyFromBech32-8 85.0 ± 0% 85.0 ± 0% ~ (all equal)
ParseCoin-8 71.0 ± 0% 71.0 ± 0% ~ (all equal)
MarshalTo-8 2.00 ± 0% 2.00 ± 0% ~ (all equal)
UintMarshal-8 31.0 ± 0% 25.0 ± 0% -19.35% (p=0.000 n=10+10)
IntMarshal-8 24.0 ± 0% 18.0 ± 0% -25.00% (p=0.000 n=10+10)
name old speed new speed delta
UintMarshal-8 2.27MB/s ±15% 2.75MB/s ± 2% +20.87% (p=0.000 n=10+8)
IntMarshal-8 2.78MB/s ± 9% 3.60MB/s ± 2% +29.69% (p=0.000 n=10+10)
Fixes #8575
Co-authored-by: Alessio Treglia <alessio@tendermint.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
2021-02-15 02:53:10 -08:00
|
|
|
if i.i.BitLen() == 0 { // The value 0
|
2020-01-24 07:32:00 -08:00
|
|
|
copy(data, []byte{0x30})
|
|
|
|
return 1, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
bz, err := i.Marshal()
|
|
|
|
if err != nil {
|
|
|
|
return 0, err
|
|
|
|
}
|
|
|
|
|
|
|
|
copy(data, bz)
|
|
|
|
return len(bz), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Unmarshal implements the gogo proto custom type interface.
|
|
|
|
func (i *Int) Unmarshal(data []byte) error {
|
|
|
|
if len(data) == 0 {
|
|
|
|
i = nil
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
if i.i == nil {
|
|
|
|
i.i = new(big.Int)
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := i.i.UnmarshalText(data); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if i.i.BitLen() > maxBitLen {
|
|
|
|
return fmt.Errorf("integer out of range; got: %d, max: %d", i.i.BitLen(), maxBitLen)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Size implements the gogo proto custom type interface.
|
|
|
|
func (i *Int) Size() int {
|
|
|
|
bz, _ := i.Marshal()
|
|
|
|
return len(bz)
|
2018-06-15 14:16:45 -07:00
|
|
|
}
|
|
|
|
|
2020-01-24 07:32:00 -08:00
|
|
|
// Override Amino binary serialization by proxying to protobuf.
|
|
|
|
func (i Int) MarshalAmino() ([]byte, error) { return i.Marshal() }
|
|
|
|
func (i *Int) UnmarshalAmino(bz []byte) error { return i.Unmarshal(bz) }
|
2019-06-18 09:03:16 -07:00
|
|
|
|
2018-10-12 01:11:09 -07:00
|
|
|
// intended to be used with require/assert: require.True(IntEq(...))
|
|
|
|
func IntEq(t *testing.T, exp, got Int) (*testing.T, bool, string, string, string) {
|
|
|
|
return t, exp.Equal(got), "expected:\t%v\ngot:\t\t%v", exp.String(), got.String()
|
|
|
|
}
|
2020-02-06 11:21:02 -08:00
|
|
|
|
|
|
|
func (ip IntProto) String() string {
|
|
|
|
return ip.Int.String()
|
|
|
|
}
|