github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/cosmos-sdk/types/int.go (about)

     1  package types
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"testing"
     7  
     8  	"github.com/tendermint/go-amino"
     9  
    10  	"math/big"
    11  )
    12  
    13  const maxBitLen = 255
    14  
    15  func newIntegerFromString(s string) (*big.Int, bool) {
    16  	return new(big.Int).SetString(s, 0)
    17  }
    18  
    19  func equal(i *big.Int, i2 *big.Int) bool { return i.Cmp(i2) == 0 }
    20  
    21  func gt(i *big.Int, i2 *big.Int) bool { return i.Cmp(i2) == 1 }
    22  
    23  func gte(i *big.Int, i2 *big.Int) bool { return i.Cmp(i2) >= 0 }
    24  
    25  func lt(i *big.Int, i2 *big.Int) bool { return i.Cmp(i2) == -1 }
    26  
    27  func lte(i *big.Int, i2 *big.Int) bool { return i.Cmp(i2) <= 0 }
    28  
    29  func add(i *big.Int, i2 *big.Int) *big.Int { return new(big.Int).Add(i, i2) }
    30  
    31  func sub(i *big.Int, i2 *big.Int) *big.Int { return new(big.Int).Sub(i, i2) }
    32  
    33  func mul(i *big.Int, i2 *big.Int) *big.Int { return new(big.Int).Mul(i, i2) }
    34  
    35  func div(i *big.Int, i2 *big.Int) *big.Int { return new(big.Int).Quo(i, i2) }
    36  
    37  func mod(i *big.Int, i2 *big.Int) *big.Int { return new(big.Int).Mod(i, i2) }
    38  
    39  func neg(i *big.Int) *big.Int { return new(big.Int).Neg(i) }
    40  
    41  func min(i *big.Int, i2 *big.Int) *big.Int {
    42  	if i.Cmp(i2) == 1 {
    43  		return new(big.Int).Set(i2)
    44  	}
    45  
    46  	return new(big.Int).Set(i)
    47  }
    48  
    49  func max(i *big.Int, i2 *big.Int) *big.Int {
    50  	if i.Cmp(i2) == -1 {
    51  		return new(big.Int).Set(i2)
    52  	}
    53  
    54  	return new(big.Int).Set(i)
    55  }
    56  
    57  // MarshalAmino for custom encoding scheme
    58  func marshalAmino(i *big.Int) (string, error) { // nolint:interfacer
    59  	bz, err := i.MarshalText()
    60  	return string(bz), err
    61  }
    62  
    63  func unmarshalText(i *big.Int, text string) error {
    64  	if err := i.UnmarshalText([]byte(text)); err != nil {
    65  		return err
    66  	}
    67  
    68  	if i.BitLen() > maxBitLen {
    69  		return fmt.Errorf("integer out of range: %s", text)
    70  	}
    71  
    72  	return nil
    73  }
    74  
    75  // UnmarshalAmino for custom decoding scheme
    76  func unmarshalAmino(i *big.Int, text string) (err error) {
    77  	return unmarshalText(i, text)
    78  }
    79  
    80  // MarshalJSON for custom encoding scheme
    81  // Must be encoded as a string for JSON precision
    82  func marshalJSON(i *big.Int) ([]byte, error) { // nolint:interfacer
    83  	text, err := i.MarshalText()
    84  	if err != nil {
    85  		return nil, err
    86  	}
    87  	return json.Marshal(string(text))
    88  }
    89  
    90  // UnmarshalJSON for custom decoding scheme
    91  // Must be encoded as a string for JSON precision
    92  func unmarshalJSON(i *big.Int, bz []byte) error {
    93  	var text string
    94  	err := json.Unmarshal(bz, &text)
    95  	if err != nil {
    96  		return err
    97  	}
    98  
    99  	return unmarshalText(i, text)
   100  }
   101  
   102  // Int wraps integer with 256 bit range bound
   103  // Checks overflow, underflow and division by zero
   104  // Exists in range from -(2^maxBitLen-1) to 2^maxBitLen-1
   105  type Int struct {
   106  	i *big.Int
   107  }
   108  
   109  // BigInt converts Int to big.Int
   110  func (i Int) BigInt() *big.Int {
   111  	if i.IsNil() {
   112  		return nil
   113  	}
   114  	return new(big.Int).Set(i.i)
   115  }
   116  
   117  // IsNil returns true if Int is uninitialized
   118  func (i Int) IsNil() bool {
   119  	return i.i == nil
   120  }
   121  
   122  // NewInt constructs Int from int64
   123  func NewInt(n int64) Int {
   124  	return Int{big.NewInt(n)}
   125  }
   126  
   127  // NewIntFromUint64 constructs an Int from a uint64.
   128  func NewIntFromUint64(n uint64) Int {
   129  	b := big.NewInt(0)
   130  	b.SetUint64(n)
   131  	return Int{b}
   132  }
   133  
   134  // NewIntFromBigInt constructs Int from big.Int
   135  func NewIntFromBigInt(i *big.Int) Int {
   136  	if i.BitLen() > maxBitLen {
   137  		panic("NewIntFromBigInt() out of bound")
   138  	}
   139  	return Int{i}
   140  }
   141  
   142  // NewIntFromString constructs Int from string
   143  func NewIntFromString(s string) (res Int, ok bool) {
   144  	i, ok := newIntegerFromString(s)
   145  	if !ok {
   146  		return
   147  	}
   148  	// Check overflow
   149  	if i.BitLen() > maxBitLen {
   150  		ok = false
   151  		return
   152  	}
   153  	return Int{i}, true
   154  }
   155  
   156  // NewIntWithDecimal constructs Int with decimal
   157  // Result value is n*10^dec
   158  func NewIntWithDecimal(n int64, dec int) Int {
   159  	if dec < 0 {
   160  		panic("NewIntWithDecimal() decimal is negative")
   161  	}
   162  	exp := new(big.Int).Exp(big.NewInt(10), big.NewInt(int64(dec)), nil)
   163  	i := new(big.Int)
   164  	i.Mul(big.NewInt(n), exp)
   165  
   166  	// Check overflow
   167  	if i.BitLen() > maxBitLen {
   168  		panic("NewIntWithDecimal() out of bound")
   169  	}
   170  	return Int{i}
   171  }
   172  
   173  // ZeroInt returns Int value with zero
   174  func ZeroInt() Int { return Int{big.NewInt(0)} }
   175  
   176  // OneInt returns Int value with one
   177  func OneInt() Int { return Int{big.NewInt(1)} }
   178  
   179  // ToDec converts Int to Dec
   180  func (i Int) ToDec() Dec {
   181  	return NewDecFromInt(i)
   182  }
   183  
   184  // Int64 converts Int to int64
   185  // Panics if the value is out of range
   186  func (i Int) Int64() int64 {
   187  	if !i.i.IsInt64() {
   188  		panic("Int64() out of bound")
   189  	}
   190  	return i.i.Int64()
   191  }
   192  
   193  // IsInt64 returns true if Int64() not panics
   194  func (i Int) IsInt64() bool {
   195  	return i.i.IsInt64()
   196  }
   197  
   198  // Uint64 converts Int to uint64
   199  // Panics if the value is out of range
   200  func (i Int) Uint64() uint64 {
   201  	if !i.i.IsUint64() {
   202  		panic("Uint64() out of bounds")
   203  	}
   204  	return i.i.Uint64()
   205  }
   206  
   207  // IsUint64 returns true if Uint64() not panics
   208  func (i Int) IsUint64() bool {
   209  	return i.i.IsUint64()
   210  }
   211  
   212  // IsZero returns true if Int is zero
   213  func (i Int) IsZero() bool {
   214  	return i.i.Sign() == 0
   215  }
   216  
   217  // IsNegative returns true if Int is negative
   218  func (i Int) IsNegative() bool {
   219  	return i.i.Sign() == -1
   220  }
   221  
   222  // IsPositive returns true if Int is positive
   223  func (i Int) IsPositive() bool {
   224  	return i.i.Sign() == 1
   225  }
   226  
   227  // Sign returns sign of Int
   228  func (i Int) Sign() int {
   229  	return i.i.Sign()
   230  }
   231  
   232  // Equal compares two Ints
   233  func (i Int) Equal(i2 Int) bool {
   234  	return equal(i.i, i2.i)
   235  }
   236  
   237  // GT returns true if first Int is greater than second
   238  func (i Int) GT(i2 Int) bool {
   239  	return gt(i.i, i2.i)
   240  }
   241  
   242  // GTE returns true if receiver Int is greater than or equal to the parameter
   243  // Int.
   244  func (i Int) GTE(i2 Int) bool {
   245  	return gte(i.i, i2.i)
   246  }
   247  
   248  // LT returns true if first Int is lesser than second
   249  func (i Int) LT(i2 Int) bool {
   250  	return lt(i.i, i2.i)
   251  }
   252  
   253  // LTE returns true if first Int is less than or equal to second
   254  func (i Int) LTE(i2 Int) bool {
   255  	return lte(i.i, i2.i)
   256  }
   257  
   258  // Add adds Int from another
   259  func (i Int) Add(i2 Int) (res Int) {
   260  	res = Int{add(i.i, i2.i)}
   261  	// Check overflow
   262  	if res.i.BitLen() > maxBitLen {
   263  		panic("Int overflow")
   264  	}
   265  	return
   266  }
   267  
   268  // AddRaw adds int64 to Int
   269  func (i Int) AddRaw(i2 int64) Int {
   270  	return i.Add(NewInt(i2))
   271  }
   272  
   273  // Sub subtracts Int from another
   274  func (i Int) Sub(i2 Int) (res Int) {
   275  	res = Int{sub(i.i, i2.i)}
   276  	// Check overflow
   277  	if res.i.BitLen() > maxBitLen {
   278  		panic("Int overflow")
   279  	}
   280  	return
   281  }
   282  
   283  // SubRaw subtracts int64 from Int
   284  func (i Int) SubRaw(i2 int64) Int {
   285  	return i.Sub(NewInt(i2))
   286  }
   287  
   288  // Mul multiples two Ints
   289  func (i Int) Mul(i2 Int) (res Int) {
   290  	// Check overflow
   291  	if i.i.BitLen()+i2.i.BitLen()-1 > maxBitLen {
   292  		panic("Int overflow")
   293  	}
   294  	res = Int{mul(i.i, i2.i)}
   295  	// Check overflow if sign of both are same
   296  	if res.i.BitLen() > maxBitLen {
   297  		panic("Int overflow")
   298  	}
   299  	return
   300  }
   301  
   302  // MulRaw multipies Int and int64
   303  func (i Int) MulRaw(i2 int64) Int {
   304  	return i.Mul(NewInt(i2))
   305  }
   306  
   307  // Quo divides Int with Int
   308  func (i Int) Quo(i2 Int) (res Int) {
   309  	// Check division-by-zero
   310  	if i2.i.Sign() == 0 {
   311  		panic("Division by zero")
   312  	}
   313  	return Int{div(i.i, i2.i)}
   314  }
   315  
   316  // QuoRaw divides Int with int64
   317  func (i Int) QuoRaw(i2 int64) Int {
   318  	return i.Quo(NewInt(i2))
   319  }
   320  
   321  // Mod returns remainder after dividing with Int
   322  func (i Int) Mod(i2 Int) Int {
   323  	if i2.Sign() == 0 {
   324  		panic("division-by-zero")
   325  	}
   326  	return Int{mod(i.i, i2.i)}
   327  }
   328  
   329  // ModRaw returns remainder after dividing with int64
   330  func (i Int) ModRaw(i2 int64) Int {
   331  	return i.Mod(NewInt(i2))
   332  }
   333  
   334  // Neg negates Int
   335  func (i Int) Neg() (res Int) {
   336  	return Int{neg(i.i)}
   337  }
   338  
   339  // return the minimum of the ints
   340  func MinInt(i1, i2 Int) Int {
   341  	return Int{min(i1.BigInt(), i2.BigInt())}
   342  }
   343  
   344  // MaxInt returns the maximum between two integers.
   345  func MaxInt(i, i2 Int) Int {
   346  	return Int{max(i.BigInt(), i2.BigInt())}
   347  }
   348  
   349  // Human readable string
   350  func (i Int) String() string {
   351  	return i.i.String()
   352  }
   353  
   354  // MarshalAmino defines custom encoding scheme
   355  func (i Int) MarshalAmino() (string, error) {
   356  	if i.i == nil { // Necessary since default Uint initialization has i.i as nil
   357  		i.i = new(big.Int)
   358  	}
   359  	return marshalAmino(i.i)
   360  }
   361  
   362  // UnmarshalAmino defines custom decoding scheme
   363  func (i *Int) UnmarshalAmino(text string) error {
   364  	if i.i == nil { // Necessary since default Int initialization has i.i as nil
   365  		i.i = new(big.Int)
   366  	}
   367  	return unmarshalAmino(i.i, text)
   368  }
   369  
   370  func (i *Int) UnmarshalFromAmino(_ *amino.Codec, data []byte) error {
   371  	if i.i == nil { // Necessary since default Int initialization has i.i as nil
   372  		i.i = new(big.Int)
   373  	}
   374  
   375  	if err := i.i.UnmarshalText(data); err != nil {
   376  		return err
   377  	}
   378  
   379  	if i.i.BitLen() > maxBitLen {
   380  		return fmt.Errorf("integer out of range: %s", string(data))
   381  	}
   382  	return nil
   383  }
   384  
   385  // MarshalJSON defines custom encoding scheme
   386  func (i Int) MarshalJSON() ([]byte, error) {
   387  	if i.i == nil { // Necessary since default Uint initialization has i.i as nil
   388  		i.i = new(big.Int)
   389  	}
   390  	return marshalJSON(i.i)
   391  }
   392  
   393  // UnmarshalJSON defines custom decoding scheme
   394  func (i *Int) UnmarshalJSON(bz []byte) error {
   395  	if i.i == nil { // Necessary since default Int initialization has i.i as nil
   396  		i.i = new(big.Int)
   397  	}
   398  	return unmarshalJSON(i.i, bz)
   399  }
   400  
   401  // MarshalYAML returns Ythe AML representation.
   402  func (i Int) MarshalYAML() (interface{}, error) { return i.String(), nil }
   403  
   404  // intended to be used with require/assert:  require.True(IntEq(...))
   405  func IntEq(t *testing.T, exp, got Int) (*testing.T, bool, string, string, string) {
   406  	return t, exp.Equal(got), "expected:\t%v\ngot:\t\t%v", exp.String(), got.String()
   407  }