github.com/Finschia/finschia-sdk@v0.48.1/types/uint.go (about)

     1  package types
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"math/big"
     7  )
     8  
     9  // Uint wraps integer with 256 bit range bound
    10  // Checks overflow, underflow and division by zero
    11  // Exists in range from 0 to 2^256-1
    12  type Uint struct {
    13  	i *big.Int
    14  }
    15  
    16  // BigInt converts Uint to big.Int
    17  func (u Uint) BigInt() *big.Int {
    18  	return new(big.Int).Set(u.i)
    19  }
    20  
    21  // NewUintFromBigUint constructs Uint from big.Uint
    22  func NewUintFromBigInt(i *big.Int) Uint {
    23  	u, err := checkNewUint(i)
    24  	if err != nil {
    25  		panic(fmt.Errorf("overflow: %s", err))
    26  	}
    27  	return u
    28  }
    29  
    30  // NewUint constructs Uint from int64
    31  func NewUint(n uint64) Uint {
    32  	i := new(big.Int)
    33  	i.SetUint64(n)
    34  	return NewUintFromBigInt(i)
    35  }
    36  
    37  // NewUintFromString constructs Uint from string
    38  func NewUintFromString(s string) Uint {
    39  	u, err := ParseUint(s)
    40  	if err != nil {
    41  		panic(err)
    42  	}
    43  	return u
    44  }
    45  
    46  // ZeroUint returns unsigned zero.
    47  func ZeroUint() Uint { return Uint{big.NewInt(0)} }
    48  
    49  // OneUint returns Uint value with one.
    50  func OneUint() Uint { return Uint{big.NewInt(1)} }
    51  
    52  var _ CustomProtobufType = (*Uint)(nil)
    53  
    54  // Uint64 converts Uint to uint64
    55  // Panics if the value is out of range
    56  func (u Uint) Uint64() uint64 {
    57  	if !u.i.IsUint64() {
    58  		panic("Uint64() out of bound")
    59  	}
    60  	return u.i.Uint64()
    61  }
    62  
    63  // IsZero returns 1 if the uint equals to 0.
    64  func (u Uint) IsZero() bool { return u.Equal(ZeroUint()) }
    65  
    66  // Equal compares two Uints
    67  func (u Uint) Equal(u2 Uint) bool { return equal(u.i, u2.i) }
    68  
    69  // GT returns true if first Uint is greater than second
    70  func (u Uint) GT(u2 Uint) bool { return gt(u.i, u2.i) }
    71  
    72  // GTE returns true if first Uint is greater than second
    73  func (u Uint) GTE(u2 Uint) bool { return u.GT(u2) || u.Equal(u2) }
    74  
    75  // LT returns true if first Uint is lesser than second
    76  func (u Uint) LT(u2 Uint) bool { return lt(u.i, u2.i) }
    77  
    78  // LTE returns true if first Uint is lesser than or equal to the second
    79  func (u Uint) LTE(u2 Uint) bool { return !u.GT(u2) }
    80  
    81  // Add adds Uint from another
    82  func (u Uint) Add(u2 Uint) Uint { return NewUintFromBigInt(new(big.Int).Add(u.i, u2.i)) }
    83  
    84  // Add convert uint64 and add it to Uint
    85  func (u Uint) AddUint64(u2 uint64) Uint { return u.Add(NewUint(u2)) }
    86  
    87  // Sub adds Uint from another
    88  func (u Uint) Sub(u2 Uint) Uint { return NewUintFromBigInt(new(big.Int).Sub(u.i, u2.i)) }
    89  
    90  // SubUint64 adds Uint from another
    91  func (u Uint) SubUint64(u2 uint64) Uint { return u.Sub(NewUint(u2)) }
    92  
    93  // Mul multiplies two Uints
    94  func (u Uint) Mul(u2 Uint) (res Uint) {
    95  	return NewUintFromBigInt(new(big.Int).Mul(u.i, u2.i))
    96  }
    97  
    98  // Mul multiplies two Uints
    99  func (u Uint) MulUint64(u2 uint64) (res Uint) { return u.Mul(NewUint(u2)) }
   100  
   101  // Quo divides Uint with Uint
   102  func (u Uint) Quo(u2 Uint) (res Uint) { return NewUintFromBigInt(div(u.i, u2.i)) }
   103  
   104  // Mod returns remainder after dividing with Uint
   105  func (u Uint) Mod(u2 Uint) Uint {
   106  	if u2.IsZero() {
   107  		panic("division-by-zero")
   108  	}
   109  	return Uint{mod(u.i, u2.i)}
   110  }
   111  
   112  // Incr increments the Uint by one.
   113  func (u Uint) Incr() Uint {
   114  	return u.Add(OneUint())
   115  }
   116  
   117  // Decr decrements the Uint by one.
   118  // Decr will panic if the Uint is zero.
   119  func (u Uint) Decr() Uint {
   120  	return u.Sub(OneUint())
   121  }
   122  
   123  // Quo divides Uint with uint64
   124  func (u Uint) QuoUint64(u2 uint64) Uint { return u.Quo(NewUint(u2)) }
   125  
   126  // Return the minimum of the Uints
   127  func MinUint(u1, u2 Uint) Uint { return NewUintFromBigInt(min(u1.i, u2.i)) }
   128  
   129  // Return the maximum of the Uints
   130  func MaxUint(u1, u2 Uint) Uint { return NewUintFromBigInt(max(u1.i, u2.i)) }
   131  
   132  // Human readable string
   133  func (u Uint) String() string { return u.i.String() }
   134  
   135  // MarshalJSON defines custom encoding scheme
   136  func (u Uint) MarshalJSON() ([]byte, error) {
   137  	if u.i == nil { // Necessary since default Uint initialization has i.i as nil
   138  		u.i = new(big.Int)
   139  	}
   140  	return marshalJSON(u.i)
   141  }
   142  
   143  // UnmarshalJSON defines custom decoding scheme
   144  func (u *Uint) UnmarshalJSON(bz []byte) error {
   145  	if u.i == nil { // Necessary since default Uint initialization has i.i as nil
   146  		u.i = new(big.Int)
   147  	}
   148  	return unmarshalJSON(u.i, bz)
   149  }
   150  
   151  // Marshal implements the gogo proto custom type interface.
   152  func (u Uint) Marshal() ([]byte, error) {
   153  	if u.i == nil {
   154  		u.i = new(big.Int)
   155  	}
   156  	return u.i.MarshalText()
   157  }
   158  
   159  // MarshalTo implements the gogo proto custom type interface.
   160  func (u *Uint) MarshalTo(data []byte) (n int, err error) {
   161  	if u.i == nil {
   162  		u.i = new(big.Int)
   163  	}
   164  	if u.i.BitLen() == 0 { // The value 0
   165  		copy(data, []byte{0x30})
   166  		return 1, nil
   167  	}
   168  
   169  	bz, err := u.Marshal()
   170  	if err != nil {
   171  		return 0, err
   172  	}
   173  
   174  	copy(data, bz)
   175  	return len(bz), nil
   176  }
   177  
   178  // Unmarshal implements the gogo proto custom type interface.
   179  func (u *Uint) Unmarshal(data []byte) error {
   180  	if len(data) == 0 {
   181  		u = nil
   182  		return nil
   183  	}
   184  
   185  	if u.i == nil {
   186  		u.i = new(big.Int)
   187  	}
   188  
   189  	if err := u.i.UnmarshalText(data); err != nil {
   190  		return err
   191  	}
   192  
   193  	if u.i.BitLen() > maxBitLen {
   194  		return fmt.Errorf("integer out of range; got: %d, max: %d", u.i.BitLen(), maxBitLen)
   195  	}
   196  
   197  	return nil
   198  }
   199  
   200  // Size implements the gogo proto custom type interface.
   201  func (u *Uint) Size() int {
   202  	bz, _ := u.Marshal()
   203  	return len(bz)
   204  }
   205  
   206  // Override Amino binary serialization by proxying to protobuf.
   207  func (u Uint) MarshalAmino() ([]byte, error)   { return u.Marshal() }
   208  func (u *Uint) UnmarshalAmino(bz []byte) error { return u.Unmarshal(bz) }
   209  
   210  // UintOverflow returns true if a given unsigned integer overflows and false
   211  // otherwise.
   212  func UintOverflow(i *big.Int) error {
   213  	if i.Sign() < 0 {
   214  		return errors.New("non-positive integer")
   215  	}
   216  	if i.BitLen() > 256 {
   217  		return fmt.Errorf("bit length %d greater than 256", i.BitLen())
   218  	}
   219  	return nil
   220  }
   221  
   222  // ParseUint reads a string-encoded Uint value and return a Uint.
   223  func ParseUint(s string) (Uint, error) {
   224  	i, ok := new(big.Int).SetString(s, 0)
   225  	if !ok {
   226  		return Uint{}, fmt.Errorf("cannot convert %q to big.Int", s)
   227  	}
   228  	return checkNewUint(i)
   229  }
   230  
   231  func checkNewUint(i *big.Int) (Uint, error) {
   232  	if err := UintOverflow(i); err != nil {
   233  		return Uint{}, err
   234  	}
   235  	return Uint{i}, nil
   236  }
   237  
   238  // RelativePow raises x to the power of n, where x (and the result, z) are scaled by factor b
   239  // for example, RelativePow(210, 2, 100) = 441 (2.1^2 = 4.41)
   240  func RelativePow(x Uint, n Uint, b Uint) (z Uint) {
   241  	if x.IsZero() {
   242  		if n.IsZero() {
   243  			z = b // 0^0 = 1
   244  			return
   245  		}
   246  		z = ZeroUint() // otherwise 0^a = 0
   247  		return
   248  	}
   249  
   250  	z = x
   251  	if n.Mod(NewUint(2)).Equal(ZeroUint()) {
   252  		z = b
   253  	}
   254  
   255  	halfOfB := b.Quo(NewUint(2))
   256  	n = n.Quo(NewUint(2))
   257  
   258  	for n.GT(ZeroUint()) {
   259  		xSquared := x.Mul(x)
   260  		xSquaredRounded := xSquared.Add(halfOfB)
   261  
   262  		x = xSquaredRounded.Quo(b)
   263  
   264  		if n.Mod(NewUint(2)).Equal(OneUint()) {
   265  			zx := z.Mul(x)
   266  			zxRounded := zx.Add(halfOfB)
   267  			z = zxRounded.Quo(b)
   268  		}
   269  		n = n.Quo(NewUint(2))
   270  	}
   271  	return z
   272  }