github.com/igggame/nebulas-go@v2.1.0+incompatible/util/uint128.go (about)

     1  package util
     2  
     3  import (
     4  	"errors"
     5  	"math/big"
     6  )
     7  
     8  const (
     9  	// Uint128Bytes defines the number of bytes for Uint128 type.
    10  	Uint128Bytes = 16
    11  
    12  	// Uint128Bits defines the number of bits for Uint128 type.
    13  	Uint128Bits = 128
    14  )
    15  
    16  var (
    17  	// ErrUint128Overflow indicates the value is greater than uint128 maximum value 2^128.
    18  	ErrUint128Overflow = errors.New("uint128: overflow")
    19  
    20  	// ErrUint128Underflow indicates the value is smaller then uint128 minimum value 0.
    21  	ErrUint128Underflow = errors.New("uint128: underflow")
    22  
    23  	// ErrUint128InvalidBytesSize indicates the bytes size is not equal to Uint128Bytes.
    24  	ErrUint128InvalidBytesSize = errors.New("uint128: invalid bytes")
    25  
    26  	// ErrUint128InvalidString indicates the string is not valid when converted to uin128.
    27  	ErrUint128InvalidString = errors.New("uint128: invalid string to uint128")
    28  )
    29  
    30  // Uint128 defines uint128 type, based on big.Int.
    31  //
    32  // For arithmetic operations, use uint128.Int.Add()/Sub()/Mul()/Div()/etc.
    33  // For example, u1.Add(u1.Int, u2.Int) sets u1 to u1 + u2.
    34  type Uint128 struct {
    35  	value *big.Int
    36  }
    37  
    38  // Validate returns error if u is not a valid uint128, otherwise returns nil.
    39  func (u *Uint128) Validate() error {
    40  	if u.value.Sign() < 0 {
    41  		return ErrUint128Underflow
    42  	}
    43  	if u.value.BitLen() > Uint128Bits {
    44  		return ErrUint128Overflow
    45  	}
    46  	return nil
    47  }
    48  
    49  // NewUint128 returns a new Uint128 struct with default value.
    50  func NewUint128() *Uint128 {
    51  	return &Uint128{big.NewInt(0)}
    52  }
    53  
    54  // NewUint128FromString returns a new Uint128 struct with given value and have a check.
    55  func NewUint128FromString(str string) (*Uint128, error) {
    56  	big := new(big.Int)
    57  	_, success := big.SetString(str, 10)
    58  	if !success {
    59  		return nil, ErrUint128InvalidString
    60  	}
    61  	if err := (&Uint128{big}).Validate(); nil != err {
    62  		return nil, err
    63  	}
    64  	return &Uint128{big}, nil
    65  }
    66  
    67  // NewUint128FromUint returns a new Uint128 with given value
    68  func NewUint128FromUint(i uint64) *Uint128 {
    69  	obj := NewUint128()
    70  	obj.value.SetUint64(i)
    71  	return obj
    72  }
    73  
    74  // NewUint128FromInt returns a new Uint128 struct with given value and have a check.
    75  func NewUint128FromInt(i int64) (*Uint128, error) {
    76  	obj := &Uint128{big.NewInt(i)}
    77  	if err := obj.Validate(); nil != err {
    78  		return nil, err
    79  	}
    80  	return obj, nil
    81  }
    82  
    83  // NewUint128FromBigInt returns a new Uint128 struct with given value and have a check.
    84  func NewUint128FromBigInt(i *big.Int) (*Uint128, error) {
    85  	obj := &Uint128{i}
    86  	if err := obj.Validate(); nil != err {
    87  		return nil, err
    88  	}
    89  	return obj, nil
    90  }
    91  
    92  // NewUint128FromFixedSizeBytes returns a new Uint128 struct with given fixed size byte array.
    93  func NewUint128FromFixedSizeBytes(bytes [16]byte) *Uint128 {
    94  	u := NewUint128()
    95  	return u.FromFixedSizeBytes(bytes)
    96  }
    97  
    98  // NewUint128FromFixedSizeByteSlice returns a new Uint128 struct with given fixed size byte slice.
    99  func NewUint128FromFixedSizeByteSlice(bytes []byte) (*Uint128, error) {
   100  	u := NewUint128()
   101  	return u.FromFixedSizeByteSlice(bytes)
   102  }
   103  
   104  // Uint128Zero zero of uint128
   105  func Uint128Zero() *Uint128 {
   106  	return NewUint128FromUint(0)
   107  }
   108  
   109  // ToFixedSizeBytes converts Uint128 to Big-Endian fixed size bytes.
   110  func (u *Uint128) ToFixedSizeBytes() ([16]byte, error) {
   111  	var res [16]byte
   112  	if err := u.Validate(); err != nil {
   113  		return res, err
   114  	}
   115  	bs := u.value.Bytes()
   116  	l := len(bs)
   117  	if l == 0 {
   118  		return res, nil
   119  	}
   120  	idx := Uint128Bytes - len(bs)
   121  	if idx < Uint128Bytes {
   122  		copy(res[idx:], bs)
   123  	}
   124  	return res, nil
   125  }
   126  
   127  // ToFixedSizeByteSlice converts Uint128 to Big-Endian fixed size byte slice.
   128  func (u *Uint128) ToFixedSizeByteSlice() ([]byte, error) {
   129  	bytes, err := u.ToFixedSizeBytes()
   130  	return bytes[:], err
   131  }
   132  
   133  // String returns the string representation of x.
   134  func (u *Uint128) String() string {
   135  	return u.value.Text(10)
   136  }
   137  
   138  // FromFixedSizeBytes converts Big-Endian fixed size bytes to Uint128.
   139  func (u *Uint128) FromFixedSizeBytes(bytes [16]byte) *Uint128 {
   140  	u.FromFixedSizeByteSlice(bytes[:])
   141  	return u
   142  }
   143  
   144  // FromFixedSizeByteSlice converts Big-Endian fixed size bytes to Uint128.
   145  func (u *Uint128) FromFixedSizeByteSlice(bytes []byte) (*Uint128, error) {
   146  	if len(bytes) != Uint128Bytes {
   147  		return nil, ErrUint128InvalidBytesSize
   148  	}
   149  	i := 0
   150  	for ; i < Uint128Bytes; i++ {
   151  		if bytes[i] != 0 {
   152  			break
   153  		}
   154  	}
   155  	if i < Uint128Bytes {
   156  		u.value.SetBytes(bytes[i:])
   157  	} else {
   158  		u.value.SetUint64(0)
   159  	}
   160  	return u, nil
   161  }
   162  
   163  // Uint64 returns the uint64 representation of x.
   164  // If x cannot be represented in a uint64, the result is undefined.
   165  func (u *Uint128) Uint64() uint64 {
   166  	return u.value.Uint64()
   167  }
   168  
   169  //Add returns u + x
   170  func (u *Uint128) Add(x *Uint128) (*Uint128, error) {
   171  	obj := &Uint128{NewUint128().value.Add(u.value, x.value)}
   172  	if err := obj.Validate(); nil != err {
   173  		return u, err
   174  	}
   175  	return obj, nil
   176  }
   177  
   178  //Sub returns u - x
   179  func (u *Uint128) Sub(x *Uint128) (*Uint128, error) {
   180  	obj := &Uint128{NewUint128().value.Sub(u.value, x.value)}
   181  	if err := obj.Validate(); nil != err {
   182  		return u, err
   183  	}
   184  	return obj, nil
   185  }
   186  
   187  //Mul returns u * x
   188  func (u *Uint128) Mul(x *Uint128) (*Uint128, error) {
   189  	obj := &Uint128{NewUint128().value.Mul(u.value, x.value)}
   190  	if err := obj.Validate(); nil != err {
   191  		return u, err
   192  	}
   193  	return obj, nil
   194  }
   195  
   196  //Div returns u / x
   197  func (u *Uint128) Div(x *Uint128) (*Uint128, error) {
   198  	obj := &Uint128{NewUint128().value.Div(u.value, x.value)}
   199  	if err := obj.Validate(); nil != err {
   200  		return u, err
   201  	}
   202  	return obj, nil
   203  }
   204  
   205  //Exp returns u^x
   206  func (u *Uint128) Exp(x *Uint128) (*Uint128, error) {
   207  	obj := &Uint128{NewUint128().value.Exp(u.value, x.value, nil)}
   208  	if err := obj.Validate(); nil != err {
   209  		return u, err
   210  	}
   211  	return obj, nil
   212  }
   213  
   214  //DeepCopy returns a deep copy of u
   215  func (u *Uint128) DeepCopy() *Uint128 {
   216  	z := new(big.Int)
   217  	z.Set(u.value)
   218  	return &Uint128{z}
   219  }
   220  
   221  // Cmp compares u and x and returns:
   222  //
   223  //   -1 if u <  x
   224  //    0 if u == x
   225  //   +1 if u >  x
   226  func (u *Uint128) Cmp(x *Uint128) int {
   227  	return u.value.Cmp(x.value)
   228  }
   229  
   230  //Bytes absolute value of u as a big-endian byte slice.
   231  func (u *Uint128) Bytes() []byte {
   232  	return u.value.Bytes()
   233  }